def tcp_udp_flows(self, vlan_id, nfvip, eth_type, nat_flows): return ( # Learn from coprocessor port/do inbound translation. (self.FROM_COPRO_TABLE, parser.OFPMatch(eth_type=eth_type, vlan_vid=vlan_id), nat_flows(nfvip)), # Packets from coprocessor go to tuple inbound table. (self.INTF_TABLE, parser.OFPMatch(eth_type=eth_type, ip_proto=socket.IPPROTO_TCP, in_port=COPROPORT, vlan_vid=vlan_id), [parser.OFPInstructionGotoTable(self.FROM_COPRO_TABLE)]), (self.INTF_TABLE, parser.OFPMatch(eth_type=eth_type, ip_proto=socket.IPPROTO_UDP, in_port=COPROPORT, vlan_vid=vlan_id), [parser.OFPInstructionGotoTable(self.FROM_COPRO_TABLE)]), # Packets from fake interface go outbound table. (self.INTF_TABLE, parser.OFPMatch(eth_type=eth_type, ip_proto=socket.IPPROTO_TCP, in_port=FAKEPORT, vlan_vid=vlan_id), [parser.OFPInstructionGotoTable(self.TO_COPRO_TABLE)]), (self.INTF_TABLE, parser.OFPMatch(eth_type=eth_type, ip_proto=socket.IPPROTO_UDP, in_port=FAKEPORT, vlan_vid=vlan_id), [parser.OFPInstructionGotoTable(self.TO_COPRO_TABLE)]))
def add_routes(self, datapath, local_port, mac): """ Add the routes to all switches when a new mac is learned """ # Add the route to the switch the device is connected to local_route = parser.OFPFlowMod( datapath=datapath, table_id=0, priority=20, cookie=3, command=ofproto.OFPFC_ADD, match=parser.OFPMatch(eth_dst=mac), instructions=[ parser.OFPInstructionGotoTable(1), parser.OFPInstructionActions( type_=ofproto.OFPIT_WRITE_ACTIONS, actions=[parser.OFPActionOutput(local_port)]) ]) datapath.send_msg(local_route) # Now add routes to all other switches that can get there bfs = self.breadth_first_search(datapath.id) for dpid, port in bfs.iteritems(): dp = self.switches[dpid] foreign_route = parser.OFPFlowMod( datapath=dp, table_id=0, priority=10, cookie=3, command=ofproto.OFPFC_ADD, match=parser.OFPMatch(eth_dst=mac), instructions=[ parser.OFPInstructionGotoTable(1), parser.OFPInstructionActions( type_=ofproto.OFPIT_WRITE_ACTIONS, actions=[parser.OFPActionOutput(port)]) ]) dp.send_msg(foreign_route) # Add the route to table 1 so we don't get messages about # this mac address anymore for dp in self.switches.values(): block_route = parser.OFPFlowMod(datapath=dp, table_id=1, priority=20, cookie=3, command=ofproto.OFPFC_ADD, match=parser.OFPMatch(eth_src=mac), instructions=[]) dp.send_msg(block_route)
def test_flow_stats(self): """Check the update method in the GaugeFlowStatsLogger class""" # add an ofproto attribute to the datapath datapath = create_mock_datapath(0) ofp_attr = {'ofproto': ofproto} datapath.configure_mock(**ofp_attr) # add the datapath as an attribute to the config dp_attr = {'dp': datapath} self.conf.configure_mock(**dp_attr) logger = watcher.GaugeFlowTableLogger(self.conf, '__name__', mock.Mock()) logger._running = True instructions = [parser.OFPInstructionGotoTable(1)] msg = flow_stats_msg(datapath, instructions) rcv_time = time.time() rcv_time_str = logger._rcv_time(rcv_time) logger.update(rcv_time, msg) log_str = self.get_file_contents("{}--flowtable--{}.json".format( datapath.name, rcv_time_str)) yaml_dict = yaml.safe_load( log_str)['OFPFlowStatsReply']['body'][0]['OFPFlowStats'] compare_flow_msg(msg, yaml_dict, self)
def test_flow_stats(self): """Check the update method in the GaugeFlowStatsLogger class""" #add an ofproto attribute to the datapath datapath = create_mock_datapath(0) ofp_attr = {'ofproto': ofproto} datapath.configure_mock(**ofp_attr) #add the datapath as an attribute to the config dp_attr = {'dp' : datapath} self.conf.configure_mock(**dp_attr) logger = watcher.GaugeFlowTableLogger(self.conf, '__name__', mock.Mock()) instructions = [parser.OFPInstructionGotoTable(1)] msg = flow_stats_msg(datapath, instructions) logger.update(time.time(), datapath.dp_id, msg) log_str = self.get_file_contents() #only parse the message part of the log text str_to_find = "msg: " index = log_str.find(str_to_find) #discard the start of the log text log_str = log_str[index + len(str_to_find):] json_dict = json.loads(log_str)['OFPFlowStatsReply']['body'][0]['OFPFlowStats'] compare_flow_msg(msg, json_dict, self)
def ipv4_flows(self, vlan_id, nfvip): return ( # Program OVS to respond to ARP on fake port. (self.TO_COPRO_TABLE, parser.OFPMatch(eth_type=ether.ETH_TYPE_ARP, vlan_vid=vlan_id), self.arp_reply_actions()), (self.INTF_TABLE, parser.OFPMatch( eth_type=ether.ETH_TYPE_ARP, eth_src=self.FAKESERVERMAC, in_port=self.FAKEPORT, arp_op=arp.ARP_REQUEST, vlan_vid=vlan_id), [parser.OFPInstructionGotoTable(self.TO_COPRO_TABLE)])) + self.tcp_udp_flows(vlan_id, nfvip, ether.ETH_TYPE_IP, self.natv4_flows)
def goto_table_id(table_id): """Return instruction to goto table by table ID. Args: table (int): table by ID to goto. Returns: ryu.ofproto.ofproto_v1_3_parser.OFPInstruction: goto instruction. """ return parser.OFPInstructionGotoTable(table_id)
def goto_table(table): """Return instruction to goto table. Args: table (ValveTable): table to goto. Returns: ryu.ofproto.ofproto_v1_3_parser.OFPInstruction: goto instruction. """ return parser.OFPInstructionGotoTable(table.table_id)
def metadata_goto_table(metadata, mask, table): """Return instructions to write metadata and goto table. Args: metadata (int): metadata to write to packet maks (int): mask to apply to metadata table (ValveTable): table to goto. Returns: list of OFPInstructions""" return [ parser.OFPInstructionWriteMetadata(metadata, mask), parser.OFPInstructionGotoTable(table.table_id) ]
def add_tcp_table(self, datapath): ofproto = datapath.ofproto parser = datapath.ofproto_parser inst = [parser.OFPInstructionGotoTable(1)] match = parser.OFPMatch() mod = parser.OFPFlowMod(datapath=datapath, table_id=0, priority=0, match=match, idle_timeout=0, hard_timeout=0, instructions=inst) datapath.send_msg(mod) self.Flowcounter[datapath.id] += 1
def test_flow_stats(self): """Check the update method of the GaugeFlowTableInfluxDBLogger class""" conf = self.create_config_obj(create_mock_datapath(0)) db_logger = gauge_influx.GaugeFlowTableInfluxDBLogger( conf, '__name__', mock.Mock()) db_logger._running = True rcv_time = int(time.time()) instructions = [parser.OFPInstructionGotoTable(1)] msg = flow_stats_msg(conf.dp, instructions) db_logger.update(rcv_time, msg) other_fields = { 'dp_name': conf.dp.name, 'dp_id': hex(conf.dp.dp_id), 'timestamp': rcv_time, 'priority': msg.body[0].priority, 'table_id': msg.body[0].table_id, 'inst_count': len(msg.body[0].instructions), 'vlan': msg.body[0].match.get('vlan_vid') ^ ofproto.OFPVID_PRESENT, 'cookie': msg.body[0].cookie, } with open(self.server.output_file, 'r') as log: output = log.readlines() for line in output: measurement, influx_data = self.parse_influx_output(line) for stat_name, stat_val in influx_data.items(): if stat_name == 'value': if measurement == 'flow_packet_count': self.assertEqual(msg.body[0].packet_count, stat_val) elif measurement == 'flow_byte_count': self.assertEqual(msg.body[0].byte_count, stat_val) else: self.fail("Unknown measurement") elif stat_name in other_fields: self.assertEqual(other_fields[stat_name], stat_val) elif stat_name in msg.body[0].match: self.assertEqual(msg.body[0].match.get(stat_name), stat_val) else: self.fail("Unknown key: {} and value: {}".format( stat_name, stat_val))
def test_flow_stats(self): """Check the update method of the GaugeFlowTableInfluxDBLogger class""" conf = self.create_config_obj(create_mock_datapath(0)) db_logger = gauge_influx.GaugeFlowTableInfluxDBLogger( conf, '__name__', mock.Mock()) rcv_time = int(time.time()) matches = self.generate_all_matches() instructions = [parser.OFPInstructionGotoTable(1)] flow_stats = [ parser.OFPFlowStats(0, 0, 0, 1, 0, 0, 0, 0, 1, 1, matches, instructions) ] message = parser.OFPFlowStatsReply(conf.dp, body=flow_stats) db_logger.update(rcv_time, conf.dp.id, message) other_fields = { 'dp_name': conf.dp.name, 'timestamp': rcv_time, 'priority': flow_stats[0].priority, 'table_id': flow_stats[0].table_id, 'inst_count': len(flow_stats[0].instructions), 'vlan': matches.get('vlan_vid') ^ ofproto.OFPVID_PRESENT } self.server.output_file.seek(0) for line in self.server.output_file.readlines(): measurement, influx_data = self.parse_influx_output(line) for stat_name, stat_val in influx_data.items(): if stat_name == 'value': if measurement == 'flow_packet_count': self.assertEqual(flow_stats[0].packet_count, stat_val) elif measurement == 'flow_byte_count': self.assertEqual(flow_stats[0].byte_count, stat_val) else: self.fail("Unknown measurement") elif stat_name in other_fields: self.assertEqual(other_fields[stat_name], stat_val) elif stat_name in matches: self.assertEqual(matches.get(stat_name), stat_val) else: self.fail("Unknown key: {} and value: {}".format( stat_name, stat_val))
def test_flow_stats(self): """Check the update method of the GaugeFlowTablePrometheusPoller class""" datapath = create_mock_datapath(2) conf = mock.Mock(dp=datapath, type='', interval=1, prometheus_port=9303, prometheus_addr='localhost', use_test_thread=True) prom_poller = gauge_prom.GaugeFlowTablePrometheusPoller( conf, '__name__', self.prom_client) rcv_time = int(time.time()) instructions = [parser.OFPInstructionGotoTable(1)] msg = flow_stats_msg(conf.dp, instructions) prom_poller.update(rcv_time, conf.dp.dp_id, msg)
def test_update(self): """Compares the data writtten to the CouchDB server and the original flow message""" db_logger = gauge_nsodbc.GaugeFlowTableDBLogger(self.conf, '__name__', mock.Mock()) rcv_time = int(time.time()) instructions = [parser.OFPInstructionGotoTable(1)] msg = flow_stats_msg(self.conf.dp, instructions) db_logger.update(rcv_time, self.conf.dp.dp_id, msg) for doc in self.server.docs: if doc.startswith(self.conf.flows_doc) and '_design' not in doc: flow_doc = self.server.docs[doc] elif doc.startswith(self.conf.switches_doc) and '_design' not in doc: switch_doc = self.server.docs[doc] self.assertEqual(switch_doc['data']['flows'][0], flow_doc['_id']) flow_doc = flow_doc['data']['OFPFlowStats'] compare_flow_msg(msg, flow_doc, self)
def _send_flow_mod(self, obj): inst_type = False table_id = 0 flow_mod = obj.get("OFPFlowMod") datapath = self.dpstore.get(flow_mod.get("datapath_id")) datapath = datapath.get("dp_obj") instructions = flow_mod.get("instructions") # FIXME: put this in a instruction parser for instruction in instructions: if "OFPInstructionActions" in instruction: inst_type = "OFPInstructionActions" actions = self._parse_action( instruction.get("OFPInstructionActions").get("actions")) if "OFPInstructionGotoTable" in instruction: inst_type = "OFPInstructionGotoTable" table_id = instruction.get("OFPInstructionGotoTable").get( "table_id") goto = ofproto_v1_3_parser.OFPInstructionGotoTable(table_id) match = flow_mod.get("match") match = self._pars_match(match) if inst_type == "OFPInstructionActions": inst = [ ofproto_v1_3_parser.OFPInstructionActions( ofproto_v1_3.OFPIT_APPLY_ACTIONS, actions) ] if inst_type == "OFPInstructionGotoTable": inst = [goto] if int(flow_mod.get("table_id")) >= 0: table_id = int(flow_mod.get("table_id")) mod = ofproto_v1_3_parser.OFPFlowMod(datapath=datapath, priority=int( flow_mod.get("priority")), match=match, instructions=inst, table_id=table_id) datapath.send_msg(mod)
def test_flow_stats(self): """Check the update method in the GaugeFlowStatsLogger class""" #add an ofproto attribute to the datapath datapath = create_mock_datapath(0) ofp_attr = {'ofproto': ofproto} datapath.configure_mock(**ofp_attr) #add the datapath as an attribute to the config dp_attr = {'dp' : datapath} self.conf.configure_mock(**dp_attr) logger = watcher.GaugeFlowTableLogger(self.conf, '__name__', mock.Mock()) instructions = [parser.OFPInstructionGotoTable(1)] msg = flow_stats_msg(datapath, instructions) logger.update(time.time(), datapath.dp_id, msg) log_str = self.get_file_contents() yaml_dict = yaml.load(log_str)['msg']['OFPFlowStatsReply']['body'][0]['OFPFlowStats'] compare_flow_msg(msg, yaml_dict, self)
def instructions_to_ryu(instructions, rule): """ Converts Instructions to a list of ryu instructions 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. instructions: A Instructions object rule: A Rule return: A tuple ([instructions], [extra messages]) """ ret = [] extra_messages = [] if instructions.goto_table is not None: ret.append(parser.OFPInstructionGotoTable(instructions.goto_table)) if instructions.write_metadata is not None: assert not "TODO" if (instructions.write_actions is not None and not instructions.write_actions.empty()): actions, extra = actions_to_ryu(instructions.write_actions, rule) ret.append( parser.OFPInstructionActions(ofproto_v1_3.OFPIT_WRITE_ACTIONS, actions)) extra_messages += extra if (instructions.apply_actions is not None and not instructions.apply_actions.empty()): actions, extra = actions_to_ryu(instructions.apply_actions, rule) ret.append( parser.OFPInstructionActions(ofproto_v1_3.OFPIT_APPLY_ACTIONS, actions)) extra_messages += extra if instructions.clear_actions is True: ret.append( parser.OFPInstructionActions(ofproto_v1_3.OFPIT_CLEAR_ACTIONS)) if instructions.meter is not None: assert not "TODO" return (ret, extra_messages)
def install_transport_bad(self, datapath): """ Set table 0 as stateful solo per usare GD, fa le somme del percorso """ req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=0, stateful=1) datapath.send_msg(req) """ Ci sta una table NULLA per i bug di OpenFLow con le Label MPLS """ """ Set table 2 as stateful, verifica le condizioni sul percorso <=""" req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=2, 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) ############################### LOOKUP/UPDATE ################ """ Tab0 """ """ Non mi interessa """ req = osparser.OFPExpMsgKeyExtract( datapath=datapath, command=osproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=0) 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=0) datapath.send_msg(req) """ Tab2 """ """ 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=2) 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=2) datapath.send_msg(req) """ Tab3 """ """ 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=3) 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=3) datapath.send_msg(req) ########################### SET HF GD DATA VARIABLE TAB 0 ############################################ ''' HF[1] = OXM_OF_MPLS_TC [pesoArchi] ''' req = osparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=0, extractor_id=1, field=ofproto.OXM_OF_MPLS_TC) datapath.send_msg(req) ''' GD[0] = 0 ''' req = osparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=0, global_data_variable_id=0, value=0) datapath.send_msg(req) ########################### SET HF GD DATA VARIABLE TAB 2 ############################################ ''' HF[1] = OXM_OF_MPLS_TC [pesoArchi] ''' req = osparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=2, extractor_id=1, field=ofproto.OXM_OF_MPLS_TC) datapath.send_msg(req) ########################### SET CONDITION TAB 2 ############################################ # condition 3: MPLS_TC <= COSTO MEMORIZZATO (FD[0]) ? # condition 3: HF[1] <= FD[0] ? req = osparser.OFPExpMsgSetCondition(datapath=datapath, table_id=2, condition_id=0, condition=osproto.CONDITION_LTE, operand_1_hf_id=1, operand_2_fd_id=0) datapath.send_msg(req) '''####################### TAB 0 ''' ''' somma il costo del link di ingresso al valore memorizzato nel pacchetto mpls_tc + 1 ''' """ Riga 1 """ # GD[0] = HF[1] + 1 -> MPLS_TC + 1 # HF [1] = GD[0] -> MPLS_TC = GD[0] # GOTO Tab 2 match = ofparser.OFPMatch(eth_type=0x8847) actions = [ osparser.OFPExpActionSetDataVariable(table_id=0, opcode=osproto.OPCODE_SUM, output_gd_id=0, operand_1_hf_id=1, operand_2_cost=2), osparser.OFPExpActionWriteContextToField( src_type=osproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_MPLS_TC) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(1) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=1198, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 1 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(2) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=1, priority=0, match=match, instructions=inst) datapath.send_msg(mod) '''# ####################### TAB 2 ''' ''' C[0] verifica se il costo memorizzato nel pacchetto e' <= di quello gia conosciuto (in pratica se il pacchetto ha fatto un percorso migliore) ''' """ 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) actions = [osparser.OFPExpActionSetState(state=1, table_id=2)] self.add_flow(datapath=datapath, table_id=2, priority=198, match=match, actions=actions) """ Riga 2 """ # 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) actions = [ osparser.OFPExpActionSetState(state=1, table_id=2), osparser.OFPExpActionSetDataVariable(table_id=2, 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(3) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=2, priority=98, match=match, instructions=inst) datapath.send_msg(mod) """ Riga 3 """ # FD[0] = HF[1] -> COSTO MEMORIZZATO = MPLS_TC # SetState(1) # azione GOTO Tab 3 match = ofparser.OFPMatch(state=0, eth_type=0x8847) actions = [ osparser.OFPExpActionSetState(state=1, table_id=2), osparser.OFPExpActionSetDataVariable(table_id=2, 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(3) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=2, priority=8, match=match, instructions=inst) datapath.send_msg(mod) '''# ####################### TAB 3 semplicemente MAC Learning ''' # 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=3, hard_timeout=10), actions = [ osparser.OFPExpActionSetState(state=i, table_id=3), ofparser.OFPActionOutput(out_port) ] self.add_flow(datapath=datapath, table_id=3, priority=0, match=match, actions=actions)
def switch_features_handler(self, event): """ Switche sent his features, check if OpenState supported """ msg = event.msg datapath = msg.datapath LOG.info("Configuring switch %d..." % datapath.id) """ Set table 0 as stateful """ req = bebaparser.OFPExpMsgConfigureStatefulTable( datapath=datapath, table_id=0, stateful=1) datapath.send_msg(req) """ Set table 1 as stateful """ req = bebaparser.OFPExpMsgConfigureStatefulTable( datapath=datapath, table_id=1, stateful=1) datapath.send_msg(req) ############################### LOOKUP/UPDATE ################ """ Set lookup extractor = {eth_dst} """ req = bebaparser.OFPExpMsgKeyExtract(datapath=datapath, command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_IPV4_SRC, ofproto.OXM_OF_IPV4_DST], table_id=0, biflow=1) datapath.send_msg(req) """ Set update extractor = {eth_src} """ req = bebaparser.OFPExpMsgKeyExtract(datapath=datapath, command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_IPV4_SRC, ofproto.OXM_OF_IPV4_DST], table_id=0, biflow=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_ETH_SRC], table_id=1) datapath.send_msg(req) """ Set update extractor = {eth_src} """ req = bebaparser.OFPExpMsgKeyExtract(datapath=datapath, command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_ETH_SRC], table_id=1) datapath.send_msg(req) ########################### SET GD DATA VARIABLE ############################################ # req = bebaparser.OFPExpMsgHeaderFieldExtract( # datapath=datapath, # table_id=0, # extractor_id=0, # field=ofproto.OXM_OF_IPV4_SRC # ) # datapath.send_msg(req) req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=0, global_data_variable_id=0, value=313 ) datapath.send_msg(req) req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=0, global_data_variable_id=2, value=22 ) datapath.send_msg(req) req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=0, global_data_variable_id=4, value=44 ) datapath.send_msg(req) req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=0, global_data_variable_id=5, value=55 ) datapath.send_msg(req) ########################### SET GD DATA VARIABLE ############################################ req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=1, global_data_variable_id=3, value=55 ) datapath.send_msg(req) ########################### SET HF DATA VARIABLE TAB 1 ############################################ # SI PUO FARE??? ''' HF[0] = OXM_OF_METADATA [id_pkt] ''' req = bebaparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=1, extractor_id=0, field=ofproto.OXM_OF_ETH_SRC ) datapath.send_msg(req) # ''' HF[0] = OXM_OF_METADATA [id_pkt] ''' # req = bebaparser.OFPExpMsgHeaderFieldExtract( # datapath=datapath, # table_id=1, # extractor_id=0, # field=bebaproto.OXM_EXP_STATE # ) # datapath.send_msg(req) # aggiunta cosi tanto per fare un nuovo commit # ''' HF[0] = OXM_OF_METADATA [id_pkt] ''' # req = bebaparser.OFPExpMsgHeaderFieldExtract( # datapath=datapath, # table_id=1, # extractor_id=0, # field=bebaproto.OXM_EXP_STATE # ) # datapath.send_msg(req) ''' ####################### TAB 0 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(condition0=0) # actions = [bebaparser.OFPExpActionSetState(state=1, table_id=0), # ofparser.OFPActionOutput(ofproto.OFPP_FLOOD)] # inst = [ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,actions)] # mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, # priority=0, match=match, instructions=inst) # datapath.send_msg(mod) # match = ofparser.OFPMatch()#condition0=1) # actions = [bebaparser.OFPExpActionSetState(state=1, table_id=0), # bebaparser.OFPExpActionSetDataVariable(table_id=0, port_id=1, opcode=bebaproto.OPCODE_SUM, output_mem_pd_id=0, operand_1_mem_pd_id=1, operand_2_mem_pd_id=1), # # bebaparser.OFPExpActionWriteContextToField(src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR,src_id=0,dst_field=ofproto.OXM_OF_MPLS_LABEL), # bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_gd_id=3, operand_1_hf_id=0, operand_2_cost=0), # ofparser.OFPActionOutput(ofproto.OFPP_FLOOD)] # inst = [ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,actions)] # mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, # priority=0, match=match, instructions=inst) # datapath.send_msg(mod) # match = ofparser.OFPMatch(eth_type=0x0800 ,ipv4_src=('10.0.0.0','255.255.255.0')) match = ofparser.OFPMatch() actions = [bebaparser.OFPExpActionSetState(state=1, table_id=0), # bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_fd_id=1, operand_1_hf_id=0, operand_2_cost=3)] # bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_fd_id=2, operand_1_gd_id=0, operand_2_gd_id=2)] bebaparser.OFPExpActionWriteContextToField(src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR,src_id=0,dst_field=ofproto.OXM_OF_METADATA)] inst = [ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), # ofparser.OFPInstructionWriteMetadata(metadata=13, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(1)] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=0, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 1 ''' match = ofparser.OFPMatch()#state=2) actions = [bebaparser.OFPExpActionSetState(state=2, table_id=1), bebaparser.OFPExpActionSetDataVariable(table_id=1, opcode=bebaproto.OPCODE_SUM, output_fd_id=1, operand_1_hf_id=0, operand_2_cost=1), ofparser.OFPActionOutput(ofproto.OFPP_FLOOD)] # bebaparser.OFPExpActionSetDataVariable(table_id=1, opcode=bebaproto.OPCODE_SUM, output_gd_id=0, operand_1_gd_id=1, operand_2_cost=3)] inst = [ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,actions)] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=1, priority=10, match=match, instructions=inst) datapath.send_msg(mod) # match = ofparser.OFPMatch(metadata=313) # actions = [bebaparser.OFPExpActionSetState(state=2, table_id=1), # bebaparser.OFPExpActionSetDataVariable(table_id=1, opcode=bebaproto.OPCODE_SUM, output_gd_id=0, operand_1_gd_id=3, operand_2_cost=3)] # inst = [ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,actions)] # mod = ofparser.OFPFlowMod(datapath=datapath, table_id=1, # priority=0, match=match, instructions=inst) # datapath.send_msg(mod) # # 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 = [bebaparser.OFPExpActionSetState(state=i, table_id=0, hard_timeout=10), # ofparser.OFPActionOutput(out_port)] # self.add_flow(datapath=datapath, table_id=0, priority=0, # match=match, actions=actions) """ Need to drop some packets for DEMO puporses only (avoid learning before manual send_eth)"""
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)
""" Make rules that form a diamond of dependencies """ flows = [ # Table 0 parser.OFPFlowStats( table_id=0, priority=10, match=parser.OFPMatch(vlan_vid=(0x1000, 0x1FFE)), instructions=[ parser.OFPInstructionGotoTable(1) ] ), parser.OFPFlowStats( table_id=0, priority=10, match=parser.OFPMatch(vlan_vid=(0x1002, 0x1FFE)), instructions=[ parser.OFPInstructionGotoTable(1) ] ), parser.OFPFlowStats( table_id=0, priority=0, match=parser.OFPMatch(), instructions=[]
""" flows = [ # Table 0 parser.OFPFlowStats(table_id=0, priority=1000, match=parser.OFPMatch(tcp_dst=80), instructions=[]), parser.OFPFlowStats(table_id=0, priority=1000, match=parser.OFPMatch(tcp_dst=443), instructions=[]), parser.OFPFlowStats(table_id=0, priority=0, match=parser.OFPMatch(), instructions=[parser.OFPInstructionGotoTable(1)]), # Table 1 parser.OFPFlowStats(table_id=1, priority=1000, match=parser.OFPMatch(eth_dst=1), instructions=[parser.OFPInstructionGotoTable(2)]), parser.OFPFlowStats(table_id=1, priority=1000, match=parser.OFPMatch(eth_dst=2), instructions=[parser.OFPInstructionGotoTable(2)]), parser.OFPFlowStats(table_id=1, priority=0, match=parser.OFPMatch(), instructions=[parser.OFPInstructionGotoTable(3)]),
def load_fsm(self, datapath): LOG.info("Loading Table 1 FSM ...") ##=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=# ## INIT - ANY """ Match firstly incoming packets. The actual version is little bit hacked, all incomming flows are forwarded to the table 2 which is performed counting of all incomming data. (TODO - remove eth_type and ip_proto?) """ match = ofparser.OFPMatch(eth_type=0x0800, ip_proto=6, state=self.INIT) actions = [ osparser.OFPExpActionSetState( state=self.ACTIVE, table_id=1, # TODO - TIMEOUTS idle_timeout=1) ] #inst = [ofparser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions)] inst = [ ofparser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(table_id=2) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=1, priority=1, match=match, instructions=inst) datapath.send_msg(mod) ##=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=# ## ACTIVE - ANY """ Match other incoming packets. Need this state since we do not want to refresh timeouts of flow entry. (TODO - remove eth_type and ip_proto?) """ match = ofparser.OFPMatch(eth_type=0x0800, ip_proto=6, state=self.ACTIVE) """ TODO - simplify ... remove useless stuff """ actions = [] #inst = [ofparser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions)] inst = [ ofparser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(table_id=2) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=1, priority=1, match=match, instructions=inst) datapath.send_msg(mod) LOG.info("Done.")
def function_dynamic_nat(self, datapath): """ Set table 1 as stateful """ req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=1, stateful=1) datapath.send_msg(req) """ Set table 2 restore """ req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=2, stateful=1) datapath.send_msg(req) ############################### LOOKUP/UPDATE ################################### """ Tab1 """ """ Set lookup extractor = {OXM_OF_METADATA} """ req = bebaparser.OFPExpMsgKeyExtract( datapath=datapath, command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_METADATA], table_id=1) datapath.send_msg(req) """ Set update extractor = {OXM_OF_METADATA} """ req = bebaparser.OFPExpMsgKeyExtract( datapath=datapath, command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_METADATA], table_id=1) datapath.send_msg(req) """ Tab2 """ """ Set lookup extractor = {OXM_OF_IPV4_SRC, OXM_OF_IP_PROTO, OXM_OF_TCP_SRC} """ req = bebaparser.OFPExpMsgKeyExtract( datapath=datapath, command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ ofproto.OXM_OF_IPV4_SRC, ofproto.OXM_OF_IP_PROTO, ofproto.OXM_OF_TCP_SRC ], table_id=2) datapath.send_msg(req) """ Set lookup extractor = {OXM_OF_IPV4_DST, OXM_OF_IP_PROTO, OXM_OF_TCP_DST} """ req = bebaparser.OFPExpMsgKeyExtract( datapath=datapath, command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ ofproto.OXM_OF_IPV4_DST, ofproto.OXM_OF_IP_PROTO, ofproto.OXM_OF_TCP_DST ], table_id=2) datapath.send_msg(req) """ Tab3 """ ########################### SET STATE TABLE 1 ############################################ for stateVal in range(1, 21): state = bebaparser.OFPExpMsgSetFlowState( datapath=datapath, state=2000 + stateVal, keys=[stateVal, 0, 0, 0, 0, 0, 0, 0], table_id=1) datapath.send_msg(state) ########################### SET HF DATA VARIABLE TAB 1 ############################################ ''' GD[0] = state_label''' req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=1, global_data_variable_id=0, value=0) datapath.send_msg(req) ''' HF[0] = OXM_EXP_STATE [state_label] ''' req = bebaparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=1, extractor_id=0, field=bebaproto.OXM_EXP_STATE) datapath.send_msg(req) ########################### SET HF DATA VARIABLE TAB 2 ############################################ ''' HF[0] = OXM_OF_IPV4_SRC [id_pkt] ''' req = bebaparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=2, extractor_id=0, field=ofproto.OXM_OF_IPV4_SRC) datapath.send_msg(req) ''' HF[1] = OXM_OF_TCP_SRC [id_pkt] ''' req = bebaparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=2, extractor_id=1, field=ofproto.OXM_OF_TCP_SRC) datapath.send_msg(req) ########################### SET HF DATA VARIABLE TAB 3 ############################################ ''' HF[0] = OXM_OF_METADATA [metadata] ''' req = bebaparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=3, extractor_id=0, field=ofproto.OXM_OF_METADATA) datapath.send_msg(req) ################################# REGOLE ############################################ ''' ####################### TAB 0 ''' match = ofparser.OFPMatch(state=0, in_port=LAN_PORT) actions = [ bebaparser.OFPExpActionSetState(state=1, table_id=0), bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_gd_id=1, operand_1_gd_id=1, operand_2_cost=1), bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=1, dst_field=ofproto.OXM_OF_METADATA) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(1) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=89, match=match, instructions=inst) datapath.send_msg(mod) # Line 12 match = ofparser.OFPMatch(state=1, in_port=LAN_PORT) actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(3) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=88, match=match, instructions=inst) datapath.send_msg(mod) # Line 13 match = ofparser.OFPMatch(state=0, in_port=INTERNET_PORT, eth_type=0x0800, ipv4_dst='1.0.0.1') actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(2) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=87, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 1 ''' # Line 0 # HF[0] = state_label # GD[0] = state_label + 0 => GD[0] + HF[0] # state_label -> metadata => GD[0] = HF[0] match = ofparser.OFPMatch(in_port=3) actions = [ bebaparser.OFPExpActionSetDataVariable(table_id=1, opcode=bebaproto.OPCODE_SUM, output_gd_id=0, operand_1_hf_id=0, operand_2_cost=0), bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_METADATA) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(2) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=1, priority=100, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 2 restore''' # Line 0 # ip.src -> R0 => HF[0] -> FD[0] => FD[0] = HF[0] + 0 # tcp.src -> R1 => HF[1] -> FD[1] => FD[1] = HF[1] + 0 match = ofparser.OFPMatch(state=0, in_port=LAN_PORT) actions = [ bebaparser.OFPExpActionSetState(state=1, table_id=2), bebaparser.OFPExpActionSetDataVariable(table_id=2, opcode=bebaproto.OPCODE_SUM, output_fd_id=0, operand_1_hf_id=0, operand_2_cost=0), bebaparser.OFPExpActionSetDataVariable(table_id=2, opcode=bebaproto.OPCODE_SUM, output_fd_id=1, operand_1_hf_id=1, operand_2_cost=0) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(3) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=2, priority=100, match=match, instructions=inst) datapath.send_msg(mod) # Line 1 # ip.dst = R0 => IPV4_DST = FD[0] # tcp.dst = R1 => TCP_DST = FD[1] match = ofparser.OFPMatch(state=1, in_port=INTERNET_PORT) actions = [ bebaparser.OFPExpActionSetState(state=1, table_id=2), bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_FLOW_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_IPV4_DST), bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_FLOW_DATA_VAR, src_id=1, dst_field=ofproto.OXM_OF_TCP_DST) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=2, priority=99, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 3 translate ''' # Line 3 # metadata(b16,b31) -> R1 => metadata(b16,b31) -> FD[1] => FD[1] = HF[0] # ip.src = 10.0.0.1 # tcp.src = R1 => TCP_SRC = FD[1] match = ofparser.OFPMatch(state=0, in_port=LAN_PORT, eth_type=0x0800) actions = [ bebaparser.OFPExpActionSetState(state=1, table_id=3), bebaparser.OFPExpActionSetDataVariable(table_id=3, opcode=bebaproto.OPCODE_SUM, output_fd_id=1, operand_1_hf_id=0, operand_2_cost=0), ofparser.OFPActionSetField(ipv4_src="1.0.0.1"), bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_FLOW_DATA_VAR, src_id=1, dst_field=ofproto.OXM_OF_TCP_SRC) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=3, priority=97, match=match, instructions=inst) datapath.send_msg(mod) # Line 4 # ip.src = 10.0.0.1 # tcp.src = R1 => TCP_SRC = FD[1] match = ofparser.OFPMatch(state=1, in_port=LAN_PORT, eth_type=0x0800) actions = [ bebaparser.OFPExpActionSetState(state=1, table_id=3), ofparser.OFPActionSetField(ipv4_src='1.0.0.1'), bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_FLOW_DATA_VAR, src_id=1, dst_field=ofproto.OXM_OF_TCP_SRC) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=3, priority=96, match=match, instructions=inst) datapath.send_msg(mod)
def function_load_balancer(self, datapath): """ Tab0 """ """ Set lookup extractor = {BiFlow} """ # GIA CONFIGURATA """ Set table 3 translate """ req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=3, stateful=1) datapath.send_msg(req) ############################### LOOKUP/UPDATE ################################### """ Tab3 """ """ Set lookup extractor = {OXM_OF_IPV4_SRC, OXM_OF_TCP_SRC} """ req = bebaparser.OFPExpMsgKeyExtract( datapath=datapath, command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_IPV4_SRC, ofproto.OXM_OF_TCP_SRC], table_id=3) datapath.send_msg(req) """ Set update extractor = {OXM_OF_IPV4_SRC, OXM_OF_TCP_SRC} """ req = bebaparser.OFPExpMsgKeyExtract( datapath=datapath, command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_IPV4_SRC, ofproto.OXM_OF_TCP_SRC], table_id=3) datapath.send_msg(req) ########################### SET GD E HF DATA VARIABLE TAB 3 ############################################ ''' GD[0] = 0''' req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=3, global_data_variable_id=0, value=0) datapath.send_msg(req) ''' GD[1] = LAN_DUE 10.0.0.2 hexadecimal''' req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=3, global_data_variable_id=1, value=0x0200000a) datapath.send_msg(req) ''' GD[2] = LAN_TRE 10.0.0.3 hexadecimal''' req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=3, global_data_variable_id=2, value=0x0300000a) datapath.send_msg(req) ''' GD[3] = PORT 80 ''' req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=3, global_data_variable_id=3, value=0x5000) datapath.send_msg(req) ################################# RULES ############################################ ''' ####################### TAB 0 ''' # Line 7 match = ofparser.OFPMatch(state=0, in_port=INTERNET_PORT, eth_type=0x0800, ipv4_dst='1.0.0.1', ip_proto=6, tcp_dst=80) actions = [ bebaparser.OFPExpActionSetState(state=1, table_id=0), bebaparser.OFPExpActionSetDataVariable(table_id=0, opcode=bebaproto.OPCODE_SUM, output_gd_id=0, operand_1_gd_id=0, operand_2_cost=1), bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_METADATA) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(3) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=93, match=match, instructions=inst) datapath.send_msg(mod) # Line 8 match = ofparser.OFPMatch(state=1, in_port=INTERNET_PORT, eth_type=0x0800, ipv4_dst='1.0.0.1', ip_proto=6, tcp_dst=80) actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(3) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=92, match=match, instructions=inst) datapath.send_msg(mod) # Line 9 match = ofparser.OFPMatch(state=0, in_port=LAN_PORT, eth_type=0x0800, ipv4_src='10.0.0.2', ip_proto=6, tcp_src=80) actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=91, match=match, instructions=inst) datapath.send_msg(mod) # Line 10 match = ofparser.OFPMatch(state=0, in_port=LAN_PORT, eth_type=0x0800, ipv4_src='10.0.0.3', ip_proto=6, tcp_src=80) actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=90, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 3 translate ''' # Line 0 # ip.dst = 10.0.0.2 # tcp.dst = 80 # 10.0.0.2 -> R0 => 10.0.0.2 -> FD[0] => FD[0] = GD[0] + 10.0.0.2 => 0 + 10.0.0.2 # 80 -> R1 => 80 -> FD[1] => GD[0] + 80 => 0 + 80 match = ofparser.OFPMatch(state=0, in_port=INTERNET_PORT, metadata=(0, 0x000000001), eth_type=0x0800, ip_proto=6) actions = [ bebaparser.OFPExpActionSetState(state=1, table_id=3), ofparser.OFPActionSetField(ipv4_dst='10.0.0.2'), ofparser.OFPActionSetField(tcp_dst=80), # tolto per test bebaparser.OFPExpActionSetDataVariable(table_id=3, opcode=bebaproto.OPCODE_SUM, output_fd_id=0, operand_1_gd_id=1, operand_2_cost=0), bebaparser.OFPExpActionSetDataVariable(table_id=3, opcode=bebaproto.OPCODE_SUM, output_fd_id=1, operand_1_gd_id=0, operand_2_cost=80) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=3, priority=100, match=match, instructions=inst) datapath.send_msg(mod) # Line 1 # ip.dst = 10.0.0.3 # tcp.dst = 80 # 10.0.0.3 -> R0 => 10.0.0.3 -> FD[0] => FD[0] = GD[0] + 10.0.0.3 => 0 + 10.0.0.3 # 80 -> R1 => 80 -> FD[1] => GD[0] + 80 => 0 + 80 match = ofparser.OFPMatch(state=0, in_port=INTERNET_PORT, metadata=(1, 0x000000001), eth_type=0x0800, ip_proto=6) actions = [ bebaparser.OFPExpActionSetState(state=1, table_id=3), ofparser.OFPActionSetField(ipv4_dst='10.0.0.3'), ofparser.OFPActionSetField(tcp_dst=80), # tolto per test bebaparser.OFPExpActionSetDataVariable(table_id=3, opcode=bebaproto.OPCODE_SUM, output_fd_id=0, operand_1_gd_id=2, operand_2_cost=0), bebaparser.OFPExpActionSetDataVariable(table_id=3, opcode=bebaproto.OPCODE_SUM, output_fd_id=1, operand_1_gd_id=0, operand_2_cost=80) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=3, priority=99, match=match, instructions=inst) datapath.send_msg(mod) # Line 2 # ip.dst = R0 => IPV4_DST = FD[0] # tcp.dst = R1 => TCP_DST = FD[1] match = ofparser.OFPMatch(state=1, in_port=INTERNET_PORT) actions = [ bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_FLOW_DATA_VAR, src_id=0, dst_field=ofproto.OXM_OF_IPV4_DST), bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_FLOW_DATA_VAR, src_id=1, dst_field=ofproto.OXM_OF_TCP_DST) ] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=3, priority=98, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 4 forward ''' # Line 4 match = ofparser.OFPMatch(in_port=LAN_PORT, eth_type=0x0800, ipv4_src='10.0.0.2', ip_proto=6, tcp_src=80) actions = [ ofparser.OFPActionSetField(ipv4_src='1.0.0.1'), ofparser.OFPActionSetField(tcp_src=80), ofparser.OFPActionSetField(eth_dst="00:00:00:00:00:01"), ofparser.OFPActionOutput(INTERNET_PORT) ] self.add_flow(datapath=datapath, table_id=4, priority=96, match=match, actions=actions) # Line 5 match = ofparser.OFPMatch(in_port=LAN_PORT, eth_type=0x0800, ipv4_src='10.0.0.3', ip_proto=6, tcp_src=80) actions = [ ofparser.OFPActionSetField(ipv4_src='1.0.0.1'), ofparser.OFPActionSetField(tcp_src=80), ofparser.OFPActionSetField(eth_dst="00:00:00:00:00:01"), ofparser.OFPActionOutput(INTERNET_PORT) ] self.add_flow(datapath=datapath, table_id=4, priority=95, match=match, actions=actions) # Line 6 match = ofparser.OFPMatch() actions = [ ofparser.OFPActionSetField(eth_dst="00:00:00:00:00:01"), ofparser.OFPActionOutput(INTERNET_PORT) ] self.add_flow(datapath=datapath, table_id=4, priority=94, match=match, actions=actions)
def function_lan_dmz_isolation(self, datapath): """ Set table 0 as stateful """ req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=0, stateful=1) datapath.send_msg(req) ############################### LOOKUP/UPDATE ################################### """ Tab0 """ """ Set lookup extractor = {BiFlow} """ 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=0, biflow=1) datapath.send_msg(req) """ Set lookup extractor = {BiFlow} """ 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=0, biflow=1) datapath.send_msg(req) """ Tab4 """ """ Stateless """ ########################### SET GD DATA VARIABLE TAB 0 ############################################ ''' GD[0] = 0''' req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=0, global_data_variable_id=0, value=0) datapath.send_msg(req) ''' GD[1] = 0 ''' req = bebaparser.OFPExpMsgsSetGlobalDataVariable( datapath=datapath, table_id=0, global_data_variable_id=0, value=0) datapath.send_msg(req) ################################# REGOLE ############################################ match = ofparser.OFPMatch(eth_type=0x0806) actions = [ofparser.OFPActionOutput(ofproto.OFPP_FLOOD)] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=100, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 0 ''' # Line 0 match = ofparser.OFPMatch(state=0, in_port=DMZ_PORT, eth_type=0x0800, ipv4_dst=('10.0.0.0', '255.255.255.0')) actions = [bebaparser.OFPExpActionSetState(state=11, table_id=0)] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionWriteMetadata(metadata=0, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=100, match=match, instructions=inst) datapath.send_msg(mod) # Line 1 match = ofparser.OFPMatch(state=0, in_port=LAN_PORT, eth_type=0x0800, ipv4_dst=('8.0.0.0', '255.255.255.0')) actions = [bebaparser.OFPExpActionSetState(state=12, table_id=0)] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionWriteMetadata(metadata=0, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=99, match=match, instructions=inst) datapath.send_msg(mod) # Line 2 match = ofparser.OFPMatch(state=11, in_port=DMZ_PORT, eth_type=0x0800, ipv4_dst=('10.0.0.0', '255.255.255.0')) actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionWriteMetadata(metadata=0, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=98, match=match, instructions=inst) datapath.send_msg(mod) # Line 3 match = ofparser.OFPMatch(state=11, in_port=LAN_PORT, eth_type=0x0800, ipv4_dst=('8.0.0.0', '255.255.255.0')) actions = [bebaparser.OFPExpActionSetState(state=2, table_id=0)] 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=0, priority=97, match=match, instructions=inst) datapath.send_msg(mod) # Line 4 match = ofparser.OFPMatch(state=12, in_port=LAN_PORT, eth_type=0x0800, ipv4_dst=('8.0.0.0', '255.255.255.0')) actions = [] inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionWriteMetadata(metadata=0, metadata_mask=0xFFFFFFFF), ofparser.OFPInstructionGotoTable(4) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=96, match=match, instructions=inst) datapath.send_msg(mod) # Line 5 match = ofparser.OFPMatch(state=12, in_port=DMZ_PORT, eth_type=0x0800, ipv4_dst=('10.0.0.0', '255.255.255.0')) actions = [bebaparser.OFPExpActionSetState(state=2, table_id=0)] 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=0, priority=95, match=match, instructions=inst) datapath.send_msg(mod) # Line 6 match = ofparser.OFPMatch(state=2) actions = [] 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=0, priority=94, match=match, instructions=inst) datapath.send_msg(mod) ''' ####################### TAB 1 ''' # NOT USED IN THIS USE CASE ''' ####################### TAB 2 restore''' # NOT USED IN THIS USE CASE ''' ####################### TAB 3 translate ''' # NOT USED IN THIS USE CASE ''' ####################### TAB 4 forward ''' # Line 0 match = ofparser.OFPMatch(in_port=DMZ_PORT, metadata=(0, 0x00000000F), eth_type=0x0800, ipv4_dst=('10.0.0.0', '255.255.255.0')) actions = [] self.add_flow(datapath=datapath, table_id=4, priority=100, match=match, actions=actions) # Line 1 match = ofparser.OFPMatch(in_port=DMZ_PORT, metadata=(1, 0x00000000F), eth_type=0x0800, ipv4_dst='10.0.0.2') actions = [ ofparser.OFPActionSetField(eth_dst="00:00:00:00:00:03"), ofparser.OFPActionOutput(LAN_PORT) ] self.add_flow(datapath=datapath, table_id=4, priority=99, match=match, actions=actions) # Line 1 BIS match = ofparser.OFPMatch(in_port=DMZ_PORT, metadata=(1, 0x00000000F), eth_type=0x0800, ipv4_dst='10.0.0.3') actions = [ ofparser.OFPActionSetField(eth_dst="00:00:00:00:00:04"), ofparser.OFPActionOutput(LAN_PORT) ] self.add_flow(datapath=datapath, table_id=4, priority=99, match=match, actions=actions) # Line 2 match = ofparser.OFPMatch(eth_type=0x0800, ipv4_dst='8.0.0.2') actions = [ ofparser.OFPActionSetField(eth_dst="00:00:00:00:00:02"), ofparser.OFPActionOutput(DMZ_PORT) ] self.add_flow(datapath=datapath, table_id=4, priority=98, match=match, actions=actions) # Line 3 match = ofparser.OFPMatch(eth_type=0x0800, ipv4_dst='10.0.0.2') actions = [ ofparser.OFPActionSetField(eth_dst="00:00:00:00:00:03"), ofparser.OFPActionOutput(LAN_PORT) ] self.add_flow(datapath=datapath, table_id=4, priority=97, match=match, actions=actions) # Line 3 BIS match = ofparser.OFPMatch(eth_type=0x0800, ipv4_dst='10.0.0.3') actions = [ ofparser.OFPActionSetField(eth_dst="00:00:00:00:00:04"), ofparser.OFPActionOutput(LAN_PORT) ] self.add_flow(datapath=datapath, table_id=4, priority=97, match=match, actions=actions)
def install_spines(self, datapath): ######################### TABLE 1 CONFIG ############### req = bebaparser.OFPExpMsgConfigureStatefulTable(datapath=datapath, table_id=0, stateful=1) datapath.send_msg(req) """ Set lookup extractor = {eth_dst} """ req = bebaparser.OFPExpMsgKeyExtract( datapath=datapath, command=bebaproto.OFPSC_EXP_SET_L_EXTRACTOR, fields=[ofproto.OXM_OF_IN_PORT], table_id=0) datapath.send_msg(req) """ Set update extractor = {eth_dst} """ req = bebaparser.OFPExpMsgKeyExtract( datapath=datapath, command=bebaproto.OFPSC_EXP_SET_U_EXTRACTOR, fields=[ofproto.OXM_OF_IN_PORT], table_id=0) datapath.send_msg(req) # mpls extractor req = bebaparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=0, extractor_id=0, field=ofproto.OXM_OF_MPLS_LABEL) datapath.send_msg(req) # timestamp extractor req = bebaparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=0, extractor_id=1, field=bebaproto.OXM_EXP_TIMESTAMP) datapath.send_msg(req) # packet length extractor req = bebaparser.OFPExpMsgHeaderFieldExtract( datapath=datapath, table_id=0, extractor_id=2, field=bebaproto.OXM_EXP_PKT_LEN) datapath.send_msg(req) req = bebaparser.OFPExpMsgSetCondition( datapath=datapath, condition=bebaproto.CONDITION_GTE, condition_id=0, table_id=0, operand_1_hf_id=1, operand_2_fd_id=4) datapath.send_msg(req) ########################### TABLE 1: MEASURING ##################### for i in LEAVES: if i == 1: out_ports = [2, 3] elif i == 2: out_ports = [1, 3] elif i == 3: out_ports = [1, 2] buckets = [] actions = [ bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=4, dst_field=ofproto.OXM_OF_MPLS_LABEL), ofparser.OFPActionOutput(out_ports[0]) ] buckets.append(ofparser.OFPBucket(actions=actions)) actions = [ bebaparser.OFPExpActionWriteContextToField( src_type=bebaproto.SOURCE_TYPE_GLOBAL_DATA_VAR, src_id=5, dst_field=ofproto.OXM_OF_MPLS_LABEL), ofparser.OFPActionOutput(out_ports[1]) ] buckets.append(ofparser.OFPBucket(actions=actions)) # send the group action req = ofparser.OFPGroupMod(datapath=datapath, type_=ofproto.OFPGT_ALL, group_id=i, buckets=buckets) datapath.send_msg(req) match = ofparser.OFPMatch(in_port=i, eth_type=0x8847) actions = [ bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_SUM, output_gd_id=4, operand_1_hf_id=0, operand_2_gd_id=out_ports[0]), bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_SUM, output_gd_id=5, operand_1_hf_id=0, operand_2_gd_id=out_ports[1]), ofparser.OFPActionGroup(i) ] self.add_flow(datapath=datapath, priority=600, table_id=0, match=match, actions=actions) # first packet of a flow match = ofparser.OFPMatch(state=0, in_port=i) actions = [ bebaparser.OFPExpActionSetState(table_id=0, state=1, idle_timeout=2), # saves timestamp bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_SUM, output_fd_id=4, operand_1_hf_id=1, operand_2_cost=PROBE_FREQ) ] insts = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(1) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=500, match=match, instructions=insts) datapath.send_msg(mod) # simple forwarding packets go to second table to forward match = ofparser.OFPMatch(state=1, in_port=i, condition0=1) actions = [ # calculates deltaT: FDV[1]=HF[1]-FDV[0]=TS_NOW - TS_LAST bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_SUB, output_fd_id=1, operand_1_hf_id=1, operand_2_fd_id=0), # calculates rate: R = (bytes / deltaT_ms) * 8 [kb/s] bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_MUL, output_fd_id=2, operand_1_fd_id=2, operand_2_cost=8), # stores the result in FDV[3]: THE FLOW ESTIMATED RATE bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_DIV, output_fd_id=2, operand_1_fd_id=2, operand_2_fd_id=1), # calculates ewma bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_EWMA, output_fd_id=3, operand_1_fd_id=3, operand_2_cost=ALPHA, operand_3_fd_id=2), # saves current timestamp bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_SUM, output_fd_id=0, operand_1_hf_id=1, operand_2_cost=0), # saves timestamp + probe freq bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_SUM, output_fd_id=4, operand_1_hf_id=1, operand_2_cost=PROBE_FREQ), # reset byte counter bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_SUB, output_fd_id=2, operand_1_fd_id=2, operand_2_fd_id=2), # saves in GDV[i] the ewma bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_SUM, output_gd_id=i, operand_1_fd_id=3, operand_2_cost=0) ] instructions = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(1) ] mod = ofparser.OFPFlowMod(datapath=datapath, priority=0, table_id=0, match=match, instructions=instructions) datapath.send_msg(mod) match = ofparser.OFPMatch(state=1, in_port=i, condition0=0) actions = [ bebaparser.OFPExpActionSetDataVariable( table_id=0, opcode=bebaproto.OPCODE_SUM, output_fd_id=2, operand_1_fd_id=2, operand_2_hf_id=2) ] instructions = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(1) ] mod = ofparser.OFPFlowMod(datapath=datapath, priority=0, table_id=0, match=match, instructions=instructions) datapath.send_msg(mod) ######################## TABLE 2: FORWARDING ################ for i in LEAVES: match = ofparser.OFPMatch(eth_dst=MAC_ADDRS[i - 1]) actions = [ofparser.OFPActionOutput(i)] self.add_flow(datapath=datapath, table_id=1, priority=0, match=match, actions=actions)
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 process_packet(self, datapath, act_state, flags, output_ports, ch_state_src, idle_to_src, hard_to_src, ch_state_dst, idle_to_dst, hard_to_dst, priority, count_in): """ Match packet - ethernet, TCP protocol, state (parameter), optional flags (parameter). """ if flags == F_DONT_CARE: match = ofparser.OFPMatch(eth_type=0x0800, ip_proto=6, state=act_state) else: match = ofparser.OFPMatch(eth_type=0x0800, ip_proto=6, state=act_state, tcp_flags=flags) """ Set actions: - Output ports (parameter - list). - SetState for both directions (parameters). """ actions = [] for port in output_ports: actions.append(ofparser.OFPActionOutput(port)) if ch_state_src != self.CH_STATE_NONE: actions.append( osparser.OFPExpActionSetState( state=ch_state_src, table_id=0, # TODO - TIMEOUTS idle_timeout=idle_to_src, hard_timeout=hard_to_src, bit=0)) if ch_state_dst != self.CH_STATE_NONE: actions.append( osparser.OFPExpActionSetState( state=ch_state_dst, table_id=0, # TODO - TIMEOUTS idle_timeout=idle_to_dst, hard_timeout=hard_to_dst, bit=1)) """ Set instructions: - Apply previously defined actions. - Optionally pass packet to table1 for counting. """ inst = [ ofparser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions) ] if count_in: inst.append(ofparser.OFPInstructionGotoTable(table_id=1)) """ Prepare and send message. """ mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=priority, match=match, instructions=inst) datapath.send_msg(mod)
def load_fsm(self, datapath): LOG.info("Loading Table 0 normal FSM ...") ##=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=# ## state INIT - ANY """ Match a first packet of a new TCP flow (regardless of TCP flags) """ match = ofparser.OFPMatch(eth_type=0x0800, ip_proto=6, state=self.INIT) """ Forward the packet to the corresponding output interface and create entries for both directions of given flow in the OPEN state (forward all consecutive packets). ( TODO - hard-coded output) """ actions = [ ofparser.OFPActionOutput(2), # Create entry for direction of incoming packet osparser.OFPExpActionSetState( state=self.OPEN, table_id=0, # TODO - TIMEOUTS idle_timeout=10, bit=0), # Create entry for opposite direction since response is expected osparser.OFPExpActionSetState( state=self.OPEN, table_id=0, # TODO - TIMEOUTS idle_timeout=10, bit=1) ] """ Apply forward actions and the creation of entries, pass the first packet to the table1 for the new TCP connections statistics computation. """ inst = [ ofparser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions), ofparser.OFPInstructionGotoTable(table_id=1) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=100, match=match, instructions=inst) datapath.send_msg(mod) ##=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=# ## state OPEN - ANY """ Forward all consecutive packets of already seen flow by matching on previously created entries. """ match = ofparser.OFPMatch(eth_type=0x0800, ip_proto=6, state=self.OPEN) """ Just output packet to the corresponding output interface. ( TODO - hard-coded output) """ actions = [ ofparser.OFPActionOutput(2), ofparser.OFPActionOutput(1), # Refresh timeouts only osparser.OFPExpActionSetState( state=self.OPEN, table_id=0, # TODO - TIMEOUTS idle_timeout=10, bit=0), # Refresh timeouts only osparser.OFPExpActionSetState( state=self.OPEN, table_id=0, # TODO - TIMEOUTS idle_timeout=10, bit=1) ] inst = [ ofparser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions) ] mod = ofparser.OFPFlowMod(datapath=datapath, table_id=0, priority=100, match=match, instructions=inst) datapath.send_msg(mod) LOG.info("Done.")
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)