class LearningSwitchControllerApp(object):

    def __init__(self, switchName):
        self.topo = Topology(db="topology.db")
        self.switchName = switchName
        self.thrift_port = self.topo.get_thrift_port(switchName)
        self.cpu_port = self.topo.get_cpu_port_index(self.switchName)
        self.controller = SimpleSwitchAPI(self.thrift_port)

        self.init()

    def init(self):
        self.controller.reset_state()
        self.add_mcast_grp()
        self.add_mirror()

    def add_mirror(self):
        if self.cpu_port:
            self.controller.mirroring_add(MIRROR_SESSION_ID, self.cpu_port)

    def add_mcast_grp(self):
        interfaces_to_port = self.topo[self.switchName]["interfaces_to_port"].copy()
        # filter lo and cpu port
        interfaces_to_port.pop('lo', None)
        interfaces_to_port.pop(self.topo.get_cpu_port_intf(self.switchName), None)

        mc_grp_id = 1
        rid = 0
        # add multicast group
        self.controller.mc_mgrp_create(mc_grp_id)
        port_list = interfaces_to_port.values()[:]
        # add multicast node group
        handle = self.controller.mc_node_create(rid, port_list)
        # associate with mc grp
        self.controller.mc_node_associate(mc_grp_id, handle)

    def learn(self, learningData):
        for macAddr, ingressPort in learningData:
            print("macAddr: %012X ingressPort: %s ", macAddr, ingressPort)
            self.controller.table_add("srcMacAddr", "NoAction", [str(macAddr)])
            self.controller.table_add("dstMacAddr", "forward", [
                                      str(macAddr)], [str(ingressPort)])

    def recv_msg_cpu(self, pkt):

        packet = Ether(str(pkt))
        if packet.type == L2_LEARN_ETHER_TYPE:
            cpu_header = CpuHeader(bytes(packet.payload))
            self.learn([(cpu_header.macAddr, cpu_header.ingressPort)])

    def run_cpu_port_loop(self):

        cpu_port_intf = str(self.topo.get_cpu_port_intf(
            self.switchName).replace("eth0", "eth1"))
        sniff(iface=cpu_port_intf, prn=self.recv_msg_cpu)
Ejemplo n.º 2
0
class FloodingController(object):

    def __init__(self, sw_name):

        self.topo = Topology(db="topology.db")
        self.sw_name = sw_name
        self.thrift_port = self.topo.get_thrift_port(sw_name)
        self.cpu_port =  self.topo.get_cpu_port_index(self.sw_name)
        self.controller = SimpleSwitchAPI(self.thrift_port)
        self.init()

    def init(self):

        self.controller.reset_state()
        self.fill_dmac_table()
        self.add_boadcast_groups()

    def fill_dmac_table(self):
        self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:01'], ['1'])
        self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:02'], ['2'])
        self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:03'], ['3'])
        self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:04'], ['4'])
        self.controller.table_set_default("dmac", "broadcast", [])

    def add_boadcast_groups(self):

        interfaces_to_port = self.topo[self.sw_name]["interfaces_to_port"].copy()
        #filter lo and cpu port
        interfaces_to_port.pop('lo', None)
        interfaces_to_port.pop(self.topo.get_cpu_port_intf(self.sw_name), None)

        mc_grp_id = 1
        rid = 0
        for ingress_port in interfaces_to_port.values():

            port_list = interfaces_to_port.values()[:]
            del(port_list[port_list.index(ingress_port)])

            #add multicast group
            self.controller.mc_mgrp_create(mc_grp_id)

            #add multicast node group
            handle = self.controller.mc_node_create(rid, port_list)

            #associate with mc grp
            self.controller.mc_node_associate(mc_grp_id, handle)

            #fill broadcast table
            self.controller.table_add("select_mcast_grp", "set_mcast_grp", [str(ingress_port)], [str(mc_grp_id)])

            mc_grp_id +=1
            rid +=1
