def getReturnAndTagActions(self, switchID): ''' Get the return and tag actions :param switchID: ID of current switch :return: return and tag flow entries to be installed ''' actions = [] #In 4 flow entries, the packet contains only tagging on last switch ID (inner tagging) need to add #the first switch ID (outer tagging) and change the ethertype to be dirReturnNoTag. # Set type of packet actions.append( ofproto_v1_3_parser.OFPActionSetField( eth_src=ExtraLayers.ReturnNoTagMAC)) #push VLAN header actions.append(ofproto_v1_3_parser.OFPActionPushVlan()) #set the DirectionReturn field to be dirReturnNoTag #tag cuurent switch ID actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=retMaskedVlanID(switchID))) # Send to ingress port. actions.append( ofproto_v1_3_parser.OFPActionOutput( (self.switch_to_parent_port[switchID]))) #return the actions list return actions
def installTestStarFlowEntries(self): """ Code written for specific test on start topology. (Measure duplication and tagging time). :return: """ datapath1 = self.id_to_datapath[1] datapath2 = self.id_to_datapath[2] # Install the flow entries on the MP. Match = ofproto_v1_3_parser.OFPMatch( in_port=1, eth_type=ExtraLayers.typeForTestingTaggingAndDuplicationTime) Actions = [ ofproto_v1_3_parser.OFPActionOutput(0xfffffffd), ofproto_v1_3_parser.OFPActionOutput(0xfffffffd), ofproto_v1_3_parser.OFPActionPopVlan(), ofproto_v1_3_parser.OFPActionSetField( eth_type=ExtraLayers.dirBackwardsThreeFlowEntries), ofproto_v1_3_parser.OFPActionPushVlan( ethertype=ExtraLayers.VLAN_ID_ETHERTYPE_QINQ), ofproto_v1_3_parser.OFPActionSetField(vlan_vid=1), ofproto_v1_3_parser.OFPActionOutput(0xfffffffd) ] Inst = [ ofproto_v1_3_parser.OFPInstructionActions( datapath1.ofproto.OFPIT_APPLY_ACTIONS, Actions) ] mod = ofproto_v1_3_parser.OFPFlowMod( datapath=datapath1, priority=NORMAL_SWITCH_FORWARDING_PRIO, match=Match, instructions=Inst) datapath1.send_msg(mod)
def getDistributionActions(self, switchID): ''' Get the distribution actions to the given switch and current number of flow entries. :param switchID: ID of current switch. :return: distribution flow entries to be installed ''' #initialize the actions set to be empty actions = [] #Distribution in 4 flow entries - because returning the packet required extra processing and distribution requires none, first distribute the original packet and then return #First- send the original packet to all the distribution switches #Then - add info about the current switch ID (inner tag) and change the direction to be return and tag direction #packet arrive with inner vlan id of prev switch and dummy switch- change return direction ,set #the outer vlan to be curr switch and return via same port #if there are port to distribute to, should add the distribution actions (send the packet to distribution as is) if (0 != len(self.switch_to_distribution_port[switchID])): #send to every switch in distribution port all the distribution ports for dist_port in self.switch_to_distribution_port[switchID]: actions.append(ofproto_v1_3_parser.OFPActionOutput(dist_port)) #Now add the info about the current switch by popping both vlan and adding current switch tag. actions.append( ofproto_v1_3_parser.OFPActionSetField( eth_src=ExtraLayers.ReturnAndTagMAC)) # set vlan ID to be current switch with solid flag. actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=(retMaskedVlanID(switchID) | ExtraLayers.solidFlag))) # Send to ingress port. actions.append(ofproto_v1_3_parser.OFPActionOutput(OF_IN_PORT)) # if the there is no any RTP start in the current switch, exit if switchID not in self.rtp_switch_to_start_points: return actions # add the RTP for each RTP ID actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=retMaskedVlanID(ExtraLayers.NULL_ID))) entryNum = 0 for entry in self.rtp_switch_to_start_points[switchID]: actions.append(ofproto_v1_3_parser.OFPActionPushVlan()) actions.append( ofproto_v1_3_parser.OFPActionSetField( eth_src=ExtraLayers.RTPMAC)) actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=retMaskedVlanID(entry['id']))) actions.append( ofproto_v1_3_parser.OFPActionOutput(entry['outPort'])) #Do no pop the vlan header from the last packet send entryNum = entryNum + 1 if entryNum < len(self.rtp_switch_to_start_points[switchID]): actions.append(ofproto_v1_3_parser.OFPActionPopVlan()) #return the actions list return actions
def actions_to_ryu(actions, rule): """ Converts a list of actions to a list of ryu actions This returns both a instruction list and any extra messages that are required to install the instructions such as group mod messages. Currently this is not smart about reusing groups. actions: A iterable list actions such as ActionSet, ActionList, or Bucket. rule: The rule being converted return: A tuple ([actions], [extra messages]) """ ret = [] extra_messages = [] for action in actions: if action[0] == 'OUTPUT': ret.append(parser.OFPActionOutput(action[1])) elif action[0] == 'COPY_TTL_OUT': ret.append(parser.OFPActionCopyTtlOut()) elif action[0] == 'COPY_TTL_IN': ret.append(parser.OFPActionCopyTtlIn()) elif action[0] == 'SET_MPLS_TTL': ret.append(parser.OFPActionSetMplsTtl(action[1])) elif action[0] == 'DEC_MPLS_TTL': ret.append(parser.OFPActionDecMplsTtl()) elif action[0] == 'PUSH_VLAN': ret.append(parser.OFPActionPushVlan(action[1])) elif action[0] == 'POP_VLAN': ret.append(parser.OFPActionPopVlan()) elif action[0] == 'PUSH_MPLS': ret.append(parser.OFPActionPushMpls(action[1])) elif action[0] == 'POP_MPLS': ret.append(parser.OFPActionPopMpls(action[1])) elif action[0] == 'SET_QUEUE': ret.append(parser.OFPActionSetQueue(action[1])) elif action[0] == 'GROUP': if isinstance(action[1], Group): group_id, extra = group_to_ryu(action[1], rule) ret.append(parser.OFPActionGroup(group_id)) extra_messages += extra else: ret.append(parser.OFPActionGroup(action[1])) elif action[0] == 'SET_NW_TTL': ret.append(parser.OFPActionSetNwTtl(action[1])) elif action[0] == 'DEC_NW_TTL': ret.append(parser.OFPActionDecNwTtl()) elif action[0] == 'SET_FIELD': set_field = {action[1][0].lower(): action[1][1]} ret.append(parser.OFPActionSetField(**set_field)) elif action[0] == 'PUSH_PBB': ret.append(parser.OFPActionPushPbb(action[1])) elif action[0] == 'POP_PBB': ret.append(parser.OFPActionPopPbb()) else: assert not "GGRR" return (ret, extra_messages)
def push_vlan_act(vlan_vid, eth_type=ether.ETH_TYPE_8021Q): """Return OpenFlow action list to push Ethernet 802.1Q header with VLAN VID. Args: vid (int): VLAN VID Returns: list: actions to push 802.1Q header with VLAN VID set. """ return [ parser.OFPActionPushVlan(eth_type), set_vlan_vid(vlan_vid), ]
def push_vlan_act(vlan_vid): """Return OpenFlow action list to push Ethernet 802.1Q header with VLAN VID. Args: vid (int): VLAN VID Returns: list: actions to push 802.1Q header with VLAN VID set. """ return [ parser.OFPActionPushVlan(ether.ETH_TYPE_8021Q), parser.OFPActionSetField(vlan_vid=vid_present(vlan_vid)) ]
def port_add_vlan_untagged(self, port, vlan, forwarding_table, mirror_act): ofmsgs = [] ofmsgs.extend(self.add_controller_ips(vlan.controller_ips, vlan)) push_vlan_act = mirror_act + [ parser.OFPActionPushVlan(ether.ETH_TYPE_8021Q), parser.OFPActionSetField(vlan_vid=vlan.vid|ofp.OFPVID_PRESENT)] push_vlan_inst = [ self.apply_actions(push_vlan_act), self.goto_table(forwarding_table) ] null_vlan = namedtuple('null_vlan', 'vid') null_vlan.vid = ofp.OFPVID_NONE ofmsgs.append(self.valve_flowmod( self.dp.vlan_table, self.valve_in_match(in_port=port.number, vlan=null_vlan), priority=self.dp.low_priority, inst=push_vlan_inst)) ofmsgs.extend(self.build_flood_rules(vlan)) return ofmsgs
def getReturnAndTagActions(self, switchID, numberOfFlowEntries): ''' Get the return and tag actions (only return actions in 3 flow entries case or the first return action for 4 flow entries case) :param switchID: ID of current switch :param numberOfFlowEntries: 3 or 4 flow entries mode :return: return and tag flow entries to be installed ''' #initialize the actions set to be empty actions = [] #3 flow entries case if (3 == numberOfFlowEntries): #transfer to "parent" port as is (the packet already contains the switch ID's tagging) actions.append( ofproto_v1_3_parser.OFPActionOutput( (self.switch_to_parent_port[switchID]))) #4 flow entries case else: #In 4 flow entries, the packet contains only tagging on last switch ID (inner tagging) need to add #the first switch ID (outer tagging) and change the ethertype to be dirReturnNoTag. # Pop vlan actions.append(ofproto_v1_3_parser.OFPActionPopVlan()) #set the DirectionReturn field to be dirReturnNoTag actions.append( ofproto_v1_3_parser.OFPActionSetField( eth_type=ExtraLayers.dirReturnNoTag)) # push a new VLAN with ethertype of vlan actions.append( ofproto_v1_3_parser.OFPActionPushVlan( ethertype=ExtraLayers.VLAN_ID_ETHERTYPE_QINQ)) # set vlan ID to be current switch (last switch field) actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=retMaskedVlanID(switchID))) #transfer to "parent" port actions.append( ofproto_v1_3_parser.OFPActionOutput( (self.switch_to_parent_port[switchID]))) #return the actions list return actions
def set_vlan(self, vlan_id): self.actions_fields.append(ofp.OFPActionPushVlan()) self.actions_fields.append(ofp.OFPActionSetField(vlan_vid=(0x1000 | vlan_id))) return self
def _packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser actions = [] vlan_exist = False if not q.empty(): # new forwarding graph(s) received; convert to flow rules forwarding_graph = q.get(block=False) #self.forwarding_graphs.append(forwarding_graph) #self.logger.info("Recived a new forwarding graph++! = {0}".format(forwarding_graph)) #print forwarding_graph["10"] #print (forwarding_graph) for i in range(len(self.vlan_dst_ip_mac)): if forwarding_graph["VLAN"] == self.vlan_dst_ip_mac[i]['VLAN']: vlan_exist = True self.logger.error("VLAN id {0} already exists!".format( forwarding_graph["VLAN"])) break if vlan_exist == False: self.vlan_dst_ip_mac.append(forwarding_graph) self.logger.info( "MAC_IP_VLAN table has been updated! = {0}".format( self.vlan_dst_ip_mac)) # get Datapath ID to identify OpenFlow switches. dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) # analyse the received packets using the packet library. pkt = packet.Packet(msg.data) eth_pkt = pkt.get_protocol(ethernet.ethernet) ip_pkt = pkt.get_protocol(ipv4.ipv4) arp_pkt = pkt.get_protocol(arp.arp) vlan_pkt = pkt.get_protocol(vlan.vlan) dst = eth_pkt.dst src = eth_pkt.src in_port = msg.match['in_port'] vlan_id = None if vlan_pkt: vlan_id = vlan_pkt.vid self.logger.info( "Recived a new packet with VLAN id {0}".format(vlan_id)) if arp_pkt: self._handle_arp(datapath, in_port, vlan_id, eth_pkt, vlan_pkt, arp_pkt) return if ip_pkt: dst_ip = ip_pkt.dst src_ip = ip_pkt.src if ip_pkt: if dpid == PISH_EXT_SWITCH: if in_port == 1 and vlan_id != None: try: mac, ip = self.mac_ip(vlan_id) self.logger.info("Retrieved MAC:{0} and IP:{1}".format( mac, ip)) actions.append(parser.OFPActionSetField(eth_dst=mac)) actions.append(parser.OFPActionSetField(ipv4_dst=ip)) actions.append(parser.OFPActionPopVlan()) actions.append( parser.OFPActionOutput(2, ofproto.OFPCML_NO_BUFFER)) match = parser.OFPMatch(eth_type=0x0800, in_port=1, vlan_vid=4106) self.add_flow(datapath, 100, match, actions) except: self.logger.info("Error in mac and ip retrieval") elif in_port == 2: re_vlan = self._vlan_id_retrieval(dst) if re_vlan != None: actions.append( parser.OFPActionSetField(eth_src=HOST_MAC)) actions.append( parser.OFPActionSetField(ipv4_src=HOST_IP)) actions.append( parser.OFPActionPushVlan(ether.ETH_TYPE_8021Q)) actions.append( parser.OFPActionSetField( vlan_vid=self.vid_present(re_vlan))) actions.append( parser.OFPActionOutput(1, ofproto.OFPCML_NO_BUFFER)) match = parser.OFPMatch(eth_type=0x0800, in_port=2) self.add_flow(datapath, 100, match, actions)
def _packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser actions = [] if not q.empty(): # new forwarding graph(s) received; convert to flow rules forwarding_graph = q.get(block=False) #self.forwarding_graphs.append(forwarding_graph) print (forwarding_graph) try: self.ds_ip = forwarding_graph[2]["ip"] print self.ds_ip except: self.ds_ip = "192.168.23.104" # get Datapath ID to identify OpenFlow switches. dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) # analyse the received packets using the packet library. pkt = packet.Packet(msg.data) eth_pkt = pkt.get_protocol(ethernet.ethernet) ip_pkt = pkt.get_protocol(ipv4.ipv4) arp_pkt = pkt.get_protocol(arp.arp) vlan_pkt = pkt.get_protocol(vlan.vlan) dst = eth_pkt.dst src = eth_pkt.src in_port = msg.match['in_port'] vlan_id = None if vlan_pkt: vlan_id = vlan_pkt.vid if arp_pkt: self._handle_arp(datapath, in_port, vlan_id, eth_pkt, vlan_pkt, arp_pkt) return if ip_pkt: dst_ip = ip_pkt.dst src_ip = ip_pkt.src if in_port == 1: self.vlan_src_ip_mac.append({"vlan":vlan_id, "MAC":src, "IP":src_ip}) if ip_pkt: if dpid == PISH_EXT_SWITCH: if in_port == 1 and vlan_id != None: actions.append(parser.OFPActionSetField(eth_dst= self.vlan_dst_ip_mac[vlan_id]["MAC"])) actions.append(parser.OFPActionSetField(ipv4_dst= self.vlan_dst_ip_mac[vlan_id]["IP"])) actions.append(parser.OFPActionPopVlan()) actions.append(parser.OFPActionOutput(2, ofproto.OFPCML_NO_BUFFER)) match = parser.OFPMatch(eth_type=0x0800, in_port=1, vlan_vid= 4106) self.add_flow(datapath, 100, match, actions) elif in_port == 2: re_vlan = self._vlan_id_retrieval(dst) actions.append(parser.OFPActionSetField(eth_src= HOST_MAC)) actions.append(parser.OFPActionSetField(ipv4_src= HOST_IP)) actions.append(parser.OFPActionPushVlan(ether.ETH_TYPE_8021Q)) actions.append(parser.OFPActionSetField(vlan_vid=self.vid_present(re_vlan))) actions.append(parser.OFPActionOutput(1, ofproto.OFPCML_NO_BUFFER)) match = parser.OFPMatch(eth_type=0x0800, in_port=2) self.add_flow(datapath, 100, match, actions)
def getDistributionActions(self, switchID, numberOfFlowEntries): ''' Get the distribution actions to the given switch and current number of flow entries. :param switchID: ID of current switch. :param numberOfFlowEntries: 3 or 4 flow entries mode. :return: distribution flow entries to be installed ''' #initialize the actions set to be empty actions = [] #For case of 3 flow entries if (3 == numberOfFlowEntries): # Distribution in 3 flow entries case - first return the packet and then add info to each packet and distribute. # Packet arrive with inner vlan id of prev switch and dummy switch- change to return direction, set # The outer vlan to be curr switch and return via same port, # Pop vlan actions.append(ofproto_v1_3_parser.OFPActionPopVlan()) #set the DirectionReturn field to be dir backwards (constant for return direction of 3 flow entries) actions.append( ofproto_v1_3_parser.OFPActionSetField( eth_type=ExtraLayers.dirBackwardsThreeFlowEntries)) # push a new VLAN with ethertype of vlan actions.append( ofproto_v1_3_parser.OFPActionPushVlan( ethertype=ExtraLayers.VLAN_ID_ETHERTYPE_QINQ)) # set vlan ID to be current switch (last switch field) with solid link masking actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=(retMaskedVlanID(switchID) | ExtraLayers.solidFlag))) #return via same port actions.append(ofproto_v1_3_parser.OFPActionOutput(OF_IN_PORT)) #if there are port to distribute to, should add the distribution actions #For the distribution , for every packet, need to add vlan actions if (0 != len(self.switch_to_distribution_port[switchID])): #now after packet returned create the distribution packet. remove both vlans , push current switch # id and then dummy switch ID and spread to all req switches # Pop vlan actions.append(ofproto_v1_3_parser.OFPActionPopVlan()) #change the vlan ID from dirbackward to be vlan eth type so we will be able to pop vlan again actions.append( ofproto_v1_3_parser.OFPActionSetField( eth_type=ExtraLayers.VLAN_ID_ETHERTYPE_QINQ)) #pop second vlan actions.append(ofproto_v1_3_parser.OFPActionPopVlan()) #push vlan with vlan id of current switch actions.append( ofproto_v1_3_parser.OFPActionPushVlan( ethertype=ExtraLayers.VLAN_ID_ETHERTYPE_QINQ)) actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=retMaskedVlanID(switchID))) #push vlan with dummy vlan because it will be removed on return path actions.append( ofproto_v1_3_parser.OFPActionPushVlan( ethertype=ExtraLayers.VLAN_ID_ETHERTYPE_QINQ)) actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=retMaskedVlanID(ExtraLayers.NULL_ID))) #send to every switch in distribution port all the distribution ports #dist_ports = (self.switch_to_distribution_port)[switchID] for dist_port in self.switch_to_distribution_port[switchID]: actions.append( ofproto_v1_3_parser.OFPActionOutput(dist_port)) #4 flow entries case else: #Distribution in 4 flow entries - because returning the packet required extra processing and distribution requires none, first distribute the original packet and then return #First- send the original packet to all the distribution switches #Then - add info about the current switch ID (inner tag) and change the direction to be return and tag direction #packet arrive with inner vlan id of prev switch and dummy switch- change return direction ,set #the outer vlan to be curr switch and return via same port #if there are port to distribute to, should add the distribution actions (send the packet to distribution as is) if (0 != len(self.switch_to_distribution_port[switchID])): #send to every switch in distribution port all the distribution ports for dist_port in self.switch_to_distribution_port[switchID]: actions.append( ofproto_v1_3_parser.OFPActionOutput(dist_port)) #Now add the info about the current switch by popping both vlan and adding current switch tag. # Pop vlan actions.append(ofproto_v1_3_parser.OFPActionPopVlan()) # Pop vlan actions.append(ofproto_v1_3_parser.OFPActionPopVlan()) #set the DirectionReturn field to be dir return and tag. actions.append( ofproto_v1_3_parser.OFPActionSetField( eth_type=ExtraLayers.dirReturnAndTag)) #Set QinQ vlan type. actions.append( ofproto_v1_3_parser.OFPActionPushVlan( ethertype=ExtraLayers.VLAN_ID_ETHERTYPE_QINQ)) # set vlan ID to be current switch with solid flag. actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=(retMaskedVlanID(switchID) | ExtraLayers.solidFlag))) #push vlan with dummy vlan becuase it will be removed on return (with ethertype that suit) actions.append( ofproto_v1_3_parser.OFPActionPushVlan( ethertype=ExtraLayers.VLAN_ETHERTYPE)) actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=retMaskedVlanID(ExtraLayers.NULL_ID))) # Send to ingress port. actions.append(ofproto_v1_3_parser.OFPActionOutput(OF_IN_PORT)) #return the actions list return actions
def getDoNotDistributeActions(self, switchID, numberOfFlowEntries): ''' Get the do not distribute actions to the given switch and current number of flow entries. :param switchID: ID of current switch. :param numberOfFlowEntries: 3 or 4 flow entries mode. :return: Do not distribute flow entries to be installed. ''' #initialize the actions set to be empty. actions = [] #3 flow entries case. if (3 == numberOfFlowEntries): #create the return packet - set the backwards direction and add the switch id as outer tagging (without solid masking) #return via the input port # Pop vlan actions.append(ofproto_v1_3_parser.OFPActionPopVlan()) #set the DirectionReturn field to be dir backwards actions.append( ofproto_v1_3_parser.OFPActionSetField( eth_type=ExtraLayers.dirBackwardsThreeFlowEntries)) # push a new VLAN with ethertype of vlan actions.append( ofproto_v1_3_parser.OFPActionPushVlan( ethertype=ExtraLayers.VLAN_ID_ETHERTYPE_QINQ)) # set vlan ID to be current switch (last switch field) actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=retMaskedVlanID(switchID))) #return via same port actions.append(ofproto_v1_3_parser.OFPActionOutput(OF_IN_PORT)) else: # Create the return packet - Set return And tag direaction and set the current switch ID with solid flag FALSE. # Pop vlan actions.append(ofproto_v1_3_parser.OFPActionPopVlan()) # Pop vlan actions.append(ofproto_v1_3_parser.OFPActionPopVlan()) #set the DirectionReturn field to be ddirReturnAndTag actions.append( ofproto_v1_3_parser.OFPActionSetField( eth_type=ExtraLayers.dirReturnAndTag)) #Push the current switch id as inner tagging actions.append( ofproto_v1_3_parser.OFPActionPushVlan( ethertype=ExtraLayers.VLAN_ID_ETHERTYPE_QINQ)) # set vlan ID to be current switch(No solid flag). actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=(retMaskedVlanID(switchID)))) #push vlan with dummy vlan becuase it will be removed on return. actions.append( ofproto_v1_3_parser.OFPActionPushVlan( ethertype=ExtraLayers.VLAN_ETHERTYPE)) actions.append( ofproto_v1_3_parser.OFPActionSetField( vlan_vid=retMaskedVlanID(ExtraLayers.NULL_ID))) #return via the ingress port. actions.append(ofproto_v1_3_parser.OFPActionOutput(OF_IN_PORT)) #return the actions list return actions