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.

I've initially posted this question on this github issue
https://github.com/faucetsdn/ryu/issues/104, it's easier to read there due
to code blocks.

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="0a0027000005",
            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=30:61:30:30:32:37,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` and `apn_mac_addr`.
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.encode('ascii')
            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!

Thanks,
Nick
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to