示例#1
0
    def __init__(self, sw_name, vtables_num=8):
        self.topo = Topology(db="../p4/topology.db")
        self.sw_name = sw_name
        self.thrift_port = self.topo.get_thrift_port(self.sw_name)
        self.cpu_port = self.topo.get_cpu_port_index(self.sw_name)
        self.controller = SimpleSwitchAPI(self.thrift_port)

        self.custom_calcs = self.controller.get_custom_crc_calcs()
        self.sketch_register_num = len(self.custom_calcs)

        self.vtables = []
        self.vtables_num = vtables_num

        # create a pool of ids (as much as the total amount of keys)
        # this pool will be used to assign index to keys which will be
        # used to index the cached key counter and the validity register
        self.ids_pool = range(0, VTABLE_ENTRIES * VTABLE_SLOT_SIZE)

        # array of bitmap, which marks available slots per cache line
        # as 0 bits and occupied slots as 1 bits
        self.mem_pool = [0] * VTABLE_ENTRIES

        # number of memory slots used (useful for lfu eviction policy)
        self.used_mem_slots = 0

        # dictionary storing the value table index, bitmap and counter/validity
        # register index in the P4 switch that corresponds to each key
        self.key_map = {}

        self.setup()
示例#2
0
class ReadCounter(object):
    def __init__(self):
        
        self.topo        = Topology(db="topology.db")
        self.controllers = {}
        self.init()

    def init(self):
        self.connect_to_switches()

    def connect_to_switches(self):
        for p4switch in self.topo.get_p4switches():
            thrift_port = self.topo.get_thrift_port(p4switch)
            self.controllers[p4switch] = SimpleSwitchAPI(thrift_port)

    def read_indirect_counters(self):

        for sw_name, controller in self.controllers.items():
            for i in range(10):
                self.controllers[sw_name].counter_read("port_counter", i)

    def read_direct_counters(self):

        for sw_name, controller in self.controllers.items():
            num_table_entries = self.controllers[sw_name].table_num_entries('ipv4_lpm')
            for i in range(int(num_table_entries)):
                self.controllers[sw_name].counter_read("direct_port_counter", i)
示例#3
0
class RoutingController(object):

    def __init__(self):
        self.topo = Topology(db="topology.db")
        self.controllers = {}
        self.init()

    def init(self):
        self.connect_to_switches()
        self.reset_states()
        self.set_table_defaults()

    def connect_to_switches(self):
        for p4switch in self.topo.get_p4switches():
            thrift_port = self.topo.get_thrift_port(p4switch)
            self.controllers[p4switch] = SimpleSwitchAPI(thrift_port)

    def reset_states(self):
        [controller.reset_state() for controller in self.controllers.values()]

    def set_table_defaults(self):
        for controller in self.controllers.values():
            controller.table_set_default("dmac", "drop", [])

    def route(self):
        k = int(sys.argv[1])

        for sw_name, controller in self.controllers.items():
            # TODO: forwarding rules for all switches

    def main(self):
        self.route()
 def __init__(self, sw_name, topology_db_file="./topology.db"):
     self.topo = Topology(db=topology_db_file)
     # print(self.topo)
     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 = SimpleSwitchAPIAsyncWrapper(self.thrift_port)