class L2Controller(object):
    def __init__(self, sw_name):
        #self.topo = Topology(db="topology.db")
        self.sw_name = sw_name
        self.thrift_port = 9090
        #self.thrift_port = self.topo.get_thrift_port(sw_name)
        #self.cpu_port =  self.topo.get_cpu_port_index(self.sw_name)
        self.cpu_port = 2
        self.controller = SimpleSwitchAPI(self.thrift_port)

        self.init()

    def init(self):
        self.controller.reset_state()
        #self.add_boadcast_groups()
        self.add_mirror()
        #self.fill_table_test()

    def add_mirror(self):
        if self.cpu_port:
            self.controller.mirroring_add(100, self.cpu_port)

    def read_register(self):
        ns_recv = self.controller.register_read("ns_recv")
        na_recv = self.controller.register_read("na_recv")
        ns_filter = self.controller.register_read("ns_filter")
        na_filter = self.controller.register_read("na_filter")
        ns_recv_no_zero = []
        for x in ns_recv:
            if x != 0:
                ns_recv_no_zero.append(x)
        na_recv_no_zero = []
        for x in na_recv:
            if x != 0:
                na_recv_no_zero.append(x)
        ns_filter_no_zero = []
        for x in ns_filter:
            if x != 0:
                ns_filter_no_zero.append(x)
        na_filter_no_zero = []
        for x in na_filter:
            if x != 0:
                na_filter_no_zero.append(x)
        print "ns_recv: ", len(ns_recv_no_zero), ns_recv_no_zero
        print "ns_filter: ", len(ns_filter_no_zero), ns_filter_no_zero
        print "na_recv: ", len(na_recv_no_zero), na_recv_no_zero
        print "na_filter: ", len(na_filter_no_zero), na_filter_no_zero
Ejemplo n.º 4
0
class L2Controller(object):
    def __init__(self, sw_name):
        self.sw_name = sw_name
        self.thrift_port = 9090
        self.cpu_port = 2
        self.controller = SimpleSwitchAPI(self.thrift_port)

        self.init()

    def init(self):
        self.controller.reset_state()
        self.add_mirror()

    def add_mirror(self):
        if self.cpu_port:
            self.controller.mirroring_add(100, self.cpu_port)

    def fill_mac_query_table_test(self):
        self.controller.table_add("mac_forward", "modify_egress_spec",
                                  ['00:00:0a:00:00:01'], ['1'])
        self.controller.table_add("mac_forward", "modify_egress_spec",
                                  ['00:00:0a:00:00:02'], ['2'])
        self.controller.table_add("mac_forward", "modify_egress_spec",
                                  ['00:00:0a:00:00:03'], ['3'])
        self.controller.table_add("mac_forward", "modify_egress_spec",
                                  ['00:00:0a:00:00:04'], ['4'])

    def mac_learn(self, learning_data):
        for mac_addr, ingress_port in learning_data:
            print "mac: %012X ingress_port: %s " % (mac_addr, ingress_port)
            self.controller.table_add("mac_query", "set_mac_in",
                                      [str(mac_addr)])
            self.controller.table_add("mac_forward", "modify_egress_spec",
                                      [str(mac_addr)], [str(ingress_port)])

    def ipv6_learn(self, learning_data):
        for target_address, index in learning_data:
            print "target_address: %012X index: %s " % (target_address, index)
            self.controller.table_add("target_address_query",
                                      "set_target_address_in",
                                      [str(target_address)], [str(index)])

    def unpack_digest(self, msg, num_samples):
        digest = []
        print len(msg), num_samples
        starting_index = 32
        for sample in range(num_samples):
            mac0, mac1, ingress_port = struct.unpack(
                ">LHH", msg[starting_index:starting_index + 8])
            starting_index += 8
            mac_addr = (mac0 << 16) + mac1
            digest.append((mac_addr, ingress_port))

        return digest

    def recv_msg_digest(self, msg):
        topic, device_id, ctx_id, list_id, buffer_id, num = struct.unpack(
            "<iQiiQi", msg[:32])
        digest = self.unpack_digest(msg, num)
        print "digest:", digest, " digest len:", len(digest)
        self.mac_learn(digest)

        self.controller.client.bm_learning_ack_buffer(ctx_id, list_id,
                                                      buffer_id)

    def run_digest_loop(self):
        sub = nnpy.Socket(nnpy.AF_SP, nnpy.SUB)
        sub.connect('ipc:///tmp/bmv2-0-notifications.ipc')
        sub.setsockopt(nnpy.SUB, nnpy.SUB_SUBSCRIBE, '')
        print "run_digest_loop"

        while True:
            msg = sub.recv()
            #print "msg:",msg
            self.recv_msg_digest(msg)

    def recv_msg_cpu(self, pkt):
        packet = Ether(str(pkt))
        if packet.type == 0x1234:
            cpu_header = CpuHeader(packet.payload)
            self.mac_learn([(cpu_header.macAddr, cpu_header.ingress_port)])

    def run_cpu_port_loop(self):
        cpu_port_intf = "docker0"
        sniff(iface=cpu_port_intf, prn=self.recv_msg_cpu)
