示例#1
0
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()
示例#2
0
    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)
示例#3
0
    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
示例#4
0
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)
示例#5
0
 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
示例#6
0
    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
示例#7
0
    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
示例#8
0
 def set_pop_vlan(self):
     self.actions_fields.append(ofp.OFPActionPopVlan())
     return self
示例#9
0
    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)
示例#10
0
    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)
示例#11
0
    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
示例#12
0
    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