Exemple #1
0
    def add_switch(self, ev):
        # Make sure that the switch has a group with id 0
        # so all the times that we edit the broadcast group
        # there is no need to check if the group exists
        group_msg = parser.OFPGroupMod(datapath=ev.switch.dp,
                                       command=ofproto.OFPGC_ADD,
                                       type_=ofproto.OFPGT_ALL,
                                       group_id=0)
        ev.switch.dp.send_msg(group_msg)

        if ev.switch.dp.id not in self.switch_graph:
            self.switch_graph[ev.switch.dp.id] = []

            self.switch_ports[ev.switch.dp.id] = [
                port.port_no for port in ev.switch.ports
            ]
            # An ugly hack to make broadcast work on the lab
            # setup. Iterating over ev.switch.ports does not
            # cover logical ports but those are used on the
            # lab computer to generate the traffic. This needs
            # to be removed for it to work in mininet.
            #self.switch_ports[ev.switch.dp.id].append(ev.switch.dp.ofproto.OFPP_NORMAL)

            self.switches[ev.switch.dp.id] = ev.switch.dp

        self.set_broadcast_tree()
Exemple #2
0
def groupdel(datapath=None, group_id=ofp.OFPG_ALL):
    """Delete a group (default all groups)."""
    return parser.OFPGroupMod(
        datapath,
        ofp.OFPGC_DELETE,
        0,
        group_id)
Exemple #3
0
    def set_broadcast_tree(self):
        """ Calculate and set a broadcast tree

        A broadcast tree is calculated and set in the
        connected openflow switches
        """

        # Extract the spanning tree from the saved information
        spanning_tree = self.calculate_spanning_tree()
        # Add the normal ports
        for dpid in spanning_tree:
            spanning_tree[dpid] += self.switch_ports[dpid]

        # Update the group buckets in the switches
        for dpid, dp in self.switches.items():
            group_msg = parser.OFPGroupMod(
                datapath=dp,
                command=ofproto.OFPGC_MODIFY,
                type_=ofproto.OFPGT_ALL,
                group_id=0,
                buckets=[
                    parser.OFPBucket(actions=[parser.OFPActionOutput(port)])
                    for port in spanning_tree[dpid]
                ])
            dp.send_msg(group_msg)
Exemple #4
0
def groupadd(datapath=None, type_=ofp.OFPGT_ALL, group_id=0, buckets=None):
    return parser.OFPGroupMod(
        datapath,
        ofp.OFPGC_ADD,
        type_,
        group_id,
        buckets)
Exemple #5
0
    def flow_example_groups(self, dp):
        # a flow to correctly forward all traffic to m1, but implemented using
        # group tables

        # you can specify multiple buckets, and each bucket can perform multple
        # actions
        buckets = [
            parser.OFPBucket(actions=[parser.OFPActionOutput(4)]),
        ]
        # create the group
        # docs: https://ryu.readthedocs.io/en/latest/ofproto_v1_3_ref.html#ryu.ofproto.ofproto_v1_3_parser.OFPGroupMod
        dp.send_msg(
            parser.OFPGroupMod(dp,
                               command=ofproto.OFPGC_ADD,
                               type_=ofproto.OFPGT_SELECT,
                               group_id=1,
                               buckets=buckets))

        # create a match to send packets to the new group
        match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP,
                                ipv4_dst='44.0.0.0/8')
        # you've been using this all along, see: self.program_flow in cockpit.py
        instructions = [
            parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                         [parser.OFPActionGroup(group_id=1)])
        ]
        dp.send_msg(
            parser.OFPFlowMod(dp,
                              match=match,
                              instructions=instructions,
                              priority=1))
Exemple #6
0
def groupmod(datapath=None, type_=ofp.OFPGT_ALL, group_id=0, buckets=None):
    """Modify a group."""
    return parser.OFPGroupMod(
        datapath,
        ofp.OFPGC_MODIFY,
        type_,
        group_id,
        buckets)
 def send_group_mod_with_weight(self, datapath, weight1, weight2):
     actions1 = [parser.OFPActionOutput(2)]
     actions2 = [parser.OFPActionOutput(3)]
     buckets = [
         parser.OFPBucket(weight1, actions=actions1),
         parser.OFPBucket(weight2, actions=actions2)
     ]
     group_id = 1
     req = parser.OFPGroupMod(datapath, ofproto.OFPGC_MODIFY,
                              ofproto.OFPGT_SELECT, group_id, buckets)
     datapath.send_msg(req)
    def send_group_mod(self, datapath):
        fproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # H1 sends packets with IP destination addresses in the range 44.0.0.0/8 to either one of host H2 or H3
        actions_1 = [parser.OFPActionOutput(2)]
        actions_2 = [parser.OFPActionOutput(3)]
        weight1 = 100
        weight2 = 100

        # Add buckets
        buckets = [
            # for network destination H2
            parser.OFPBucket(weight1, actions=actions_1),
            # for network destination H3
            parser.OFPBucket(weight2, actions=actions_2)
        ]
        group_id = 1
        req = parser.OFPGroupMod(datapath, ofproto.OFPGC_ADD,
                                 ofproto.OFPGT_SELECT, group_id, buckets)
        datapath.send_msg(req)
 def send_group_mod(self, datapath):
     ofproto = datapath.ofproto
     parser = datapath.ofproto_parser
     
     actions_1 = [parser.OFPActionOutput(2)]
     actions_2 = [parser.OFPActionOutput(3)]
     weight1 = 100
     weight2 = 100
     
     # Add buckets
     buckets = [
                # for network destination H2
                parser.OFPBucket(weight1, actions = actions_1),
                # for network destination H3
                parser.OFPBucket(weight2, actions = actions_2)
                ]
     
     group_id = 1
     req = parser.OFPGroupMod(datapath, ofproto.OFPGC_ADD,
                              ofproto.OFPGT_SELECT, group_id, buckets)
     datapath.send_msg(req)
Exemple #10
0
def group_to_ryu(group, rule):
    """ Converts a group to the group id, and a group mod

        group: The group action
        rule: The original rule
        return: (group_id, extra_messages)
    """
    extra_messages = []

    type_ = getattr(ofproto_v1_3, "OFPGT_" + group.type_.upper())
    group_id = group_ofdpa_id(group, rule)
    buckets = []
    for bucket in group.buckets:
        actions, messages = actions_to_ryu(bucket, rule)
        buckets.append(parser.OFPBucket(actions=actions))
        extra_messages += messages

    extra_messages.append(
        parser.OFPGroupMod(None,
                           type_=type_,
                           group_id=group_id,
                           buckets=buckets))
    return (group_id, extra_messages)
