def _switch_features_handler(self, ev): datapath = ev.msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser match = parser.OFPMatch() reg = oxm_fields.NiciraExtended1('reg0', 0, type_desc.Int4), actions_x = [ parser.NXActionMultipath( fields=nicira_ext.NX_HASH_FIELDS_SYMMETRIC_L4, basis=1024, algorithm=nicira_ext.NX_MP_ALG_HRW, max_link=1, arg=0, ofs_nbits=nicira_ext.ofs_nbits(0, 31), dst="reg0") ] actions_x.append( parser.NXActionResubmitTable(in_port=8080, table_id=10)) self.add_flow(datapath, 999, match, actions_x, table=0) actions = [ parser.NXActionOutputReg(ofs_nbits=nicira_ext.ofs_nbits(0, 31), src="reg0", max_len=2048) ] learn_action = parser.NXActionLearn( table_id=15, specs=[ # Match parser.NXFlowSpecMatch( src=('eth_type_nxm', 16), dst=('eth_type', 0), n_bits=16, ), parser.NXFlowSpecMatch( src=("ip_proto_nxm", 8), dst=('ip_proto', 0), n_bits=8, ), # Actions parser.NXFlowSpecLoad( src=('reg6', 0), dst=('reg7', 0), n_bits=32, ), ], fin_idle_timeout=1, fin_hard_timeout=1, ) actions.append(learn_action) self.add_flow(datapath, 999, match, actions, table=10)
def natv6_flows(self, nfvip): nat_base = nfvip.network.network_address assert nfvip.network.prefixlen == 64, 'NFVIPS IPv4 all must be /64' # pylint: disable=no-member return self.apply_actions([ # ipv6_src fc01::5 -> fc04::5:0:1, ipv6_dst fc01::1 -> fc04::1 parser.NXActionRegLoad(value=(int(nat_base) & ((2**64) - 1)), dst=self.AREG, ofs_nbits=nicira_ext.ofs_nbits(0, 63)), parser.NXActionRegLoad(value=(int(nat_base) >> 64), dst=self.AREG, ofs_nbits=nicira_ext.ofs_nbits(64, 127)), ] + self.nat_actions(ether.ETH_TYPE_IPV6, nfvip, 32))
def _get_rewrite_ip_and_output_actions(self, ofproto, parser): """ Retrieve the actions that rewrite the dst IP field with the reg6 (the tunnel key), set the first bit of that field, and output to the metadata service OVS port. The IP is set to <reg6> | 0x8000000, so that the transparent proxy can extract the <reg6> from the source IP address, and be able to identify the source VM. reg6 holds the local DF id identifying the VM. """ return [ parser.NXActionRegMove( src_field='reg6', dst_field='ipv4_src', n_bits=32, ), parser.NXActionRegLoad( ofs_nbits=nicira_ext.ofs_nbits(31, 31), dst="ipv4_src", value=1, ), parser.OFPActionOutput( self._ofport, ofproto.OFPCML_NO_BUFFER, ) ]
def _make_ingress_classification_flow(self, lport, port_num): match = self.parser.OFPMatch(in_port=port_num) network_id = lport.lswitch.unique_key LOG.debug( "match in_port=%(in_port)s for ingress classification " "of %(lport)s in network %(network)s", { 'in_port': port_num, 'lport': lport, 'network': network_id }) # Reset in_port to 0 to avoid drop by output command. actions = [ self.parser.OFPActionSetField(reg6=lport.unique_key), self.parser.OFPActionSetField(metadata=network_id), self.parser.NXActionRegLoad( dst='in_port', value=0, ofs_nbits=nicira_ext.ofs_nbits(0, 31), ), self.parser.NXActionResubmit(), ] self.mod_flow( table_id=const.INGRESS_CLASSIFICATION_DISPATCH_TABLE, priority=const.PRIORITY_MEDIUM, match=match, actions=actions, )
def arp_reply_actions(self): # pylint: disable=no-member common_reply = self.common_reply_actions() return self.apply_actions([ parser.NXActionRegLoad(value=arp.ARP_REPLY, dst='arp_op', ofs_nbits=nicira_ext.ofs_nbits(0, 2)), parser.NXActionRegMove(src_field='arp_sha', dst_field='arp_tha', n_bits=48, src_ofs=0, dst_ofs=0), parser.NXActionRegMove(src_field='arp_tpa', dst_field=self.AREG, n_bits=32, src_ofs=0, dst_ofs=0), parser.NXActionRegMove(src_field='arp_spa', dst_field='arp_tpa', n_bits=32, src_ofs=0, dst_ofs=0), parser.NXActionRegMove(src_field=self.AREG, dst_field='arp_spa', n_bits=32, src_ofs=0, dst_ofs=0), parser.OFPActionSetField(arp_sha=FAKECLIENTMAC), ] + common_reply)
def _get_instructions(self): ofproto = self.datapath.ofproto parser = self.datapath.ofproto_parser actions = [parser.OFPActionSetField(arp_op=arp.ARP_REPLY), parser.NXActionRegMove(src_field='arp_sha', dst_field='arp_tha', n_bits=48), parser.NXActionRegMove(src_field='arp_spa', dst_field='arp_tpa', n_bits=32), parser.OFPActionSetField(eth_src=self.mac_address), parser.OFPActionSetField(arp_sha=self.mac_address), parser.OFPActionSetField(arp_spa=self.interface_ip), parser.NXActionRegMove(src_field='reg6', dst_field='reg7', n_bits=32), parser.NXActionRegLoad( dst='in_port', ofs_nbits=nicira_ext.ofs_nbits(0, 31), value=0)] instructions = [ parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), parser.OFPInstructionGotoTable(const.INGRESS_DISPATCH_TABLE), ] return instructions
def _install_snat_egress_conntrack(self, match, ext_host_ip): """implements single sNAT pass for multiple tenant deployment :param match: - OVS match expression passed as a parameter :param ext_host_ip: - unique ip to translate tenant IPs to it :returns: None ----Translation logic follows next rules:---- ipv4_src -> reg5 (temporary save internal tenant local IP) reg6 -> ipv4_src (replace content of ipv4_src with host unique value) last_bit(1) -> ipv4_src (turn unique value into legal IP address) reg6-> ct_mark (save unique value associated with port into OS conn. track table) reg5 -> ct_label (save original tenant local IP for return flow) """ parser = self.parser ofproto = self.ofproto actions = [ parser.NXActionRegMove(src_field='ipv4_src', dst_field='reg5', n_bits=32), parser.NXActionRegMove(src_field='reg6', dst_field='ipv4_src', n_bits=32), parser.NXActionRegLoad( ofs_nbits=nicira_ext.ofs_nbits(31, 31), dst="ipv4_src", value=1, ), parser.NXActionCT(alg=0, flags=const.CT_FLAG_COMMIT, recirc_table=const.EGRESS_SNAT_TABLE, zone_ofs_nbits=const.NAT_TRACKING_ZONE, zone_src='', actions=[ parser.NXActionNAT( flags=const.CT_FLAG_COMMIT, range_ipv4_min=ext_host_ip, range_ipv4_max=ext_host_ip, ), parser.NXActionRegMove(dst_field='ct_mark', src_field='reg6', n_bits=32), parser.NXActionRegMove(dst_field='ct_label', src_field='reg5', n_bits=32), ]) ] action_inst = parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions) inst = [action_inst] self.mod_flow(inst=inst, table_id=const.EGRESS_NAT_TABLE, priority=const.PRIORITY_LOW, match=match)
def natv4_flows(self, nfvip): nat_base = nfvip.network.network_address assert nfvip.network.prefixlen == 16, 'NFVIPS IPv4 all must be /16' # pylint: disable=no-member return self.apply_actions([ # ipv4_src 192.168.2.5->10.10.5.1, ipv4_dst 192.168.2.1->10.10.0.1 parser.NXActionRegLoad(value=int(nat_base), dst=self.AREG, ofs_nbits=nicira_ext.ofs_nbits(0, 31)), ] + self.nat_actions(ether.ETH_TYPE_IP, nfvip, 8))
def _install_default_flows(self, datapath): parser = datapath.ofproto_parser match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP, ct_state=(0x0, self.CT_TRK)) actions = [ parser.NXActionCT(flags=0x0, zone_src=None, zone_ofs_nbits=ofs_nbits(14, 15), recirc_table=self.conntrack_scratch, alg=0, actions=[]) ] flows.add_resubmit_next_service_flow(datapath, self.tbl_num, match, actions, priority=flows.DEFAULT_PRIORITY, resubmit_table=self.next_table) # Match all new connections on scratch table match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP, ct_zone=ofs_nbits(14, 15), ct_state=(self.CT_NEW | self.CT_TRK, self.CT_NEW | self.CT_TRK)) actions = [ parser.NXActionCT(flags=0x1, zone_src=None, zone_ofs_nbits=ofs_nbits(14, 15), recirc_table=self.connection_event_table, alg=0, actions=[]) ] flows.add_drop_flow(datapath, self.conntrack_scratch, match, actions, priority=flows.DEFAULT_PRIORITY) match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP) flows.add_resubmit_next_service_flow(datapath, self.tbl_num, match, [], priority=flows.MINIMUM_PRIORITY, resubmit_table=self.next_table)
def ct(cls, ofproto, action_str): str_to_port = {'ftp': 21, 'tftp': 69} flags = 0 zone_src = "" zone_ofs_nbits = 0 recirc_table = nicira_ext.NX_CT_RECIRC_NONE alg = 0 ct_actions = [] if len(action_str) > 2: if (not action_str.startswith('ct(') or action_str[-1] != ')'): raise ryu.exception.OFPInvalidActionString( action_str=action_str) rest = tokenize_ofp_instruction_arg(action_str[len('ct('):-1]) else: rest = [] for arg in rest: if arg == 'commit': flags |= nicira_ext.NX_CT_F_COMMIT rest = rest[len('commit'):] elif arg == 'force': flags |= nicira_ext.NX_CT_F_FORCE elif arg.startswith('exec('): ct_actions = ofp_instruction_from_str(ofproto, arg[len('exec('):-1]) else: try: k, v = arg.split('=', 1) if k == 'table': recirc_table = str_to_int(v) elif k == 'zone': m = re.search('\[(\d*)\.\.(\d*)\]', v) if m: zone_ofs_nbits = nicira_ext.ofs_nbits( int(m.group(1)), int(m.group(2))) zone_src = nxm_field_name_to_ryu(v[:m.start(0)]) else: zone_ofs_nbits = str_to_int(v) elif k == 'alg': alg = str_to_port[arg[len('alg='):]] except Exception: raise ryu.exception.OFPInvalidActionString( action_str=action_str) return dict( NXActionCT={ 'flags': flags, 'zone_src': zone_src, 'zone_ofs_nbits': zone_ofs_nbits, 'recirc_table': recirc_table, 'alg': alg, 'actions': ct_actions })
def ct(cls, ofproto, action_str): str_to_port = {'ftp': 21, 'tftp': 69} flags = 0 zone_src = "" zone_ofs_nbits = 0 recirc_table = nicira_ext.NX_CT_RECIRC_NONE alg = 0 ct_actions = [] if len(action_str) > 2: if (not action_str.startswith('ct(') or action_str[-1] != ')'): raise ryu.exception.OFPInvalidActionString( action_str=action_str) rest = tokenize_ofp_instruction_arg(action_str[len('ct('):-1]) else: rest = [] for arg in rest: if arg == 'commit': flags |= nicira_ext.NX_CT_F_COMMIT rest = rest[len('commit'):] elif arg == 'force': flags |= nicira_ext.NX_CT_F_FORCE elif arg.startswith('exec('): ct_actions = ofp_instruction_from_str( ofproto, arg[len('exec('):-1]) else: try: k, v = arg.split('=', 1) if k == 'table': recirc_table = str_to_int(v) elif k == 'zone': m = re.search('\[(\d*)\.\.(\d*)\]', v) if m: zone_ofs_nbits = nicira_ext.ofs_nbits( int(m.group(1)), int(m.group(2))) zone_src = nxm_field_name_to_ryu( v[:m.start(0)]) else: zone_ofs_nbits = str_to_int(v) elif k == 'alg': alg = str_to_port[arg[len('alg='):]] except Exception: raise ryu.exception.OFPInvalidActionString( action_str=action_str) return dict(NXActionCT={'flags': flags, 'zone_src': zone_src, 'zone_ofs_nbits': zone_ofs_nbits, 'recirc_table': recirc_table, 'alg': alg, 'actions': ct_actions})
def _install_snat_ingress_after_conntrack(self, unique_key, vm_mac, external_host_mac): """complements reverse sNAT translation from unique IP to tenant IP :param unique_key: - key to match with :param vm_mac: - original VM mac address to restore :returns: None ---Translation complement follows next rules:--- unique_key -> reg7 ( load unique port key into dedicated register) ct_label -> ipv4_src (restore original local tenant IP) change src/dst mac addresses to push packet further to destination """ parser = self.parser ofproto = self.ofproto match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP, ct_mark=int(unique_key)) actions = [ parser.OFPActionSetField(eth_src=external_host_mac), parser.OFPActionSetField(eth_dst=vm_mac), parser.NXActionRegLoad( ofs_nbits=nicira_ext.ofs_nbits(0, 31), dst='reg7', value=unique_key), parser.NXActionRegMove( src_field='ct_label', dst_field='ipv4_dst', n_bits=32) ] action_inst = parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions) goto_inst = parser.OFPInstructionGotoTable( const.INGRESS_DISPATCH_TABLE) inst = [action_inst, goto_inst] self.mod_flow( inst=inst, table_id=const.INGRESS_SNAT_TABLE, priority=const.PRIORITY_LOW, match=match) actions = [self.parser.OFPActionOutput( self.external_ofport, self.ofproto.OFPCML_NO_BUFFER)] self.mod_flow( actions=actions, table_id=const.INGRESS_DISPATCH_TABLE, priority=const.PRIORITY_DEFAULT)
def _install_ingress_goto_rules(self): parser = self.parser match = parser.OFPMatch(in_port=self.external_ofport) actions = [parser.NXActionRegLoad( dst='in_port', value=0, ofs_nbits=nicira_ext.ofs_nbits(0, 31))] inst = [parser.OFPInstructionActions( self.datapath.ofproto.OFPIT_APPLY_ACTIONS, actions), parser.OFPInstructionGotoTable(const.INGRESS_NAT_TABLE)] self.mod_flow(inst=inst, table_id=const.INGRESS_CLASSIFICATION_DISPATCH_TABLE, priority=const.PRIORITY_DEFAULT, match=match)
def _install_dispatch_flows(self, flow_classifier): lport = self._get_flow_classifier_lport(flow_classifier) # End-of-chain # 1) Restore network ID in metadata and zero reg6 + reg2 # 2) Restore port ID in reg7 in dest port # 3) Resubmit to the next table lswitch = lport.lswitch actions = [ self.parser.OFPActionSetField(metadata=lswitch.unique_key), self.parser.OFPActionSetField(reg6=0), self.parser.OFPActionSetField(reg2=0), ] if flow_classifier.source_port == lport: done_bit = _SRC_BIT elif flow_classifier.dest_port == lport: done_bit = _DST_BIT # FIXME (dimak) maybe get it from L2 table actions.append( self.parser.OFPActionSetField(reg7=lport.unique_key)) actions += [ self.parser.NXActionRegLoad( dst='reg3', value=1, ofs_nbits=nicira_ext.ofs_nbits(done_bit, done_bit), ), self.parser.NXActionResubmitTable( table_id=self._get_flow_classifier_table(flow_classifier)) ] self.mod_flow( table_id=constants.SFC_END_OF_CHAIN_TABLE, priority=constants.PRIORITY_MEDIUM, match=self.parser.OFPMatch(reg2=flow_classifier.unique_key), actions=actions, )
def add_arp_flow(self): # need to get iface number from ovs ofproto = self.datapath.ofproto match = self.parser.OFPMatch(in_port=self.mpls_port_id) match.set_dl_type(ether.ETH_TYPE_ARP) match.set_arp_tpa(utils.ipv4_text_to_int(self.interface_ip)) match.set_arp_opcode(arp.ARP_REQUEST) actions = [ self.parser.OFPActionSetField(arp_op=arp.ARP_REPLY), self.parser.NXActionRegMove(src_field='arp_sha', dst_field='arp_tha', n_bits=48), self.parser.NXActionRegMove(src_field='arp_sha', dst_field='eth_dst', n_bits=48), self.parser.NXActionRegMove(src_field='arp_spa', dst_field='arp_tpa', n_bits=32), self.parser.OFPActionSetField(eth_src=self.mac_address), self.parser.OFPActionSetField(arp_sha=self.mac_address), self.parser.OFPActionSetField(arp_spa=self.interface_ip), self.parser.NXActionRegLoad(dst='in_port', ofs_nbits=nicira_ext.ofs_nbits(0, 31), value=0), self.parser.OFPActionOutput(self.mpls_port_id, ofproto.OFPCML_NO_BUFFER) ] inst = [ self.parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions) ] self.mod_flow( inst=inst, match=match, table_id=const.INGRESS_CLASSIFICATION_DISPATCH_TABLE, )
def _match_actions_by_network_type(self, lport, network_id, network_type): actions = [ self.parser.NXActionRegLoad( dst='in_port', value=0, ofs_nbits=nicira_ext.ofs_nbits(0, 31), ), self.parser.OFPActionSetField(metadata=network_id), ] if network_type == NET_VLAN: vlan_vid = self.ofproto.OFPVID_PRESENT vlan_vid |= lport.lswitch.segmentation_id actions.append(self.parser.OFPActionPopVlan()) elif network_type == NET_FLAT: vlan_vid = 0 match = self.parser.OFPMatch( in_port=self.int_ofports[lport.lswitch.physical_network], vlan_vid=vlan_vid, ) return match, actions
def _install_ingress_nat_rules(self, floatingip): network_id = floatingip.floating_lport.lswitch.unique_key # TODO(Fei Rao) check the network type if self._is_first_external_network(network_id): # if it is the first floating ip on this node, then # install the common goto flow rule. parser = self.parser self.mod_flow( table_id=const.INGRESS_CLASSIFICATION_DISPATCH_TABLE, priority=const.PRIORITY_DEFAULT, match=parser.OFPMatch(in_port=self.external_ofport), inst=[ parser.OFPInstructionActions( self.ofproto.OFPIT_APPLY_ACTIONS, [ parser.NXActionRegLoad( dst='in_port', value=0, ofs_nbits=nicira_ext.ofs_nbits(0, 31), ), ], ), parser.OFPInstructionGotoTable(const.INGRESS_NAT_TABLE), ], ) # Take over reg7 == 0 for the external_ofport match = parser.OFPMatch(reg7=0) actions = [self.parser.OFPActionOutput( self.external_ofport, self.ofproto.OFPCML_NO_BUFFER)] self.mod_flow( actions=actions, table_id=const.INGRESS_DISPATCH_TABLE, priority=const.PRIORITY_MEDIUM, match=match) self._install_floatingip_arp_responder(floatingip) self._install_dnat_ingress_rules(floatingip) self._increase_external_network_count(network_id)
def config_switch(self, parser): mod_flow = self.parent.mod_flow ul_port = self.parent.ul_port dl_port = self.parent.dl_port flag_commit = 1 flag_snat = 1 flag_dnat = 2 ct_state_minus_trk = (0, 32) ct_state_plus_trk = (32, 32) # dl -> ul (priv -> pubilc, orig -> translated) # # ip,in_port="ul_port" actions=ct(commit,zone=1,nat(dst=dst)),output:"dl_port" match = {'in_port': dl_port, 'eth_type': 0x0800} actions = [ action_ct( parser, { 'flags': flag_commit, 'zone_ofs_nbits': nicira_ext.ofs_nbits(0, 1), 'actions': [ action_nat( parser, { 'flags': flag_dnat, 'range_ipv4_min': self.conf.range_ipv4_min, 'range_ipv4_max': self.conf.range_ipv4_max, 'range_proto_min': self.conf.range_port_min, 'range_proto_max': self.conf.range_port_max, }) ] }), parser.OFPActionSetField(eth_dst=self.conf.uplink_dst_mac), ] mod_flow(match=match, actions=actions, output=ul_port) # ul -> dl (pubilc -> priv, translated -> orig) # # ct_state=-trk,ip,in_port="dl_port" actions=ct(table=0,zone=1,nat) match = { 'in_port': ul_port, 'eth_type': 0x0800, 'ct_state': ct_state_minus_trk, } actions = [ action_ct( parser, { 'flags': 0, 'zone_ofs_nbits': nicira_ext.ofs_nbits(0, 1), 'recirc_table': 0, 'actions': [action_nat(parser, {'flags': 0})], }), parser.OFPActionSetField(eth_dst=self.conf.downlink_dst_mac), ] mod_flow(match=match, actions=actions, output=dl_port) # ct_state=+trk,ct_zone=1,in_port="dl_port" actions=output:"ul_port" match = { 'in_port': ul_port, 'eth_type': 0x0800, 'ct_state': ct_state_plus_trk, 'ct_zone': 1, } actions = [ parser.OFPActionSetField(eth_dst=self.conf.downlink_dst_mac), ] mod_flow(match=match, actions=actions, output=dl_port)
def nat_actions(self, eth_type, nfvip, nat_offset): ip_ver = nfvip.ip.version ip_src_nxm = 'ipv%u_src_nxm' % ip_ver ip_dst_nxm = 'ipv%u_dst_nxm' % ip_ver ipbits = nfvip.ip.max_prefixlen # pylint: disable=no-member return [ parser.NXActionRegMove(src_field='ipv%u_src' % ip_ver, dst_field=self.AREG, n_bits=nat_offset, src_ofs=0, dst_ofs=nat_offset), parser.NXActionRegMove(src_field='ipv%u_dst' % ip_ver, dst_field=self.AREG, n_bits=nat_offset, src_ofs=0, dst_ofs=0), # we have to load output port numbers into reg1 and reg2 because NXFlowSpecOutput() won't take a literal. parser.NXActionRegLoad(value=self.FAKEPORT, dst=self.FAKEPORTREG, ofs_nbits=nicira_ext.ofs_nbits(0, 15)), parser.NXActionRegLoad(value=self.COPROPORT, dst=self.COPROPORTREG, ofs_nbits=nicira_ext.ofs_nbits(0, 15)), # now program an inbound flow to perform NAT. parser.NXActionLearn( table_id=self.FROM_COPRO_TABLE, priority=2, hard_timeout=self.IDLE, specs=[ parser.NXFlowSpecMatch(src=eth_type, dst=('eth_type_nxm', 0), n_bits=16), parser.NXFlowSpecMatch(src=(ip_src_nxm, 0), dst=(ip_src_nxm, 0), n_bits=ipbits), parser.NXFlowSpecMatch(src=(ip_dst_nxm, 0), dst=(ip_dst_nxm, 0), n_bits=ipbits), parser.NXFlowSpecLoad(src=int(self.FAKECLIENTMAC), dst=('eth_src_nxm', 0), n_bits=48), parser.NXFlowSpecLoad(src=int(self.FAKESERVERMAC), dst=('eth_dst_nxm', 0), n_bits=48), ] + self.reg_copy(self.AREG, ip_src_nxm, ipbits) + [ parser.NXFlowSpecLoad(src=int(nfvip.ip), dst=(ip_dst_nxm, 0), n_bits=ipbits), parser.NXFlowSpecOutput(src=(self.FAKEPORTREG, 0), dst='', n_bits=16), ]), # now program outbound an outbound flow. parser.NXActionLearn( table_id=self.TO_COPRO_TABLE, priority=2, idle_timeout=self.IDLE, specs=[ parser.NXFlowSpecMatch(src=eth_type, dst=('eth_type_nxm', 0), n_bits=16), parser.NXFlowSpecMatch(src=int(nfvip.ip), dst=(ip_src_nxm, 0), n_bits=ipbits), ] + self.reg_copy(self.AREG, ip_dst_nxm, ipbits) + [ parser.NXFlowSpecLoad(src=('eth_dst_nxm', 0), dst=('eth_src_nxm', 0), n_bits=48), parser.NXFlowSpecLoad(src=('eth_src_nxm', 0), dst=('eth_dst_nxm', 0), n_bits=48), parser.NXFlowSpecLoad(src=(ip_dst_nxm, 0), dst=(ip_src_nxm, 0), n_bits=ipbits), parser.NXFlowSpecLoad(src=(ip_src_nxm, 0), dst=(ip_dst_nxm, 0), n_bits=ipbits), parser.NXFlowSpecOutput(src=(self.COPROPORTREG, 0), dst='', n_bits=16), ]), # now that future flows are programmed, handle the packet we have. parser.OFPActionSetField(eth_src=self.FAKECLIENTMAC), parser.OFPActionSetField(eth_dst=self.FAKESERVERMAC), parser.NXActionRegMove(src_field=self.AREG, dst_field=('ipv%u_src' % ip_ver), n_bits=ipbits, src_ofs=0, dst_ofs=0), parser.OFPActionSetField(**{'ipv%u_dst' % ip_ver: str(nfvip.ip)}), parser.OFPActionOutput(self.FAKEPORT) ]
def _add_tap_metadata_port(self, ofport, mac): """ Add the flows that can be added with the current available information: Regular Client->Server packets have IP rewritten, and sent to OVS port TCP Syn packets are sent to controller, so that response flows can be added. Packets from the OVS port are detected and sent for classification. """ self._ofport = ofport datapath = self.get_datapath() ofproto = datapath.ofproto parser = datapath.ofproto_parser self._add_incoming_flows() # Regular packet match = parser.OFPMatch(eth_type=ethernet.ether.ETH_TYPE_IP) actions = self._get_rewrite_ip_and_output_actions(ofproto, parser) inst = [ parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions, ) ] self.mod_flow( datapath=datapath, table_id=const.METADATA_SERVICE_TABLE, command=ofproto.OFPFC_ADD, priority=const.PRIORITY_MEDIUM, match=match, inst=inst, ) # TCP SYN packet match = parser.OFPMatch( eth_type=ethernet.ether.ETH_TYPE_IP, ip_proto=ipv4.inet.IPPROTO_TCP, tcp_flags=(TCP_SYN, TCP_SYN | TCP_ACK), ) learn_actions = self._get_learn_actions(ofproto, parser) learn_actions.extend(actions) inst = [ parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, learn_actions, ) ] self.mod_flow( datapath=datapath, table_id=const.METADATA_SERVICE_TABLE, command=ofproto.OFPFC_ADD, priority=const.PRIORITY_HIGH, match=match, inst=inst, ) # Response packet actions = [ parser.NXActionRegLoad(ofs_nbits=nicira_ext.ofs_nbits(0, 31), dst="in_port", value=0), ] inst = [ parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions, ), parser.OFPInstructionGotoTable(const.METADATA_SERVICE_REPLY_TABLE), ] self.mod_flow( datapath=datapath, table_id=const.INGRESS_CLASSIFICATION_DISPATCH_TABLE, command=ofproto.OFPFC_ADD, priority=const.PRIORITY_MEDIUM, match=parser.OFPMatch(in_port=ofport), inst=inst, ) self._create_arp_responder(mac)
def get_add_output_flow_msg(datapath, table, match, actions=None, instructions=None, priority=MINIMUM_PRIORITY, cookie=0x0, idle_timeout=0, hard_timeout=0, output_port=None, output_reg=None, copy_table=None, max_len=None): """ Add a flow to a table that sends the packet to the specified port Args: datapath (ryu.controller.controller.Datapath): Datapath to push the flow to table (int): Table number to apply the flow to match (MagmaMatch): The match for the flow actions ([OFPAction]): List of actions for the flow. instructions ([OFPInstruction]): List of instructions for the flow. This will default to a single OFPInstructionsActions to apply `actions`. Ignored if `actions` is set. priority (int): Flow priority cookie (hex): cookie value for the flow idle_timeout (int): idle timeout for the flow hard_timeout (int): hard timeout for the flow output_port (int): the port to send the packet copy_table (int): optional table to send the packet to max_len (int): Max length to send to controller Raises: MagmaOFError: if the flow can't be added Exception: If the actions contain NXActionResubmitTable. """ ofproto, parser = datapath.ofproto, datapath.ofproto_parser _check_resubmit_action(actions, parser) if actions is None: actions = [] if output_reg is not None: output_action = parser.NXActionOutputReg2(ofs_nbits=ofs_nbits(0, 31), src=output_reg, max_len=1234) else: if max_len is None: output_action = parser.OFPActionOutput(output_port) else: output_action = parser.OFPActionOutput(output_port, max_len) actions = actions + [ output_action, ] if copy_table: actions.append(parser.NXActionResubmitTable(table_id=copy_table)) inst = __get_instructions_for_actions(ofproto, parser, actions, instructions) ryu_match = parser.OFPMatch(**match.ryu_match) return parser.OFPFlowMod(datapath=datapath, priority=priority, match=ryu_match, instructions=inst, table_id=table, cookie=cookie, idle_timeout=idle_timeout, hard_timeout=hard_timeout)