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