Exemple #11
0
    def install_probing(self, datapath):
        '''Redirect node rules'''
        if datapath.id == 2:
            '''Packet duplication group entry'''
            buckets = []
            actions = [
                ofparser.OFPActionSetField(mpls_label=17),
                ofparser.OFPActionOutput(port=3)
            ]
            buckets.append(ofparser.OFPBucket(actions=actions))
            actions = [
                ofparser.OFPActionSetField(mpls_label=100),
                ofparser.OFPActionOutput(port=1)
            ]
            buckets.append(ofparser.OFPBucket(actions=actions))

            req = ofparser.OFPGroupMod(datapath=datapath,
                                       type_=ofproto.OFPGT_ALL,
                                       group_id=0,
                                       buckets=buckets)
            datapath.send_msg(req)
            '''Probing rule: packet duplicated in both primary and detour path'''
            match = ofparser.OFPMatch(in_port=2,
                                      state=100,
                                      eth_dst="00:00:00:00:00:06",
                                      eth_src="00:00:00:00:00:01",
                                      eth_type=0x8847)
            actions = [
                osparser.OFPExpActionSetState(state=17,
                                              table_id=0,
                                              hard_timeout=10,
                                              hard_rollback=100),
                ofparser.OFPActionGroup(0)
            ]
            self.add_flow(datapath=datapath,
                          table_id=0,
                          priority=10,
                          match=match,
                          actions=actions)
            '''Match on probe packet: switch back to the primary path'''
            match = ofparser.OFPMatch(in_port=1,
                                      mpls_label=100,
                                      eth_dst="00:00:00:00:00:06",
                                      eth_src="00:00:00:00:00:01",
                                      eth_type=0x8847)
            actions = [osparser.OFPExpActionSetState(state=0, table_id=0)]
            self.add_flow(datapath=datapath,
                          table_id=0,
                          priority=10,
                          match=match,
                          actions=actions)
            '''Failure: switch on the detour path and set probing timeout'''
            match = ofparser.OFPMatch(in_port=1,
                                      mpls_label=17,
                                      eth_dst="00:00:00:00:00:06",
                                      eth_src="00:00:00:00:00:01",
                                      eth_type=0x8847)
            actions = [
                osparser.OFPExpActionSetState(state=17,
                                              table_id=0,
                                              hard_timeout=10,
                                              hard_rollback=100),
                ofparser.OFPActionOutput(port=3)
            ]
            self.add_flow(datapath=datapath,
                          table_id=0,
                          priority=10,
                          match=match,
                          actions=actions,
                          command=ofproto.OFPFC_MODIFY)
        '''Detect node rules'''
        if datapath.id == 3:
            '''Probe handler group entry'''
            buckets = []
            actions = [ofparser.OFPActionOutput(port=2)]
            buckets.append(ofparser.OFPBucket(watch_port=2, actions=actions))
            actions = []
            buckets.append(ofparser.OFPBucket(watch_port=1, actions=actions))
            req = ofparser.OFPGroupMod(datapath=datapath,
                                       type_=ofproto.OFPGT_FF,
                                       group_id=0,
                                       buckets=buckets)
            datapath.send_msg(req)
            '''Probe handler: if the link is up, the probe packet will be forwarded toward the next node, otherwise drop'''
            match = ofparser.OFPMatch(in_port=1,
                                      state=0,
                                      mpls_label=100,
                                      eth_dst="00:00:00:00:00:06",
                                      eth_src="00:00:00:00:00:01",
                                      eth_type=0x8847)
            actions = [ofparser.OFPActionGroup(group_id=0)]
            self.add_flow(datapath=datapath,
                          table_id=0,
                          priority=100,
                          match=match,
                          actions=actions)
            '''It sends back a probe packet coming from the no more "unreachable node"'''
            match = ofparser.OFPMatch(in_port=2,
                                      state=0,
                                      mpls_label=100,
                                      eth_dst="00:00:00:00:00:06",
                                      eth_src="00:00:00:00:00:01",
                                      eth_type=0x8847)
            actions = [ofparser.OFPActionOutput(1)]
            self.add_flow(datapath=datapath,
                          table_id=0,
                          priority=10,
                          match=match,
                          actions=actions)
        '''Unreachable node'''
        if datapath.id == 4:
            '''probe handler: it sends back a probe message coming from the previous node'''
            match = ofparser.OFPMatch(in_port=1,
                                      state=0,
                                      mpls_label=100,
                                      eth_dst="00:00:00:00:00:06",
                                      eth_src="00:00:00:00:00:01",
                                      eth_type=0x8847)
            actions = [ofparser.OFPActionOutput(ofproto.OFPP_IN_PORT)]
            self.add_flow(datapath=datapath,
                          table_id=0,
                          priority=100,
                          match=match,
                          actions=actions)
Exemple #12
0
 def install_group_entries(self, datapath):
     for group_entry in f_t_parser.group_entries_dict[datapath.id]:
         buckets = f_t_parser.group_entries_dict[datapath.id][group_entry]
         req = ofparser.OFPGroupMod(datapath, ofproto.OFPGC_ADD,
                                    ofproto.OFPGT_FF, group_entry, buckets)
         datapath.send_msg(req)
Exemple #13
0
def groupdel(datapath=None, group_id=ofp.OFPG_ALL):
    return parser.OFPGroupMod(datapath, ofp.OFPGC_DELETE, 0, group_id)
Exemple #14
0
    def switch_features_handler(self, ev):
        
        msg = ev.msg
        datapath = msg.datapath

        LOG.info("Configuring switch %d..." % datapath.id)

        """ Set table 0 as stateful """
        req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, 
                                                    table_id=0, 
                                                    stateful=1)
        datapath.send_msg(req)

        """ Set lookup extractor = {ip_src, ip_dst, tcp_src, tcp_dst} """
        req = osparser.OFPExpMsgKeyExtract(datapath=datapath, 
                                                command=osproto.OFPSC_EXP_SET_L_EXTRACTOR, 
                                                fields=[ofproto.OXM_OF_IPV4_SRC,ofproto.OXM_OF_IPV4_DST,ofproto.OXM_OF_TCP_SRC,ofproto.OXM_OF_TCP_DST], 
                                                table_id=0)
        datapath.send_msg(req)

        """ Set update extractor = {ip_src, ip_dst, tcp_src, tcp_dst} (same as lookup) """
        req = osparser.OFPExpMsgKeyExtract(datapath=datapath, 
                                                command=osproto.OFPSC_EXP_SET_U_EXTRACTOR, 
                                                fields=[ofproto.OXM_OF_IPV4_SRC,ofproto.OXM_OF_IPV4_DST,ofproto.OXM_OF_TCP_SRC,ofproto.OXM_OF_TCP_DST], 
                                                table_id=0)
        datapath.send_msg(req)

        """ Group table setup """
        buckets = []
        # Action Bucket: <PWD port_i , SetState(i-1)
        for port in range(2,SWITCH_PORTS+1):
            max_len = 2000
            dest_ip=self.int_to_ip_str(port)
            dest_eth=self.int_to_mac_str(port)
            dest_tcp=(port)*100
            actions = [ osparser.OFPExpActionSetState(state=port, table_id=0),
                        ofparser.OFPActionSetField(ipv4_dst=dest_ip),
                        ofparser.OFPActionSetField(eth_dst=dest_eth),
                        ofparser.OFPActionSetField(tcp_dst=dest_tcp),
                        ofparser.OFPActionOutput(port=port, max_len=max_len) ]

            buckets.append(ofparser.OFPBucket(weight=100, 
                                                watch_port=ofproto.OFPP_ANY, 
                                                watch_group=ofproto.OFPG_ANY,
                                                actions=actions))

        req = ofparser.OFPGroupMod(datapath=datapath, 
                                     command=ofproto.OFPGC_ADD,
                                     type_=ofproto.OFPGT_SELECT, 
                                     group_id=1, 
                                     buckets=buckets)
        datapath.send_msg(req)
        

        
        """ ARP packets flooding """
        match = ofparser.OFPMatch(eth_type=0x0806)
        actions = [ofparser.OFPActionOutput(port=ofproto.OFPP_FLOOD)]
        self.add_flow(datapath=datapath, table_id=0, priority=100,
                        match=match, actions=actions)

        """ Reverse path flow """
        for in_port in range(2, SWITCH_PORTS + 1):
            src_ip=self.int_to_ip_str(in_port)
            src_eth=self.int_to_mac_str(in_port)
            src_tcp=in_port*100
            # we need to match an IPv4 (0x800) TCP (6) packet to do SetField()
            match = ofparser.OFPMatch(in_port=in_port, eth_type=0x800, ip_proto=6, ipv4_src=src_ip,eth_src=src_eth,tcp_src=src_tcp)
            actions = [ofparser.OFPActionSetField(ipv4_src="10.0.0.2"),
                       ofparser.OFPActionSetField(eth_src="00:00:00:00:00:02"),
                       ofparser.OFPActionSetField(tcp_src=80),
                       ofparser.OFPActionOutput(port=1, max_len=0)]                   
            self.add_flow(datapath=datapath, table_id=0, priority=100,
                    match=match, actions=actions)

        """ Forwarding consistency rules"""
        match = ofparser.OFPMatch(in_port=1, state=0, eth_type=0x800, ip_proto=6)
        actions = [ofparser.OFPActionGroup(1)]
        self.add_flow(datapath=datapath, table_id=0, priority=100,
                match=match, actions=actions)

        for state in range(2,SWITCH_PORTS+1):
            dest_ip=self.int_to_ip_str(state)
            dest_eth=self.int_to_mac_str(state)
            dest_tcp=(state)*100
            match = ofparser.OFPMatch(in_port=1, state=state, eth_type=0x800, ip_proto=6)
            actions = [ ofparser.OFPActionSetField(ipv4_dst=dest_ip),
                        ofparser.OFPActionSetField(eth_dst=dest_eth),
                        ofparser.OFPActionSetField(tcp_dst=dest_tcp),
                        ofparser.OFPActionOutput(port=state, max_len=0)]        
            self.add_flow(datapath=datapath, table_id=0, priority=100,
                    match=match, actions=actions)
