Пример #1
0
    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
Пример #2
0
    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)
Пример #3
0
    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] = {}
Пример #4
0
    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
Пример #5
0
    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)
Пример #6
0
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
Пример #7
0
    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)
Пример #8
0
    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
Пример #9
0
    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)
Пример #10
0
    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)