示例#5
0
class NCacheController(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(self.sw_name)
        self.cpu_port = self.topo.get_cpu_port_index(self.sw_name)
        self.controller = SimpleSwitchAPI(self.thrift_port)

        self.custom_calcs = self.controller.get_custom_crc_calcs()
        self.sketch_register_num = len(self.custom_calcs)

        self.setup()

    def setup(self):
        if self.cpu_port:
            self.controller.mirroring_add(CONTROLLER_MIRROR_SESSION,
                                          self.cpu_port)

    # set a static allocation scheme for l2 forwarding where the mac address of
    # each host is associated with the port connecting this host to the switch
    def set_forwarding_table(self):
        for host in self.topo.get_hosts_connected_to(self.sw_name):
            port = self.topo.node_to_node_port_num(self.sw_name, host)
            host_mac = self.topo.get_host_mac(host)
            print str(host_mac) + str(port)
            self.controller.table_add("l2_forward", "set_egress_port",
                                      [str(host_mac)], [str(port)])

    def main(self):
        self.set_forwarding_table()
def send_packet(interface, args, program):

    # a l2 implementation
    #dstAddr = socket.gethostbyname(args.d)
    #print(socket.getaddrinfo(sys.argv[1], None, 0, socket.SOCK_STREAM))
    #ether_dst = get_dst_mac(dstAddr)
    #if not ether_dst:
    #    print "Mac address for %s was not found in the ARP table" % dstAddr
    #    exit(1)
    #pkt= Ether(src=get_if_hwaddr(interface),dst=ether_dst)
    #pkt=pkt/IP(dst=dstAddr)

    #warning!
    #if want to send TCP ,must change the parser of p4

    if program == "f":
        topo = Topology(db="../p4src_flowsize/topology.db")  #set the topology
    elif program == "i":
        topo = Topology(db="../p4src_interval/topology.db")  #set the topology
    dstAddr = topo.get_host_ip(args.d)
    pkt = IP(dst=dstAddr)
    if args.type == "tcp":
        pkt = pkt / TCP()
    elif args.type == "udp":
        pkt = pkt / UDP()
        pkt = pkt / flag() / "load0load1load2load3"
    else:
        pkt = pkt / ICMP()
    while True:
        raw_input("Testing! Press the return key to send a packet using " +
                  args.type.lower())
        print "Sending on interface %s \n" % (interface)
        #sendp(pkt, iface=iface, verbose=False)
        for i in range(args.number):
            send(pkt)
示例#7
0
class RoutingController(object):
    def __init__(self):

        self.topo = Topology(db="topology.db")
        self.controllers = {}
        self.init()

    def init(self):
        self.connect_to_switches()
        self.reset_states()
        self.set_table_defaults()

    def reset_states(self):
        [controller.reset_state() for controller in self.controllers.values()]

    def connect_to_switches(self):
        for p4switch in self.topo.get_p4switches():
            thrift_port = self.topo.get_thrift_port(p4switch)
            self.controllers[p4switch] = SimpleSwitchAPI(thrift_port)

    def set_table_defaults(self):
        for controller in self.controllers.values():
            controller.table_set_default("ipv4_lpm", "drop", [])
            controller.table_set_default("ecmp_group_to_nhop", "drop", [])

    def route(self):
        """implement this function"""

    def main(self):
        self.route()
示例#8
0
class RoutingController(object):

    def __init__(self):

        self.topo = Topology(db="topology.db")
        self.controllers = {}
        self.init()

    def init(self):
        self.connect_to_switches()
        self.reset_states()
        self.set_table_defaults()

    def reset_states(self):
        [controller.reset_state() for controller in self.controllers.values()]

    def connect_to_switches(self):
        for p4switch in self.topo.get_p4switches():
            thrift_port = self.topo.get_thrift_port(p4switch)
            self.controllers[p4switch] = SimpleSwitchAPI(thrift_port)

    def set_table_defaults(self):
        for controller in self.controllers.values():
            controller.table_set_default("ipv4_lpm", "drop", [])

    def route(self):


    def main(self):
        self.route()


if __name__ == "__main__":
    controller = RoutingController().main()
示例#9
0
 def __init__(self):
     self.topo = Topology(db="./topology.db")  #set the topology
     self.controllers = {}                   #the switches
     self.custom_calcs={}
     self.register_num={}
     self.registers={}
     self.init()
示例#10
0
 def __init__(self, sw_name):
     self.sw_name = sw_name
     self.topo = Topology(db='topology.db')
     self.thrift_port = self.topo.get_thrift_port(sw_name)
     self.controller = SimpleSwitchAPI(self.thrift_port)
     self.sub = None
     self.flag = 1
示例#11
0
    def __init__(self, sw_name):

        self.sw_name = sw_name
        self.topo = Topology(db="topology.db")
        self.sw_name = sw_name
        self.thrift_port = self.topo.get_thrift_port(sw_name)
        self.controller = SimpleSwitchAPI(self.thrift_port)
示例#12
0
 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.controller = SimpleSwitchAPI(self.thrift_port)
     self.registers = []
     self.cpu_port_intf = str(
         self.topo.get_cpu_port_intf(self.sw_name).replace("eth0", "eth1"))
示例#13
0
class RoutingController(object):

    def __init__(self):

        self.topo = Topology(db="topology.db")
        self.controllers = {}
        self.init()

    def init(self):
        self.connect_to_switches()
        self.reset_states()
        self.set_table_defaults()

    def reset_states(self):
        [controller.reset_state() for controller in self.controllers.values()]

    def connect_to_switches(self):
        for p4switch in self.topo.get_p4switches():
            thrift_port = self.topo.get_thrift_port(p4switch)
            self.controllers[p4switch] = SimpleSwitchAPI(thrift_port)

    def set_table_defaults(self):
        for controller in self.controllers.values():
            controller.table_set_default("ipv4_lpm", "drop", [])
            


    def ipv4_lpm(self,sw):
        for host in self.topo.get_hosts_connected_to("s1"):
            dstip=self.topo.get_host_ip(host)
            shortestways=self.topo.get_shortest_paths_between_nodes(sw, host)
            nhopmac=self.topo.node_to_node_mac(shortestways[0][1],sw)
            nhopport=self.topo.node_to_node_port_num(sw, shortestways[0][1])
            self.controllers[sw].table_add("ipv4_lpm", "set_nhop", [dstip+'/24'],[nhopmac, str(nhopport)])
            print("From switch "+str(sw)+" to host "+str(dstip)+", next hop is "+str(shortestways[0][1])+", egress port is "+str(nhopport)+'\n')

        for sw2 in self.controllers.keys():
            if sw==sw2 :
                continue
            shortestways=self.topo.get_shortest_paths_between_nodes(sw, sw2)
            nhopmac=self.topo.node_to_node_mac(shortestways[0][1],sw)
            nhopport=self.topo.node_to_node_port_num(sw, shortestways[0][1])
            dstip="20.0."+str(sw2[1:])+".0/24"
            self.controllers[sw].table_add("ipv4_lpm", "set_nhop", [dstip],[nhopmac, str(nhopport)])
            print("From switch "+str(sw)+" to switch "+str(sw2)+" at "+str(dstip)+", next hop is "+str(shortestways[0][1])+", egress port is "+str(nhopport)+'\n')
    def op(self,sw):
        self.controllers[sw].table_add("op","NetChain_insert",[str(3)],[])
        self.controllers[sw].table_add("op","NetChain_delete",[str(4)],[])
    def pkt_for_me(self,sw):
        self.controllers[sw].table_add("pkt_for_me", "NoAction", ["20.0."+str(sw[1:])+".0/24",'35678'],[])

    def seq(self,sw):
        self.controllers[sw].table_add("seq","assignseq",[str(0)],[])
                
    def read_write_trans(self,sw):
            self.controllers[sw].table_add("read_write_trans","NetChain_write",["20.0."+str(sw[1:])+".1",str(1)],[])
            self.controllers[sw].table_add("read_write_trans","NetChain_read",["20.0."+str(sw[1:])+".1",str(2)],[])
            self.controllers[sw].table_add("read_write_trans","NetChain_transfer",["20.0."+str(sw[1:])+".1",str(6)],[])
示例#14
0
 def __init__(self, program):
     if program == "f":
         self.topo = Topology(
             db="../p4src_flowsize/topology.db")  #set the topology
     elif program == "i":
         self.topo = Topology(
             db="../p4src_interval/topology.db")  #set the topology
     self.controllers = {}  #the switches
     self.init()
示例#15
0
 def __init__(self):
     self.topo = Topology(db='topology.db')
     dic = self.topo.get_p4switches()
     self.sw_name = [sw for sw in dic.keys()]
     self.controller = {
         sw: SimpleSwitchAPI(self.topo.get_thrift_port(sw))
         for sw in self.sw_name
     }
     self.multicast_table = dict()
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)
示例#17
0
    def __init__(self, sw_name):
        self.topo = Topology(db="./topology.db")
        self.sw_name = sw_name
        self.thrift_port = self.topo.get_thrift_port(self.sw_name)
        self.cpu_port = self.topo.get_cpu_port_index(self.sw_name)
        self.controller = SimpleSwitchAPI(self.thrift_port)

        self.custom_calcs = self.controller.get_custom_crc_calcs()
        self.sketch_register_num = len(self.custom_calcs)

        self.setup()