Exemple #15
0
    def install_spines(self, datapath):
        ######################### TABLE 1 CONFIG ###############
        req = bebaparser.OFPExpMsgConfigureStatefulTable(
            datapath=datapath,
            table_id=0,
            stateful=1)
        datapath.send_msg(req)

        """ Set lookup extractor = {eth_dst} """
        req = bebaparser.OFPExpMsgKeyExtract(datapath=datapath,
                                             command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR,
                                             fields=[ofproto.OXM_OF_IN_PORT],
                                             table_id=0)
        datapath.send_msg(req)

        """ Set update extractor = {eth_dst}  """
        req = bebaparser.OFPExpMsgKeyExtract(datapath=datapath,
                                             command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR,
                                             fields=[ofproto.OXM_OF_IN_PORT],
                                             table_id=0)
        datapath.send_msg(req)

        # multiply factor
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath,
            table_id=0,
            global_data_variable_id=0,
            value=8000)
        datapath.send_msg(req)

        # averaging points
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath,
            table_id=0,
            global_data_variable_id=1,
            value=AVG_SAMPLES)
        datapath.send_msg(req)

        # mpls extractor
        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=0,
            extractor_id=0,
            field=ofproto.OXM_OF_MPLS_LABEL
        )
        datapath.send_msg(req)

        # timestamp
        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=0,
            extractor_id=1,
            field=bebaproto.OXM_EXP_TIMESTAMP
        )
        datapath.send_msg(req)

        # packet lenght
        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=0,
            extractor_id=2,
            field=bebaproto.OXM_EXP_PKT_LEN)
        datapath.send_msg(req)

        req = bebaparser.OFPExpMsgSetCondition(
            datapath=datapath,
            condition=bebaproto.CONDITION_GTE,
            condition_id=0,
            table_id=0,
            operand_1_fd_id=4,
            operand_2_gd_id=1)
        datapath.send_msg(req)

        ########################### TABLE 1: MEASURING #####################

        for i in LEAVES:
            if i == 1:
                out_ports = [6, 7]
            elif i == 2:
                out_ports = [5, 7]
            elif i == 3:
                out_ports = [5, 6]

            buckets = []
            actions = [
                bebaparser.OFPExpActionWriteContextToField(src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=3,
                                                           dst_field=ofproto.OXM_OF_MPLS_LABEL),
                ofparser.OFPActionOutput(out_ports[0] - 4)]
            buckets.append(ofparser.OFPBucket(actions=actions))

            actions = [
                bebaparser.OFPExpActionWriteContextToField(src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=4,
                                                           dst_field=ofproto.OXM_OF_MPLS_LABEL),
                ofparser.OFPActionOutput(out_ports[1] - 4)]
            buckets.append(ofparser.OFPBucket(actions=actions))

            # send the group action
            req = ofparser.OFPGroupMod(datapath=datapath,
                                       type_=ofproto.OFPGT_ALL,
                                       group_id=i,
                                       buckets=buckets)
            datapath.send_msg(req)

            match = ofparser.OFPMatch(in_port=i, eth_type=0x8847)
            actions = [bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_gd_id=3,
                                                              operand_1_hf_id=0, operand_2_gd_id=out_ports[0]),
                       bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_gd_id=4,
                                                              operand_1_hf_id=0, operand_2_gd_id=out_ports[1]),
                       ofparser.OFPActionGroup(i)]
            self.add_flow(datapath=datapath, priority=100, table_id=0, match=match, actions=actions)

            # simple forwarding packets go to second table to forward
            match = ofparser.OFPMatch(in_port=i, condition0=1)
            actions = [  # calculates deltaT: FDV[1]=HF[1]-FDV[0]=TS_NOW - TS_LAST
                bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUB, output_fd_id=1,
                                                       operand_1_hf_id=1, operand_2_fd_id=0),
                # calculates rate: R = (bytes / deltaT_us) * 1000 kB/s
                bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_MUL, output_fd_id=2,
                                                       operand_1_fd_id=2, operand_2_gd_id=0),
                # stores the result in FDV[3]: THE FLOW ESTIMATED RATE
                bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_DIV, output_fd_id=2,
                                                       operand_1_fd_id=2, operand_2_fd_id=1),
                # calculates ewma
                bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_EWMA, output_fd_id=3,
                                                       operand_1_fd_id=3, operand_2_cost=bebaproto.EWMA_PARAM_0375,
                                                       operand_3_fd_id=2),
                # saves current timestamp
                bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_fd_id=0,
                                                       operand_1_hf_id=1, operand_2_cost=0),
                # counter returns to zero
                bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUB, output_fd_id=4,
                                                       operand_1_fd_id=4, operand_2_fd_id=4),
                # saves in GDV[i+4] the ewma port[1,2,3]->[5,6,7]
                bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_gd_id=i + 4,
                                                       operand_1_fd_id=3, operand_2_cost=0)]
            instructions = [ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions),
                            ofparser.OFPInstructionGotoTable(1)]
            mod = ofparser.OFPFlowMod(datapath=datapath, priority=0, table_id=0, match=match, instructions=instructions)
            datapath.send_msg(mod)

            match = ofparser.OFPMatch(in_port=i, condition0=0)
            actions = [bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_fd_id=2,
                                                              operand_1_fd_id=2, operand_2_hf_id=2),
                       bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_fd_id=4,
                                                              operand_1_fd_id=4, operand_2_cost=1)]
            instructions = [ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions),
                            ofparser.OFPInstructionGotoTable(1)]
            mod = ofparser.OFPFlowMod(datapath=datapath, priority=0, table_id=0, match=match, instructions=instructions)
            datapath.send_msg(mod)

        ######################## TABLE 2: FORWARDING ################
        for i in LEAVES:
            match = ofparser.OFPMatch(eth_dst=MAC_ADDRS[i - 1])
            actions = [ofparser.OFPActionOutput(i)]
            self.add_flow(datapath=datapath, table_id=1, priority=0, match=match, actions=actions)
