def actions_to_ryu(actions, rule): """ Converts a list of actions to a list of ryu actions This returns both a instruction list and any extra messages that are required to install the instructions such as group mod messages. Currently this is not smart about reusing groups. actions: A iterable list actions such as ActionSet, ActionList, or Bucket. rule: The rule being converted return: A tuple ([actions], [extra messages]) """ ret = [] extra_messages = [] for action in actions: if action[0] == 'OUTPUT': ret.append(parser.OFPActionOutput(action[1])) elif action[0] == 'COPY_TTL_OUT': ret.append(parser.OFPActionCopyTtlOut()) elif action[0] == 'COPY_TTL_IN': ret.append(parser.OFPActionCopyTtlIn()) elif action[0] == 'SET_MPLS_TTL': ret.append(parser.OFPActionSetMplsTtl(action[1])) elif action[0] == 'DEC_MPLS_TTL': ret.append(parser.OFPActionDecMplsTtl()) elif action[0] == 'PUSH_VLAN': ret.append(parser.OFPActionPushVlan(action[1])) elif action[0] == 'POP_VLAN': ret.append(parser.OFPActionPopVlan()) elif action[0] == 'PUSH_MPLS': ret.append(parser.OFPActionPushMpls(action[1])) elif action[0] == 'POP_MPLS': ret.append(parser.OFPActionPopMpls(action[1])) elif action[0] == 'SET_QUEUE': ret.append(parser.OFPActionSetQueue(action[1])) elif action[0] == 'GROUP': if isinstance(action[1], Group): group_id, extra = group_to_ryu(action[1], rule) ret.append(parser.OFPActionGroup(group_id)) extra_messages += extra else: ret.append(parser.OFPActionGroup(action[1])) elif action[0] == 'SET_NW_TTL': ret.append(parser.OFPActionSetNwTtl(action[1])) elif action[0] == 'DEC_NW_TTL': ret.append(parser.OFPActionDecNwTtl()) elif action[0] == 'SET_FIELD': set_field = {action[1][0].lower(): action[1][1]} ret.append(parser.OFPActionSetField(**set_field)) elif action[0] == 'PUSH_PBB': ret.append(parser.OFPActionPushPbb(action[1])) elif action[0] == 'POP_PBB': ret.append(parser.OFPActionPopPbb()) else: assert not "GGRR" return (ret, extra_messages)
def pop_mpls(eth_type): """Return OpenFlow action list to pop MPLS header and rewrite ethertype. Args: eth_type (int): ethertype that is set in the packet. Returns: list: actions to pop MPLS header and rewrite ethertype. """ return [parser.OFPActionPopMpls(eth_type)]
def _packet_in_handler(self, ev): # If you hit this you might want to increase # the "miss_send_length" of your switch if ev.msg.msg_len < ev.msg.total_len: self.logger.debug("packet truncated: only %s of %s bytes", ev.msg.msg_len, ev.msg.total_len) msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser in_port = msg.match['in_port'] pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] pkt_tcp = pkt.get_protocol(tcp.tcp) ip = pkt.get_protocol(ipv4.ipv4) if eth.ethertype == ether_types.ETH_TYPE_LLDP: # ignore lldp packet return dst = eth.dst src = eth.src dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) # learn a mac address to avoid FLOOD next time. Private_key = 0 table_id = 1 #l = [257,260] last_item = 4 # we have to assign the correct user ports self.mac_to_port[dpid][src] = in_port if dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] else: out_port = ofproto.OFPP_FLOOD actions = [parser.OFPActionOutput(out_port)] priority = 1 if ip and dpid in self.Edgeswitch and in_port in range( 2, last_item + 1): if (dpid, src, ip.src, in_port) in self.Hostinfo: if src in self.Key.keys(): file = open("/home/abdullah/ryu/Key.txt", "r") contents = file.read() dictionary = ast.literal_eval(contents) file.close() self.Key = dictionary if self.Key[src][1] != 0: # I have to waite the user answer t = self.Key[src] lst = list(t) lst[3] = lst[1]**lst[2] % 21841 #private key t = tuple(lst) self.Key[src] = t Private_key = lst[3] else: return print ip.src, "is an authenticated user and its location", dpid, in_port else: return if msg.table_id == 0 and pkt_tcp.bits == 2: if Private_key != 0: match = parser.OFPMatch(in_port=in_port, eth_src=src, eth_type=0x8847, mpls_label=Private_key) actions = [ parser.OFPActionPopMpls(), parser.OFPActionOutput(out_port) ] inst = [ parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions) ] mod = parser.OFPFlowMod(datapath=datapath, table_id=0, priority=10, match=match, instructions=inst) datapath.send_msg(mod) self.Flowcounter[dpid] += 1 actions = [] match = parser.OFPMatch(in_port=in_port, eth_type=0x0800, ip_proto=6, tcp_flags=2) self.add_flow(datapath, 5, match, actions, table_id=0) return else: match = parser.OFPMatch(in_port=in_port, eth_type=0x0800, ip_proto=6, tcp_flags=2) actions = [parser.OFPActionOutput(out_port)] inst = [ parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions) ] mod = parser.OFPFlowMod(datapath=datapath, table_id=0, priority=10, match=match, instructions=inst) datapath.send_msg(mod) self.Flowcounter[dpid] += 1 print pkt return elif dpid in self.Edgeswitch: self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port) table_id = 1 else: self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port) table_id = 0 # install a flow to avoid packet_in next time if out_port != ofproto.OFPP_FLOOD: if Private_key != 0 and dpid in self.Edgeswitch: match = parser.OFPMatch(in_port=in_port, eth_src=src) actions = [] self.add_flow(datapath, 5, match, actions, table_id=1) match = parser.OFPMatch(in_port=in_port, eth_dst=dst, eth_src=src, eth_type=0x8847, mpls_label=Private_key) priority = 10 table_id = 1 actions = [ parser.OFPActionPopMpls(), parser.OFPActionOutput(out_port) ] else: match = parser.OFPMatch(in_port=in_port, eth_dst=dst, eth_src=src) # verify if we have a valid buffer_id, if yes avoid to send both # flow_mod & pa enumerate(cket_out if msg.buffer_id != ofproto.OFP_NO_BUFFER: self.add_flow(datapath, priority, match, actions, msg.buffer_id, table_id=table_id) return else: self.add_flow(datapath, priority, match, actions, table_id=table_id) else: pass data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) datapath.send_msg(out)
def install_edge(self, datapath): """ Table 0 is stateless """ """ Set table 1 as stateful solo per usare GD""" req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=1, stateful=1) datapath.send_msg(req) """ Set table 3 as stateful """ req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=3, stateful=1) datapath.send_msg(req) """ Set table 4 as stateful """ req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=4, stateful=1) datapath.send_msg(req) """ Set table 5 as stateful """ req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=5, stateful=1) datapath.send_msg(req) ############################### LOOKUP/UPDATE ################ """ Tab1 """ """ Non mi interessa """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=1) datapath.send_msg(req) """ Non mi interessa """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=1) datapath.send_msg(req) """ Tab3 """ """ Set lookup extractor = {MPLS_label} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_MPLS_LABEL], table_id=3) datapath.send_msg(req) """ Set update extractor = {MPLS_label} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_MPLS_LABEL], table_id=3) datapath.send_msg(req) """ Tab4 """ """ Set lookup extractor = {MAC_SRC} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=4) datapath.send_msg(req) """ Set update extractor = {MAC_SRC} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=4) datapath.send_msg(req) """ Tab5 """ """ Set lookup extractor = {MAC_DST} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_DST], table_id=5) datapath.send_msg(req) """ Set update extractor = {MAC_SRC} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=5) datapath.send_msg(req) ########################### SET HF GD DATA VARIABLE TAB 1 ############################################ ''' GD[0] = datapath.id<<6 + numero crescente''' req = osparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=1, global_data_variable_id=0, value=(datapath.id << 6) + 1) datapath.send_msg(req) ########################### SET HF GD DATA VARIABLE TAB 3 ############################################ ''' HF[0] = OXM_OF_MPLS_LABEL [id_pkt] ''' req = osparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=3, extractor_id=0, field=ofproto.OXM_OF_MPLS_LABEL) datapath.send_msg(req) ''' HF[1] = OXM_OF_MPLS_TC [pesoArchi] ''' req = osparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=3, extractor_id=1, field=ofproto.OXM_OF_MPLS_TC) datapath.send_msg(req) ''' GD[0] = 0 ''' req = osparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=3, global_data_variable_id=0, value=0) datapath.send_msg(req) ''' GD[1] = datapath.id ''' req = osparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=3, global_data_variable_id=1, value=0) datapath.send_msg(req) ########################### SET HF GD DATA VARIABLE TAB 4 ############################################ ''' HF[0] = OXM_OF_MPLS_LABEL [id_pkt] ''' req = osparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=4, extractor_id=0, field=ofproto.OXM_OF_MPLS_LABEL) datapath.send_msg(req) ''' HF[1] = OXM_OF_MPLS_TC [pesoArchi] ''' req = osparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=4, extractor_id=1, field=ofproto.OXM_OF_MPLS_TC) datapath.send_msg(req) ''' GD[0] = datapath.id ''' req = osparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=4, global_data_variable_id=0, value=1) datapath.send_msg(req) ########################### SET CONDITION TAB 4 ############################################ # condition 0: MPLS_TC <= COSTO MEMORIZZATO (FD[0]) ? # condition 0: HF[1] <= FD[0] ? req = osparser.OFPExpMsgSetCondition(datapath=datapath, table_id=4, condition_id=0, condition=osproto.CONDITION_LTE, operand_1_hf_id=1, operand_2_fd_id=0) datapath.send_msg(req) # condition 1: MPLS_TC <= 1 --> ovvero e il primo hop ? # condition 1: HF[1] <= GD[0] ? req = osparser.OFPExpMsgSetCondition(datapath=datapath, table_id=4, condition_id=1, condition=osproto.CONDITION_LTE, operand_1_hf_id=1, operand_2_gd_id=0) datapath.send_msg(req) ''' ####################### TAB 0 PushLabelMPLS ''' # Se il pacchetto proviene da una porta host (HOST_PORT) push label mpls e GOTO Tab 1 match = ofparser.OFPMatch(in_port=HOST_PORT) actions = [ofparser.OFPActionPushMpls()] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(1) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=8, match=match, instructions=inst) datapath.send_msg(mod) # Se proviene da un'altra porta ha gia la label MPLS GOTO Tab 1 giusto per dirlo esplicitamente perche ci andrebbe da solo CREDO NON DEVO FARE LA PushMpls match = ofparser.OFPMatch() actions = [] #se proviene da un altra porta ha gia la label MPLS inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(1) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=0, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 1 marca il pkt con ID_PKT ''' # Setta la label_mpls se non e gia stata configurata con il valore GD[0] + 1 -> (id_switch << 6) + 1 match = ofparser.OFPMatch(eth_type=0x8847, mpls_label=0) actions = [ osparser.OFPExpActionWriteContextToField( src_type=osproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_MPLS_LABEL), osparser.OFPExpActionSetDataVariable(table_id=1, opcode=osproto.OPCODE_SUM, output_gd_id=0, operand_1_gd_id=0, operand_2_cost=1) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(2) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=1, priority=8, match=match, instructions=inst) datapath.send_msg(mod) match = ofparser.OFPMatch(eth_type=0x8847) actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(2) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=1, priority=0, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 2 NULLA serve solo per i bug di OpenFlow, servono 2 stage xke le modifiche MPLS siano visibili''' # Non fa niente, ci sta solo per risolvere bug (presunti) di OpenFlow match = ofparser.OFPMatch(eth_type=0x8847) actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(3) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=2, priority=0, match=match, instructions=inst) datapath.send_msg(mod) '''####################### TAB 3 Verifica i duplicati, lo stato e' dato da mpls_label''' ''' somma il costo del link di ingresso al valore memorizzato nel pacchetto mpls_tc + 1 ''' ''' scrive il campo metada = 1 se e' un pacchetto duplicato ovvero nello stato 1 ''' """ Riga 1 """ # GD[0] = HF[1] + 1 -> MPLS_TC + 1 # HF [1] = GD[0] -> MPLS_TC = GD[0] # WriteMetadata = 1 -> pacchetto duplicato # SetState(1) # GOTO Tab 2 match = ofparser.OFPMatch(state=1, eth_type=0x8847) actions = [ osparser.OFPExpActionSetDataVariable(table_id=3, opcode=osproto.OPCODE_SUM, output_gd_id=0, operand_1_hf_id=1, operand_2_cost=1), osparser.OFPExpActionWriteContextToField( src_type=osproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_MPLS_TC), # osparser.OFPExpActionSetState(state=1, table_id=3, idle_timeout=15)] osparser.OFPExpActionSetState(state=1, table_id=3) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionWriteMetadata(metadata=1, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=3, priority=1198, match=match, instructions=inst) datapath.send_msg(mod) """ Riga 2 """ # GD[0] = HF[1] + 1 -> MPLS_TC + 1 # HF [1] = GD[0] -> MPLS_TC = GD[0] # SetState(1) # GOTO Tab 4 match = ofparser.OFPMatch(state=0, eth_type=0x8847) actions = [ osparser.OFPExpActionSetDataVariable(table_id=3, opcode=osproto.OPCODE_SUM, output_gd_id=0, operand_1_hf_id=1, operand_2_cost=1), osparser.OFPExpActionWriteContextToField( src_type=osproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_MPLS_TC), # osparser.OFPExpActionSetState(state=1, table_id=3, idle_timeout=15)] osparser.OFPExpActionSetState(state=1, table_id=3) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=3, priority=198, match=match, instructions=inst) datapath.send_msg(mod) '''# ####################### TAB 4 verifica le condizioni C[0] e C[1]''' ''' C[0] verifica se il costo memorizzato nel pacchetto e' <= di quello gia conosciuto (in pratica se il pacchetto ha fatto un percorso migliore) ''' ''' C[1] serve semplicemente a capire se e' lo switch direttametne collegato all'host che parla e quindi non bisogna fare il pop della label MPLS ''' ''' le righe BIS verificano la C[1] e non eseguono il POP della label MPLS ''' ''' metadata = 1 e' un pacchetto duplicato quindi DROP ''' ''' nel caso imposta metadata = 3 cioe' non e' un pacchetto duplicato ma il costo e' maggiore di quello conosciuto, inoltro senza aggiornare stato ''' """ Riga 1 """ # C[0]: MPLS_TC > COSTO MEMORIZZATO -> HF[1] > FD[0] # MetaData: 1 -> Pacchetto duplicato # azione DROP match = ofparser.OFPMatch(state=1, eth_type=0x8847, condition0=0, metadata=1) actions = [osparser.OFPExpActionSetState(state=1, table_id=4)] self.add_flow(datapath=datapath, table_id=4, priority=1198, match=match, actions=actions) """ Riga 2 """ # C[0]: MPLS_TC > COSTO MEMORIZZATO -> HF[1] > FD[0] # MetaData: 0 -> Pacchetto NON duplicato # SetState(1) # WriteMetadata = 3 -> pacchetto da percorso peggiore ma NON duplicato # azione GOTO Tab 3 match = ofparser.OFPMatch(state=1, eth_type=0x8847, condition0=0, condition1=0, metadata=0) actions = [ osparser.OFPExpActionSetState(state=1, table_id=4), ofparser.OFPActionPopMpls() ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionWriteMetadata(metadata=3, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=198, match=match, instructions=inst) datapath.send_msg(mod) """ Riga 2 BIS """ # C[0]: MPLS_TC > COSTO MEMORIZZATO -> HF[1] > FD[0] # MetaData: 0 -> Pacchetto NON duplicato # SetState(1) # WriteMetadata = 3 -> pacchetto da percorso peggiore ma NON duplicato # azione GOTO Tab 3 match = ofparser.OFPMatch(state=1, eth_type=0x8847, condition0=0, condition1=1, metadata=0) actions = [osparser.OFPExpActionSetState(state=1, table_id=4)] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionWriteMetadata(metadata=3, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=198, match=match, instructions=inst) datapath.send_msg(mod) """ Riga 3 """ # C[0]: MPLS_TC <= COSTO MEMORIZZATO -> HF[1] <= FD[0] # FD[0] = HF[1] -> COSTO MEMORIZZATO = MPLS_TC # SetState(1) # azione GOTO Tab 3 match = ofparser.OFPMatch(state=1, eth_type=0x8847, condition0=1, condition1=0) actions = [ osparser.OFPExpActionSetState(state=1, table_id=4), osparser.OFPExpActionSetDataVariable(table_id=4, opcode=osproto.OPCODE_SUM, output_fd_id=0, operand_1_hf_id=1, operand_2_cost=0), ofparser.OFPActionPopMpls() ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=98, match=match, instructions=inst) datapath.send_msg(mod) """ Riga 3 BIS """ # C[0]: MPLS_TC <= COSTO MEMORIZZATO -> HF[1] <= FD[0] # FD[0] = HF[1] -> COSTO MEMORIZZATO = MPLS_TC # SetState(1) # azione GOTO Tab 3 match = ofparser.OFPMatch(state=1, eth_type=0x8847, condition0=1, condition1=1) actions = [ osparser.OFPExpActionSetState(state=1, table_id=4), osparser.OFPExpActionSetDataVariable(table_id=4, opcode=osproto.OPCODE_SUM, output_fd_id=0, operand_1_hf_id=1, operand_2_cost=0) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=98, match=match, instructions=inst) datapath.send_msg(mod) """ Riga 4 """ # FD[0] = HF[1] -> COSTO MEMORIZZATO = MPLS_TC # SetState(1) # azione GOTO Tab 3 match = ofparser.OFPMatch(state=0, eth_type=0x8847, condition1=0) actions = [ osparser.OFPExpActionSetState(state=1, table_id=4), osparser.OFPExpActionSetDataVariable(table_id=4, opcode=osproto.OPCODE_SUM, output_fd_id=0, operand_1_hf_id=1, operand_2_cost=0), ofparser.OFPActionPopMpls() ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=8, match=match, instructions=inst) datapath.send_msg(mod) """ Riga 4 BIS """ # FD[0] = HF[1] -> COSTO MEMORIZZATO = MPLS_TC # SetState(1) # azione GOTO Tab 3 match = ofparser.OFPMatch(state=0, eth_type=0x8847, condition1=1) actions = [ osparser.OFPExpActionSetState(state=1, table_id=4), osparser.OFPExpActionSetDataVariable(table_id=4, opcode=osproto.OPCODE_SUM, output_fd_id=0, operand_1_hf_id=1, operand_2_cost=0) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=8, match=match, instructions=inst) datapath.send_msg(mod) '''# ####################### TAB 5 semplicemente MAC Learning ''' ''' Mac Learning ampliato per gestire i metadata = 1 o metadata = 3 ''' ''' metadata = 1 se e' arrivato fin qui significa che il costo nel pacchetto e' minore di quello conosciuto (ha seguito un percorso migliore) AGGIORNARE e DROP''' ''' metadata = 3 non e' un pacchetto duplicato ma il costo del percorso seguito e' peggiore di quello conosciuto NON AGGIORNARE e INOLTRA ''' # Per ogni input port, per ogni stato for i in range(1, N + 1): for s in range(N + 1): match = ofparser.OFPMatch(in_port=i, state=s) if s == 0: out_port = ofproto.OFPP_FLOOD #serve la flood, dipende se sto su S1 o S6 else: out_port = s # actions = [osparser.OFPExpActionSetState(state=i, table_id=5, hard_timeout=10), actions = [ osparser.OFPExpActionSetState(state=i, table_id=5), ofparser.OFPActionOutput(out_port) ] self.add_flow(datapath=datapath, table_id=5, priority=0, match=match, actions=actions) # Configuro le entry con azione DROP per i pacchetti duplicati (con metadata = 1) match = ofparser.OFPMatch(in_port=i, metadata=1) # actions = [osparser.OFPExpActionSetState(state=i, table_id=5, hard_timeout=10)] actions = [osparser.OFPExpActionSetState(state=i, table_id=5)] self.add_flow(datapath=datapath, table_id=5, priority=1198, match=match, actions=actions) # Per ogni stato for s in range(N + 1): match = ofparser.OFPMatch(state=s, metadata=3) if s == 0: out_port = ofproto.OFPP_FLOOD #serve la flood, dipende se sto su S1 o S6 else: out_port = s # Configuro le entry per l'output(in_port) senza aggiornare lo stato actions = [ofparser.OFPActionOutput(out_port)] self.add_flow(datapath=datapath, table_id=5, priority=198, match=match, actions=actions)
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)
def install_edge(self, datapath): """ Table 0 is stateless """ """ Set table 1 as stateful for GD""" req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=1, stateful=1) datapath.send_msg(req) """ Set table 3 as stateful """ req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=3, stateful=1) datapath.send_msg(req) """ Set table 4 as stateful """ req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=4, stateful=1) datapath.send_msg(req) """ Set table 5 as stateful """ req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=5, stateful=1) datapath.send_msg(req) ############################### LOOKUP/UPDATE ################ """ Tab1 """ """ Don't care """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=1) datapath.send_msg(req) """ Don't care """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=1) datapath.send_msg(req) """ Tab3 """ """ Set lookup extractor = {MPLS_label} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_MPLS_LABEL], table_id=3) datapath.send_msg(req) """ Set update extractor = {MPLS_label} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_MPLS_LABEL], table_id=3) datapath.send_msg(req) """ Tab4 """ """ Set lookup extractor = {MAC_SRC} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=4) datapath.send_msg(req) """ Set update extractor = {MAC_SRC} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=4) datapath.send_msg(req) """ Tab5 """ """ Set lookup extractor = {MAC_DST} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_DST], table_id=5) datapath.send_msg(req) """ Set update extractor = {MAC_SRC} """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=5) datapath.send_msg(req) ########################### SET HF GD DATA VARIABLE TAB 1 ############################################ ''' GD[0] = datapath.id<<6 + sequence number''' req = osparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=1, global_data_variable_id=0, value=(datapath.id << 6) + 1) datapath.send_msg(req) ########################### SET HF GD DATA VARIABLE TAB 3 ############################################ ''' HF[0] = OXM_OF_MPLS_LABEL [id_pkt] ''' req = osparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=3, extractor_id=0, field=ofproto.OXM_OF_MPLS_LABEL) datapath.send_msg(req) ''' HF[1] = OXM_OF_MPLS_TC [linkWeight] ''' req = osparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=3, extractor_id=1, field=ofproto.OXM_OF_MPLS_TC) datapath.send_msg(req) ''' GD[0] = 0 ''' req = osparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=3, global_data_variable_id=0, value=0) datapath.send_msg(req) ''' GD[1] = datapath.id ''' req = osparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=3, global_data_variable_id=1, value=0) datapath.send_msg(req) ########################### SET HF GD DATA VARIABLE TAB 4 ############################################ ''' HF[0] = OXM_OF_MPLS_LABEL [id_pkt] ''' req = osparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=4, extractor_id=0, field=ofproto.OXM_OF_MPLS_LABEL) datapath.send_msg(req) ''' HF[1] = OXM_OF_MPLS_TC [linkWeight] ''' req = osparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=4, extractor_id=1, field=ofproto.OXM_OF_MPLS_TC) datapath.send_msg(req) ''' GD[0] = datapath.id ''' req = osparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=4, global_data_variable_id=0, value=1) datapath.send_msg(req) ########################### SET CONDITION TAB 4 ############################################ # condition 0: MPLS_TC <= KNOWN WEIGHT (FD[0]) # condition 0: HF[1] <= FD[0] ? req = osparser.OFPExpMsgSetCondition(datapath=datapath, table_id=4, condition_id=0, condition=osproto.CONDITION_LTE, operand_1_hf_id=1, operand_2_fd_id=0) datapath.send_msg(req) # condition 1: MPLS_TC <= 1 --> first hop # condition 1: HF[1] <= GD[0] ? req = osparser.OFPExpMsgSetCondition(datapath=datapath, table_id=4, condition_id=1, condition=osproto.CONDITION_LTE, operand_1_hf_id=1, operand_2_gd_id=0) datapath.send_msg(req) ''' ####################### TAB 0 PushLabelMPLS ''' # Input from host port (HOST_PORT) push label mpls e GOTO Tab 1 match = ofparser.OFPMatch(in_port=HOST_PORT) actions = [ofparser.OFPActionPushMpls()] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(1) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=8, match=match, instructions=inst) datapath.send_msg(mod) match = ofparser.OFPMatch() actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(1) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=0, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 1 mark pkt with ID_PKT ''' # Set label_mpls: GD[0] + 1 -> (id_switch << 6) + 1 match = ofparser.OFPMatch(eth_type=0x8847, mpls_label=0) actions = [ osparser.OFPExpActionWriteContextToField( src_type=osproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_MPLS_LABEL), osparser.OFPExpActionSetDataVariable(table_id=1, opcode=osproto.OPCODE_SUM, output_gd_id=0, operand_1_gd_id=0, operand_2_cost=1) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(2) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=1, priority=8, match=match, instructions=inst) datapath.send_msg(mod) match = ofparser.OFPMatch(eth_type=0x8847) actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(2) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=1, priority=0, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 2 ''' match = ofparser.OFPMatch(eth_type=0x8847) actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(3) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=2, priority=0, match=match, instructions=inst) datapath.send_msg(mod) '''####################### TAB 3 Check duplicate, State: mpls_label''' """ Line 1 """ # GD[0] = HF[1] + 1 -> MPLS_TC + 1 # HF [1] = GD[0] -> MPLS_TC = GD[0] # WriteMetadata = 1 -> duplicate pkt # SetState(1) # GOTO Tab 2 match = ofparser.OFPMatch(state=1, eth_type=0x8847) actions = [ osparser.OFPExpActionSetDataVariable(table_id=3, opcode=osproto.OPCODE_SUM, output_gd_id=0, operand_1_hf_id=1, operand_2_cost=1), osparser.OFPExpActionWriteContextToField( src_type=osproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_MPLS_TC), # osparser.OFPExpActionSetState(state=1, table_id=3, idle_timeout=15)] osparser.OFPExpActionSetState(state=1, table_id=3) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionWriteMetadata(metadata=1, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=3, priority=1198, match=match, instructions=inst) datapath.send_msg(mod) """ Line 2 """ # GD[0] = HF[1] + 1 -> MPLS_TC + 1 # HF [1] = GD[0] -> MPLS_TC = GD[0] # SetState(1) # GOTO Tab 4 match = ofparser.OFPMatch(state=0, eth_type=0x8847) actions = [ osparser.OFPExpActionSetDataVariable(table_id=3, opcode=osproto.OPCODE_SUM, output_gd_id=0, operand_1_hf_id=1, operand_2_cost=1), osparser.OFPExpActionWriteContextToField( src_type=osproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_MPLS_TC), osparser.OFPExpActionSetState(state=1, table_id=3) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=3, priority=198, match=match, instructions=inst) datapath.send_msg(mod) '''# ####################### TAB 4 check condition C[0] e C[1]''' """ Line 1 """ # C[0]: MPLS_TC > KNOWN WEIGHT -> HF[1] > FD[0] # MetaData: 1 -> duplicate pkt # action DROP match = ofparser.OFPMatch(state=1, eth_type=0x8847, condition0=0, metadata=1) actions = [osparser.OFPExpActionSetState(state=1, table_id=4)] self.add_flow(datapath=datapath, table_id=4, priority=1198, match=match, actions=actions) """ Line 2 """ # C[0]: MPLS_TC > KNOWN WEIGHT -> HF[1] > FD[0] # MetaData: 0 -> NOT duplicate # SetState(1) # WriteMetadata = 3 -> WORSE PATH, NOT duplicate # action GOTO Tab 3 match = ofparser.OFPMatch(state=1, eth_type=0x8847, condition0=0, condition1=0, metadata=0) actions = [ osparser.OFPExpActionSetState(state=1, table_id=4), ofparser.OFPActionPopMpls() ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionWriteMetadata(metadata=3, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=198, match=match, instructions=inst) datapath.send_msg(mod) """ Line 2 BIS """ # C[0]: MPLS_TC > KNOWN WEIGHT -> HF[1] > FD[0] # MetaData: 0 -> NOT duplicate # SetState(1) # WriteMetadata = 3 -> WORSE PATH, NOT duplicate # action GOTO Tab 3 match = ofparser.OFPMatch(state=1, eth_type=0x8847, condition0=0, condition1=1, metadata=0) actions = [osparser.OFPExpActionSetState(state=1, table_id=4)] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionWriteMetadata(metadata=3, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=198, match=match, instructions=inst) datapath.send_msg(mod) """ Line 3 """ # C[0]: MPLS_TC <= KNOWN WEIGHT -> HF[1] <= FD[0] # FD[0] = HF[1] -> KNOWN WEIGHT = MPLS_TC # SetState(1) # action GOTO Tab 3 match = ofparser.OFPMatch(state=1, eth_type=0x8847, condition0=1, condition1=0) actions = [ osparser.OFPExpActionSetState(state=1, table_id=4), osparser.OFPExpActionSetDataVariable(table_id=4, opcode=osproto.OPCODE_SUM, output_fd_id=0, operand_1_hf_id=1, operand_2_cost=0), ofparser.OFPActionPopMpls() ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=98, match=match, instructions=inst) datapath.send_msg(mod) """ Line 3 BIS """ # C[0]: MPLS_TC <= KNOWN WEIGHT -> HF[1] <= FD[0] # FD[0] = HF[1] -> KNOWN WEIGHT = MPLS_TC # SetState(1) # action GOTO Tab 3 match = ofparser.OFPMatch(state=1, eth_type=0x8847, condition0=1, condition1=1) actions = [ osparser.OFPExpActionSetState(state=1, table_id=4), osparser.OFPExpActionSetDataVariable(table_id=4, opcode=osproto.OPCODE_SUM, output_fd_id=0, operand_1_hf_id=1, operand_2_cost=0) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=98, match=match, instructions=inst) datapath.send_msg(mod) """ Line 4 """ # FD[0] = HF[1] -> KNOWN WEIGHT = MPLS_TC # SetState(1) # action GOTO Tab 3 match = ofparser.OFPMatch(state=0, eth_type=0x8847, condition1=0) actions = [ osparser.OFPExpActionSetState(state=1, table_id=4), osparser.OFPExpActionSetDataVariable(table_id=4, opcode=osproto.OPCODE_SUM, output_fd_id=0, operand_1_hf_id=1, operand_2_cost=0), ofparser.OFPActionPopMpls() ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=8, match=match, instructions=inst) datapath.send_msg(mod) """ Line 4 BIS """ # FD[0] = HF[1] -> KNOWN WEIGHT = MPLS_TC # SetState(1) # action GOTO Tab 3 match = ofparser.OFPMatch(state=0, eth_type=0x8847, condition1=1) actions = [ osparser.OFPExpActionSetState(state=1, table_id=4), osparser.OFPExpActionSetDataVariable(table_id=4, opcode=osproto.OPCODE_SUM, output_fd_id=0, operand_1_hf_id=1, operand_2_cost=0) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(5) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=4, priority=8, match=match, instructions=inst) datapath.send_msg(mod) '''# ####################### TAB 5 simply MAC Learning ''' ''' Mac Learning, check if metadata = 1 or metadata = 3 ''' # For each input port, for each state for i in range(1, N + 1): for s in range(N + 1): match = ofparser.OFPMatch(in_port=i, state=s) if s == 0: out_port = ofproto.OFPP_FLOOD else: out_port = s # actions = [osparser.OFPExpActionSetState(state=i, table_id=5, hard_timeout=10), actions = [ osparser.OFPExpActionSetState(state=i, table_id=5), ofparser.OFPActionOutput(out_port) ] self.add_flow(datapath=datapath, table_id=5, priority=0, match=match, actions=actions) # DROP duplicate pkt (metadata = 1) match = ofparser.OFPMatch(in_port=i, metadata=1) # actions = [osparser.OFPExpActionSetState(state=i, table_id=5, hard_timeout=10)] actions = [osparser.OFPExpActionSetState(state=i, table_id=5)] self.add_flow(datapath=datapath, table_id=5, priority=1198, match=match, actions=actions) # For each state for s in range(N + 1): match = ofparser.OFPMatch(state=s, metadata=3) if s == 0: out_port = ofproto.OFPP_FLOOD else: out_port = s actions = [ofparser.OFPActionOutput(out_port)] self.add_flow(datapath=datapath, table_id=5, priority=198, 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, ev): datapath = ev.msg.datapath # ofp = datapath.ofproto # ofp_parser = datapath.ofproto_parser from ryu.ofproto import ofproto_v1_3 as ofp from ryu.ofproto import ofproto_v1_3_parser as ofp_parser mod = [ ofp_parser.OFPFlowMod( datapath=datapath, table_id=0, priority=0, instructions=[ofp_parser.OFPInstructionGotoTable(table_id=1)]), ofp_parser.OFPFlowMod( datapath=datapath, table_id=0, priority=1, match=ofp_parser.OFPMatch(eth_type=ether_types.ETH_TYPE_ARP), instructions=[ofp_parser.OFPInstructionGotoTable(table_id=3)]), ofp_parser.OFPFlowMod( datapath=datapath, table_id=1, priority=0, instructions=[ofp_parser.OFPInstructionGotoTable(table_id=2)]), ofp_parser.OFPFlowMod( datapath=datapath, table_id=1, priority=1, match=ofp_parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP), instructions=[ ofp_parser.OFPInstructionActions( type_=ofp.OFPIT_APPLY_ACTIONS, actions=[ ofp_parser.OFPActionPushMpls(), # ofp_parser.OFPActionSetField(mpls_label=0x1234), ofp_parser.OFPActionPushMpls(), # ofp_parser.OFPActionSetField(mpls_label=0x1235) ]), ofp_parser.OFPInstructionGotoTable(table_id=3) ]), ofp_parser.OFPFlowMod( datapath=datapath, table_id=1, priority=2, match=ofp_parser.OFPMatch(eth_type=ether_types.ETH_TYPE_MPLS, mpls_bos=0), instructions=[ ofp_parser.OFPInstructionActions( type_=ofp.OFPIT_APPLY_ACTIONS, actions=[ ofp_parser.OFPActionPopMpls( ether_types.ETH_TYPE_MPLS) ]), ofp_parser.OFPInstructionGotoTable(table_id=2), ]), ofp_parser.OFPFlowMod( datapath=datapath, table_id=2, priority=0, instructions=[ofp_parser.OFPInstructionGotoTable(table_id=3)]), ofp_parser.OFPFlowMod( datapath=datapath, table_id=2, priority=1, match=ofp_parser.OFPMatch(eth_type=ether_types.ETH_TYPE_MPLS, mpls_bos=1), instructions=[ ofp_parser.OFPInstructionActions( type_=ofp.OFPIT_APPLY_ACTIONS, actions=[ ofp_parser.OFPActionPopMpls( ether_types.ETH_TYPE_IP) ]), ofp_parser.OFPInstructionGotoTable(table_id=3) ]), ofp_parser.OFPFlowMod( datapath=datapath, table_id=3, priority=0, instructions=[ ofp_parser.OFPInstructionActions( type_=ofp.OFPIT_APPLY_ACTIONS, actions=[ ofp_parser.OFPActionOutput( port=ofp.OFPP_CONTROLLER), ofp_parser.OFPActionOutput(port=ofp.OFPP_FLOOD) ]) ]) ] for msg in mod: datapath.send_msg(msg)