示例#18
0
    def __init__(self, sw_name, iface_name, logf):
        self.sw_name = str(sw_name)
        self.iface_name = str(iface_name)
        self.topo = Topology(db="./topology.db")
        self.logf = logf

        self.thrift_port = self.topo.get_thrift_port(sw_name)
        self.counter = 1

        logf = open(self.logf, "w")
        logf.write(self.sw_name + "-" + self.iface_name + "\n")
        logf.close()
示例#19
0
    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.controller = SimpleSwitchAPI(self.thrift_port)

        self.custom_calcs = self.controller.get_custom_crc_calcs()
        self.register_num =  len(self.custom_calcs)

        self.init()
        self.registers = []
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
示例#21
0
    def __init__(self, sw_name, program):
        threading.Thread.__init__(self)
        if program == "f":
            self.topo = Topology(
                db="../p4src_flowsize/topology.db")  #set the topology
        elif program == "i":
            self.topo = Topology(
                db="../p4src_interval/topology.db")  #set the topology

        self.program = program
        self.sw_name = sw_name
        self.thrift_port = self.topo.get_thrift_port(sw_name)
        self.controller = SimpleSwitchAPI(self.thrift_port)
示例#22
0
    def __init__(self, subnets=0):

        self.topo = Topology(db="topology.db")
        self.controllers = {}

        destination_subnets = self.generate_ips("10.0.1.0/24", "10.250.250.0/24")
        h2 = destination_subnets[0]
        h3  = destination_subnets[-1]
        #remove them
        destination_subnets = destination_subnets[1:-1]
        #filter entries
        destination_subnets = destination_subnets[:subnets]
        # put them back
        destination_subnets = [h2] + destination_subnets + [h3]
        self.destination_subnets= destination_subnets