Exemple #16
0
def groupadd(datapath=None, type_=ofp.OFPGT_ALL, group_id=0, buckets=None):
    """Add a group."""
    return [
        groupdel(datapath=datapath, group_id=group_id),
        parser.OFPGroupMod(datapath, ofp.OFPGC_ADD, type_, group_id, buckets)]
    def install_spines(self, datapath):
        ######################### TABLE 1 CONFIG ###############
        req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath,
                                                         table_id=0,
                                                         stateful=1)
        datapath.send_msg(req)
        """ Set lookup extractor = {eth_dst} """
        req = bebaparser.OFPExpMsgKeyExtract(
            datapath=datapath,
            command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR,
            fields=[ofproto.OXM_OF_IN_PORT],
            table_id=0)
        datapath.send_msg(req)
        """ Set update extractor = {eth_dst}  """
        req = bebaparser.OFPExpMsgKeyExtract(
            datapath=datapath,
            command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR,
            fields=[ofproto.OXM_OF_IN_PORT],
            table_id=0)
        datapath.send_msg(req)

        # mpls extractor
        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=0,
            extractor_id=0,
            field=ofproto.OXM_OF_MPLS_LABEL)
        datapath.send_msg(req)

        # timestamp extractor
        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=0,
            extractor_id=1,
            field=bebaproto.OXM_EXP_TIMESTAMP)
        datapath.send_msg(req)

        # packet length extractor
        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=0,
            extractor_id=2,
            field=bebaproto.OXM_EXP_PKT_LEN)
        datapath.send_msg(req)

        req = bebaparser.OFPExpMsgSetCondition(
            datapath=datapath,
            condition=bebaproto.CONDITION_GTE,
            condition_id=0,
            table_id=0,
            operand_1_hf_id=1,
            operand_2_fd_id=4)
        datapath.send_msg(req)

        ########################### TABLE 1: MEASURING #####################

        for i in LEAVES:
            if i == 1:
                out_ports = [2, 3]
            elif i == 2:
                out_ports = [1, 3]
            elif i == 3:
                out_ports = [1, 2]

            buckets = []
            actions = [
                bebaparser.OFPExpActionWriteContextToField(
                    src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR,
                    src_id=4,
                    dst_field=ofproto.OXM_OF_MPLS_LABEL),
                ofparser.OFPActionOutput(out_ports[0])
            ]
            buckets.append(ofparser.OFPBucket(actions=actions))

            actions = [
                bebaparser.OFPExpActionWriteContextToField(
                    src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR,
                    src_id=5,
                    dst_field=ofproto.OXM_OF_MPLS_LABEL),
                ofparser.OFPActionOutput(out_ports[1])
            ]
            buckets.append(ofparser.OFPBucket(actions=actions))

            # send the group action
            req = ofparser.OFPGroupMod(datapath=datapath,
                                       type_=ofproto.OFPGT_ALL,
                                       group_id=i,
                                       buckets=buckets)
            datapath.send_msg(req)

            match = ofparser.OFPMatch(in_port=i, eth_type=0x8847)
            actions = [
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUM,
                    output_gd_id=4,
                    operand_1_hf_id=0,
                    operand_2_gd_id=out_ports[0]),
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUM,
                    output_gd_id=5,
                    operand_1_hf_id=0,
                    operand_2_gd_id=out_ports[1]),
                ofparser.OFPActionGroup(i)
            ]
            self.add_flow(datapath=datapath,
                          priority=600,
                          table_id=0,
                          match=match,
                          actions=actions)

            # first packet of a flow
            match = ofparser.OFPMatch(state=0, in_port=i)
            actions = [
                bebaparser.OFPExpActionSetState(table_id=0,
                                                state=1,
                                                idle_timeout=2),
                # saves timestamp
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUM,
                    output_fd_id=4,
                    operand_1_hf_id=1,
                    operand_2_cost=PROBE_FREQ)
            ]
            insts = [
                ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                               actions),
                ofparser.OFPInstructionGotoTable(1)
            ]
            mod = ofparser.OFPFlowMod(datapath=datapath,
                                      table_id=0,
                                      priority=500,
                                      match=match,
                                      instructions=insts)
            datapath.send_msg(mod)

            # simple forwarding packets go to second table to forward
            match = ofparser.OFPMatch(state=1, in_port=i, condition0=1)
            actions = [  # calculates deltaT: FDV[1]=HF[1]-FDV[0]=TS_NOW - TS_LAST
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUB,
                    output_fd_id=1,
                    operand_1_hf_id=1,
                    operand_2_fd_id=0),
                # calculates rate: R = (bytes / deltaT_ms) * 8 [kb/s]
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_MUL,
                    output_fd_id=2,
                    operand_1_fd_id=2,
                    operand_2_cost=8),
                # stores the result in FDV[3]: THE FLOW ESTIMATED RATE
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_DIV,
                    output_fd_id=2,
                    operand_1_fd_id=2,
                    operand_2_fd_id=1),
                # calculates ewma
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_EWMA,
                    output_fd_id=3,
                    operand_1_fd_id=3,
                    operand_2_cost=ALPHA,
                    operand_3_fd_id=2),
                # saves current timestamp
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUM,
                    output_fd_id=0,
                    operand_1_hf_id=1,
                    operand_2_cost=0),
                # saves timestamp + probe freq
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUM,
                    output_fd_id=4,
                    operand_1_hf_id=1,
                    operand_2_cost=PROBE_FREQ),
                # reset byte counter
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUB,
                    output_fd_id=2,
                    operand_1_fd_id=2,
                    operand_2_fd_id=2),
                # saves in GDV[i] the ewma
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUM,
                    output_gd_id=i,
                    operand_1_fd_id=3,
                    operand_2_cost=0)
            ]
            instructions = [
                ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                               actions),
                ofparser.OFPInstructionGotoTable(1)
            ]
            mod = ofparser.OFPFlowMod(datapath=datapath,
                                      priority=0,
                                      table_id=0,
                                      match=match,
                                      instructions=instructions)
            datapath.send_msg(mod)

            match = ofparser.OFPMatch(state=1, in_port=i, condition0=0)
            actions = [
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUM,
                    output_fd_id=2,
                    operand_1_fd_id=2,
                    operand_2_hf_id=2)
            ]
            instructions = [
                ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                               actions),
                ofparser.OFPInstructionGotoTable(1)
            ]
            mod = ofparser.OFPFlowMod(datapath=datapath,
                                      priority=0,
                                      table_id=0,
                                      match=match,
                                      instructions=instructions)
            datapath.send_msg(mod)

        ######################## TABLE 2: FORWARDING ################
        for i in LEAVES:
            match = ofparser.OFPMatch(eth_dst=MAC_ADDRS[i - 1])
            actions = [ofparser.OFPActionOutput(i)]
            self.add_flow(datapath=datapath,
                          table_id=1,
                          priority=0,
                          match=match,
                          actions=actions)
