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)
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)