Beispiel #1
0
 def add_pktgen_flow(self, datapath, table_id, priority, match, pkttmp_id,
                     actions):
     if len(actions) > 0:
         inst = [
             bebaparser.OFPInstructionInSwitchPktGen(pkttmp_id, actions)
         ]
     else:
         inst = []
     mod = ofparser.OFPFlowMod(datapath=datapath,
                               table_id=table_id,
                               priority=priority,
                               match=match,
                               instructions=inst)
     datapath.send_msg(mod)
 def test30(self, datapath):
     self.send_table_mod(datapath)
     self.send_key_lookup(datapath)
     self.send_key_update(datapath)
     actions = []
     match = ofparser.OFPMatch(in_port=5, eth_type=0x800, ip_proto=1)
     i = bebaparser.OFPInstructionInSwitchPktGen(0, actions)
     i.instr_type = 56
     inst = [i]
     mod = ofparser.OFPFlowMod(datapath=datapath,
                               table_id=0,
                               priority=100,
                               match=match,
                               instructions=inst)
     datapath.send_msg(mod)
    def install_leaves(self, datapath):
        # Send probe packet to packet generation table
        req = bebaparser.OFPExpMsgAddPktTmp(datapath=datapath,
                                            pkttmp_id=0,
                                            pkt_data=pkt_raw)
        datapath.send_msg(req)

        ##################################### 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=PROBE_FREQ)
        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 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=10,
                                      match=match,
                                      instructions=instructions)
            datapath.send_msg(mod)

        match = ofparser.OFPMatch()
        instructions = [ofparser.OFPInstructionGotoTable(2)]
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=0,
                                  priority=0,
                                  match=match,
                                  instructions=instructions)
        datapath.send_msg(mod)

        # using low bitrate flows to refresh the estimates. For testing purposes only
        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)

        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_hf_id=1,
            operand_2_fd_id=4)
        datapath.send_msg(req)

        ############################### TABLE 2 FLOWS #############################

        match = ofparser.OFPMatch(state=0)
        actions = [
            bebaparser.OFPExpActionSetState(table_id=2,
                                            state=1,
                                            idle_timeout=2),
            # saves timestamp
            bebaparser.OFPExpActionSetDataVariable(table_id=2,
                                                   opcode=bebaproto.OPCODE_SUM,
                                                   output_fd_id=4,
                                                   operand_1_hf_id=1,
                                                   operand_2_cost=PROBE_FREQ),
            ofparser.OFPActionOutput(3)
        ]
        self.add_flow(datapath=datapath,
                      table_id=2,
                      priority=500,
                      match=match,
                      actions=actions)
        """ For every packet coming from spine ports, calculates ewma """
        for i in UPPER_PORTS:
            # simply ewma measuring
            match = ofparser.OFPMatch(state=1, 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_ms) * 8 [kb/s]
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    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=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=ALPHA,
                    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),
                # saves timestamp + probe freq
                bebaparser.OFPExpActionSetDataVariable(
                    table_id=2,
                    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=2,
                    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=2,
                    opcode=bebaproto.OPCODE_SUM,
                    output_gd_id=i,
                    operand_1_fd_id=3,
                    operand_2_cost=0)
            ]
            # actions for the packet
            actions = actions_ewma_1 + [ofparser.OFPActionOutput(3)]
            # action group for the probes
            probe_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(i)
            ]
            probe_actions2 = [
                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))
            ]
            # apply packet actions
            insts = [
                ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                               actions),
                # apply packet generation
                bebaparser.OFPInstructionInSwitchPktGen(
                    pkttmp_id=0, actions=probe_actions1),
                bebaparser.OFPInstructionInSwitchPktGen(pkttmp_id=0,
                                                        actions=probe_actions2)
            ]
            mod = ofparser.OFPFlowMod(datapath=datapath,
                                      table_id=2,
                                      priority=30,
                                      match=match,
                                      instructions=insts)
            datapath.send_msg(mod)

            match = ofparser.OFPMatch(state=1, 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)
            ]
            self.add_flow(datapath=datapath,
                          table_id=2,
                          priority=30,
                          match=match,
                          actions=actions_ewma_2 +
                          [ofparser.OFPActionOutput(3)])

            # using low bitrate flows to refresh the estimates. For testing purposes only
            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 """
        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)

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

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

        # in case of 2 Spines
        for destLeaf in [1, 2]:
            # C[destLeaf]: in which port there is less utilization for that destination?
            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)

        # 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=RTT),
            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=RTT),
            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:
                if leafNo != datapath.id:
                    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
                match = ofparser.OFPMatch(in_port=3,
                                          state=s,
                                          metadata=metadata)  # , condition4=0)
                actions = [ofparser.OFPActionOutput(s)]
                self.add_flow(datapath=datapath,
                              table_id=3,
                              priority=30,
                              match=match,
                              actions=actions)
    def install_stateful(self, datapath):
        # Send probe packet to packet generation table
        for i in [1, 2, 3, 4]:
            req = bebaparser.OFPExpMsgAddPktTmp(datapath=datapath,
                                                pkttmp_id=i,
                                                pkt_data=pkts[i - 1])
            datapath.send_msg(req)

        # configure stateful stage
        req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath,
                                                         table_id=1,
                                                         stateful=1)
        datapath.send_msg(req)
        """ Set lookup extractor = {ip_dst} """
        req = bebaparser.OFPExpMsgKeyExtract(
            datapath=datapath,
            command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR,
            fields=[ofproto.OXM_OF_IPV4_DST],
            table_id=1)
        datapath.send_msg(req)
        """ Set update extractor = {ip_dst} (same as lookup) """
        req = bebaparser.OFPExpMsgKeyExtract(
            datapath=datapath,
            command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR,
            fields=[ofproto.OXM_OF_IPV4_DST],
            table_id=1)
        datapath.send_msg(req)

        # sampling time
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath,
            table_id=1,
            global_data_variable_id=1,
            value=SAMPLING_TIME)
        datapath.send_msg(req)

        # sampling time
        req = bebaparser.OFPExpMsgsSetGlobalDataVariable(
            datapath=datapath,
            table_id=1,
            global_data_variable_id=0,
            value=THRESHOLD)
        datapath.send_msg(req)

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

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

        # threshold exceeding condition
        req = bebaparser.OFPExpMsgSetCondition(
            datapath=datapath,
            condition=bebaproto.CONDITION_GTE,
            condition_id=2,
            table_id=1,
            operand_1_fd_id=2,
            operand_2_gd_id=0)
        datapath.send_msg(req)

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

        # metadata extractor
        req = bebaparser.OFPExpMsgHeaderFieldExtract(
            datapath=datapath,
            table_id=1,
            extractor_id=0,
            field=ofproto.OXM_OF_METADATA)
        datapath.send_msg(req)

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

        ############################# TAB 0: STATELESS ####################################
        # configure stateful stage
        req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath,
                                                         table_id=0,
                                                         stateful=1)
        datapath.send_msg(req)
        """ Set lookup extractor = {ip_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 = {ip_dst} (same as lookup) """
        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)
        """ #T0_R1 """
        # Parse MPLS info: send state in metadata in the right position
        # it is needed to match the right ip extractor in tab 1
        match = ofparser.OFPMatch(eth_type=0x8847)
        actions = [
            bebaparser.OFPExpActionSetDataVariable(table_id=0,
                                                   opcode=bebaproto.OPCODE_SUM,
                                                   output_fd_id=0,
                                                   operand_1_hf_id=0,
                                                   operand_2_cost=0),
            bebaparser.OFPExpActionWriteContextToField(
                src_type=bebaproto.SOURCE_TYPE_FLOW_DATA_VAR,
                src_id=0,
                dst_field=ofproto.OXM_OF_METADATA),
            ofparser.OFPActionPopMpls()
        ]
        instructions = [
            ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                           actions),
            ofparser.OFPInstructionWriteMetadata(metadata=0x88470000,
                                                 metadata_mask=0xffff0000),
            ofparser.OFPInstructionGotoTable(1)
        ]
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=0,
                                  priority=100,
                                  match=match,
                                  instructions=instructions)
        datapath.send_msg(mod)
        """ #T0_R2 """
        # if pkt has dscp=13 it's passing through the second stateful switch,
        #   so this packet has not to be counted: directly to forwarding
        match = ofparser.OFPMatch(eth_type=0x800)
        instructions = [ofparser.OFPInstructionGotoTable(2)]
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=0,
                                  priority=0,
                                  match=match,
                                  instructions=instructions)
        datapath.send_msg(mod)
        """ #T0_R3 """
        # All other packets go to tab 1 for counting
        match = ofparser.OFPMatch(eth_type=0x800, ip_dscp=0)
        instructions = [ofparser.OFPInstructionGotoTable(1)]
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=0,
                                  priority=50,
                                  match=match,
                                  instructions=instructions)
        datapath.send_msg(mod)
        """ #T0_R4 """
        # For now packets coming from host ports are dropped
        match = ofparser.OFPMatch(in_port=HOST_PORT)
        actions = []
        self.add_flow(datapath=datapath,
                      table_id=0,
                      priority=500,
                      match=match,
                      actions=actions)

        ############################### TAB 1: STATEFUL ############################################
        """ For each state entry
            FDV[0]: count
            FDV[1]: delta timestamp
            FDV[2]: ewma representing switch's own state
            FDV[3]: global state
        """

        # common instructions
        instGoto2 = [ofparser.OFPInstructionGotoTable(2)]

        # this entry saves the state contained in the mpls pkt
        match = ofparser.OFPMatch(metadata=(0x88470000, 0xffff0000),
                                  eth_type=0x800)
        actions = [
            bebaparser.OFPExpActionSetDataVariable(table_id=1,
                                                   opcode=bebaproto.OPCODE_SUM,
                                                   output_fd_id=3,
                                                   operand_1_hf_id=0,
                                                   operand_2_fd_id=2)
        ]
        insts = [
            ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                           actions)
        ]
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=1,
                                  priority=200,
                                  match=match,
                                  instructions=insts)
        datapath.send_msg(mod)

        # packet counter ++
        actionUpdateCounter = [
            bebaparser.OFPExpActionSetDataVariable(table_id=1,
                                                   opcode=bebaproto.OPCODE_SUM,
                                                   output_fd_id=0,
                                                   operand_1_fd_id=0,
                                                   operand_2_cost=1)
        ]
        # reset counter to 0
        actionResetCounter = [
            bebaparser.OFPExpActionSetDataVariable(table_id=1,
                                                   opcode=bebaproto.OPCODE_SUB,
                                                   output_fd_id=0,
                                                   operand_1_fd_id=0,
                                                   operand_2_fd_id=0)
        ]
        # save timestamp+sampling_time
        actionSaveTimestamp = [
            bebaparser.OFPExpActionSetDataVariable(table_id=1,
                                                   opcode=bebaproto.OPCODE_SUM,
                                                   output_fd_id=1,
                                                   operand_1_hf_id=1,
                                                   operand_2_gd_id=1)
        ]

        # Calculates EWMA on packet number
        actionEvaluateEWMA = [
            bebaparser.OFPExpActionSetDataVariable(
                table_id=1,
                opcode=bebaproto.OPCODE_MUL,
                output_fd_id=0,
                operand_1_fd_id=0,
                operand_2_cost=MULTIPLY_FACTOR),
            bebaparser.OFPExpActionSetDataVariable(
                table_id=1,
                opcode=bebaproto.OPCODE_EWMA,
                output_fd_id=2,
                operand_1_fd_id=2,
                operand_2_cost=bebaproto.EWMA_PARAM_0875,
                operand_3_fd_id=0)
        ]

        actionSetDSCPAttack = [ofparser.OFPActionSetField(ip_dscp=26)]
        actionSetDSCPNormal = [ofparser.OFPActionSetField(ip_dscp=13)]
        """ Measures and state transitions """
        """ #T1_R1 """
        """ First packet of a flow """
        match = ofparser.OFPMatch(state=0, eth_type=0x800)
        actions = [bebaparser.OFPExpActionSetState(state=1, table_id=1, idle_timeout=MONITORING_TIMEOUT)] + \
                  actionUpdateCounter + actionSaveTimestamp + actionSetDSCPNormal
        insts = [
            ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                           actions)
        ] + instGoto2
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=1,
                                  priority=50,
                                  match=match,
                                  instructions=insts)
        datapath.send_msg(mod)
        """ #T1_R2 """
        """ State is MONITORING; in between the window
            ACTIONS: counter++ and set NORMAL DSCP info"""
        match = ofparser.OFPMatch(state=1, condition0=0, eth_type=0x800)
        actions = actionUpdateCounter + actionSetDSCPNormal
        insts = [
            ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                           actions)
        ] + instGoto2
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=1,
                                  priority=15,
                                  match=match,
                                  instructions=insts)
        datapath.send_msg(mod)
        """ #T1_R3 """
        """ State is MONITORING; sampling time expired
            ACTIONS: evaluate EWMA, counter = 0, save new timestamp+SAMPLING, push mpls, write ewma value to label"""

        for i in [1, 2, 3, 4]:
            match = ofparser.OFPMatch(ipv4_dst='10.0.0.' + str(i),
                                      state=1,
                                      condition0=1,
                                      eth_type=0x800)
            actions = actionEvaluateEWMA + actionResetCounter + actionSaveTimestamp
            insp_actions = [
                bebaparser.OFPExpActionWriteContextToField(
                    src_type=bebaproto.SOURCE_TYPE_FLOW_DATA_VAR,
                    src_id=2,
                    dst_field=ofproto.OXM_OF_MPLS_LABEL),
                ofparser.OFPActionSetField(mpls_tc=datapath.id),
                ofparser.OFPActionOutput(2)
            ]
            insts = [
                ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                               actions),
                bebaparser.OFPInstructionInSwitchPktGen(pkttmp_id=i,
                                                        actions=insp_actions)
            ] + instGoto2
            mod = ofparser.OFPFlowMod(datapath=datapath,
                                      table_id=1,
                                      priority=20,
                                      match=match,
                                      instructions=insts)
            datapath.send_msg(mod)
        """ #T1_R4 """
        """ State is in MONITORING, the switch's own state is over threshold now
            ACTIONS: go to ATTACK state and trigger the control message """
        match = ofparser.OFPMatch(state=1, condition2=1, eth_type=0x800)
        # apply mitigation policy
        actions = [bebaparser.OFPExpActionSetState(state=2, table_id=1)] +\
                  actionSetDSCPAttack
        insts = [
            ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                           actions)
        ] + instGoto2
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=1,
                                  priority=30,
                                  match=match,
                                  instructions=insts)
        datapath.send_msg(mod)
        """ #T1_R5 """
        """ State is MONITORING, The sum of the 2 states is over threshold now """
        match = ofparser.OFPMatch(state=1, condition1=1, eth_type=0x800)
        actions = [bebaparser.OFPExpActionSetState(state=2, table_id=1)
                   ] + actionSetDSCPAttack
        insts = [
            ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                           actions)
        ] + instGoto2
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=1,
                                  priority=30,
                                  match=match,
                                  instructions=insts)
        datapath.send_msg(mod)
        """ #T1_R6 """
        """ State is ATTACK, no more over threshold, either the sum of states or switch's own state"""
        match = ofparser.OFPMatch(state=2,
                                  condition1=0,
                                  condition2=0,
                                  eth_type=0x800)
        actions = [bebaparser.OFPExpActionSetState(state=1, table_id=1, idle_timeout=MONITORING_TIMEOUT)] +\
                  actionSetDSCPNormal
        insts = [
            ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                           actions),
            # RETURNED UNDER THRESHOLD
            ofparser.OFPInstructionWriteMetadata(metadata=11,
                                                 metadata_mask=0xffffffff)
        ] + instGoto2
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=1,
                                  priority=100,
                                  match=match,
                                  instructions=insts)
        datapath.send_msg(mod)
        """ #T1_R7 """
        """ State is ATTACK, monitor condition is valid"""
        match = ofparser.OFPMatch(state=2, condition0=0, eth_type=0x800)
        actions = actionUpdateCounter + actionSetDSCPAttack
        insts = [
            ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                           actions),
            ofparser.OFPInstructionWriteMetadata(metadata=22,
                                                 metadata_mask=0xffffffff)
        ] + instGoto2
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=1,
                                  priority=50,
                                  match=match,
                                  instructions=insts)
        datapath.send_msg(mod)
        """ #T1_R8 """
        """ State is ATTACK, trigger control message """
        for i in [1, 2, 3, 4]:
            match = ofparser.OFPMatch(ipv4_dst='10.0.0.' + str(i),
                                      state=2,
                                      condition0=1,
                                      eth_type=0x800)
            actions = actionEvaluateEWMA + actionResetCounter + actionSaveTimestamp + actionSetDSCPAttack
            insp_actions = [
                bebaparser.OFPExpActionWriteContextToField(
                    src_type=bebaproto.SOURCE_TYPE_FLOW_DATA_VAR,
                    src_id=2,
                    dst_field=ofproto.OXM_OF_MPLS_LABEL),
                ofparser.OFPActionSetField(mpls_tc=datapath.id),
                ofparser.OFPActionOutput(2)
            ]
            insts = [
                ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                               actions),
                bebaparser.OFPInstructionInSwitchPktGen(pkttmp_id=i,
                                                        actions=insp_actions)
            ] + instGoto2
            mod = ofparser.OFPFlowMod(datapath=datapath,
                                      table_id=1,
                                      priority=50,
                                      match=match,
                                      instructions=insts)
            datapath.send_msg(mod)

        ########################    TAB 2: STATELESS    ########################################
        """ #T2_R1 """
        # Pkts destined to host attached to switch
        match = ofparser.OFPMatch(eth_type=0x800,
                                  ipv4_dst=server_dict[datapath.id])
        actions = [ofparser.OFPActionOutput(HOST_PORT)]
        self.add_flow(datapath=datapath,
                      table_id=2,
                      priority=70,
                      match=match,
                      actions=actions)

        # SW 2
        """ #T2_R2-3 """
        if datapath.id == 2:
            """ Stateful switches IN_PORT output actions """
            match = ofparser.OFPMatch(in_port=1,
                                      eth_type=0x800,
                                      ipv4_dst=addrs[3])
            actions = [ofparser.OFPActionOutput(ofproto.OFPP_IN_PORT)]
            self.add_flow(datapath=datapath,
                          table_id=2,
                          priority=50,
                          match=match,
                          actions=actions)

            match = ofparser.OFPMatch(in_port=2,
                                      eth_type=0x800,
                                      ipv4_dst=addrs[2])
            actions = [ofparser.OFPActionOutput(ofproto.OFPP_IN_PORT)]
            self.add_flow(datapath=datapath,
                          table_id=2,
                          priority=50,
                          match=match,
                          actions=actions)

        # SW 6
        elif datapath.id == 6:
            """ #T2_R4-5 """
            """ Stateful switches IN_PORT output actions """
            match = ofparser.OFPMatch(in_port=1,
                                      eth_type=0x800,
                                      ipv4_dst=addrs[2])
            actions = [ofparser.OFPActionOutput(ofproto.OFPP_IN_PORT)]
            self.add_flow(datapath=datapath,
                          table_id=2,
                          priority=50,
                          match=match,
                          actions=actions)

            match = ofparser.OFPMatch(in_port=2,
                                      eth_type=0x800,
                                      ipv4_dst=addrs[3])
            actions = [ofparser.OFPActionOutput(ofproto.OFPP_IN_PORT)]
            self.add_flow(datapath=datapath,
                          table_id=2,
                          priority=50,
                          match=match,
                          actions=actions)

        # All other packets -> out
        """ #T2_R6-7 """
        for p in CORE_PORTS:
            match = ofparser.OFPMatch(in_port=p, eth_type=0x800)
            actions = [ofparser.OFPActionOutput(1 if p == 2 else 2)]
            self.add_flow(datapath=datapath,
                          table_id=2,
                          priority=0,
                          match=match,
                          actions=actions)