Exemple #18
0
    def install_leaves(self, datapath):
        ##################################### TABLE 0: DISPATCHING ##################################################

        ######################### TABLE 0 CONFIG ###############
        req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath,
                                                         table_id=0,
                                                         stateful=1)
        datapath.send_msg(req)
        """ Set lookup extractor = {eth_dst} """
        req = bebaparser.OFPExpMsgKeyExtract(
            datapath=datapath,
            command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR,
            fields=[ofproto.OXM_OF_IN_PORT],
            table_id=0)
        datapath.send_msg(req)
        """ Set update extractor = {eth_dst}  """
        req = bebaparser.OFPExpMsgKeyExtract(
            datapath=datapath,
            command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR,
            fields=[ofproto.OXM_OF_IN_PORT],
            table_id=0)
        datapath.send_msg(req)
        """ Field extractor for mpls label """
        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=0,
            extractor_id=0,
            field=ofproto.OXM_OF_MPLS_LABEL)
        datapath.send_msg(req)
        """ Field extractor for timestamp """
        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=0,
            extractor_id=1,
            field=bebaproto.OXM_EXP_TIMESTAMP)
        datapath.send_msg(req)
        """ Packet counter_max for designing probe frequency """
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath, table_id=0, global_data_variable_id=0, value=9)
        datapath.send_msg(req)
        """ Condition C0: if counter reaches counter_max, then trigger probe sending """
        req = bebaparser.OFPExpMsgSetCondition(
            datapath=datapath,
            table_id=0,
            condition_id=0,
            condition=bebaproto.CONDITION_GTE,
            operand_1_fd_id=0,
            operand_2_gd_id=0)
        datapath.send_msg(req)

        req = bebaparser.OFPExpMsgSetCondition(
            datapath=datapath,
            table_id=0,
            condition_id=3,
            condition=bebaproto.CONDITION_GTE,
            operand_1_fd_id=0,
            operand_2_gd_id=0)
        datapath.send_msg(req)

        ##################################### TABLE 0 FLOWS ##################################################
        """ RECEIVE PROBE ACTION """
        """ When a probe is received tab0 sends it to tab3"""
        """ match: 	MPLS """
        """ no action """
        """ instruction: goto tab3"""

        match = ofparser.OFPMatch(eth_type=0x8847)
        instructions = [ofparser.OFPInstructionGotoTable(3)]
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=0,
                                  priority=200,
                                  match=match,
                                  instructions=instructions)
        datapath.send_msg(mod)

        for i in UPPER_PORTS:
            """ Writes metadata 1 if C0 is true (i.e. if it's time to send probe) to inform the Util Table (2) """
            match = ofparser.OFPMatch(in_port=i, condition0=1)
            actions = [
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUB,
                    output_fd_id=0,
                    operand_1_fd_id=0,
                    operand_2_gd_id=0),
                ofparser.OFPActionPushMpls()
            ]  #push mpls for tab 2
            instructions = [
                ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                               actions),
                ofparser.OFPInstructionWriteMetadata(metadata=1,
                                                     metadata_mask=0xffffffff),
                ofparser.OFPInstructionGotoTable(2)
            ]
            mod = ofparser.OFPFlowMod(datapath=datapath,
                                      table_id=0,
                                      priority=50,
                                      match=match,
                                      instructions=instructions)
            datapath.send_msg(mod)
            """ If C0 is false, update the counter (i++) and go to Util Table for ewma measuring """
            match = ofparser.OFPMatch(in_port=i, condition0=0)
            actions = [
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=0,
                    opcode=bebaproto.OPCODE_SUM,
                    output_fd_id=0,
                    operand_1_fd_id=0,
                    operand_2_cost=1)
            ]
            instructions = [
                ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                               actions),
                ofparser.OFPInstructionGotoTable(2)
            ]
            mod = ofparser.OFPFlowMod(datapath=datapath,
                                      table_id=0,
                                      priority=30,
                                      match=match,
                                      instructions=instructions)
            datapath.send_msg(mod)
        """ For packets from down ports (attached to hosts): go to ToR Discovery table (1) """
        for i in DOWN_PORTS:
            match = ofparser.OFPMatch(in_port=i)
            instructions = [ofparser.OFPInstructionGotoTable(1)]
            mod = ofparser.OFPFlowMod(datapath=datapath,
                                      table_id=0,
                                      priority=0,
                                      match=match,
                                      instructions=instructions)
            datapath.send_msg(mod)

        for i in [0, 1]:
            match = ofparser.OFPMatch(in_port=3,
                                      eth_type=0x0800,
                                      ip_proto=6,
                                      tcp_dst=10000 + i)
            actions = [ofparser.OFPActionOutput(i + 1)]
            self.add_flow(datapath=datapath,
                          table_id=0,
                          priority=200,
                          match=match,
                          actions=actions)

            match = ofparser.OFPMatch(in_port=3,
                                      eth_type=0x0800,
                                      ip_proto=6,
                                      tcp_src=10000 + i)
            actions = [ofparser.OFPActionOutput(i + 1)]
            self.add_flow(datapath=datapath,
                          table_id=0,
                          priority=200,
                          match=match,
                          actions=actions)

        ######################## TABLE 1 ToR DISCOVERY  #########################################################

        # this cycle writes metadata specifying to which leaf belongs the packet
        for i in LEAVES:
            if (i != datapath.id):
                match = ofparser.OFPMatch(eth_dst=MAC_ADDRS[i - 1])
                instructions = [
                    ofparser.OFPInstructionWriteMetadata(
                        metadata=i, metadata_mask=0xffffffff),
                    ofparser.OFPInstructionGotoTable(3)
                ]
                mod = ofparser.OFPFlowMod(datapath=datapath,
                                          table_id=1,
                                          priority=0,
                                          match=match,
                                          instructions=instructions)
                datapath.send_msg(mod)

        ######################### TABLE 2: ACTIVE PROBING ######################################################

        ################### TABLE 2 CONFIG #########

        req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath,
                                                         table_id=2,
                                                         stateful=1)
        datapath.send_msg(req)
        """ Set lookup extractor = {IN_PORT} """
        req = bebaparser.OFPExpMsgKeyExtract(
            datapath=datapath,
            command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR,
            fields=[ofproto.OXM_OF_IN_PORT],
            table_id=2)
        datapath.send_msg(req)
        """ Set update extractor = {IN_PORT}  """
        req = bebaparser.OFPExpMsgKeyExtract(
            datapath=datapath,
            command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR,
            fields=[ofproto.OXM_OF_IN_PORT],
            table_id=2)
        datapath.send_msg(req)
        # multiply factor: convert to kbit/s
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath,
            table_id=2,
            global_data_variable_id=0,
            value=8000)
        datapath.send_msg(req)

        # number of averaging samples
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath, table_id=2, global_data_variable_id=3, value=40)
        datapath.send_msg(req)

        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=2,
            extractor_id=1,
            field=bebaproto.OXM_EXP_TIMESTAMP)
        datapath.send_msg(req)

        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=2,
            extractor_id=2,
            field=bebaproto.OXM_EXP_PKT_LEN)
        datapath.send_msg(req)

        req = bebaparser.OFPExpMsgSetCondition(
            datapath=datapath,
            condition=bebaproto.CONDITION_GTE,
            condition_id=0,
            table_id=2,
            operand_1_fd_id=4,
            operand_2_gd_id=3)
        datapath.send_msg(req)

        ############################### TABLE 2 FLOWS #############################
        """ For every packet coming from spine ports, calculates ewma """
        for i in UPPER_PORTS:
            #simply ewma measuring
            match = ofparser.OFPMatch(in_port=i, condition0=1)
            actions_ewma_1 = [  #calculates deltaT: FDV[1]=HF[1]-FDV[0]=TS_NOW - TS_LAST
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    opcode=bebaproto.OPCODE_SUB,
                    output_fd_id=1,
                    operand_1_hf_id=1,
                    operand_2_fd_id=0),
                #calculates rate: R = (bytes / deltaT_us) * 1000 kB/s
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    opcode=bebaproto.OPCODE_MUL,
                    output_fd_id=2,
                    operand_1_fd_id=2,
                    operand_2_gd_id=0),
                #stores the result in FDV[3]: THE FLOW ESTIMATED RATE
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    opcode=bebaproto.OPCODE_DIV,
                    output_fd_id=2,
                    operand_1_fd_id=2,
                    operand_2_fd_id=1),
                #calculates ewma
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    opcode=bebaproto.OPCODE_EWMA,
                    output_fd_id=3,
                    operand_1_fd_id=3,
                    operand_2_cost=bebaproto.EWMA_PARAM_0250,
                    operand_3_fd_id=2),
                #saves current timestamp
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    opcode=bebaproto.OPCODE_SUM,
                    output_fd_id=0,
                    operand_1_hf_id=1,
                    operand_2_cost=0),
                #counter returns to zero
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    opcode=bebaproto.OPCODE_SUB,
                    output_fd_id=4,
                    operand_1_fd_id=4,
                    operand_2_fd_id=4),
                # saves in GDV[i] the ewma
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    opcode=bebaproto.OPCODE_SUM,
                    output_gd_id=i,
                    operand_1_fd_id=3,
                    operand_2_cost=0)
            ]
            self.add_flow(datapath=datapath,
                          table_id=2,
                          priority=30,
                          match=match,
                          actions=actions_ewma_1 +
                          [ofparser.OFPActionOutput(3)])

            match = ofparser.OFPMatch(in_port=i, condition0=0)
            actions_ewma_2 = [
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    opcode=bebaproto.OPCODE_SUM,
                    output_fd_id=2,
                    operand_1_fd_id=2,
                    operand_2_hf_id=2),
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    opcode=bebaproto.OPCODE_SUM,
                    output_fd_id=4,
                    operand_1_fd_id=4,
                    operand_2_cost=1)
            ]
            self.add_flow(datapath=datapath,
                          table_id=2,
                          priority=30,
                          match=match,
                          actions=actions_ewma_2 +
                          [ofparser.OFPActionOutput(3)])
            """ PROBES: When it matches metadata=1 it means that this packet has to be duplicated to piggyback on it the probe """

            #group mod for packet duplication and probing
            buckets = []
            actions1 = [
                ofparser.OFPActionSetField(mpls_tc=datapath.id),  #the GDV[i]
                bebaparser.OFPExpActionWriteContextToField(
                    src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR,
                    src_id=i,
                    dst_field=ofproto.OXM_OF_MPLS_LABEL),
                ofparser.OFPActionOutput(ofproto.OFPP_IN_PORT)
            ]
            buckets.append(ofparser.OFPBucket(actions=actions1))

            actions1 = [
                ofparser.OFPActionSetField(
                    mpls_tc=datapath.id),  #the GDV[other]
                bebaparser.OFPExpActionWriteContextToField(
                    src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR,
                    src_id=(1 if i == 2 else 2),
                    dst_field=ofproto.OXM_OF_MPLS_LABEL),
                ofparser.OFPActionOutput((1 if i == 2 else 2))
            ]
            buckets.append(ofparser.OFPBucket(actions=actions1))

            req = ofparser.OFPGroupMod(datapath=datapath,
                                       type_=ofproto.OFPGT_ALL,
                                       group_id=i,
                                       buckets=buckets)
            datapath.send_msg(req)

            # actual match and actions: group action, popMpls() and output(3)
            match = ofparser.OFPMatch(in_port=i, eth_type=0x8847, metadata=1)
            actions = [
                ofparser.OFPActionGroup(i),
                ofparser.OFPActionPopMpls(),
                ofparser.OFPActionOutput(3)
            ]
            self.add_flow(datapath=datapath,
                          table_id=2,
                          priority=100,
                          match=match,
                          actions=actions)

            for j in [0, 1]:
                match = ofparser.OFPMatch(in_port=i,
                                          eth_type=0x0800,
                                          ip_proto=6,
                                          tcp_dst=10000 + j,
                                          condition0=1)
                actions = actions_ewma_1 + [ofparser.OFPActionOutput(3)]
                self.add_flow(datapath=datapath,
                              table_id=2,
                              priority=150,
                              match=match,
                              actions=actions)

                match = ofparser.OFPMatch(in_port=i,
                                          eth_type=0x0800,
                                          ip_proto=6,
                                          tcp_src=10000 + j,
                                          condition0=1)
                actions = actions_ewma_1 + [ofparser.OFPActionOutput(3)]
                self.add_flow(datapath=datapath,
                              table_id=2,
                              priority=150,
                              match=match,
                              actions=actions)

                match = ofparser.OFPMatch(in_port=i,
                                          eth_type=0x0800,
                                          ip_proto=6,
                                          tcp_dst=10000 + j,
                                          condition0=0)
                actions = actions_ewma_2 + [ofparser.OFPActionOutput(3)]
                self.add_flow(datapath=datapath,
                              table_id=2,
                              priority=150,
                              match=match,
                              actions=actions)

                match = ofparser.OFPMatch(in_port=i,
                                          eth_type=0x0800,
                                          ip_proto=6,
                                          tcp_src=10000 + j,
                                          condition0=0)
                actions = actions_ewma_2 + [ofparser.OFPActionOutput(3)]
                self.add_flow(datapath=datapath,
                              table_id=2,
                              priority=150,
                              match=match,
                              actions=actions)

        ######################## TABLE 3: FORWARDING ##############################################################

        ######################## TABLE 3 CONFIG #####################################################################

        ##### GDV[1] contains path utilization to dest 1 on port 1
        ##### GDV[2] contains path utilization to dest 2 on port 1
        ##### GDV[3] contains path utilization to dest 1 on port 2
        ##### GDV[4] contains path utilization to dest 2 on port 2

        req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath,
                                                         table_id=3,
                                                         stateful=1)
        datapath.send_msg(req)
        """ Set lookup extractor = {ETH_DST IP_PROTO TCP_DST} """
        req = bebaparser.OFPExpMsgKeyExtract(
            datapath=datapath,
            command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR,
            fields=[
                ofproto.OXM_OF_IPV4_SRC, ofproto.OXM_OF_IPV4_DST,
                ofproto.OXM_OF_TCP_SRC, ofproto.OXM_OF_TCP_DST
            ],
            table_id=3)
        datapath.send_msg(req)
        """ Set update extractor = {}  """
        req = bebaparser.OFPExpMsgKeyExtract(
            datapath=datapath,
            command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR,
            fields=[
                ofproto.OXM_OF_IPV4_SRC, ofproto.OXM_OF_IPV4_DST,
                ofproto.OXM_OF_TCP_SRC, ofproto.OXM_OF_TCP_DST
            ],
            table_id=3)
        datapath.send_msg(req)

        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=3,
            extractor_id=0,
            field=ofproto.OXM_OF_MPLS_LABEL)
        datapath.send_msg(req)

        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=3,
            extractor_id=1,
            field=bebaproto.OXM_EXP_TIMESTAMP)
        datapath.send_msg(req)

        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=3,
            extractor_id=2,
            field=bebaproto.OXM_EXP_PKT_LEN)
        datapath.send_msg(req)

        # GDV[0] = multiply factor
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath,
            table_id=3,
            global_data_variable_id=0,
            value=8000)
        datapath.send_msg(req)

        # GDV[6] = packets needed for average
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath,
            table_id=3,
            global_data_variable_id=6,
            value=40 - 1)
        datapath.send_msg(req)

        # GDV[5] = elephant flow threshold
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath,
            table_id=3,
            global_data_variable_id=5,
            value=2000)  # 2000 kb/s
        datapath.send_msg(req)

        # Lower flow threshold
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath,
            table_id=3,
            global_data_variable_id=7,
            value=300)
        datapath.send_msg(req)

        for i in [1, 2, 3]:
            req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
                datapath=datapath,
                table_id=3,
                global_data_variable_id=i,
                value=0)
            datapath.send_msg(req)

        #################################### TABLE 3 FLOWS ###################################

        # many conditions as the number of LEAVES-1
        # for i in LEAVES except datapath.id: create condition[i]

        # in the case of 2 Spines. For more spines the configuration becomes more complex
        for destLeaf in [1, 2]:
            # C[destinationLeaf]: which port is less utilized?
            req = bebaparser.OFPExpMsgSetCondition(
                datapath=datapath,
                condition=bebaproto.CONDITION_LTE,
                condition_id=destLeaf,
                table_id=3,
                operand_1_gd_id=destLeaf,
                operand_2_gd_id=destLeaf + 2)
            datapath.send_msg(req)

        # C[0], has the flow exceeded threshold? i.e. flow_rate >= threshold => FDV[3] >= GDV[5]
        req = bebaparser.OFPExpMsgSetCondition(
            datapath=datapath,
            condition=bebaproto.CONDITION_GTE,
            condition_id=0,
            table_id=3,
            operand_1_fd_id=3,
            operand_2_gd_id=5)
        datapath.send_msg(req)

        # C[3], is the other flow lower than a value? FDV[4] < GDV[7] ?
        req = bebaparser.OFPExpMsgSetCondition(
            datapath=datapath,
            condition=bebaproto.CONDITION_LTE,
            condition_id=3,
            table_id=3,
            operand_1_fd_id=4,
            operand_2_gd_id=7)
        datapath.send_msg(req)

        # C[4]: did the counter reach counterMax? FDV[5] = GDV[6] ?
        req = bebaparser.OFPExpMsgSetCondition(
            datapath=datapath,
            condition=bebaproto.CONDITION_EQ,
            condition_id=4,
            table_id=3,
            operand_1_fd_id=5,
            operand_2_gd_id=6)
        datapath.send_msg(req)

        # leaf number dependent flows
        if datapath.id == 1:
            #LEAF 1 new flows: fetch the destination leaf and check the appropriate condition
            match1true = ofparser.OFPMatch(metadata=2, condition1=1,
                                           state=0)  #dst=2, port 1
            match2true = ofparser.OFPMatch(metadata=3, condition2=1,
                                           state=0)  #dst=3, port 1
            match1false = ofparser.OFPMatch(metadata=2, condition1=0,
                                            state=0)  #dst=2, port 2
            match2false = ofparser.OFPMatch(metadata=3, condition2=0,
                                            state=0)  #dst=3, port 2
        elif datapath.id == 2:
            #LEAF 2 new flows: fetch the destination leaf and check the appropriate condition
            match1true = ofparser.OFPMatch(metadata=1, condition1=1,
                                           state=0)  #dst=1, port 1
            match2true = ofparser.OFPMatch(metadata=3, condition2=1,
                                           state=0)  #dst=3, port 1
            match1false = ofparser.OFPMatch(metadata=1, condition1=0,
                                            state=0)  #dst=1, port 2
            match2false = ofparser.OFPMatch(metadata=3, condition2=0,
                                            state=0)  #dst=3, port 2
        elif datapath.id == 3:
            #LEAF 3 new flows: fetch the destination leaf and check the appropriate condition
            match1true = ofparser.OFPMatch(metadata=1, condition1=1,
                                           state=0)  #dst=1, port 1
            match2true = ofparser.OFPMatch(metadata=2, condition2=1,
                                           state=0)  #dst=2, port 1
            match1false = ofparser.OFPMatch(metadata=1, condition1=0,
                                            state=0)  #dst=1, port 2
            match2false = ofparser.OFPMatch(metadata=2, condition2=0,
                                            state=0)  #dst=2, port 2

        #if port 1 is better, set_state(1) and output 1
        actions_true = [
            bebaparser.OFPExpActionSetState(state=1,
                                            table_id=3,
                                            idle_timeout=5),
            ofparser.OFPActionOutput(1)
        ]
        #if port 2 is better, set_state(2) and output 2
        actions_false = [
            bebaparser.OFPExpActionSetState(state=2,
                                            table_id=3,
                                            idle_timeout=5),
            ofparser.OFPActionOutput(2)
        ]

        self.add_flow(datapath=datapath,
                      table_id=3,
                      priority=20,
                      match=match1true,
                      actions=actions_true)
        self.add_flow(datapath=datapath,
                      table_id=3,
                      priority=20,
                      match=match2true,
                      actions=actions_true)
        self.add_flow(datapath=datapath,
                      table_id=3,
                      priority=20,
                      match=match1false,
                      actions=actions_false)
        self.add_flow(datapath=datapath,
                      table_id=3,
                      priority=20,
                      match=match2false,
                      actions=actions_false)
        """ extract external probes' data and store in GDVs """

        match = ofparser.OFPMatch(eth_type=0x8847, mpls_tc=datapath.id)
        self.add_flow(datapath=datapath,
                      table_id=3,
                      priority=300,
                      match=match,
                      actions=[])

        for i in UPPER_PORTS:
            for leafNo in LEAVES:
                match = ofparser.OFPMatch(in_port=i,
                                          eth_type=0x8847,
                                          mpls_tc=leafNo)
                """ actions: save in GDVs external probes' data """
                if datapath.id == 1:
                    if leafNo == 2:
                        actions = [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_gd_id=(1 if i == 1 else 3),
                                operand_1_hf_id=0,
                                operand_2_cost=0)
                        ]
                    elif leafNo == 3:
                        actions = [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_gd_id=(2 if i == 1 else 4),
                                operand_1_hf_id=0,
                                operand_2_cost=0)
                        ]
                elif datapath.id == 2:
                    if leafNo == 1:
                        actions = [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_gd_id=(1 if i == 1 else 3),
                                operand_1_hf_id=0,
                                operand_2_cost=0)
                        ]
                    elif leafNo == 3:
                        actions = [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_gd_id=(2 if i == 1 else 4),
                                operand_1_hf_id=0,
                                operand_2_cost=0)
                        ]
                elif datapath.id == 3:
                    if leafNo == 1:
                        actions = [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_gd_id=(1 if i == 1 else 3),
                                operand_1_hf_id=0,
                                operand_2_cost=0)
                        ]
                    elif leafNo == 2:
                        actions = [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_gd_id=(2 if i == 1 else 4),
                                operand_1_hf_id=0,
                                operand_2_cost=0)
                        ]

                self.add_flow(datapath=datapath,
                              table_id=3,
                              priority=200,
                              match=match,
                              actions=actions)

        for s in UPPER_PORTS:
            for metadata in LEAVES:
                # normal conditions, installed flows continue flowing, calculates ewma if counter reaches max
                match = ofparser.OFPMatch(in_port=3,
                                          state=s,
                                          metadata=metadata,
                                          condition4=1)
                actions_ewma = [  #calculates deltaT: FDV[1]=HF[1]-FDV[0]=TS_NOW - TS_LAST
                    bebaparser.OFPExpActionSetDataVariable(
                        table_id=3,
                        opcode=bebaproto.OPCODE_SUB,
                        output_fd_id=1,
                        operand_1_hf_id=1,
                        operand_2_fd_id=0),
                    #calculates rate: R = (bytes / deltaT_us) * 1000 kB/s
                    bebaparser.OFPExpActionSetDataVariable(
                        table_id=3,
                        opcode=bebaproto.OPCODE_MUL,
                        output_fd_id=2,
                        operand_1_fd_id=2,
                        operand_2_gd_id=0),
                    #stores the result in FDV[3]: THE FLOW ESTIMATED RATE
                    bebaparser.OFPExpActionSetDataVariable(
                        table_id=3,
                        opcode=bebaproto.OPCODE_DIV,
                        output_fd_id=2,
                        operand_1_fd_id=2,
                        operand_2_fd_id=1),
                    #calculates ewma
                    bebaparser.OFPExpActionSetDataVariable(
                        table_id=3,
                        opcode=bebaproto.OPCODE_EWMA,
                        output_fd_id=3,
                        operand_1_fd_id=3,
                        operand_2_cost=bebaproto.EWMA_PARAM_0250,
                        operand_3_fd_id=2),
                    #saves current timestamp
                    bebaparser.OFPExpActionSetDataVariable(
                        table_id=3,
                        opcode=bebaproto.OPCODE_SUM,
                        output_fd_id=0,
                        operand_1_hf_id=1,
                        operand_2_cost=0),
                    #counter returns to zero
                    bebaparser.OFPExpActionSetDataVariable(
                        table_id=3,
                        opcode=bebaproto.OPCODE_SUB,
                        output_fd_id=5,
                        operand_1_fd_id=5,
                        operand_2_fd_id=5)
                ]

                # FDV[4] = flow's alternative path utilization
                if datapath.id == 1:
                    if metadata == 2:
                        actions_ewma += [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_fd_id=4,
                                operand_1_gd_id=(1 if s == 2 else 3),
                                operand_2_cost=0)
                        ]
                    elif metadata == 3:
                        actions_ewma += [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_fd_id=4,
                                operand_1_gd_id=(2 if s == 2 else 4),
                                operand_2_cost=0)
                        ]
                elif datapath.id == 2:
                    if metadata == 1:
                        actions_ewma += [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_fd_id=4,
                                operand_1_gd_id=(1 if s == 2 else 3),
                                operand_2_cost=0)
                        ]
                    elif metadata == 3:
                        actions_ewma += [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_fd_id=4,
                                operand_1_gd_id=(2 if s == 2 else 4),
                                operand_2_cost=0)
                        ]
                elif datapath.id == 3:
                    if metadata == 1:
                        actions_ewma += [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_fd_id=4,
                                operand_1_gd_id=(1 if s == 2 else 3),
                                operand_2_cost=0)
                        ]
                    elif metadata == 2:
                        actions_ewma += [
                            bebaparser.OFPExpActionSetDataVariable(
                                table_id=3,
                                opcode=bebaproto.OPCODE_SUM,
                                output_fd_id=4,
                                operand_1_gd_id=(2 if s == 2 else 4),
                                operand_2_cost=0)
                        ]
                actions = actions_ewma + [ofparser.OFPActionOutput(s)]
                self.add_flow(datapath=datapath,
                              table_id=3,
                              priority=30,
                              match=match,
                              actions=actions)
                # normal conditions
                match = ofparser.OFPMatch(in_port=3,
                                          state=s,
                                          metadata=metadata,
                                          condition4=0)
                actions_ewma_bg = [
                    bebaparser.OFPExpActionSetDataVariable(
                        table_id=3,
                        opcode=bebaproto.OPCODE_SUM,
                        output_fd_id=2,
                        operand_1_fd_id=2,
                        operand_2_hf_id=2),
                    bebaparser.OFPExpActionSetDataVariable(
                        table_id=3,
                        opcode=bebaproto.OPCODE_SUM,
                        output_fd_id=5,
                        operand_1_fd_id=5,
                        operand_2_cost=1)
                ]
                actions = actions_ewma_bg + [ofparser.OFPActionOutput(s)]
                self.add_flow(datapath=datapath,
                              table_id=3,
                              priority=30,
                              match=match,
                              actions=actions)

                ########### match for extended states: same thing as in normal states but evaluate condition0 ##########
                match = ofparser.OFPMatch(in_port=3,
                                          state=s + (1 << 5),
                                          metadata=metadata,
                                          condition0=1,
                                          condition4=1)
                actions = actions_ewma + [ofparser.OFPActionOutput(s)]
                self.add_flow(datapath=datapath,
                              table_id=3,
                              priority=35,
                              match=match,
                              actions=actions)

                match = ofparser.OFPMatch(in_port=3,
                                          state=s + (1 << 5),
                                          metadata=metadata,
                                          condition0=1,
                                          condition4=0)
                actions = actions_ewma_bg + [ofparser.OFPActionOutput(s)]
                self.add_flow(datapath=datapath,
                              table_id=3,
                              priority=35,
                              match=match,
                              actions=actions)

                ############# condition[0] and [3] are verified, (i.e. big flow) change port ###########
                match = ofparser.OFPMatch(in_port=3,
                                          state=s,
                                          condition0=1,
                                          condition3=1)
                actions = [
                    bebaparser.OFPExpActionSetState(
                        state=(1 if s == 2 else 2) + (1 << 5),
                        table_id=3,
                        idle_timeout=5),
                    ofparser.OFPActionOutput(1 if s == 2 else 2)
                ]
                self.add_flow(datapath=datapath,
                              table_id=3,
                              priority=40,
                              match=match,
                              actions=actions)

                ########### if the flow returns to a rate under the threshold #############################
                match = ofparser.OFPMatch(in_port=3,
                                          state=s + (1 << 5),
                                          condition0=0)
                actions = [
                    bebaparser.OFPExpActionSetState(state=s,
                                                    table_id=3,
                                                    idle_timeout=5),
                    ofparser.OFPActionOutput(s)
                ]
                self.add_flow(datapath=datapath,
                              table_id=3,
                              priority=50,
                              match=match,
                              actions=actions)