faucetsdn / ryu

Ryu component-based software defined networking framework
https://ryu-sdn.org
Apache License 2.0
1.51k stars 1.16k forks source link

Modifying a Nicira Action #104

Closed koolzz closed 4 years ago

koolzz commented 4 years ago

Hi,

I'm trying to modify the NXActionSample2 action and wanted to ask for your help. Basically I have an OVS patch that modifies the Sampling action and adds a few custom fields. I currently use it with ovs-ofctl, but It would be great if I can just modify Ryu to accept the new args.

Here is my ovs-ofctl

sudo ovs-ofctl add-flow cwag_br0 "table=15,priority=12,metadata=0x75945885e85,actions=sample(probability=600,collector_set_id=1,obs_domain_id=1,obs_point_id=1,apn_mac_addr=58:bc:27:13:31:50,msisdn=5101006096,apn_name=\"cwc wifi offload\",pdp_start_epoch=100,sampling_port=gre0),resubmit(,20)"

Here is the corresponding OVS flow it creates

 cookie=0x0, duration=33.792s, table=15, n_packets=0, n_bytes=0, priority=12,metadata=0x75945885e85 actions=sample(probability=600,collector_set_id=1,obs_domain_id=1,obs_point_id=1,pdp_start_epoch=100,apn_mac_addr=58:bc:27:13:31:50,msisdn=5101006096,apn_name="cwc wifi offload",sampling_port=gre0),resubmit(,20)

The added fields from the standard Sample action are:

msisdn:
apn_mac_addr
apn_name
pdp_start_epoch

Here is the struct in ovs:

struct nx_action_sample2 {
    ovs_be16 type;                  /* OFPAT_VENDOR. */
    ovs_be16 len;                   /* Length is 32. */
    ovs_be32 vendor;                /* NX_VENDOR_ID. */
    ovs_be16 subtype;               /* NXAST_SAMPLE. */
    ovs_be16 probability;           /* Fraction of packets to sample. */
    ovs_be32 collector_set_id;      /* ID of collector set in OVSDB. */
    ovs_be32 obs_domain_id;         /* ID of sampling observation domain. */
    ovs_be32 obs_point_id;          /* ID of sampling observation point. */
    ovs_be16 sampling_port;         /* Sampling port. */
    uint8_t  msisdn[16];
    struct   eth_addr apn_mac_addr;
    uint8_t  apn_name[24];
    uint64_t pdp_start_epoch;
    uint8_t  direction;             /* NXAST_SAMPLE3 only. */
    uint8_t  zeros[5];              /* Pad to a multiple of 8 bytes */
 };
 OFP_ASSERT(sizeof(struct nx_action_sample2) == 88);

/* not sure if this is requried */
struct ofpact_sample {
    OFPACT_PADDED_MEMBERS(
        struct ofpact ofpact;
        uint16_t probability;   /* Always positive. */
        uint32_t collector_set_id;
        uint32_t obs_domain_id;
        uint32_t obs_point_id;
        ofp_port_t sampling_port;
        enum nx_action_sample_direction direction;
        uint8_t msisdn[16];
        struct eth_addr apn_mac_addr;
        uint8_t apn_name[24];
        uint64_t pdp_start_epoch;
    );
};

Currently with some hacking I've achieved this with RYU:

parser.NXActionSample2(
            probability=self.ipfix_config.probability, collector_set_id=self.ipfix_config.collector_set_id,
            obs_domain_id=self.ipfix_config.obs_domain_id, obs_point_id=self.ipfix_config.obs_point_id,
            apn_mac_addr=[10, 0, 39, 0, 0, 5],
            msisdn="5101006096", apn_name="cwc wifi offload", pdp_start_epoch=100,
            sampling_port=32768,
            )

 cookie=0x0, duration=11.112s, table=203, n_packets=0, n_bytes=0, priority=12 actions=sample(probability=65535,collector_set_id=1,obs_domain_id=1,obs_point_id=1,pdp_start_epoch=7205759403792793600,apn_mac_addr=0a:00:27:00:00:05,msisdn=5101006096,apn_name="cwc wifi offload",sampling_port=gre0),resubmit(,16),set_field:0->reg0,set_field:0->reg3

All the fields are correct except the pdp_start_epoch. I assume its because I messed up the struct packing as I'm not sure how to properly pack/encode the mac addr. Here is the relevant RYU code ( I've tried using ofp.oxm_from_user_header, ofp.oxm_serialize_header functions but didn't get anywhere so just encoding to ascii worked best for me.


    class NXActionSample2(NXAction):

        _subtype = nicira_ext.NXAST_SAMPLE2

        # probability, collector_set_id, obs_domain_id,
        # obs_point_id, msisdn, apn_mac_addr, apn_name, sampling_port
        _fmt_str = '!HIIIH16s6s24sQ6x'

        def __init__(self,
                     probability,
                     msisdn,
                     apn_mac_addr,
                     apn_name,
                     pdp_start_epoch,
                     collector_set_id=0,
                     obs_domain_id=0,
                     obs_point_id=0,
                     sampling_port=0,
                     type_=None, len_=None, experimenter=None, subtype=None):
            super(NXActionSample2, self).__init__()
            self.probability = probability
            self.collector_set_id = collector_set_id
            self.obs_domain_id = obs_domain_id
            self.obs_point_id = obs_point_id

            self.msisdn = msisdn.encode('ascii')
            self.apn_mac_addr = apn_mac_addr
            self.apn_name = apn_name.encode('ascii')
            self.pdp_start_epoch = pdp_start_epoch

            self.sampling_port = sampling_port

        @classmethod
        def parser(cls, buf):
            (probability,
             collector_set_id,
             obs_domain_id,
             obs_point_id,
             sampling_port,
             msisdn,
             apn_mac_addr,
             apn_name,
             pdp_start_epoch) = struct.unpack_from(
                cls._fmt_str, buf, 0)

            return cls(probability,
                       msisdn,
                       apn_mac_addr,
                       apn_name,
                       pdp_start_epoch,
                       collector_set_id,
                       obs_domain_id,
                       obs_point_id,
                       sampling_port)

        def serialize_body(self):
            data = bytearray()
            msg_pack_into(self._fmt_str, data, 0,
                          self.probability,
                          self.collector_set_id,
                          self.obs_domain_id,
                          self.obs_point_id,
                          self.sampling_port,
                          self.msisdn,
                          *self.apn_mac_addr,
                          self.apn_name,
                          self.pdp_start_epoch)
            return data

Would really appreciate your help, thank you!

gizmoguy commented 4 years ago

I don't see any obvious bugs in this github issue report.

For asking questions about how to use ryu please ask on our mailing list: https://sourceforge.net/projects/ryu/lists/ryu-devel

If you have in fact found a bug, please reopen a github issue with a reproduction case, expected outcome and outcome you actually get.

koolzz commented 4 years ago

I don't see any obvious bugs in this github issue report.

For asking questions about how to use ryu please ask on our mailing list: https://sourceforge.net/projects/ryu/lists/ryu-devel

If you have in fact found a bug, please reopen a github issue with a reproduction case, expected outcome and outcome you actually get.

Thanks, will do