Beispiel #5
0
    def switch_features_handler(self, event):
        """ Switch sent his features, check if OpenState supported """
        msg = event.msg
        datapath = msg.datapath

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

        # Send probe packet to packet generation table
        req = bebaparser.OFPExpMsgAddPktTmp(datapath=datapath,
                                            pkttmp_id=0,
                                            pkt_data=pkt_raw)
        datapath.send_msg(req)

        req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath,
                                                         table_id=0,
                                                         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=0)
        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=0)
        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=1234)
        datapath.send_msg(req)

        # match
        match = ofparser.OFPMatch()
        actions = [ofparser.OFPActionOutput(ofproto.OFPP_FLOOD)]
        probe_actions = [
            ofparser.OFPActionSetField(mpls_tc=3),
            bebaparser.OFPExpActionWriteContextToField(
                src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR,
                src_id=0,
                dst_field=ofproto.OXM_OF_MPLS_LABEL),
            ofparser.OFPActionOutput(2)
        ]
        insts = [
            ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                           actions),
            bebaparser.OFPInstructionInSwitchPktGen(pkttmp_id=0,
                                                    actions=probe_actions)
        ]
        mod = ofparser.OFPFlowMod(datapath=datapath,
                                  table_id=0,
                                  priority=0,
                                  match=match,
                                  instructions=insts)
        datapath.send_msg(mod)

        match = ofparser.OFPMatch(eth_type=0x8847)
        actions = [
            ofparser.OFPActionSetField(mpls_tc=5),
            ofparser.OFPActionOutput(1)
        ]
        self.add_flow(datapath=datapath,
                      table_id=0,
                      priority=0,
                      match=match,
                      actions=actions)