def pop_vlan(): """Return OpenFlow action to pop outermost Ethernet 802.1Q VLAN header. Returns: ryu.ofproto.ofproto_v1_3_parser.OFPActionPopVlan: Pop VLAN. """ return parser.OFPActionPopVlan()
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 build_flood_rule_actions(self, vlan, eth_dst): flood_acts = [] tagged_ports = self.build_flood_ports_for_vlan(vlan.tagged, eth_dst) for port in tagged_ports: flood_acts.append(parser.OFPActionOutput(port.number)) untagged_ports = self.build_flood_ports_for_vlan(vlan.untagged, eth_dst) if untagged_ports: flood_acts.append(parser.OFPActionPopVlan()) for port in untagged_ports: flood_acts.append(parser.OFPActionOutput(port.number)) return flood_acts
def learn_host_on_vlan_port(self, port, vlan, eth_src): ofmsgs = [] in_port = port.number # hosts learned on this port never relearned if port.permanent_learn: learn_timeout = 0 # antispoof this host ofmsgs.append(self.valve_flowdrop( self.dp.eth_src_table, self.valve_in_match(vlan=vlan, eth_src=eth_src), priority=(self.dp.highest_priority-1))) else: learn_timeout = self.dp.timeout ofmsgs.extend(self.delete_host_from_vlan(eth_src, vlan)) mirror_acts = [] if in_port in self.dp.mirror_from_port: mirror_port_num = self.dp.mirror_from_port[in_port] mirror_acts = [parser.OFPActionOutput(mirror_port_num)] # Update datapath to no longer send packets from this mac to controller # note the use of hard_timeout here and idle_timeout for the dst table # this is to ensure that the source rules will always be deleted before # any rules on the dst table. Otherwise if the dst table rule expires # but the src table rule is still being hit intermittantly the switch # will flood packets to that dst and not realise it needs to relearn # the rule ofmsgs.append(self.valve_flowmod( self.dp.eth_src_table, self.valve_in_match(in_port=in_port, vlan=vlan, eth_src=eth_src), priority=self.dp.highest_priority, inst=[self.goto_table(self.dp.eth_dst_table)], hard_timeout=learn_timeout)) # update datapath to output packets to this mac via the associated port if vlan.port_is_tagged(in_port): dst_act = [parser.OFPActionOutput(in_port)] else: dst_act = [ parser.OFPActionPopVlan(), parser.OFPActionOutput(in_port)] if mirror_acts: dst_act.extend(mirror_acts) inst = [self.apply_actions(dst_act)] ofmsgs.append(self.valve_flowmod( self.dp.eth_dst_table, self.valve_in_match(vlan=vlan, eth_dst=eth_src), priority=self.dp.high_priority, inst=inst, idle_timeout=learn_timeout)) 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_pop_vlan(self): self.actions_fields.append(ofp.OFPActionPopVlan()) 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