Ejemplo n.º 5
0
class L2Controller(object):

    def __init__(self, sw_name):

        self.topo = Topology(db="topology.db")
        self.sw_name = sw_name
        self.thrift_port = self.topo.get_thrift_port(sw_name)
        self.cpu_port =  self.topo.get_cpu_port_index(self.sw_name)
        self.controller = SimpleSwitchAPI(self.thrift_port)

        self.init()

    def init(self):

        self.controller.reset_state()
        self.add_boadcast_groups()
        self.add_mirror()
        #self.fill_table_test()

    def add_mirror(self):

        if self.cpu_port:
            self.controller.mirroring_add(100, self.cpu_port)

    def add_boadcast_groups(self):

        interfaces_to_port = self.topo[self.sw_name]["interfaces_to_port"].copy()
        #filter lo and cpu port
        interfaces_to_port.pop('lo', None)
        interfaces_to_port.pop(self.topo.get_cpu_port_intf(self.sw_name), None)

        mc_grp_id = 1
        rid = 0
        for ingress_port in interfaces_to_port.values():

            port_list = interfaces_to_port.values()[:]
            del(port_list[port_list.index(ingress_port)])

            #add multicast group
            self.controller.mc_mgrp_create(mc_grp_id)

            #add multicast node group
            handle = self.controller.mc_node_create(rid, port_list)

            #associate with mc grp
            self.controller.mc_node_associate(mc_grp_id, handle)

            #fill broadcast table
            self.controller.table_add("broadcast", "set_mcast_grp", [str(ingress_port)], [str(mc_grp_id)])

            mc_grp_id +=1
            rid +=1

    def fill_table_test(self):
        self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:01'], ['1'])
        self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:02'], ['2'])
        self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:03'], ['3'])
        self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:04'], ['4'])


    def learn(self, learning_data):

        for mac_addr, ingress_port in  learning_data:
            print "mac: %012X ingress_port: %s " % (mac_addr, ingress_port)
            self.controller.table_add("smac", "NoAction", [str(mac_addr)])
            self.controller.table_add("dmac", "forward", [str(mac_addr)], [str(ingress_port)])

    def unpack_digest(self, msg, num_samples):

        digest = []
        print len(msg), num_samples
        starting_index = 32
        for sample in range(num_samples):
            mac0, mac1, ingress_port = struct.unpack(">LHH", msg[starting_index:starting_index+8])
            starting_index +=8
            mac_addr = (mac0 << 16) + mac1
            digest.append((mac_addr, ingress_port))

        return digest

    def recv_msg_digest(self, msg):

        topic, device_id, ctx_id, list_id, buffer_id, num = struct.unpack("<iQiiQi",
                                                                          msg[:32])
        digest = self.unpack_digest(msg, num)
        self.learn(digest)

        #Acknowledge digest
        self.controller.client.bm_learning_ack_buffer(ctx_id, list_id, buffer_id)


    def run_digest_loop(self):

        sub = nnpy.Socket(nnpy.AF_SP, nnpy.SUB)
        notifications_socket = self.controller.client.bm_mgmt_get_info().notifications_socket
        sub.connect(notifications_socket)
        sub.setsockopt(nnpy.SUB, nnpy.SUB_SUBSCRIBE, '')

        while True:
            msg = sub.recv()
            self.recv_msg_digest(msg)

    def recv_msg_cpu(self, pkt):

        packet = Ether(str(pkt))

        if packet.type == 0x1234:
            cpu_header = CpuHeader(packet.payload)
            self.learn([(cpu_header.macAddr, cpu_header.ingress_port)])

    def run_cpu_port_loop(self):

        cpu_port_intf = str(self.topo.get_cpu_port_intf(self.sw_name).replace("eth0", "eth1"))
        sniff(iface=cpu_port_intf, prn=self.recv_msg_cpu)
