def register_gateway(self, ev): datapath = ev.datapath dpid = datapath.id if dpid in [10, 11, 12]: datacenter_id = 1 else: datacenter_id = 2 if dpid in self.potential_gateway.keys(): self.gateways[dpid] = self.potential_gateway[dpid] FlowManager.install_missing_flow_for_gateway(datapath) FlowManager.install_this_datacenter_flow(datapath, datacenter_id) FlowManager.check_priority_on_gateway(datapath) record = self.gateways[dpid] for (key, value) in record.items(): if key == 'NAT': FlowManager.install_NAT_flow_for_gateway(datapath, value) # port to other datacenters elif isinstance(key, int): FlowManager.install_other_datacenter_flow(datapath, key, value) return
def init_controller(self): hub.sleep(25) # test part print('start to init') # detect connections between switch and gateway self._check_switch_gateway_connection() # init arp manager for gateway round robin self.arp_manager.init_arp() # install flow entry for table 4 on ovs (to adjust whether dst is a gateway or not) # del the missing flow in table 2 in every ovs and install new one (for register host) for dpid in self.datapathes.keys(): if dpid in self.gateways.keys(): continue else: self.flow_manager.install_gateway_adjustment_flow_entry(dpid) FlowManager.substitute_missing_flow(self.datapathes[dpid]) FlowManager.install_arp_flow_entry(self.datapathes[dpid]) # install statistics flow entry on gateway for gw_id in self.gateways.keys(): dpids = Util.difference_between_list(self.datapathes.keys(), self.gateways.keys()) if gw_id in [10, 11, 12]: this_datacenter_id = 1 else: this_datacenter_id = 2 for datacenter_id in self.all_datacenter_id: if datacenter_id != this_datacenter_id: FlowManager.install_statistics_flow( self.datapathes[gw_id], dpids, this_datacenter_id, self.all_datacenter_id)
def register_switch(self, ev): datapath = ev.datapath dpid = datapath.id self.datapathes[dpid] = datapath ports = copy.copy(datapath.ports) self.dpid_to_ports[dpid] = ports # choose datatcenter_id according to dpid # if dpid == 1 or dpid == 2 or dpid == 3 or dpid == 10 or dpid == 11 or dpid == 12: # datacenter_id = 1 # else: # datacenter_id = 2 # TODO only for datacenter 1 right now datacenter_id = 1 vmac = MacManager.get_vmac_new_switch(dpid=dpid, datacenter_id=datacenter_id) self.dpid_to_vmac[dpid] = vmac self.lldp_manager.lldp_detect(datapath) if dpid in self.potential_gateway.keys(): return FlowManager.install_subnet_flow(ev, self.subnets) # 区别dst_ip是否为公网ip FlowManager.install_adjust_datacenter_flow( ev, datacenter_id) # 判断dst_mac是否在本数据中心 FlowManager.install_missing_flow_for_switch(ev) self.meters[dpid] = {}
def register_host(self, ev): msg = ev.msg dp = msg.datapath dpid = dp.id pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] src = eth.src in_port = msg.match['in_port'] tenant_id = self.host_pmac[src] # choose datacenter_id according to src_pmac if src in [ '00:00:00:00:00:01', '00:00:00:00:00:02', '00:00:00:00:00:03', '00:00:00:00:00:04', '00:00:00:00:00:05', '00:00:00:00:00:06', '00:00:00:00:00:07', '10:00:00:00:00:00' ]: datacenter_id = 1 else: datacenter_id = 2 src_vmac = self.mac_manager.get_vmac_new_host( dpid=dpid, port_id=in_port, datacenter_id=datacenter_id, tenant_id=tenant_id) self.pmac_to_vmac[src] = src_vmac self.vmac_to_pmac[src_vmac] = src print(self.vmac_to_pmac) if tenant_id in self.tenant_speed.keys(): # test print('add meter') meter_id = self.meter_manager.add_meter( datapath=dp, speed=self.tenant_speed[tenant_id]) print('meter id is ' + str(meter_id)) FlowManager.transfer_src_pmac_to_vmac(ev, src, src_vmac, meter_id=meter_id) else: FlowManager.transfer_src_pmac_to_vmac(ev, src, src_vmac) FlowManager.transfer_dst_vmac_to_pmac(ev, src_vmac, src) FlowManager.install_receiving_flow_entry(dp, src, in_port) return
def __init__(self, *args, **kwargs): super(Controller, self).__init__(*args, **kwargs) self.this_dc_id = 1 conf = DictionaryConfiguration(self.this_dc_id) # configurations for the system # arp table for different tenants self.arp_table = conf.arp_table # pmac -> tenant_id self.host_pmac = conf.host_pmac # tenant_id -> tenant_level self.tenant_level = conf.tenant_level # record all potential subnet self.subnets = conf.subnets # record all potential gateway # 'NAT' : port_no # datacenter_id : port_no self.potential_gateway = conf.potential_gateway # remote datacenter_id -> {dpid -> peer} # if there is no peer, then peer is -1 self.gateways_datacenter_port = conf.gateway_datacenter_port # record all potential gateway_ip # datacenter_id -> [gateway_ip]s self.gateway_ip = conf.gateway_ip # record speed for tenant # tenant_id -> speed self.tenant_speed = conf.tenant_speed # record all datacenter_id self.all_datacenter_id = conf.all_datacenter_id # record for system # data in controller self.vmac_to_pmac = { # {vmac -> vmac} } self.pmac_to_vmac = { # {pmac -> vmac} } self.dpid_to_vmac = {} # {dpid -> vmac} self.datapathes = {} # {dpid -> datapath} self.dpid_to_ports = {} # {dpid -> ports} self.dpid_to_dpid = {} # {(dpid, port_id) -> dpid} self.switch_topo = nx.Graph() # switch topo self.port_speed = { } # {dpid -> {remote_dpid -> 'max_speed' - 'cur_speed'}} self.meters = {} # {dpid -> {meter_id -> band_id}} self.gateways = {} # {dpid -> {port_no -> datacenter_id}} self.gateway_vmac = {} # {dpid -> vmac} self.host_queue = {} # gateway_id -> queue for host self.switch_gateway_connection = { } # (switch_id, gateway_id) -> (switch_port, gateway_port) self.host_gateway = {} # {vmac -> gateway_id} # components self.flow_manager = FlowManager(datapathes=self.datapathes, gateways=self.gateways) self.lldp_manager = LLDPListener( datapathes=self.datapathes, dpid_potrs=self.dpid_to_ports, dpid_to_dpid=self.dpid_to_dpid, topo=self.switch_topo, DEFAULT_TTL=self.DEFAULT_TTL, port_speed=self.port_speed, potential_gateways=self.potential_gateway) self.swtich_manager = SwitchManager( datapathes=self.datapathes, dpid_to_ports=self.dpid_to_ports, dpid_to_vmac=self.dpid_to_vmac, lldp_manager=self.lldp_manager, meters=self.meters, subnets=self.subnets, potential_gateway=self.potential_gateway) self.arp_manager = ArpManager( arp_table=self.arp_table, pmac_to_vmac=self.pmac_to_vmac, gateway_ip=self.gateway_ip, gateways=self.gateways, dpid_to_vmac=self.dpid_to_vmac, switch_gateway_connection=self.switch_gateway_connection, datapathes=self.datapathes, host_gateway=self.host_gateway) self.mac_manager = MacManager(tenant_level=self.tenant_level) self.meter_manager = MeterModifier(meters=self.meters) self.host_manager = HostManager(host_pmac=self.host_pmac, mac_manager=self.mac_manager, pmac_to_vmac=self.pmac_to_vmac, vmac_to_pmac=self.vmac_to_pmac, tenant_speed=self.tenant_speed, meter_manager=self.meter_manager) self.topo_manager = TopoManager(topo=self.switch_topo, dpid_to_dpid=self.dpid_to_dpid) self.gateway_manager = GatewayManager( gateways=self.gateways, potential_gateway=self.potential_gateway, gateway_flow_table_inquire_time=self.GATEWAY_FLOW_INQUIRY_TIME, datapathes=self.datapathes, gateway_port_inquire_time=self.GATEWAY_PORT_INQUIRY_TIME, gateway_datacenter_port_max_speed=self.DEFAULT_GG_BW, balance_time_interval=self.GATEWAY_BALANCE_TIME, all_datacenter_id=self.all_datacenter_id, topo_manager=self.topo_manager, meter_manager=self.meter_manager) # hub self.init_hub = hub.spawn(self.init_controller)
class Controller(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] DEFAULT_TTL = 120 # default ttl for LLDP packet PORT_INQUIRY_TIME = 10 # default time interval for port inquiry PORT_SPEED_CAL_INTERVAL = 5 # default time interval to calculate port speed GATEWAY_FLOW_INQUIRY_TIME = 1 # default time interval for gateway flow table inquiry GATEWAY_PORT_INQUIRY_TIME = 1 # default time interval for gateway datacenter port inquiry IP_REPLACE_MAC_TIMEOUT = 50 # default timeout for the table which modify mac_dst according to ip GATEWAY_BALANCE_TIME = 2 # default time interval for gateway balance adjustment # port_speed DEFAULT_SS_BW = 300 # default bandwidth between switch DEFAULT_GG_BW = 1250000 # default bandwidth between gateway in different datacenter def __init__(self, *args, **kwargs): super(Controller, self).__init__(*args, **kwargs) self.this_dc_id = 1 conf = DictionaryConfiguration(self.this_dc_id) # configurations for the system # arp table for different tenants self.arp_table = conf.arp_table # pmac -> tenant_id self.host_pmac = conf.host_pmac # tenant_id -> tenant_level self.tenant_level = conf.tenant_level # record all potential subnet self.subnets = conf.subnets # record all potential gateway # 'NAT' : port_no # datacenter_id : port_no self.potential_gateway = conf.potential_gateway # remote datacenter_id -> {dpid -> peer} # if there is no peer, then peer is -1 self.gateways_datacenter_port = conf.gateway_datacenter_port # record all potential gateway_ip # datacenter_id -> [gateway_ip]s self.gateway_ip = conf.gateway_ip # record speed for tenant # tenant_id -> speed self.tenant_speed = conf.tenant_speed # record all datacenter_id self.all_datacenter_id = conf.all_datacenter_id # record for system # data in controller self.vmac_to_pmac = { # {vmac -> vmac} } self.pmac_to_vmac = { # {pmac -> vmac} } self.dpid_to_vmac = {} # {dpid -> vmac} self.datapathes = {} # {dpid -> datapath} self.dpid_to_ports = {} # {dpid -> ports} self.dpid_to_dpid = {} # {(dpid, port_id) -> dpid} self.switch_topo = nx.Graph() # switch topo self.port_speed = { } # {dpid -> {remote_dpid -> 'max_speed' - 'cur_speed'}} self.meters = {} # {dpid -> {meter_id -> band_id}} self.gateways = {} # {dpid -> {port_no -> datacenter_id}} self.gateway_vmac = {} # {dpid -> vmac} self.host_queue = {} # gateway_id -> queue for host self.switch_gateway_connection = { } # (switch_id, gateway_id) -> (switch_port, gateway_port) self.host_gateway = {} # {vmac -> gateway_id} # components self.flow_manager = FlowManager(datapathes=self.datapathes, gateways=self.gateways) self.lldp_manager = LLDPListener( datapathes=self.datapathes, dpid_potrs=self.dpid_to_ports, dpid_to_dpid=self.dpid_to_dpid, topo=self.switch_topo, DEFAULT_TTL=self.DEFAULT_TTL, port_speed=self.port_speed, potential_gateways=self.potential_gateway) self.swtich_manager = SwitchManager( datapathes=self.datapathes, dpid_to_ports=self.dpid_to_ports, dpid_to_vmac=self.dpid_to_vmac, lldp_manager=self.lldp_manager, meters=self.meters, subnets=self.subnets, potential_gateway=self.potential_gateway) self.arp_manager = ArpManager( arp_table=self.arp_table, pmac_to_vmac=self.pmac_to_vmac, gateway_ip=self.gateway_ip, gateways=self.gateways, dpid_to_vmac=self.dpid_to_vmac, switch_gateway_connection=self.switch_gateway_connection, datapathes=self.datapathes, host_gateway=self.host_gateway) self.mac_manager = MacManager(tenant_level=self.tenant_level) self.meter_manager = MeterModifier(meters=self.meters) self.host_manager = HostManager(host_pmac=self.host_pmac, mac_manager=self.mac_manager, pmac_to_vmac=self.pmac_to_vmac, vmac_to_pmac=self.vmac_to_pmac, tenant_speed=self.tenant_speed, meter_manager=self.meter_manager) self.topo_manager = TopoManager(topo=self.switch_topo, dpid_to_dpid=self.dpid_to_dpid) self.gateway_manager = GatewayManager( gateways=self.gateways, potential_gateway=self.potential_gateway, gateway_flow_table_inquire_time=self.GATEWAY_FLOW_INQUIRY_TIME, datapathes=self.datapathes, gateway_port_inquire_time=self.GATEWAY_PORT_INQUIRY_TIME, gateway_datacenter_port_max_speed=self.DEFAULT_GG_BW, balance_time_interval=self.GATEWAY_BALANCE_TIME, all_datacenter_id=self.all_datacenter_id, topo_manager=self.topo_manager, meter_manager=self.meter_manager) # hub self.init_hub = hub.spawn(self.init_controller) # self.gateway_statistics_inquiry_hub = hub.spawn(self.gateway_manager.inquiry_gateway_flow_table_info) # self.gateways_datacenter_port_hub = hub.spawn(self.gateway_manager.inquiry_gateway_datacenter_port) # self.gateway_banlance_hub = hub.spawn(self.gateway_manager.gateway_balance_hub) # self.gateway_init_record_hub = hub.spawn(self.gateway_manager.init_gateway_record) # test hub # self.test_hub = hub.spawn(self.test) @set_ev_cls(ofp_event.EventOFPStateChange, [MAIN_DISPATCHER, DEAD_DISPATCHER]) def switch_state_change_handler(self, ev): dp = ev.datapath dpid = dp.id if ev.state == MAIN_DISPATCHER: # check whether it connect twice if dpid in self.datapathes.keys(): return # install lldp packet flow entry, register ovs self.lldp_manager.install_lldp_flow(ev) self.swtich_manager.register_switch(ev) if dpid in self.potential_gateway: self.gateway_manager.register_gateway(ev) elif ev.state == DEAD_DISPATCHER: self.swtich_manager.unregister_switch(dp) @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def packet_in_handler(self, ev): msg = ev.msg dp = msg.datapath dpid = dp.id # choose datacenter_id according to dpid if dpid in [1, 2, 3, 10, 11, 12]: this_datacenter_id = 1 else: this_datacenter_id = 2 ofproto = dp.ofproto parser = dp.ofproto_parser pkt = packet.Packet(msg.data) in_port = msg.match['in_port'] i = iter(pkt) eth_pkt = six.next(i) assert type(eth_pkt) == ethernet.ethernet dst = eth_pkt.dst src = eth_pkt.src special_pkt = six.next(i) # check the type of this pkt # lldp if type(special_pkt) == lldp.lldp: self.lldp_manager.lldp_packet_in(ev) return # arp packet elif type(special_pkt) == arp.arp: # test # print('a arp packte is coming===============') # print('the src is ' + str(src)) tenant_id = MacManager.get_tenant_id_with_vmac(src) self.arp_manager.handle_arp(datapath=dp, in_port=in_port, tenant_id=tenant_id, pkt=pkt) return # check if the source has no record if not src in self.pmac_to_vmac.keys( ) and not src in self.vmac_to_pmac.keys(): # first check whether this is pmac for host(not a vmac for host or switch, not a pmac for port that connect ovs) if src in self.host_pmac.keys(): # test print('new host coming!!==============' + src) self.host_manager.register_host(ev) # if src is a vmac, which means this host has been registered elif src in self.vmac_to_pmac.keys(): # first check whether dst is a host vmac (for table 7) if dst in self.vmac_to_pmac.keys(): print('pkt from ' + src + ' to ' + dst) # find the route dst_dpid = MacManager.get_dpid_with_vmac(dst) path = self.topo_manager.get_path(dpid, dst_dpid) # install flow entry for only this switch datapath = self.datapathes[dpid] port = path[0][1] self.flow_manager.install_wildcard_sending_flow( dp=datapath, out_port=port, dst_dpid=dst_dpid, buffer_id=msg.buffer_id) # finally send the packet if len(path) > 0: out_port = path[0][1] actions = [parser.OFPActionOutput(out_port)] else: actions = [] data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data out_packet = parser.OFPPacketOut(datapath=dp, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) dp.send_msg(out_packet) # come from table 6, add mac dst according to ip elif dst == FlowManager.TABLE6_MISSING_FLOW_ADDRESS: assert type(special_pkt) == ipv4.ipv4 # find dst_vmac ip_dst = special_pkt.dst tenant_id = MacManager.get_tenant_id_with_vmac(src) dst_pmac = self.arp_table[tenant_id][ip_dst] dst_vmac = self.pmac_to_vmac[dst_pmac] match = parser.OFPMatch(eth_type=0x800, ipv4_dst=ip_dst) actions = [parser.OFPActionSetField(eth_dst=dst_vmac)] instructions = [ parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), parser.OFPInstructionGotoTable(table_id=6) ] idle_timeout = self.IP_REPLACE_MAC_TIMEOUT FlowManager.add_flow_with_timeout(dp, 1, match, instructions, idle_timeout=idle_timeout, table_id=5, buffer_id=msg.buffer_id) data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data dst_datacenter_id = MacManager.get_datacenter_id_with_vmac( dst_vmac) if dst_datacenter_id == this_datacenter_id: switch_id = MacManager.get_dpid_with_vmac(src) dst_switch_id = MacManager.get_dpid_with_vmac(dst_vmac) path = self.topo_manager.get_path(switch_id, dst_switch_id) port = path[0][1] actions = [ parser.OFPActionSetField(eth_dst=dst_vmac), parser.OFPActionOutput(port) ] else: gateway_id = self.host_gateway[src] switch_id = MacManager.get_dpid_with_vmac(src) port = self.switch_gateway_connection[(switch_id, gateway_id)][0] actions = [ parser.OFPActionSetField(eth_dst=dst_vmac), parser.OFPActionOutput(port) ] out_packet = parser.OFPPacketOut(datapath=dp, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) dp.send_msg(out_packet) @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER) def flow_stats_reply_handler(self, ev): msg = ev.msg dp = msg.datapath dpid = dp.id if dpid in self.gateways.keys(): self.gateway_manager.gateway_statistics_handler(ev) return # @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER) def port_stats_reply_handler(self, ev): msg = ev.msg dp = msg.datapath dpid = dp.id if dpid in self.gateways.keys(): self.gateway_manager.gateway_port_reply_handler(ev) return def init_controller(self): hub.sleep(25) # test part print('start to init') # detect connections between switch and gateway self._check_switch_gateway_connection() # init arp manager for gateway round robin self.arp_manager.init_arp() # install flow entry for table 4 on ovs (to adjust whether dst is a gateway or not) # del the missing flow in table 2 in every ovs and install new one (for register host) for dpid in self.datapathes.keys(): if dpid in self.gateways.keys(): continue else: self.flow_manager.install_gateway_adjustment_flow_entry(dpid) FlowManager.substitute_missing_flow(self.datapathes[dpid]) FlowManager.install_arp_flow_entry(self.datapathes[dpid]) # install statistics flow entry on gateway for gw_id in self.gateways.keys(): dpids = Util.difference_between_list(self.datapathes.keys(), self.gateways.keys()) if gw_id in [10, 11, 12]: this_datacenter_id = 1 else: this_datacenter_id = 2 for datacenter_id in self.all_datacenter_id: if datacenter_id != this_datacenter_id: FlowManager.install_statistics_flow( self.datapathes[gw_id], dpids, this_datacenter_id, self.all_datacenter_id) # init record for gateway # self.gateway_manager.init_gateway_record() def _check_switch_gateway_connection(self): for dpid in self.datapathes.keys(): if dpid in self.gateways.keys(): continue else: for gw_id in self.gateways.keys(): # find the port connecting to gateway port1 = self.topo_manager.get_path(dpid, gw_id)[0][1] port2 = self.topo_manager.get_path(gw_id, dpid)[0][1] self.switch_gateway_connection[(dpid, gw_id)] = (port1, port2) return # test hub def test(self): hub.sleep(10) while True: hub.sleep(1) print(self.gateway_manager.gateway_port_speed) print('===================================') # hub.sleep(10) # f = open('test.txt', 'w') # i = 0 # while(True): # hub.sleep(1) # f.write(str(i) + '\n') # print(i) # i += 1 # f.write(str(self.gateway_manager.gateway_port_speed)) # f.write('\n') # print(self.gateway_manager.gateway_port_speed) # # if i >= 30: # f.close() return
def packet_in_handler(self, ev): msg = ev.msg dp = msg.datapath dpid = dp.id # choose datacenter_id according to dpid if dpid in [1, 2, 3, 10, 11, 12]: this_datacenter_id = 1 else: this_datacenter_id = 2 ofproto = dp.ofproto parser = dp.ofproto_parser pkt = packet.Packet(msg.data) in_port = msg.match['in_port'] i = iter(pkt) eth_pkt = six.next(i) assert type(eth_pkt) == ethernet.ethernet dst = eth_pkt.dst src = eth_pkt.src special_pkt = six.next(i) # check the type of this pkt # lldp if type(special_pkt) == lldp.lldp: self.lldp_manager.lldp_packet_in(ev) return # arp packet elif type(special_pkt) == arp.arp: # test # print('a arp packte is coming===============') # print('the src is ' + str(src)) tenant_id = MacManager.get_tenant_id_with_vmac(src) self.arp_manager.handle_arp(datapath=dp, in_port=in_port, tenant_id=tenant_id, pkt=pkt) return # check if the source has no record if not src in self.pmac_to_vmac.keys( ) and not src in self.vmac_to_pmac.keys(): # first check whether this is pmac for host(not a vmac for host or switch, not a pmac for port that connect ovs) if src in self.host_pmac.keys(): # test print('new host coming!!==============' + src) self.host_manager.register_host(ev) # if src is a vmac, which means this host has been registered elif src in self.vmac_to_pmac.keys(): # first check whether dst is a host vmac (for table 7) if dst in self.vmac_to_pmac.keys(): print('pkt from ' + src + ' to ' + dst) # find the route dst_dpid = MacManager.get_dpid_with_vmac(dst) path = self.topo_manager.get_path(dpid, dst_dpid) # install flow entry for only this switch datapath = self.datapathes[dpid] port = path[0][1] self.flow_manager.install_wildcard_sending_flow( dp=datapath, out_port=port, dst_dpid=dst_dpid, buffer_id=msg.buffer_id) # finally send the packet if len(path) > 0: out_port = path[0][1] actions = [parser.OFPActionOutput(out_port)] else: actions = [] data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data out_packet = parser.OFPPacketOut(datapath=dp, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) dp.send_msg(out_packet) # come from table 6, add mac dst according to ip elif dst == FlowManager.TABLE6_MISSING_FLOW_ADDRESS: assert type(special_pkt) == ipv4.ipv4 # find dst_vmac ip_dst = special_pkt.dst tenant_id = MacManager.get_tenant_id_with_vmac(src) dst_pmac = self.arp_table[tenant_id][ip_dst] dst_vmac = self.pmac_to_vmac[dst_pmac] match = parser.OFPMatch(eth_type=0x800, ipv4_dst=ip_dst) actions = [parser.OFPActionSetField(eth_dst=dst_vmac)] instructions = [ parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions), parser.OFPInstructionGotoTable(table_id=6) ] idle_timeout = self.IP_REPLACE_MAC_TIMEOUT FlowManager.add_flow_with_timeout(dp, 1, match, instructions, idle_timeout=idle_timeout, table_id=5, buffer_id=msg.buffer_id) data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data dst_datacenter_id = MacManager.get_datacenter_id_with_vmac( dst_vmac) if dst_datacenter_id == this_datacenter_id: switch_id = MacManager.get_dpid_with_vmac(src) dst_switch_id = MacManager.get_dpid_with_vmac(dst_vmac) path = self.topo_manager.get_path(switch_id, dst_switch_id) port = path[0][1] actions = [ parser.OFPActionSetField(eth_dst=dst_vmac), parser.OFPActionOutput(port) ] else: gateway_id = self.host_gateway[src] switch_id = MacManager.get_dpid_with_vmac(src) port = self.switch_gateway_connection[(switch_id, gateway_id)][0] actions = [ parser.OFPActionSetField(eth_dst=dst_vmac), parser.OFPActionOutput(port) ] out_packet = parser.OFPPacketOut(datapath=dp, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data) dp.send_msg(out_packet)
def adjust_balance(self, datacenter_id, gw_id): # first check whether there is enough ability # port ability number = len([10, 11, 12]) max_speed = self.gateway_datacenter_port_max_speed ability = number * max_speed actual = 0 for id in [10, 11, 12]: for dpid in self.dpid_flow[id][datacenter_id].keys(): actual += self.dpid_flow[id][datacenter_id][dpid] # test print(actual) print(ability) # able to send all pkts if True: free_gateway = self._find_free_gateway(datacenter_id) if free_gateway == -1: print('no free gateway ++++++++++++++++++++++++++++') print(self.gateway_port_speed) # TODO no free gateway return else: path = self.topo_manager.get_path(gw_id, free_gateway) print(gw_id) print(free_gateway) print(path) # pick some switches to free gateway dpids, speed = self._find_switches_for_free_gateway(gw_id, datacenter_id) # lead these dpids to free_gateway for dpid in dpids: # TODO create log to recover FlowManager.install_balance_flow_entry_for_gateway(self.datapathes[gw_id], dpid, 1, path[0][1]) return # unable to send all pkts else: print('adjusting=========================================') free_gateway = self._find_free_gateway(datacenter_id) dpids = [] speed = 0 if free_gateway == -1: # TODO no free gateway return else: path = self.topo_manager.get_path(gw_id, free_gateway) # pick some switches to free gateway dpids, speed = self._find_switches_for_free_gateway(gw_id, datacenter_id) # lead these dpids to free_gateway # see whether need to install meter to free_gateway original_speed = self.gateway_port_speed[free_gateway][datacenter_id] if True: # if original_speed + speed > max_speed: # need to install meter # meter_id = self.meter_manager.add_meter(datapath=self.datapathes[free_gateway], # speed=speed_difference) # for dpid in dpids: # # TODO create log to recover # FlowManager.install_balance_flow_entry_for_gateway(self.datapathes[gw_id], dpid, # self.datacenter_id, path[0][1], # meter_id) # send to queue queue_id = 1 print('set to queue+++++++++++++++++++++++++++++++++') for dpid in dpids: FlowManager.install_gateway_balance_flow_with_queue(gateway=self.datapathes[gw_id], dpid=dpid, this_datacenter_id=1, queue_id=queue_id, port_no=path[0][1]) else: for dpid in dpids: # TODO create log to recover FlowManager.install_balance_flow_entry_for_gateway(self.datapathes[gw_id], dpid, 1, path[0][1]) # TODO here are only for the test # set s2 on g1 to q2 on port 6 FlowManager.install_gateway_balance_flow_with_queue(gateway=self.datapathes[gw_id], dpid=2, this_datacenter_id=1, queue_id=2, port_no=6) # set s3 on g3 to q3 on port 6 FlowManager.install_gateway_balance_flow_with_queue(gateway=self.datapathes[12], dpid=3, this_datacenter_id=1, queue_id=3, port_no=6) # # check whether need to install meter for gw_id # if self.gateway_port_speed[gw_id][datacenter_id] - speed > max_speed: # # TODO here only find the second biggest switch to add meter # mark = 0 # mark_speed = 0 # for dpid in self.dpid_flow[gw_id][datacenter_id].keys(): # if dpid in dpids: # continue # if self.dpid_flow[gw_id][datacenter_id][dpid] > speed: # mark = dpid # mark_speed = self.dpid_flow[gw_id][datacenter_id][dpid] # # TODO a fixed meter with 0.6 # meter_id = self.meter_manager.add_meter(datapath=self.datapathes[gw_id], # speed=mark_speed * 0.6) # FlowManager.install_limit_speed_flow_entry_for_gateway(self.datapathes[gw_id], # mark, # self.datacenter_id, # meter_id) # # check whether other gateway need to install speed limit entry # for id in self.gateways.keys(): # if id == gw_id or id == free_gateway: # continue # else: # if self.gateway_port_speed[id][datacenter_id] > max_speed * self.balance_threshold: # # TODO here only find the second biggest switch to add meter # mark = 0 # mark_speed = 0 # for dpid in self.dpid_flow[id][datacenter_id].keys(): # if dpid in dpids: # continue # if self.dpid_flow[id][datacenter_id][dpid] > speed: # mark = dpid # mark_speed = self.dpid_flow[id][datacenter_id][dpid] # # TODO a fixed meter with 0.8 # meter_id = self.meter_manager.add_meter(datapath=self.datapathes[id], # speed=mark_speed * 0.8) # FlowManager.install_limit_speed_flow_entry_for_gateway(self.datapathes[id], # mark, # self.datacenter_id, # meter_id) return
def handle_arp(self, datapath, in_port, tenant_id, pkt): i = iter(pkt) pkt_ethernet = six.next(i) assert type(pkt_ethernet) == ethernet.ethernet src_vmac = pkt_ethernet.src pkt_arp = six.next(i) assert type(pkt_arp) == arp.arp # test print(str(pkt_arp.src_mac) + ' ask mac for ' + pkt_arp.dst_ip) parser = datapath.ofproto_parser dst_ip = pkt_arp.dst_ip src_ip = pkt_arp.src_ip dst_pmac = '' # TODO deal with arp reply becuase there is something wired in Ping process if not pkt_arp.opcode == arp.ARP_REQUEST: print('Its a reply from ' + pkt_ethernet.src + ' and is to ' + dst_ip) return # first check whether it is requesting a gateway mac if dst_ip in self.gateway_ip: # check which datacenter this src is in datacenter_id = MacManager.get_datacenter_id_with_vmac(src_vmac) if src_vmac in ['12:00:01:00:01:01', '12:00:01:00:02:01', '11:00:02:00:03:02', '12:00:01:00:01:08']: gateway_id = 10 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['11:00:02:00:01:02', '11:00:02:00:02:02']: gateway_id = 11 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['11:00:02:00:01:03', '12:00:01:00:03:01']: gateway_id = 12 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['21:00:02:00:05:01']: gateway_id = 14 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['22:00:01:00:04:01']: gateway_id = 13 gateway_vmac = self.dpid_to_vmac[gateway_id] else: return # test print(gateway_id) print(gateway_vmac) # fake a arp pkt and answer, wait to send pkt = self._create_arp_pkt(pkt, gateway_vmac) actions = [parser.OFPActionOutput(port=in_port)] out = datapath.ofproto_parser.OFPPacketOut( datapath=datapath, in_port=datapath.ofproto.OFPP_CONTROLLER, buffer_id=datapath.ofproto.OFP_NO_BUFFER, actions=actions, data=pkt ) #install flow entry for switch in table 8 src_dpid = MacManager.get_dpid_with_vmac(src_vmac) dp = self.datapathes[src_dpid] ofproto = dp.ofproto parser = datapath.ofproto_parser out_port = self.switch_gateway_connection[(src_dpid, gateway_id)][0] match = parser.OFPMatch(eth_src=src_vmac) actions = [parser.OFPActionOutput(out_port)] instructions = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] FlowManager.add_flow(dp, 1, match, instructions, table_id=8, buffer_id=None) # send the pkt datapath.send_msg(out) self.host_gateway[src_vmac] = gateway_id return # TODO NAT ask for host elif False: return # it is one host requesting another host ip else: # check if it is master host asking if src_vmac == '12:00:01:00:01:08': for tenant_id in self.arp_table.keys(): if dst_ip in self.arp_table[tenant_id].keys(): dst_pmac = self.arp_table[tenant_id][dst_ip] else: continue dst_vmac = self.pmac_to_vmac[dst_pmac] # fake a arp pkt and answer pkt = self._create_arp_pkt(pkt, dst_vmac) actions = [parser.OFPActionOutput(port=in_port)] out = datapath.ofproto_parser.OFPPacketOut( datapath=datapath, in_port=datapath.ofproto.OFPP_CONTROLLER, buffer_id=datapath.ofproto.OFP_NO_BUFFER, actions=actions, data=pkt ) # gateway dst_datacenter_id = MacManager.get_datacenter_id_with_vmac(dst_vmac) src_datacenter_id = MacManager.get_datacenter_id_with_vmac(src_vmac) if dst_datacenter_id != src_datacenter_id: if not src_vmac in self.host_gateway.keys(): # need to install gateway flow entry if src_vmac in ['12:00:01:00:01:01', '12:00:01:00:02:01', '11:00:02:00:03:02', '12:00:01:00:01:08']: gateway_id = 10 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['11:00:02:00:01:02', '11:00:02:00:02:02']: gateway_id = 11 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['11:00:02:00:01:03', '12:00:01:00:03:01']: gateway_id = 12 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['21:00:02:00:05:01']: gateway_id = 14 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['22:00:01:00:04:01']: gateway_id = 13 gateway_vmac = self.dpid_to_vmac[gateway_id] else: return # install flow entry src_dpid = MacManager.get_dpid_with_vmac(src_vmac) print(src_dpid) print('++++++++++++++++++++++++++++++++++++++++++++++') dp = self.datapathes[src_dpid] ofproto = dp.ofproto parser = datapath.ofproto_parser out_port = self.switch_gateway_connection[(src_dpid, gateway_id)][0] match = parser.OFPMatch(eth_src=src_vmac) actions = [parser.OFPActionOutput(out_port)] instructions = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] FlowManager.add_flow(dp, 1, match, instructions, table_id=8, buffer_id=None) self.host_gateway[src_vmac] = gateway_id datapath.send_msg(out) return # check if it is asking master host if dst_ip == '191.168.111.1': dst_vmac = '12:00:01:00:01:08' # fake a arp pkt and answer pkt = self._create_arp_pkt(pkt, dst_vmac) actions = [parser.OFPActionOutput(port=in_port)] out = datapath.ofproto_parser.OFPPacketOut( datapath=datapath, in_port=datapath.ofproto.OFPP_CONTROLLER, buffer_id=datapath.ofproto.OFP_NO_BUFFER, actions=actions, data=pkt ) # gateway dst_datacenter_id = MacManager.get_datacenter_id_with_vmac(dst_vmac) src_datacenter_id = MacManager.get_datacenter_id_with_vmac(src_vmac) if dst_datacenter_id != src_datacenter_id: if not src_vmac in self.host_gateway.keys(): # need to install gateway flow entry if src_vmac in ['12:00:01:00:01:01', '12:00:01:00:02:01', '11:00:02:00:03:02', '12:00:01:00:01:08']: gateway_id = 10 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['11:00:02:00:01:02', '11:00:02:00:02:02']: gateway_id = 11 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['11:00:02:00:01:03', '12:00:01:00:03:01']: gateway_id = 12 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['21:00:02:00:05:01']: gateway_id = 14 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['22:00:01:00:04:01']: gateway_id = 13 gateway_vmac = self.dpid_to_vmac[gateway_id] else: return # install flow entry src_dpid = MacManager.get_dpid_with_vmac(src_vmac) print(src_dpid) print('++++++++++++++++++++++++++++++++++++++++++++++') dp = self.datapathes[src_dpid] ofproto = dp.ofproto parser = datapath.ofproto_parser out_port = self.switch_gateway_connection[(src_dpid, gateway_id)][0] match = parser.OFPMatch(eth_src=src_vmac) actions = [parser.OFPActionOutput(out_port)] instructions = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] FlowManager.add_flow(dp, 1, match, instructions, table_id=8, buffer_id=None) self.host_gateway[src_vmac] = gateway_id datapath.send_msg(out) return # if there is record for this dst_ip, get dst_pmac from arp_table if dst_ip in self.arp_table[tenant_id].keys(): dst_pmac = self.arp_table[tenant_id][dst_ip] else: return if not dst_pmac in self.pmac_to_vmac.keys(): print('arp error:no such host recorded for ip:', dst_ip) print(dst_pmac) return dst_vmac = self.pmac_to_vmac[dst_pmac] # test # print('This packet is from ' + pkt_ethernet.src + ' and is to ' + dst_ip) print('reply ' + str(pkt_arp.src_mac) + ', the mac for ' + pkt_arp.dst_ip + ' is ' + str(dst_vmac)) # check whether this pkt is in other datacenters # if it is, install flow entry to table 8 (send to gateway) dst_datacenter_id = MacManager.get_datacenter_id_with_vmac(dst_vmac) src_datacenter_id = MacManager.get_datacenter_id_with_vmac(src_vmac) if dst_datacenter_id != src_datacenter_id: if not src_vmac in self.host_gateway.keys(): # need to install gateway flow entry if src_vmac in ['12:00:01:00:01:01', '12:00:01:00:02:01', '11:00:02:00:03:02', '12:00:01:00:01:08']: gateway_id = 10 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['11:00:02:00:01:02', '11:00:02:00:02:02']: gateway_id = 11 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['11:00:02:00:01:03', '12:00:01:00:03:01']: gateway_id = 12 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['21:00:02:00:05:01']: gateway_id = 14 gateway_vmac = self.dpid_to_vmac[gateway_id] elif src_vmac in ['22:00:01:00:04:01']: gateway_id = 13 gateway_vmac = self.dpid_to_vmac[gateway_id] else: return # install flow entry src_dpid = MacManager.get_dpid_with_vmac(src_vmac) print(src_dpid) print('++++++++++++++++++++++++++++++++++++++++++++++') dp = self.datapathes[src_dpid] ofproto = dp.ofproto parser = datapath.ofproto_parser out_port = self.switch_gateway_connection[(src_dpid, gateway_id)][0] match = parser.OFPMatch(eth_src=src_vmac) actions = [parser.OFPActionOutput(out_port)] instructions = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] FlowManager.add_flow(dp, 1, match, instructions, table_id=8, buffer_id=None) self.host_gateway[src_vmac] = gateway_id # fake a arp pkt and answer pkt = self._create_arp_pkt(pkt, dst_vmac) actions = [parser.OFPActionOutput(port=in_port)] out = datapath.ofproto_parser.OFPPacketOut( datapath=datapath, in_port=datapath.ofproto.OFPP_CONTROLLER, buffer_id=datapath.ofproto.OFP_NO_BUFFER, actions=actions, data=pkt ) datapath.send_msg(out)
def __init__(self, *args, **kwargs): super(Controller, self).__init__(*args, **kwargs) # configurations for the system self.datacenter_id = 2 # arp table for different tenants self.arp_table = { # {tenant_id ->{ip -> mac}} 1: { # d1 '191.168.1.1': '00:00:00:00:00:01', '191.168.1.2': '00:00:00:00:00:02', '191.168.1.3': '00:00:00:00:00:03', '192.168.1.4': '00:00:00:00:00:04', '191.168.1.4': '00:00:00:00:00:05', '191.168.1.6': '00:00:00:00:00:09', # d2 '191.168.2.1': '00:00:00:00:01:01', '192.168.2.2': '00:00:00:00:01:02' }, 2: { # d1 '191.168.1.1': '00:00:00:00:00:0a', '191.168.1.2': '00:00:00:00:00:0b', '191.168.1.3': '00:00:00:00:00:0c', # d2 '191.168.2.1': '00:00:00:00:01:03', '192.168.2.2': '00:00:00:00:01:04' } } # pmac -> tenant_id self.host_pmac = { '00:00:00:00:00:01': 1, '00:00:00:00:00:02': 1, '00:00:00:00:00:03': 1, '00:00:00:00:00:04': 1, '00:00:00:00:00:05': 1, '10:00:00:00:00:00': 1, '00:00:00:00:04:00': 1, '00:00:00:00:00:09': 1, '00:00:00:00:01:00': 1, '00:00:00:00:02:00': 1, '00:00:00:00:00:0a': 2, '00:00:00:00:00:0b': 2, '00:00:00:00:00:0c': 2, '00:00:00:00:03:00': 2, '00:00:00:00:05:00': 2, '00:00:00:00:01:01': 1, '00:00:00:00:01:02': 1, '00:00:00:00:01:03': 2, '00:00:00:00:01:04': 2 } # tenant_id -> tenant_level self.tenant_level = {1: 1, 2: 2} # record all potential subnet self.subnets = ['191.0.0.0/8', '192.0.0.0/8', '10.0.0.0/8'] # record all potential gateway # 'NAT' : port_no # datacenter_id : port_no self.potential_gateway = {10: {'NAT': 5, 1: 3}, 11: {'NAT': 6, 1: 3}} # remote datacenter_id -> {dpid -> peer} # if there is no peer, then peer is -1 self.gateways_datacenter_port = {2: {10: -1, 11: 12, 12: 11}} # record all potential gateway_ip self.gateway_ip = ['191.0.0.1', '192.0.0.1'] # record speed for tenant # tenant_id -> speed self.tenant_speed = {1: 1024 * 8, 2: 1024 * 8} # record all datacenter_id self.all_datacenter_id = [1, 2] # record for system # data in controller self.vmac_to_pmac = { # {vmac -> vmac} '11:00:01:00:01:02': '00:00:00:00:00:02', '11:00:01:00:02:01': '00:00:00:00:00:03', '12:00:02:00:04:03': '00:00:00:00:00:0c', '11:00:01:00:03:01': '00:00:00:00:00:04', '12:00:02:00:01:06': '00:00:00:00:00:0a', '11:00:01:00:04:01': '00:00:00:00:00:05', '11:00:01:00:05:03': '00:00:00:00:00:09', '11:00:01:00:01:01': '00:00:00:00:00:01', '12:00:02:00:01:07': '00:00:00:00:00:0b' } self.pmac_to_vmac = { # {pmac -> vmac} '00:00:00:00:00:02': '11:00:01:00:01:02', '00:00:00:00:00:03': '11:00:01:00:02:01', '00:00:00:00:00:0c': '12:00:02:00:04:03', '00:00:00:00:00:04': '11:00:01:00:03:01', '00:00:00:00:00:0a': '12:00:02:00:01:06', '00:00:00:00:00:05': '11:00:01:00:04:01', '00:00:00:00:00:09': '11:00:01:00:05:03', '00:00:00:00:00:01': '11:00:01:00:01:01', '00:00:00:00:00:0b': '12:00:02:00:01:07' } self.dpid_to_vmac = {} # {dpid -> vmac} self.datapathes = {} # {dpid -> datapath} self.dpid_to_ports = {} # {dpid -> ports} self.dpid_to_dpid = {} # {(dpid, port_id) -> dpid} self.switch_topo = nx.Graph() # switch topo self.port_speed = { } # {dpid -> {remote_dpid -> 'max_speed' - 'cur_speed'}} self.gateway_port_speed = {} # {gateway_id -> {port_no -> speed}} self.meters = {} # {dpid -> {meter_id -> band_id}} self.gateways = {} # {dpid -> {port_no -> datacenter_id}} self.gateway_vmac = {} # {dpid -> vmac} self.host_queue = {} # gateway_id -> queue for host self.switch_gateway_connection = { } # (switch_id, gateway_id) -> (switch_port, gateway_port) self.host_gateway = {} # {vmac -> gateway_id} # components self.flow_manager = FlowManager(datapathes=self.datapathes, gateways=self.gateways) self.lldp_manager = LLDPListener( datapathes=self.datapathes, dpid_potrs=self.dpid_to_ports, dpid_to_dpid=self.dpid_to_dpid, topo=self.switch_topo, DEFAULT_TTL=self.DEFAULT_TTL, port_speed=self.port_speed, potential_gateways=self.potential_gateway) self.swtich_manager = SwitchManager( datapathes=self.datapathes, dpid_to_ports=self.dpid_to_ports, datacenter_id=self.datacenter_id, dpid_to_vmac=self.dpid_to_vmac, lldp_manager=self.lldp_manager, meters=self.meters, subnets=self.subnets, potential_gateway=self.potential_gateway) self.arp_manager = ArpManager( arp_table=self.arp_table, pmac_to_vmac=self.pmac_to_vmac, gateway_ip=self.gateway_ip, gateways=self.gateways, dpid_to_vmac=self.dpid_to_vmac, switch_gateway_connection=self.switch_gateway_connection, datapathes=self.datapathes, host_gateway=self.host_gateway, datacenter_id=self.datacenter_id) self.mac_manager = MacManager(tenant_level=self.tenant_level) self.meter_manager = MeterModifier(meters=self.meters) self.host_manager = HostManager(host_pmac=self.host_pmac, mac_manager=self.mac_manager, datacenter_id=self.datacenter_id, pmac_to_vmac=self.pmac_to_vmac, vmac_to_pmac=self.vmac_to_pmac, tenant_speed=self.tenant_speed, meter_manager=self.meter_manager) self.topo_manager = TopoManager(topo=self.switch_topo, dpid_to_dpid=self.dpid_to_dpid) self.gateway_manager = GatewayManager( gateways=self.gateways, potential_gateway=self.potential_gateway, datacenter_id=self.datacenter_id, gateway_flow_table_inquire_time=self.GATEWAY_FLOW_INQUIRY_TIME, datapathes=self.datapathes, gateway_port_inquire_time=self.GATEWAY_PORT_INQUIRY_TIME, gateway_datacenter_port_max_speed=self.DEFAULT_GG_BW, balance_time_interval=self.GATEWAY_BALANCE_TIME, all_datacenter_id=self.all_datacenter_id, topo_manager=self.topo_manager, meter_manager=self.meter_manager) # hub self.init_hub = hub.spawn(self.init_controller) self.gateway_statistics_inquiry_hub = hub.spawn( self.gateway_manager.inquiry_gateway_flow_table_info) self.gateways_datacenter_port_hub = hub.spawn( self.gateway_manager.inquiry_gateway_datacenter_port) self.gateway_banlance_hub = hub.spawn( self.gateway_manager.gateway_balance_hub) self.gateway_init_record_hub = hub.spawn( self.gateway_manager.init_gateway_record)