示例#23
0
class P4Obj:
    """Utility class for p4run-related stuff. Given by the p4run fixture."""
    def __init__(self, workdir):
        self.topo_path = os.path.join(workdir, "topology.db")
        self.topo = Topology(self.topo_path)

    def host_IPs(self):
        """Returns a dict of hosts and IPs.

        Returns the first IP of a host if there are multiple.
        """
        return { h: self.topo.get_host_ip(h) for h in self.topo.get_hosts() }

    def iponly(self, ip):
        """Utility function to strip netmask from IP: iponly('10.0.0.1/24') => '10.0.0.1'"""
        return ip.split('/')[0]
示例#24
0
    def __init__(self, num_hashes=3):

        self.topo = Topology(db="topology.db")
        self.controllers = {}
        self.num_hashes = num_hashes

        # gets a controller API for each switch: {"s1": controller, "s2": controller...}
        self.connect_to_switches()
        # creates the 3 hashes that will use the p4 switch
        self.create_local_hashes()

        # initializes the switch
        # resets all registers, configures the 3 x 2 hash functions
        # reads the registers
        # populates the tables and mirroring id
        self.init()
        self.registers = {}
示例#25
0
    def __init__(self):
        """Initializes the topology and data structures."""

        if not os.path.exists("topology.db"):
            print "Could not find topology object!\n"
            raise Exception

        self.topo = Topology(db="topology.db")
        self.controllers = {}
        self.connect_to_switches()
        self.reset_states()

        # Preconfigure all MAC addresses
        self.install_macs()

        # Install nexthop indices and populate registers.
        self.install_nexthop_indices()
        self.update_nexthops()
示例#26
0
    def obtain_mininet_topo(self):
        topo = Topology(db="topology.db")
        for switch in self.all_switches:
            if switch not in self.switch_mapper:
                self.switch_mapper[switch] = {}

            host = switch.replace("s", "h")
            host_details = topo.node(host)
            ip_address = host_details[switch]["ip"].split("/")[0]
            self.host_ips[host] = ip_address

            switch_details = topo.node(switch)
            self.thrift_port[switch] = switch_details["thrift_port"]

            for interface, port in switch_details["interfaces_to_port"].items(
            ):
                if interface != "lo":
                    node = switch_details["interfaces_to_node"][interface]
                    self.switch_mapper[switch][node] = port