Ejemplo n.º 6
0
class BlinkController:

    def __init__(self, topo_db, sw_name, ip_controller, port_controller, log_dir, \
        monitoring=True, routing_file=None):

        self.topo = Topology(db=topo_db)
        self.sw_name = sw_name
        self.thrift_port = self.topo.get_thrift_port(sw_name)
        self.cpu_port = self.topo.get_cpu_port_index(self.sw_name)
        self.controller = SimpleSwitchAPI(self.thrift_port)
        self.controller.reset_state()
        self.log_dir = log_dir

        print 'connecting to ', ip_controller, port_controller
        # Socket used to communicate with the controller
        self.sock_controller = socket.socket(socket.AF_INET,
                                             socket.SOCK_STREAM)
        server_address = (ip_controller, port_controller)
        self.sock_controller.connect(server_address)
        print 'Connected!'

        # Send the switch name to the controller
        self.sock_controller.sendall(str(sw_name))

        self.make_logging()

        if monitoring:
            # Monitoring scheduler
            self.t_sched = sched_timer.RepeatingTimer(10, 0.5, self.scheduling)
            self.t_sched.start()

        self.mapping_dic = {}
        tmp = list(self.topo.get_hosts()) + list(self.topo.get_p4switches())
        self.mapping_dic = {k: v for v, k in enumerate(tmp)}
        self.log.info(str(self.mapping_dic))

        self.routing_file = routing_file
        print 'routing_file ', routing_file
        if self.routing_file is not None:
            json_data = open(self.routing_file)
            self.topo_routing = json.load(json_data)

    def make_logging(self):
        # Logger for the pipeline
        logger.setup_logger('p4_to_controller', self.log_dir+'/p4_to_controller_'+ \
            str(self.sw_name)+'.log', level=logging.INFO)
        self.log = logging.getLogger('p4_to_controller')

        # Logger for the sliding window
        logger.setup_logger('p4_to_controller_sw', self.log_dir+'/p4_to_controller_'+ \
            str(self.sw_name)+'_sw.log', level=logging.INFO)
        self.log_sw = logging.getLogger('p4_to_controller_sw')

        # Logger for the rerouting
        logger.setup_logger('p4_to_controller_rerouting', self.log_dir+'/p4_to_controller_'+ \
            str(self.sw_name)+'_rerouting.log', level=logging.INFO)
        self.log_rerouting = logging.getLogger('p4_to_controller_rerouting')

        # Logger for the Flow Selector
        logger.setup_logger('p4_to_controller_fs', self.log_dir+'/p4_to_controller_'+ \
            str(self.sw_name)+'_fs.log', level=logging.INFO)
        self.log_fs = logging.getLogger('p4_to_controller_fs')

    def scheduling(self):

        for host in list(self.topo.get_hosts()):
            prefix = self.topo.get_host_ip(host) + '/24'

            # Print log about the sliding window
            for id_prefix in [
                    self.mapping_dic[host] * 2, self.mapping_dic[host] * 2 + 1
            ]:

                with HiddenPrints():
                    sw_time = float(
                        self.controller.register_read('sw_time',
                                                      index=id_prefix)) / 1000.
                    sw_index = self.controller.register_read('sw_index',
                                                             index=id_prefix)
                    sw_sum = self.controller.register_read('sw_sum',
                                                           index=id_prefix)
                self.log_sw.info('sw_time\t' + host + '\t' + prefix + '\t' +
                                 str(id_prefix) + '\t' + str(sw_time))
                self.log_sw.info('sw_index\t' + host + '\t' + prefix + '\t' +
                                 str(id_prefix) + '\t' + str(sw_index))

                if sw_sum >= 32:
                    self.log_sw.info('sw_sum\t' + host + '\t' + prefix + '\t' +
                                     str(id_prefix) + '\t' + str(sw_sum) +
                                     '\tREROUTING')
                else:
                    self.log_sw.info('sw_sum\t' + host + '\t' + prefix + '\t' +
                                     str(id_prefix) + '\t' + str(sw_sum))

                sw = []
                tmp = 'sw ' + host + ' ' + prefix + ' ' + str(id_prefix) + '\t'
                for i in range(0, 10):
                    with HiddenPrints():
                        binvalue = int(
                            self.controller.register_read(
                                'sw', (id_prefix * 10) + i))
                    tmp = tmp + str(binvalue) + ','
                    sw.append(binvalue)
                tmp = tmp[:-1]
                self.log_sw.info(str(tmp))

        # Print log about rerouting
        for host in list(self.topo.get_hosts()):
            prefix = self.topo.get_host_ip(host) + '/24'

            for id_prefix in [
                    self.mapping_dic[host] * 2, self.mapping_dic[host] * 2 + 1
            ]:

                with HiddenPrints():
                    nh_avaibility_1 = self.controller.register_read(
                        'nh_avaibility_1', index=id_prefix)
                    nh_avaibility_2 = self.controller.register_read(
                        'nh_avaibility_2', index=id_prefix)
                    nh_avaibility_3 = self.controller.register_read(
                        'nh_avaibility_3', index=id_prefix)
                    nbflows_progressing_2 = self.controller.register_read(
                        'nbflows_progressing_2', index=id_prefix)
                    nbflows_progressing_3 = self.controller.register_read(
                        'nbflows_progressing_3', index=id_prefix)
                    rerouting_ts = self.controller.register_read(
                        'rerouting_ts', index=id_prefix)
                    threshold = self.controller.register_read(
                        'threshold_registers', index=id_prefix)

                self.log_rerouting.info('nh_avaibility\t'+host+'\t'+prefix+'\t'+ \
                str(id_prefix)+'\t'+str(nh_avaibility_1)+'\t'+ \
                str(nh_avaibility_2)+'\t'+str(nh_avaibility_3))
                self.log_rerouting.info('nblows_progressing\t'+host+'\t'+prefix+'\t'+ \
                str(id_prefix)+'\t'+str(nbflows_progressing_2)+'\t'+ \
                str(nbflows_progressing_3))
                self.log_rerouting.info('rerouting_ts\t'+host+'\t'+prefix+'\t'+ \
                str(id_prefix)+'\t'+str(rerouting_ts))
                self.log_rerouting.info('threshold\t'+host+'\t'+prefix+'\t'+ \
                str(id_prefix)+'\t'+str(threshold))

                nexthop_str = ''
                nha = [nh_avaibility_1, nh_avaibility_2, nh_avaibility_3]
                i = 0
                if self.routing_file is not None:
                    bgp_type = 'customer' if id_prefix % 2 == 0 else 'customer_provider_peer'
                    if bgp_type not in self.topo_routing['switches'][
                            self.sw_name]['prefixes'][host]:
                        nexthop_str = 'NoPathAvailable'
                    else:
                        if len(self.topo_routing['switches'][self.sw_name]
                               ['prefixes'][host][bgp_type]) == 2:
                            self.topo_routing['switches'][self.sw_name][
                                'prefixes'][host][bgp_type].append(
                                    self.topo_routing['switches'][self.sw_name]
                                    ['prefixes'][host][bgp_type][-1])
                        for nexthop in self.topo_routing['switches'][
                                self.sw_name]['prefixes'][host][bgp_type]:
                            tmp = 'y' if nha[i] == 0 else 'n'
                            nexthop_str = nexthop_str + str(
                                nexthop) + '(' + tmp + ')\t'
                            i += 1
                        nexthop_str = nexthop_str[:-1]
                self.log_rerouting.info('nexthop\t'+host+'\t'+prefix+'\t'+ \
                str(id_prefix)+'\t'+str(nexthop_str))

        # Print log about the flow selector
        for host in list(self.topo.get_hosts()):
            prefix = self.topo.get_host_ip(host) + '/24'

            for id_prefix in [
                    self.mapping_dic[host] * 2, self.mapping_dic[host] * 2 + 1
            ]:

                sw = []
                tmp = 'fs_key ' + host + ' ' + prefix + ' ' + str(
                    id_prefix) + '\t'
                for i in range(0, 64):
                    with HiddenPrints():
                        binvalue = int(
                            self.controller.register_read(
                                'flowselector_key', 64 * id_prefix + i))
                    tmp = tmp + str(binvalue) + ','
                    sw.append(binvalue)
                tmp = tmp[:-1]
                self.log_fs.info(str(tmp))

                sw = []
                tmp = 'fs ' + host + ' ' + prefix + ' ' + str(id_prefix) + '\t'
                for i in range(0, 64):
                    with HiddenPrints():
                        binvalue = int(
                            self.controller.register_read(
                                'flowselector_ts', 64 * id_prefix + i))
                    tmp = tmp + str(binvalue) + ','
                    sw.append(binvalue)
                tmp = tmp[:-1]
                self.log_fs.info(str(tmp))

                sw = []
                tmp = 'fs_last_ret ' + host + ' ' + prefix + ' ' + str(
                    id_prefix) + '\t'
                for i in range(0, 64):
                    with HiddenPrints():
                        binvalue = int(
                            self.controller.register_read(
                                'flowselector_last_ret', 64 * id_prefix + i))
                    tmp = tmp + str(binvalue) + ','
                    sw.append(binvalue)
                tmp = tmp[:-1]
                self.log_fs.info(str(tmp))

                sw = []
                tmp = 'fs_last_ret_bin ' + host + ' ' + prefix + ' ' + str(
                    id_prefix) + '\t'
                for i in range(0, 64):
                    with HiddenPrints():
                        binvalue = int(
                            self.controller.register_read(
                                'flowselector_last_ret_bin',
                                64 * id_prefix + i))
                    tmp = tmp + str(binvalue) + ','
                    sw.append(binvalue)
                tmp = tmp[:-1]
                self.log_fs.info(str(tmp))

                sw = []
                tmp = 'fs_fwloops ' + host + ' ' + prefix + ' ' + str(
                    id_prefix) + '\t'
                for i in range(0, 64):
                    with HiddenPrints():
                        binvalue = int(
                            self.controller.register_read(
                                'flowselector_fwloops', 64 * id_prefix + i))
                    tmp = tmp + str(binvalue) + ','
                    sw.append(binvalue)
                tmp = tmp[:-1]
                self.log_fs.info(str(tmp))

                sw = []
                tmp = 'fs_correctness ' + host + ' ' + prefix + ' ' + str(
                    id_prefix) + '\t'
                for i in range(0, 64):
                    with HiddenPrints():
                        binvalue = int(
                            self.controller.register_read(
                                'flowselector_correctness',
                                64 * id_prefix + i))
                    tmp = tmp + str(binvalue) + ','
                    sw.append(binvalue)
                tmp = tmp[:-1]
                self.log_fs.info(str(tmp))

    def forwarding(self):
        p4switches = self.topo.get_p4switches()
        interfaces_to_node = p4switches[self.sw_name]['interfaces_to_node']

        for k, v in interfaces_to_node.items():

            try:
                dst_mac = self.topo.get_hosts()[v][self.sw_name]['mac']
            except KeyError:
                dst_mac = self.topo.get_p4switches()[v][self.sw_name]['mac']

            src_mac = p4switches[self.sw_name][v]['mac']
            outport = p4switches[self.sw_name]['interfaces_to_port'][
                p4switches[self.sw_name][v]['intf']]

            self.log.info('table add send set_nh ' + str(self.mapping_dic[v]) +
                          ' => ' + str(outport) + ' ' + str(src_mac) + ' ' +
                          str(dst_mac))
            self.controller.table_add(
                'send', 'set_nh', [str(self.mapping_dic[v])],
                [str(outport), str(src_mac),
                 str(dst_mac)])

    def run(self):

        sock_list = [self.sock_controller]
        controller_data = ''

        while True:
            inready, outready, excepready = select.select(sock_list, [], [])

            for sock in inready:
                if sock == self.sock_controller:
                    data_tmp = ''
                    toreturn = None

                    try:
                        data_tmp = sock.recv(100000000)
                    except socket.error, e:
                        err = e.args[0]
                        if not (err == errno.EAGAIN
                                or err == errno.EWOULDBLOCK):
                            print 'p4_to_controller: ', e
                            sock.close()
                            sock = None

                    if len(data_tmp) > 0:
                        controller_data += data_tmp

                        next_data = ''
                        while len(controller_data
                                  ) > 0 and controller_data[-1] != '\n':
                            next_data = controller_data[-1] + next_data
                            controller_data = controller_data[:-1]

                        toreturn = controller_data
                        controller_data = next_data

                    if toreturn is not None:
                        for line in toreturn.split('\n'):
                            if line.startswith('table add '):
                                line = line.rstrip('\n').replace(
                                    'table add ', '')

                                fwtable_name = line.split(' ')[0]
                                action_name = line.split(' ')[1]

                                match_list = line.split(' => ')[0].split(
                                    ' ')[2:]
                                action_list = line.split(' => ')[1].split(' ')

                                print line
                                print fwtable_name, action_name, match_list, action_list

                                self.log.info(line)
                                self.controller.table_add(fwtable_name, action_name, \
                                    match_list, action_list)

                            if line.startswith('do_register_write'):
                                line = line.rstrip('\n')
                                linetab = line.split(' ')

                                register_name = linetab[1]
                                index = int(linetab[2])
                                value = int(linetab[3])

                                self.log.info(line)
                                self.controller.register_write(register_name, \
                                    index, value)

                            if line.startswith('reset_states'):
                                self.log.info('RESETTING_STATES')

                                # First stop the scheduler to avoid concurrent used
                                # of the Thirft server
                                self.t_sched.cancel()
                                while self.t_sched.running:  # Wait the end of the log printing
                                    time.sleep(0.5)

                                time.sleep(1)

                                # Reset the state of the switch
                                self.controller.register_reset(
                                    'nh_avaibility_1')
                                self.controller.register_reset(
                                    'nh_avaibility_2')
                                self.controller.register_reset(
                                    'nh_avaibility_3')
                                self.controller.register_reset(
                                    'nbflows_progressing_2')
                                self.controller.register_reset(
                                    'nbflows_progressing_3')
                                self.controller.register_reset('rerouting_ts')
                                self.controller.register_reset(
                                    'timestamp_reference')
                                self.controller.register_reset('sw_time')
                                self.controller.register_reset('sw_index')
                                self.controller.register_reset('sw_sum')
                                self.controller.register_reset('sw')
                                self.controller.register_reset(
                                    'flowselector_key')
                                self.controller.register_reset(
                                    'flowselector_nep')
                                self.controller.register_reset(
                                    'flowselector_ts')
                                self.controller.register_reset(
                                    'flowselector_last_ret')
                                self.controller.register_reset(
                                    'flowselector_last_ret_bin')
                                self.controller.register_reset(
                                    'flowselector_correctness')
                                self.controller.register_reset(
                                    'flowselector_fwloops')

                                print self.sw_name, ' RESET.'

                                # Restart the scheduler
                                time.sleep(1)
                                self.t_sched.start()