class CMSController(object):

    def __init__(self, sw_name, set_hash):

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

        self.custom_calcs = self.controller.get_custom_crc_calcs()
        self.register_num =  len(self.custom_calcs)

        self.init()
        self.registers = []

    def init(self):
        if self.set_hash:
            self.set_crc_custom_hashes()
        self.create_hashes()

    def set_forwarding(self):
        self.controller.table_add("forwarding", "set_egress_port", ['1'], ['2'])
        self.controller.table_add("forwarding", "set_egress_port", ['2'], ['1'])

    def reset_registers(self):
        for i in range(self.register_num):
            self.controller.register_reset("sketch{}".format(i))

    def flow_to_bytestream(self, flow):
        return socket.inet_aton(flow[0]) + socket.inet_aton(flow[1]) + struct.pack(">HHB",flow[2], flow[3], 6)

    def set_crc_custom_hashes(self):
        i = 0
        for custom_crc32, width in sorted(self.custom_calcs.items()):
            self.controller.set_crc32_parameters(custom_crc32, crc32_polinomials[i], 0xffffffff, 0xffffffff, True, True)
            i+=1

    def create_hashes(self):
        self.hashes = []
        for i in range(self.register_num):
            self.hashes.append(Crc(32, crc32_polinomials[i], True, 0xffffffff, True, 0xffffffff))

    #Implement below
    #TODO 1: implement the read_registers(self) function
    def read_registers(self):
        pass

    #TODO 2: implement the get_cms(self, flow, mod) function
    def get_cms(self, flow, mod):
        pass

    #TODO 3: implement the main function that decodes all the registers, and compares them to the ground truth
    def decode_registers(self, eps, n, mod, ground_truth_file="sent_flows.pickle"):
        pass
示例#28
0
class myController(object):
    def __init__(self):
        self.topo = Topology(db="topology.db")
        self.controllers = {}
        self.connect_to_switches()
 
    def connect_to_switches(self):
        for p4switch in self.topo.get_p4switches():
            thrift_port = self.topo.get_thrift_port(p4switch)
            #print "p4switch:", p4switch, "thrift_port:", thrift_port
            self.controllers[p4switch] = SimpleSwitchAPI(thrift_port)   
 
    def recv_msg_cpu(self, pkt):
        print "interface:", pkt.sniffed_on
        print "summary:", pkt.summary()
	global val1,val2

	if TCP in pkt and pkt[TCP].flags==2:
	  src = pkt.sprintf('{IP:%IP.src%}')
          dst = pkt.sprintf('{IP:%IP.dst%}')
          count1[(src, dst)] += 1
	  val1=count1[(src, dst)]
	  print "count1[",src,",",dst,"]=",count1[(src, dst)]
	if TCP in pkt and pkt[TCP].flags==18:
	  src = pkt.sprintf('{IP:%IP.src%}')
          dst = pkt.sprintf('{IP:%IP.dst%}')
          count2[(dst, src)] += 1
          val2=count2[(dst, src)]
	  print "count2[",dst,",",src,"]=",count2[(dst, src)]
	
	print "val1:", val1, " val2:", val2
        if (val1-val2>=3) and (TCP in pkt) and pkt[TCP].flags==2:
	   src = pkt.sprintf('{IP:%IP.src%}')
	   if src not in blockip:
             self.controllers["s1"].table_add("block_pkt", "_drop", [str(src)], [])
	     blockip.append(src) 
	   
     
    def run_cpu_port_loop(self):
        cpu_interfaces = [str(self.topo.get_cpu_port_intf(sw_name).replace("eth0", "eth1")) for sw_name in self.controllers]
        sniff(iface=cpu_interfaces, prn=self.recv_msg_cpu)
示例#29
0
class FillRegisters(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.controller = SimpleSwitchAPI(self.thrift_port)

    def fill_registers(self):

        for i in range(128):
            self.controller.register_write("recirculate_register", i, i)
class RoutingController(object):

    def __init__(self):
        self.topo = Topology(db="topology.db")
        self.controllers = {}
        self.init()

    def init(self):
        self.connect_to_switches()
        self.reset_states()
        self.set_table_defaults()

    # Establishes a connection with the simple switch `thrift` server 
    # using the `SimpleSwitchAPI` object 
    # and saves those objects in the `self.controllers` dictionary. 
    # This dictionary has the form of: `{'sw_name' : SimpleSwitchAPI()}`.
    def connect_to_switches(self):
        for p4switch in self.topo.get_p4switches():
            thrift_port = self.topo.get_thrift_port(p4switch)
            self.controllers[p4switch] = SimpleSwitchAPI(thrift_port)

    # Iterates over the `self.controllers` object 
    # and runs the `reset_state` function which empties the state 
    # (registers, tables, etc) for every switch.
    def reset_states(self):
        [controller.reset_state() for controller in self.controllers.values()]

    # For each P4 switch, it sets the default action for `dmac` table
    def set_table_defaults(self):
        for controller in self.controllers.values():
            controller.table_set_default("dmac", "drop", [])

    # Create forwarding rules for the dmac table
    def route(self):
        #TODO: install routing rules for circle topology
        print('ERROR: routes not installed\n')

    def main(self):
        self.route()