class L2Controller(object):
    def __init__(self, sw_name):
        self.topo = Topology(db="topology.db")
        self.sw_name = sw_name
        self.thrift_port = self.topo.get_thrift_port(sw_name)
        self.cpu_port = self.topo.get_cpu_port_index(self.sw_name)
        self.controller = SimpleSwitchAPI(self.thrift_port)

        self.init()

    def init(self):
        self.controller.reset_state()
        self.add_boadcast_groups()
        self.add_mirror()

    def add_mirror(self):
        if self.cpu_port:
            self.controller.mirroring_add(100, self.cpu_port)

    def add_boadcast_groups(self):
        interfaces_to_port = self.topo[
            self.sw_name]["interfaces_to_port"].copy()
        # filter lo and cpu port
        interfaces_to_port.pop('lo', None)
        interfaces_to_port.pop(self.topo.get_cpu_port_intf(self.sw_name), None)

        mc_grp_id = 1
        rid = 0
        for ingress_port in interfaces_to_port.values():

            port_list = interfaces_to_port.values()[:]
            del (port_list[port_list.index(ingress_port)])

            #add multicast group
            self.controller.mc_mgrp_create(mc_grp_id)

            #add multicast node group
            handle = self.controller.mc_node_create(rid, port_list)

            #associate with mc grp
            self.controller.mc_node_associate(mc_grp_id, handle)

            #fill broadcast table
            self.controller.table_add("broadcast", "set_mcast_grp",
                                      [str(ingress_port)], [str(mc_grp_id)])

            mc_grp_id += 1
            rid += 1

    def learn_route(self, learning_data):
        for mac_addr, ingress_port in learning_data:
            print "mac: %012X ingress_port: %s " % (mac_addr, ingress_port)
            self.controller.table_add("smac", "NoAction", [str(mac_addr)])
            self.controller.table_add("dmac", "forward", [str(mac_addr)],
                                      [str(ingress_port)])

    def learn_connection(self, srcA, dstA, srcP, dstP):
        print("========== UPDATING CONNECTION ==========")
        connection = srcA
        connection = connection << 32
        connection = connection | dstA
        connection = connection << 16
        connection = connection | srcP
        connection = connection << 16
        connection = connection | dstP
        self.controller.table_add("tcp_forward", "NoAction", [str(connection)],
                                  [])

        connection = dstA
        connection = connection << 32
        connection = connection | srcA
        connection = connection << 16
        connection = connection | dstP
        connection = connection << 16
        connection = connection | srcP
        self.controller.table_add("tcp_forward", "NoAction", [str(connection)],
                                  [])

        print("========== UPDATE FINISHED ==========")

    def recv_msg_cpu(self, pkt):
        packet = Ether(str(pkt))

        if packet.type == 0x1234:
            learning = CpuRoute(packet.payload)
            print("got a packet of type route")
            self.learn_route([(learning.macAddr, learning.ingress_port)])
        if packet.type == 0xF00D:
            learning = CpuCookie(packet.payload)
            print("got a packet of type cookie")
            self.learn_connection(learning.srcAddr, learning.dstAddr,
                                  learning.srcPort, learning.dstPort)

    def run_cpu_port_loop(self):
        cpu_port_intf = str(
            self.topo.get_cpu_port_intf(self.sw_name).replace("eth0", "eth1"))
        sniff(iface=cpu_port_intf, prn=self.recv_msg_cpu)