Exemplo n.º 1
0
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)
Exemplo n.º 2
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)],[])
Exemplo n.º 3
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]
        flow_size_max = length
        flow_gen_mode = 'perflow'
        per_flow_mode = 'tiled'
        num_flows = len(iperf_host_list) / 2
        gap_dist = 'persist'
        gap_max = length + 1000

    if mode == "mix":
        gen_memcached(mc_host_list, length)
    gen_iperf(iperf_host_list, length)

    traces = memcached_traces + iperf_traces
    traces.sort()

    f = open(out_file, "w")
    for i in mc_host_list:
        f.write(topo.get_host_ip("h%d" % i))
        f.write(' ')
    f.write("\n")

    for trace in traces:
        f.write("h%d " % trace[1])
        f.write("%f " % (trace[0] / 1000.0))
        if "." in trace[2]:
            f.write("2 %s %f\n" % (trace[2], trace[3] / 1000.0))
        else:
            if trace[3] == -1:
                f.write("1 %s\n" % trace[2])
            else:
                f.write("0 %s %d\n" % (trace[2], trace[3]))
import random
import time
from p4utils.utils.topology import Topology
from subprocess import Popen

topo = Topology(db="topology.db")

iperf_send = "mx {0} iperf3 -c {1} -M 9000 -t {2} --bind {3} -p {5} 2>&1 >/dev/null"
iperf_recv = "mx {0} iperf3 -s -p {1} --one-off 2>&1 >/dev/null"

Popen("sudo killall iperf iperf3", shell=True)

dst_port1 = random.randint(1024, 65000)
dst_port2 = random.randint(1024, 65000)

Popen(iperf_recv.format("h3", dst_port1), shell=True)
Popen(iperf_recv.format("h4", dst_port2), shell=True)

time.sleep(1)

import sys

duration = int(sys.argv[1])

Popen(iperf_send.format("h1", topo.get_host_ip("h3"), duration,
                        topo.get_host_ip("h1"), dst_port1, dst_port1),
      shell=True)
Popen(iperf_send.format("h2", topo.get_host_ip("h4"), duration,
                        topo.get_host_ip("h2"), dst_port2, dst_port2),
      shell=True)
Exemplo n.º 6
0
def demo(reactor):
    lines = WaitForLines()
    stdio.StandardIO(lines)

    ##### Preparation #######################################################

    # These are our servers.
    server_hosts = [
        # host, port, num CPUs
        ('h1', 9000, 1),
        ('h1', 9001, 2),
        ('h2', 9002, 4),
        ('h2', 9003, 8),
    ]

    # Run the server and client programs and get a "remote control" to them.
    servers = yield all_results([
        remote_module('myutils.server', port, ncpus, host=host)
        for host, port, ncpus in server_hosts
    ])
    clients = yield all_results([
        remote_module('myutils.client', host='h3'),
        remote_module('myutils.client', host='h4'),
    ])

    # Build an (ip, port) => server remote dict to use later.
    topo = Topology('./topology.db')
    server_IPs = {(topo.get_host_ip(h), p): remote
                  for (h, p, _), remote in zip(server_hosts, servers)}

    # Teach my load balancer controller how to get load from the servers.
    # In real life I could be e.g. SSHing into the servers, or using my
    # monitoring infrastructure.
    def get_load(ip, port):
        return server_IPs[(ip, port)].callRemote('get_load', 20)

    def set_weights(loads):
        return [1.0 / load for load in loads]

    # And start the controller.
    lb = yield MetricsLoadBalancer.get_initialised(
        's1', get_metrics=get_load, metrics_to_weights=set_weights)

    # Create a server pool on the loadbalancer.
    pool_handle = yield lb.add_pool('10.0.0.1', 8000)
    for ip, port in server_IPs.keys():
        yield lb.add_dip(pool_handle, ip, port)
    yield lb.commit()

    ##### Now the fun begins ################################################

    setup_graph(server_IPs, lb, 10)

    print('---------------- press Enter to start clients -----------------')
    yield lines.line_received

    @defer.inlineCallbacks
    def client0():
        """Client 0 will send long-running requests: closes after 10 seconds."""
        print('client0 running')
        yield clients[0].callRemote('start_echo_clients',
                                    '10.0.0.1',
                                    8000,
                                    count=4)
        yield sleep(10)
        yield clients[0].callRemote('close_all_connections')

    @defer.inlineCallbacks
    def client1():
        """Client 1 will send bursts of short connections (2s)."""
        print('client1 running')
        yield clients[1].callRemote('start_echo_clients',
                                    '10.0.0.1',
                                    8000,
                                    count=20)
        yield sleep(2)
        yield clients[1].callRemote('close_all_connections')

    # Run client0 every 13 seconds.
    task.LoopingCall(client0).start(13)

    # Run client1 every 4 seconds.
    task.LoopingCall(client1).start(3)

    print(
        '---------------- press Enter to start adjusting weights ----------------'
    )
    yield lines.line_received

    lb.start_loop()
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 get_conn_host_infos(self, p4switch):
        connected_hosts = self.topo.get_hosts_connected_to(p4switch)
        if connected_hosts:
            host = connected_hosts[0]
            switch_infos = self.topo.node(p4switch)
            host_mac = self.topo.get_host_mac(host)
            host_ip = self.topo.get_host_ip(host) + '/32'
            output_iface = self.topo.interface_to_port(
                p4switch, switch_infos[host]['intf'])
            return host_ip, host_mac, output_iface
        else:
            return None, None, None

    def add_ecmp_group(self, p4switch, ss_api, neigh, paths, ecmp_group):
        host_ip, host_mac, output_iface = self.get_conn_host_infos(neigh)
        if host_ip:
            next_hops = [path[1] for path in paths]
            dst_macs_ports = [
                (self.topo.node_to_node_mac(next_hop, p4switch),
                 self.topo.node_to_node_port_num(p4switch, next_hop))
                for next_hop in next_hops
            ]
            if ecmp_group.get(p4switch):
                if ecmp_group[p4switch].get(tuple(dst_macs_ports)):
                    ecmp_group[p4switch][tuple(
                        dst_macs_ports
                    )] = ecmp_group[p4switch][tuple(dst_macs_ports)] + 1
                else:
                    ecmp_group[p4switch][tuple(dst_macs_ports)] = 1
            else:
                ecmp_group[p4switch] = {}
                ecmp_group[p4switch][tuple(dst_macs_ports)] = 1

            print('Adding multipath entries')
            ss_api.table_add('ipv4_lpm', 'ecmp_group', [host_ip],
                             [str(1), str(len(next_hops))])
            index = 0
            for dst_mac_port in dst_macs_ports:
                ss_api.table_add(
                    'ecmp_group_to_nhop', 'set_nhop',
                    [str(1), str(index)],
                    [dst_mac_port[0], str(dst_mac_port[1])])
                index = index + 1

        return None

    def add_route_via_best(self, p4switch, ss_api, neigh, path):
        host_ip, host_mac, output_iface = self.get_conn_host_infos(neigh)
        if host_ip:
            neigh_mac = self.topo.node_to_node_mac(neigh, p4switch)
            output_iface = self.topo.node_to_node_port_num(p4switch, neigh)
            print('Add route via best', host_ip, neigh_mac, output_iface)
            ss_api.table_add('ipv4_lpm', 'set_nhop', [host_ip],
                             [neigh_mac, str(output_iface)])

    def add_directly_conn_host(self, p4switch, ss_api):
        host_ip, host_mac, output_iface = self.get_conn_host_infos(p4switch)
        if host_ip:
            print('Add directly connected route ', host_ip, host_mac,
                  output_iface)
            ss_api.table_add('ipv4_lpm', 'set_nhop', [host_ip],
                             [host_mac, str(output_iface)])

    def route(self):
        """implement this function"""
        ecmp_group = {}
        for p4switch, ss_api in self.controllers.items():
            for neigh in self.topo.get_p4switches():
                if p4switch == neigh:
                    # Check if we have connected hosts
                    self.add_directly_conn_host(p4switch, ss_api)
                else:
                    shortest_path = self.topo.get_shortest_paths_between_nodes(
                        p4switch, neigh)
                    if len(shortest_path) < 2:
                        # There is only 1 path
                        self.add_route_via_best(p4switch, ss_api, neigh,
                                                shortest_path)
                    else:
                        # multipath
                        self.add_ecmp_group(p4switch, ss_api, neigh,
                                            shortest_path, ecmp_group)

            #print(self.topo.node(p4switch)['interfaces_to_node'])
            #for iface, neigh in self.topo.node(p4switch)['interfaces_to_node'].items():
            #    print(self.topo.node_to_node_port_num(p4switch, neigh))

    def main(self):
        self.route()
import random
import time
from p4utils.utils.topology import Topology
from subprocess import Popen

topo = Topology(db="topology.db")

iperf_send = "mx {0} iperf3 -c {1} -M 9000 -t {2} --bind {3} --cport {4} -p {5} 2>&1 >/dev/null"
iperf_recv = "mx {0} iperf3 -s -p {1} --one-off 2>&1 >/dev/null"

Popen("sudo killall iperf iperf3", shell=True)

dst_port1 = random.randint(1024, 65000)
dst_port2 = random.randint(1024, 65000)

Popen(iperf_recv.format("h3", dst_port1), shell=True)
Popen(iperf_recv.format("h4", dst_port2), shell=True)

time.sleep(1)

import sys
duration = int(sys.argv[1])

Popen(iperf_send.format("h1", topo.get_host_ip("h3"), duration, topo.get_host_ip("h1"), dst_port1, dst_port1), shell=True)
Popen(iperf_send.format("h2", topo.get_host_ip("h4"), duration, topo.get_host_ip("h2"), dst_port2, dst_port2), shell=True)

Exemplo n.º 9
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()
        '''
        OPTIONS FOR DEMO
        '''
        self.apply_src_priority = True
        self.apply_dst_priority = False
        self.src_high_priority = 'h1'
        self.src_low_priority = 'h4'
        self.dst_high_priority = 'h5'
        self.dst_low_priority = 'h8'

    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 set_tables(self):
        # From project 6
        # Function outside of route() that sets the egress type table

        # loops through all switches
        for sw_name, controller in self.controllers.items():

            # gets the interface and node type
            for interface, node in self.topo.get_interfaces_to_node(
                    sw_name).items():

                node_type = self.topo.get_node_type(node)
                port_number = self.topo.interface_to_port(sw_name, interface)

                # numerates the node types to be put in the table
                if node_type == 'host':
                    node_type_num = 1

                    # NEW - CODE TO SET PRIORITY BASED ON HOST NUMBER
                    host_ip = self.topo.get_host_ip(node) + "/24"
                    priority_num = 2
                    if str(
                            node
                    ) == self.src_high_priority and self.apply_src_priority:
                        priority_num = 1
                    elif str(
                            node
                    ) == self.src_low_priority and self.apply_src_priority:
                        priority_num = 3
                    elif str(
                            node
                    ) == self.dst_high_priority and self.apply_dst_priority:
                        priority_num = 1
                    elif str(
                            node
                    ) == self.dst_low_priority and self.apply_dst_priority:
                        priority_num = 3
                    print "Node name: {}, ip address: {}, priority: {}".format(
                        str(node), str(host_ip), str(priority_num))
                    self.controllers[sw_name].table_add(
                        "priority_type", "set_priority", [str(host_ip)],
                        [str(priority_num)])
                    if self.apply_dst_priority:
                        self.controllers[sw_name].table_add(
                            "priority_type_dst", "set_priority",
                            [str(host_ip)], [str(priority_num)])

                elif node_type == 'switch':
                    node_type_num = 2

                # fills the table
                self.controllers[sw_name].table_add("egress_type", "set_type",
                                                    [str(port_number)],
                                                    [str(node_type_num)])

    def add_mirroring_ids(self):

        for sw_name, controller in self.controllers.items():
            # adding port 1 (it seems like the first argument is standard)
            controller.mirroring_add(100, 1)

    def route(self):

        switch_ecmp_groups = {
            sw_name: {}
            for sw_name in self.topo.get_p4switches().keys()
        }

        for sw_name, controller in self.controllers.items():

            for sw_dst in self.topo.get_p4switches():

                #if its ourselves we create direct connections
                if sw_name == sw_dst:
                    for host in self.topo.get_hosts_connected_to(sw_name):
                        sw_port = self.topo.node_to_node_port_num(
                            sw_name, host)
                        host_ip = self.topo.get_host_ip(host) + "/32"
                        host_mac = self.topo.get_host_mac(host)

                        #add rule
                        print "table_add at {}:".format(sw_name)
                        self.controllers[sw_name].table_add(
                            "ipv4_lpm", "set_nhop", [str(host_ip)],
                            [str(host_mac), str(sw_port)])

                #check if there are directly connected hosts
                else:
                    if self.topo.get_hosts_connected_to(sw_dst):
                        paths = self.topo.get_shortest_paths_between_nodes(
                            sw_name, sw_dst)
                        for host in self.topo.get_hosts_connected_to(sw_dst):

                            if len(paths) == 1:
                                next_hop = paths[0][1]

                                host_ip = self.topo.get_host_ip(host) + "/24"
                                sw_port = self.topo.node_to_node_port_num(
                                    sw_name, next_hop)
                                dst_sw_mac = self.topo.node_to_node_mac(
                                    next_hop, sw_name)

                                #add rule
                                print "table_add at {}:".format(sw_name)
                                self.controllers[sw_name].table_add(
                                    "ipv4_lpm", "set_nhop", [str(host_ip)],
                                    [str(dst_sw_mac),
                                     str(sw_port)])

                            elif len(paths) > 1:
                                next_hops = [x[1] for x in paths]
                                dst_macs_ports = [
                                    (self.topo.node_to_node_mac(
                                        next_hop, sw_name),
                                     self.topo.node_to_node_port_num(
                                         sw_name, next_hop))
                                    for next_hop in next_hops
                                ]
                                host_ip = self.topo.get_host_ip(host) + "/24"

                                #check if the ecmp group already exists. The ecmp group is defined by the number of next
                                #ports used, thus we can use dst_macs_ports as key
                                if switch_ecmp_groups[sw_name].get(
                                        tuple(dst_macs_ports), None):
                                    ecmp_group_id = switch_ecmp_groups[
                                        sw_name].get(tuple(dst_macs_ports),
                                                     None)
                                    print "table_add at {}:".format(sw_name)
                                    self.controllers[sw_name].table_add(
                                        "ipv4_lpm", "ecmp_group",
                                        [str(host_ip)], [
                                            str(ecmp_group_id),
                                            str(len(dst_macs_ports))
                                        ])

                                #new ecmp group for this switch
                                else:
                                    new_ecmp_group_id = len(
                                        switch_ecmp_groups[sw_name]) + 1
                                    switch_ecmp_groups[sw_name][tuple(
                                        dst_macs_ports)] = new_ecmp_group_id

                                    #add group
                                    for i, (mac,
                                            port) in enumerate(dst_macs_ports):
                                        print "table_add at {}:".format(
                                            sw_name)
                                        self.controllers[sw_name].table_add(
                                            "ecmp_group_to_nhop", "set_nhop",
                                            [str(new_ecmp_group_id),
                                             str(i)],
                                            [str(mac), str(port)])

                                    #add forwarding rule
                                    print "table_add at {}:".format(sw_name)
                                    self.controllers[sw_name].table_add(
                                        "ipv4_lpm", "ecmp_group",
                                        [str(host_ip)], [
                                            str(new_ecmp_group_id),
                                            str(len(dst_macs_ports))
                                        ])

    def main(self):
        self.set_tables()
        self.add_mirroring_ids()
        self.route()
Exemplo n.º 10
0
class GenFault(object):
    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()

    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 loop(self):
        switches = raw_input(
            "type the switch's name to gen loop,seperated by ','\nmust be physically loop-able:\n"
        ).split(',')

        IPs = []
        for sw_name in self.controllers.keys():
            for host in self.topo.get_hosts_connected_to(sw_name):
                host_ip = self.topo.get_host_ip(host) + "/24"
                IPs.append(host_ip)

        for i in range(len(switches)):
            sw_name = switches[i]
            self.controllers[sw_name].table_clear("ecmp_group_to_nhop")
            self.controllers[sw_name].table_clear("ipv4_lpm")

            #next_hop=NULL
            if i == len(switches) - 1:
                next_hop = switches[0]
            else:
                next_hop = switches[i + 1]

            sw_port = self.topo.node_to_node_port_num(sw_name, next_hop)
            dst_sw_mac = self.topo.node_to_node_mac(next_hop, sw_name)
            #print "table_add at {}:".format(sw_name)
            for host_ip in IPs:
                self.controllers[sw_name].table_add("ipv4_lpm", "set_nhop", [str(host_ip)],\
                                [str(dst_sw_mac), str(sw_port)])

    def blackhole(self, args):
        if args.sw_name == None:
            pass
            print "Not implemented yet,please specify the switch name"
        else:
            self.controllers[args.sw_name].table_clear("ecmp_group_to_nhop")
            self.controllers[args.sw_name].table_clear("ipv4_lpm")
            print args.sw_name, "has been shut down"

    def remove_cpu(self):
        # log=open("./router.log","w")
        # log.write(str(self.topo))

        print(1)
        print(self.topo.get_shortest_paths_between_nodes("s5", "h2"))
        # print(self.topo["sw-cpu"])
        # print(self.topo.network_graph["sw-cpu"])

        self.topo.network_graph.remove_node("sw-cpu")
        # self.topo.save("../p4src_interval/topology.db")
        # self.topo.load("../p4src_interval/topology.db")
        # del self.topo
        #self.topo=Topology(db="../p4src_interval/topology.db")
        print("\n\n\n\n\n")

        print(2)
        print(self.topo.get_shortest_paths_between_nodes("h1", "h8"))

        # print(self.topo["sw-cpu"])
        # print(self.topo.network_graph["sw-cpu"])

        # log=open("./router1.log","w")
        # log.write(str(self.topo))

    def reroute(self):
        #log=open("./router.log","w")
        #log.write(str(self.topo))
        self.topo.network_graph.remove_node("sw-cpu")
        switch_ecmp_groups = {
            sw_name: {}
            for sw_name in self.topo.get_p4switches().keys()
        }
        for sw_name, controllers in self.controllers.items():
            controllers.table_clear("ecmp_group_to_nhop")
            controllers.table_clear("ipv4_lpm")
            for sw_dst in self.topo.get_p4switches():
                #if its ourselves we create direct connections
                if sw_name == sw_dst:
                    for host in self.topo.get_hosts_connected_to(sw_name):
                        sw_port = self.topo.node_to_node_port_num(
                            sw_name, host)
                        host_ip = self.topo.get_host_ip(host) + "/32"
                        host_mac = self.topo.get_host_mac(host)

                        #add rule
                        print "table_add at {}:".format(sw_name)
                        # log.write("[1] table_add ipv4_lpm set_nhop at {} to host {} using port {}\n".format(sw_name,host,sw_port))
                        self.controllers[sw_name].table_add(
                            "ipv4_lpm", "set_nhop", [str(host_ip)],
                            [str(host_mac), str(sw_port)])

                #check if there are directly connected hosts
                else:
                    if self.topo.get_hosts_connected_to(sw_dst):
                        paths = self.topo.get_shortest_paths_between_nodes(
                            sw_name, sw_dst)
                        for host in self.topo.get_hosts_connected_to(sw_dst):

                            if len(paths) == 1:
                                next_hop = paths[0][1]

                                host_ip = self.topo.get_host_ip(host) + "/24"
                                sw_port = self.topo.node_to_node_port_num(
                                    sw_name, next_hop)
                                dst_sw_mac = self.topo.node_to_node_mac(
                                    next_hop, sw_name)

                                #add rule
                                print "table_add at {}:".format(sw_name)
                                # log.write("[2] table_add ipv4_lpm set_nhop at {} to host {} using port {} to nexthop {}\n".format(sw_name,host,sw_port,next_hop))
                                self.controllers[sw_name].table_add(
                                    "ipv4_lpm", "set_nhop", [str(host_ip)],
                                    [str(dst_sw_mac),
                                     str(sw_port)])

                            elif len(paths) > 1:
                                next_hops = [x[1] for x in paths]
                                dst_macs_ports = [
                                    (self.topo.node_to_node_mac(
                                        next_hop, sw_name),
                                     self.topo.node_to_node_port_num(
                                         sw_name, next_hop))
                                    for next_hop in next_hops
                                ]
                                host_ip = self.topo.get_host_ip(host) + "/24"

                                #check if the ecmp group already exists. The ecmp group is defined by the number of next
                                #ports used, thus we can use dst_macs_ports as key
                                if switch_ecmp_groups[sw_name].get(
                                        tuple(dst_macs_ports), None):
                                    ecmp_group_id = switch_ecmp_groups[
                                        sw_name].get(tuple(dst_macs_ports),
                                                     None)
                                    print "table_add at {}:".format(sw_name)
                                    # log.write("[3] table_add ipv4_lpm ecmp_group at {} to switch {} to paths{}\n".format(sw_name,sw_dst,paths))
                                    self.controllers[sw_name].table_add(
                                        "ipv4_lpm", "ecmp_group",
                                        [str(host_ip)], [
                                            str(ecmp_group_id),
                                            str(len(dst_macs_ports))
                                        ])

                                #new ecmp group for this switch
                                else:
                                    new_ecmp_group_id = len(
                                        switch_ecmp_groups[sw_name]) + 1
                                    switch_ecmp_groups[sw_name][tuple(
                                        dst_macs_ports)] = new_ecmp_group_id

                                    #add group
                                    for i, (mac,
                                            port) in enumerate(dst_macs_ports):
                                        print "table_add at {}:".format(
                                            sw_name)
                                        #log.write("[4] table_add ipv4_lpm ecmp_group at {} to switch {} to paths{}\n".format(sw_name,sw_dst,paths))
                                        # log.write("[4] table_add ipv4_lpm ecmp_group at {} to switch {} using port {}\n".format(sw_name,sw_dst,port))
                                        self.controllers[sw_name].table_add(
                                            "ecmp_group_to_nhop", "set_nhop",
                                            [str(new_ecmp_group_id),
                                             str(i)],
                                            [str(mac), str(port)])

                                    #add forwarding rule
                                    print "table_add at {}:".format(sw_name)
                                    # log.write("[5] table_add ipv4_lpm ecmp_group at {} to switch {} to paths{}\n".format(sw_name,sw_dst,paths))

                                    self.controllers[sw_name].table_add(
                                        "ipv4_lpm", "ecmp_group",
                                        [str(host_ip)], [
                                            str(new_ecmp_group_id),
                                            str(len(dst_macs_ports))
                                        ])
Exemplo n.º 11
0
class FlowtableManager(object):
    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()

    def add_forward_table(self):
        host_list = [h for h in self.topo.get_hosts().keys()]
        for src in self.sw_name:
            self.controller[src].table_set_default('ingress.ipv4_c.ipv4',
                                                   'drop', [])
            direct_sw_list = self.topo.get_switches_connected_to(src)
            for sw in direct_sw_list:
                port = self.topo.node_to_node_port_num(src, sw)
                self.controller[src].table_add(
                    'egress.mac_c.adjust_mac', 'set_mac', [str(port)], [
                        str(self.topo.node_to_node_mac(src, sw)),
                        str(self.topo.node_to_node_mac(sw, src))
                    ])
            direct_host_list = self.topo.get_hosts_connected_to(src)
            for h in direct_host_list:
                ip = self.topo.get_host_ip(h)
                port = self.topo.node_to_node_port_num(src, h)
                self.controller[src].table_add('ingress.ipv4_c.ipv4',
                                               'forward', [str(ip) + '/32'],
                                               [str(port)])
                self.controller[src].table_add(
                    'egress.mac_c.adjust_mac', 'set_mac', [str(port)], [
                        str(self.topo.node_to_node_mac(src, h)),
                        str(self.topo.node_to_node_mac(h, src))
                    ])
            indirect_host_list = list(
                set(host_list).difference(direct_host_list))
            for h in indirect_host_list:
                ip = self.topo.get_host_ip(h)
                path = self.topo.get_shortest_paths_between_nodes(src, h)[0]
                port = self.topo.node_to_node_port_num(src, path[1])
                self.controller[src].table_add('ingress.ipv4_c.ipv4',
                                               'forward', [str(ip) + '/32'],
                                               [str(port)])

    def add_multicast_table(self):
        for sw in self.sw_name:
            self.multicast_table.update({sw: {}})
            port = self.topo.get_interfaces_to_port(sw)
            num = len(port) - 1
            if sw + '-cpu-eth0' in port.keys():
                num -= 1
            self.controller[sw].mc_mgrp_create('1')
            for i in range(int(comb(num, 2))):
                self.controller[sw].mc_mgrp_create(str(i + 2))
            port_list = []
            for i in range(num):
                port_list.append(str(i + 1))
            self.controller[sw].mc_node_create('0', port_list)
            self.controller[sw].mc_node_associate('1', '0')
            n = 2
            for i in range(num):
                for j in range(i + 1, num):
                    port_list = [str(i + 1), str(j + 1)]
                    self.controller[sw].mc_node_create(str(n - 1), port_list)
                    self.controller[sw].mc_node_associate(str(n), str(n - 1))
                    self.multicast_table[sw].update({
                        (str(i + 1), str(j + 1)): n
                    })
                    n += 1

    def add_forward_entry(self, sw, ip, port):
        try:
            self.controller[sw].table_add('ingress.ipv4_c.ipv4', 'forward',
                                          [str(ip)], [str(port)])
        except:
            print('add_forward_entry error')

    def add_l3_entry(self, sw, act=[], key=[]):
        try:
            self.controller[sw].table_add('ingress.ipv4_c.l3_match_to_index',
                                          'protect', key, act)
        except:
            print('add_l3_entry error')
Exemplo n.º 12
0
class Controller(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 install_rules(self):

        for sw_name, controller in self.controllers.items():
            for sw_dst in self.topo.get_p4switches():
                #if its ourselves we create direct connections
                if sw_name == sw_dst:
                    for host in self.topo.get_hosts_connected_to(sw_name):
                        sw_port = self.topo.node_to_node_port_num(
                            sw_name, host)
                        host_ip = self.topo.get_host_ip(host) + "/32"
                        host_mac = self.topo.get_host_mac(host)

                        #add rule
                        print "table_add at {}:".format(sw_name)
                        self.controllers[sw_name].table_add(
                            "ipv4_lpm", "set_nhop", [str(host_ip)],
                            [str(host_mac), str(sw_port)])
                #check if there are directly connected hosts
                else:
                    if self.topo.get_hosts_connected_to(sw_dst):
                        paths = self.topo.get_shortest_paths_between_nodes(
                            sw_name, sw_dst)
                        for host in self.topo.get_hosts_connected_to(sw_dst):
                            next_hop = paths[0][1]
                            host_ip = self.topo.get_host_ip(host) + "/24"
                            sw_port = self.topo.node_to_node_port_num(
                                sw_name, next_hop)
                            dst_sw_mac = self.topo.node_to_node_mac(
                                next_hop, sw_name)

                            #add rule
                            print "table_add at {}:".format(sw_name)
                            self.controllers[sw_name].table_add(
                                "ipv4_lpm", "set_nhop", [str(host_ip)],
                                [str(dst_sw_mac),
                                 str(sw_port)])

    def main(self):
        self.install_rules()
Exemplo n.º 13
0
class RSVPController(object):
    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.init()

        # sorted by timeouts
        self.current_reservations = {}
        # initial link capacity
        self.links_capacity = self.build_links_capacity()

        self.update_lock = threading.Lock()
        self.timeout_thread = threading.Thread(
            target=self.reservations_timeout_thread, args=(1, ))
        self.timeout_thread.daemon = True
        self.timeout_thread.start()

    def init(self):
        """Connects to switches and resets.
        """
        self.connect_to_switches()
        self.reset_states()

    def reset_states(self):
        """Resets registers, tables, etc.
        """
        [controller.reset_state() for controller in self.controllers.values()]

    def connect_to_switches(self):
        """Connects to all the switches in the topology and saves them
         in self.controllers.
        """
        for p4switch in self.topo.get_p4switches():
            thrift_port = self.topo.get_thrift_port(p4switch)
            self.controllers[p4switch] = SimpleSwitchAPI(thrift_port)

    def build_links_capacity(self):
        """Builds link capacities dictionary

        Returns:
            dict: {edge: bw}
        """

        links_capacity = {}
        # Iterates all the edges in the topology formed by switches
        for src, dst in self.topo.network_graph.keep_only_p4switches().edges:
            bw = self.topo.network_graph.edges[(src, dst)]['bw']
            # add both directions
            links_capacity[(src, dst)] = bw
            links_capacity[(dst, src)] = bw

        return links_capacity

    def reservations_timeout_thread(self, refresh_rate=1):
        """Every refresh_rate checks all the reservations. If any times out
        tries to delete it.

        Args:
            refresh_rate (int, optional): Refresh rate. Defaults to 1.
        """

        while True:
            # sleeps
            time.sleep(refresh_rate)

            # locks the self.current_reservations data structure. This is done
            # because the CLI can also access the reservations.
            with self.update_lock:
                to_remove = []

                # iterates all the reservations and updates its timeouts
                # if timeout is reached we delete it
                for reservation, data in self.current_reservations.items():
                    data['timeout'] -= refresh_rate
                    # has expired?
                    if data['timeout'] <= 0:
                        to_remove.append(reservation)

                # removes all the reservations that expired
                for reservation in to_remove:
                    self.del_reservation(*reservation)

    def set_mpls_tbl_labels(self):
        """We set all the table defaults to reach all the hosts/networks in the network
        """

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

            # get all direct hosts and add direct entry
            for host in self.topo.get_hosts_connected_to(sw_name):
                sw_port = self.topo.node_to_node_port_num(sw_name, host)
                host_ip = self.topo.get_host_ip(host)
                host_mac = self.topo.get_host_mac(host)

                # adds direct forwarding rule
                controller.table_add(
                    "FEC_tbl", "ipv4_forward",
                    ["0.0.0.0/0", str(host_ip)],
                    [str(host_mac), str(sw_port)])

            for switch in self.topo.get_switches_connected_to(sw_name):
                sw_port = self.topo.node_to_node_port_num(sw_name, switch)
                # reverse port mac
                other_switch_mac = self.topo.node_to_node_mac(switch, sw_name)

                # we add a normal rule and a penultimate one
                controller.table_add("mpls_tbl", "mpls_forward",
                                     [str(sw_port), '0'],
                                     [str(other_switch_mac),
                                      str(sw_port)])
                controller.table_add("mpls_tbl", "penultimate",
                                     [str(sw_port), '1'],
                                     [str(other_switch_mac),
                                      str(sw_port)])

    def build_mpls_path(self, switches_path):
        """Using a path of switches builds the mpls path. In our simplification
        labels are port indexes. 

        Args:
            switches_path (list): path of switches to allocate

        Returns:
            list: label path
        """

        # label path
        label_path = []
        # iterate over all pair of switches in the path
        for current_node, next_node in zip(switches_path, switches_path[1:]):
            # we get sw1->sw2 port number from topo object
            label = self.topo.node_to_node_port_num(current_node, next_node)
            label_path.append(label)
        return label_path

    def get_sorted_paths(self, src, dst):
        """Gets all paths between src, dst 
        sorted by length. This function uses the internal networkx API.

        Args:
            src (str): src name
            dst (str): dst name

        Returns:
            list: paths between src and dst
        """

        paths = self.topo.get_all_paths_between_nodes(src, dst)
        # trim src and dst
        paths = [x[1:-1] for x in paths]
        return paths

    def get_shortest_path(self, src, dst):
        """Computes shortest path. Simple function used to test the system 
        by always allocating the shortest path. 

        Args:
            src (str): src name
            dst (str): dst name

        Returns:
            list: shortest path between src,dst
        """

        return self.get_sorted_paths(src, dst)[0]

    def check_if_reservation_fits(self, path, bw):
        """Checks if a the candidate reservation fits in the current
        state of the network. Using the path of switches, checks if all
        the edges (links) have enough space. Otherwise, returns False.

        Args:
            path (list): list of switches
            bw (float): requested bandwidth in mbps

        Returns:
            bool: true if allocation can be performed on path
        """

        # iterates over all pairs of switches (edges)
        for link in zip(path, path[1:]):
            # checks if there is enough capacity
            if (self.links_capacity[link] - bw) < 0:
                return False
        return True

    def add_link_capacity(self, path, bw):
        """Adds bw capacity to a all the edges along path. This 
        function is used when an allocation is removed.

        Args:
            path (list): list of switches
            bw (float): requested bandwidth in mbps
        """

        # iterates over all pairs of switches (edges)
        for link in zip(path, path[1:]):
            # adds capacity
            self.links_capacity[link] += bw

    def sub_link_capacity(self, path, bw):
        """subtracts bw capacity to a all the edges along path. This 
        function is used when an allocation is added.

        Args:
            path (list): list of switches
            bw (float): requested bandwidth in mbps
        """

        # iterates over all pairs of switches (edges)
        for link in zip(path, path[1:]):
            # subtracts capacity
            self.links_capacity[link] -= bw

    def get_available_path(self, src, dst, bw):
        """Checks all paths from src to dst and picks the 
        shortest path that can allocate bw.

        Args:
            src (str): src name
            dst (str): dst name
            bw (float): requested bandwidth in mbps

        Returns:
            list/bool: best path/ False if none
        """

        # get all paths sorted from shorter to longer
        paths = self.get_sorted_paths(src, dst)

        for path in paths:
            # checks if the path has capacity
            if self.check_if_reservation_fits(path, bw):
                return path
        return False

    def get_meter_rates_from_bw(self, bw, burst_size=700000):
        """Returns the CIR and PIR rates and bursts to configure 
          meters at bw.

        Args:
            bw (float): desired bandwdith in mbps
            burst_size (int, optional): Max capacity of the meter buckets. Defaults to 50000.

        Returns:
            list: [(rate1, burst1), (rate2, burst2)]
        """

        rates = []
        rates.append((0.125 * bw, burst_size))
        rates.append((0.125 * bw, burst_size))
        return rates

    def set_direct_meter_bandwidth(self, sw_name, meter_name, handle, bw):
        """Sets a meter entry (using a table handle) to color packets using
           bw mbps

        Args:
            sw_name (str): switch name
            meter_name (str): meter name
            handle (int): entry handle
            bw (float): desired bandwidth to rate limit
        """

        rates = self.get_meter_rates_from_bw(bw)
        self.controllers[sw_name].meter_set_rates(meter_name, handle, rates)

    def _add_reservation(self, src, dst, duration, bandwidth, priority, path,
                         update):
        """Adds or updates a single reservation

        Args:
            src (str): src name
            dst (str): dst name
            duration (float): reservation timeout
            bandwidth (float): requested bandwidth in mbps
            priority (int): reservation priority
            path (list): switch path were to allocate the reservation
            update (bool): update flag
        """

        # We build the label path. For that we use self.build_mpls_path and
        # reverse the returned labels, since our rsvp.p4 will push them in
        # reverse order.
        label_path = [str(x) for x in self.build_mpls_path(path)[::-1]]

        # Get required info to add a table rule

        # get ingress switch as the first node in the path
        src_gw = path[0]
        # compute the action name using the length of the labels path
        action = "mpls_ingress_{}_hop".format(len(label_path))
        # src lpm address
        src_ip = str(self.topo.get_host_ip(src) + "/32")
        # dst exact address
        dst_ip = str(self.topo.get_host_ip(dst))
        # match list
        match = [src_ip, dst_ip]

        # if we have a label path
        if len(label_path) != 0:

            # If the entry is new we simply add it
            if not update:
                entry_handle = self.controllers[src_gw].table_add(
                    "FEC_tbl", action, match, label_path)
                self.set_direct_meter_bandwidth(src_gw, "rsvp_meter",
                                                entry_handle, bandwidth)
            # if the entry is being updated we modify if using its handle
            else:
                entry = self.current_reservations.get((src, dst), None)
                entry_handle = self.controllers[src_gw].table_modify(
                    "FEC_tbl", action, entry['handle'], label_path)
                self.set_direct_meter_bandwidth(src_gw, "rsvp_meter",
                                                entry_handle, bandwidth)

            # udpates controllers link and reservation structures if rules were added succesfully
            if entry_handle:
                self.sub_link_capacity(path, bandwidth)
                self.current_reservations[(src, dst)] = {
                    "timeout": (duration),
                    "bw": (bandwidth),
                    "priority": (priority),
                    'handle': entry_handle,
                    'path': path
                }
                print("Successful reservation({}->{}): path: {}".format(
                    src, dst, "->".join(path)))
            else:
                print("\033[91mFailed reservation({}->{}): path: {}\033[0m".
                      format(src, dst, "->".join(path)))

        else:
            print("Warning: Hosts are connected to the same switch!")

    def add_reservation(self, src, dst, duration, bandwidth, priority):
        """Adds a new reservation taking into account the priority. This
        addition can potentially move or delete other allocations.

        Args:
            src (str): src name
            dst (str): dst name
            duration (float): reservation timeout
            bandwidth (float): requested bandwidth in mbps
            priority (int): reservation priority
        """

        # locks the self.current_reservations data structure. This is done
        # because there is a thread that could access it concurrently.
        with self.update_lock:

            # if reservation exists, we allocate it again, by just updating the entry
            # for that we set the FLAG UPDATE_ENTRY and restore its link capacity
            # such the new re-allocation with a possible new bw/prioirty can be done
            # taking new capacities into account.
            UPDATE_ENTRY = False
            if self.current_reservations.get((src, dst), None):
                data = self.current_reservations[(src, dst)]
                path = data['path']
                bw = data['bw']
                # updates link capacities
                self.add_link_capacity(path, bw)
                UPDATE_ENTRY = True

            # finds the best (if exists) path to allocate the requestes reservation
            path = self.get_available_path(src, dst, bandwidth)

            if path:
                # add or update the reservation
                self._add_reservation(src, dst, duration, bandwidth, priority,
                                      path, UPDATE_ENTRY)

            # Cant be allocated! However, it might be possible to re-allocate things
            else:
                # check if the flow could be placed removing lower priorities
                previous_links_capacities = self.links_capacity.copy()
                for reservation, data in self.current_reservations.items():
                    # make sure we do not remove ourselves
                    # again in case this is a modification
                    if reservation == (src, dst):
                        continue
                    if data['priority'] < priority:
                        self.add_link_capacity(data['path'], data['bw'])

                # check if it fits in a newtwork without lower priority flows
                path = self.get_available_path(src, dst, bandwidth)

                # we rebalance lower priority reservations if possible
                if path:
                    # adds main new allocation
                    self._add_reservation(src, dst, duration, bandwidth,
                                          priority, path, UPDATE_ENTRY)

                    # re-allocate everything if possible
                    for reservation, data in sorted(
                            self.current_reservations.items(),
                            key=lambda x: x[1]['priority'],
                            reverse=True):
                        if data['priority'] < priority:
                            src, dst = reservation[0], reservation[1]
                            path = self.get_available_path(
                                src, dst, data['bw'])
                            if path:
                                # add or update the reservation
                                self._add_reservation(src, dst,
                                                      data['timeout'],
                                                      data['bw'],
                                                      data['priority'], path,
                                                      True)
                            else:
                                # delete it
                                data = self.current_reservations[(src, dst)]
                                path = data['path']
                                bw = data['bw']
                                self.sub_link_capacity(path, bw)
                                print(
                                    "\033[91mDeleting allocation {}->{} due to a higher priority allocation!\033[0m"
                                    .format(src, dst))
                                self.del_reservation(src, dst)

                else:
                    # restore capacities
                    self.links_capacity = previous_links_capacities
                    # if we failed and it was an entry to be updated we remove it
                    if UPDATE_ENTRY:
                        data = self.current_reservations[(src, dst)]
                        path = data['path']
                        bw = data['bw']
                        self.sub_link_capacity(path, bw)
                        print("Deleting new allocation. Does not fit anymore!")
                        self.del_reservation(src, dst)
                    print(
                        "\033[91mRESERVATION FAILURE: no bandwidth available!\033[0m"
                    )

    def del_reservation(self, src, dst):
        """Deletes a reservation between src and dst, if exists. To 
        delete the reservation the self.current_reservations data structure 
        is used to retrieve all the needed information. After deleting the reservation
        from the ingress switch, path capacities are updated.

        Args:
            src (str): src name
            dst (str): dst name
        """

        # checks if there is an allocation between src->dst
        entry = self.current_reservations.get((src, dst), None)
        if entry:
            # gets handle to delete entry
            entry_handle = entry['handle']
            # gets src ingress switch
            sw_gw = self.topo.get_host_gateway_name(src)
            # removes table entry using the handle
            self.controllers[sw_gw].table_delete("FEC_tbl", entry_handle, True)
            # updates links capacity
            self.add_link_capacity(entry['path'], entry['bw'])
            # removes the reservation from the controllers memory
            del (self.current_reservations[(src, dst)])
            print(
                "\nRSVP Deleted/Expired Reservation({}->{}): path: {}".format(
                    src, dst, "->".join(entry['path'])))
        else:
            print("No entry for {} -> {}".format(src, dst))

    def del_all_reservations(self):
        """Deletes all the current reservations
        """

        # locks the self.current_reservations data structure. This is done
        # because there is a thread that could access it concurrently.
        with self.update_lock:

            # makes a copy of all the reservation pairs
            reservation_keys = self.current_reservations.keys()
            for src, dst in reservation_keys:
                self.del_reservation(src, dst)
Exemplo n.º 14
0
class RoutingController(object):

    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()

        

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

        self.set_crc_custom_hashes()

    
    

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

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

    def set_table_defaults(self):
        for controllers in self.controllers.values():
            controllers.table_set_default("ipv4_lpm", "drop", [])
            controllers.table_set_default("ecmp_group_to_nhop", "drop", [])
    
    def set_custom_calcs(self):
        for p4switch in self.topo.get_p4switches():
            self.custom_calcs[p4switch]=self.controllers[p4switch].get_custom_crc_calcs()
            self.register_num[p4switch] =len(self.custom_calcs[p4switch])     

    def reset_all_registers(self):
        for sw, controller in self.controllers.items():
            for register in controller.get_register_arrays():
                controller.register_reset(register)

 

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

   
    


    def route(self):

        switch_ecmp_groups = {sw_name:{} for sw_name in self.topo.get_p4switches().keys()}
        # self.topo.network_graph.remove_node("sw-cpu")

        for sw_name, controllers in self.controllers.items():
            for sw_dst in self.topo.get_p4switches():

                #if its ourselves we create direct connections
                if sw_name == sw_dst:
                    for host in self.topo.get_hosts_connected_to(sw_name):
                        sw_port = self.topo.node_to_node_port_num(sw_name, host)
                        host_ip = self.topo.get_host_ip(host) + "/32"
                        host_mac = self.topo.get_host_mac(host)

                        #add rule
                        print "table_add at {}:".format(sw_name)
                        self.controllers[sw_name].table_add("ipv4_lpm", "set_nhop", [str(host_ip)], [str(host_mac), str(sw_port)])

                #check if there are directly connected hosts
                else:
                    if self.topo.get_hosts_connected_to(sw_dst):
                        paths = self.topo.get_shortest_paths_between_nodes(sw_name, sw_dst)
                        for host in self.topo.get_hosts_connected_to(sw_dst):

                            if len(paths) == 1:
                                next_hop = paths[0][1]

                                host_ip = self.topo.get_host_ip(host) + "/24"
                                sw_port = self.topo.node_to_node_port_num(sw_name, next_hop)
                                dst_sw_mac = self.topo.node_to_node_mac(next_hop, sw_name)

                                #add rule
                                print "table_add at {}:".format(sw_name)
                                self.controllers[sw_name].table_add("ipv4_lpm", "set_nhop", [str(host_ip)],
                                                                    [str(dst_sw_mac), str(sw_port)])

                            elif len(paths) > 1:
                                next_hops = [x[1] for x in paths]
                                dst_macs_ports = [(self.topo.node_to_node_mac(next_hop, sw_name),
                                                   self.topo.node_to_node_port_num(sw_name, next_hop))
                                                  for next_hop in next_hops]
                                host_ip = self.topo.get_host_ip(host) + "/24"

                                #check if the ecmp group already exists. The ecmp group is defined by the number of next
                                #ports used, thus we can use dst_macs_ports as key
                                if switch_ecmp_groups[sw_name].get(tuple(dst_macs_ports), None):
                                    ecmp_group_id = switch_ecmp_groups[sw_name].get(tuple(dst_macs_ports), None)
                                    print "table_add at {}:".format(sw_name)
                                    self.controllers[sw_name].table_add("ipv4_lpm", "ecmp_group", [str(host_ip)],
                                                                        [str(ecmp_group_id), str(len(dst_macs_ports))])

                                #new ecmp group for this switch
                                else:
                                    new_ecmp_group_id = len(switch_ecmp_groups[sw_name]) + 1
                                    switch_ecmp_groups[sw_name][tuple(dst_macs_ports)] = new_ecmp_group_id

                                    #add group
                                    for i, (mac, port) in enumerate(dst_macs_ports):
                                        print "table_add at {}:".format(sw_name)
                                        self.controllers[sw_name].table_add("ecmp_group_to_nhop", "set_nhop",
                                                                            [str(new_ecmp_group_id), str(i)],
                                                                            [str(mac), str(port)])

                                    #add forwarding rule
                                    print "table_add at {}:".format(sw_name)
                                    self.controllers[sw_name].table_add("ipv4_lpm", "ecmp_group", [str(host_ip)],
                                                                        [str(new_ecmp_group_id), str(len(dst_macs_ports))])
		




    def main(self):
        self.route()

        # for switch_id, controller in enumerate(self.controllers.values()):
            # controller.register_write("switch_id", 0, switch_id)
            # controller.register_write("swap_control", 0, 0)
            # controller.register_write("sketch_fg", 0, 0)
            # controller.register_write("previous_ingress_timestamp", 0, 0)

        for switch_id, switch_name in enumerate(self.controllers.keys()):
            print "{} {}".format(switch_id, switch_name)
Exemplo n.º 15
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 add_mirroring_ids(self):

        for sw_name, controller in self.controllers.items():
            controller.mirroring_add(100, 1)

    def set_egress_type_table(self):

        for sw_name, controller in self.controllers.items():

            for intf, node in self.topo.get_interfaces_to_node(
                    sw_name).items():
                node_type = self.topo.get_node_type(node)
                port_number = self.topo.interface_to_port(sw_name, intf)

                if node_type == 'host':
                    node_type_num = 1
                elif node_type == 'switch':
                    node_type_num = 2

                print "table_add at {}:".format(sw_name)
                self.controllers[sw_name].table_add("egress_type",
                                                    "set_egress_type",
                                                    [str(port_number)],
                                                    [str(node_type_num)])

    def route(self):

        switch_ecmp_groups = {
            sw_name: {}
            for sw_name in self.topo.get_p4switches().keys()
        }

        for sw_name, controller in self.controllers.items():
            for sw_dst in self.topo.get_p4switches():

                #if its ourselves we create direct connections
                if sw_name == sw_dst:
                    for host in self.topo.get_hosts_connected_to(sw_name):
                        sw_port = self.topo.node_to_node_port_num(
                            sw_name, host)
                        host_ip = self.topo.get_host_ip(host) + "/32"
                        host_mac = self.topo.get_host_mac(host)

                        #add rule
                        print "table_add at {}:".format(sw_name)
                        self.controllers[sw_name].table_add(
                            "ipv4_lpm", "set_nhop", [str(host_ip)],
                            [str(host_mac), str(sw_port)])

                #check if there are directly connected hosts
                else:
                    if self.topo.get_hosts_connected_to(sw_dst):
                        paths = self.topo.get_shortest_paths_between_nodes(
                            sw_name, sw_dst)
                        for host in self.topo.get_hosts_connected_to(sw_dst):

                            if len(paths) == 1:
                                next_hop = paths[0][1]

                                host_ip = self.topo.get_host_ip(host) + "/24"
                                sw_port = self.topo.node_to_node_port_num(
                                    sw_name, next_hop)
                                dst_sw_mac = self.topo.node_to_node_mac(
                                    next_hop, sw_name)

                                #add rule
                                print "table_add at {}:".format(sw_name)
                                self.controllers[sw_name].table_add(
                                    "ipv4_lpm", "set_nhop", [str(host_ip)],
                                    [str(dst_sw_mac),
                                     str(sw_port)])

                            elif len(paths) > 1:
                                next_hops = [x[1] for x in paths]
                                dst_macs_ports = [
                                    (self.topo.node_to_node_mac(
                                        next_hop, sw_name),
                                     self.topo.node_to_node_port_num(
                                         sw_name, next_hop))
                                    for next_hop in next_hops
                                ]
                                host_ip = self.topo.get_host_ip(host) + "/24"

                                #check if the ecmp group already exists. The ecmp group is defined by the number of next
                                #ports used, thus we can use dst_macs_ports as key
                                if switch_ecmp_groups[sw_name].get(
                                        tuple(dst_macs_ports), None):
                                    ecmp_group_id = switch_ecmp_groups[
                                        sw_name].get(tuple(dst_macs_ports),
                                                     None)
                                    print "table_add at {}:".format(sw_name)
                                    self.controllers[sw_name].table_add(
                                        "ipv4_lpm", "ecmp_group",
                                        [str(host_ip)], [
                                            str(ecmp_group_id),
                                            str(len(dst_macs_ports))
                                        ])

                                #new ecmp group for this switch
                                else:
                                    new_ecmp_group_id = len(
                                        switch_ecmp_groups[sw_name]) + 1
                                    switch_ecmp_groups[sw_name][tuple(
                                        dst_macs_ports)] = new_ecmp_group_id

                                    #add group
                                    for i, (mac,
                                            port) in enumerate(dst_macs_ports):
                                        print "table_add at {}:".format(
                                            sw_name)
                                        self.controllers[sw_name].table_add(
                                            "ecmp_group_to_nhop", "set_nhop",
                                            [str(new_ecmp_group_id),
                                             str(i)],
                                            [str(mac), str(port)])

                                    #add forwarding rule
                                    print "table_add at {}:".format(sw_name)
                                    self.controllers[sw_name].table_add(
                                        "ipv4_lpm", "ecmp_group",
                                        [str(host_ip)], [
                                            str(new_ecmp_group_id),
                                            str(len(dst_macs_ports))
                                        ])

    def main(self):
        self.set_egress_type_table()
        self.add_mirroring_ids()
        self.route()
Exemplo n.º 16
0
            routing_info = json.load(json_data)

            for host in topo.get_hosts():
                threshold_tmp = threshold
                if "threshold" in routing_info['switches'][sw_name]:
                    threshold_tmp = routing_info['switches'][sw_name][
                        'threshold']

                do_register_write(sock, 'threshold_registers', mapping_dic[host]*2, \
                threshold_tmp)
                do_register_write(sock, 'threshold_registers', mapping_dic[host]*2+1, \
                threshold_tmp)

            for host, nh in routing_info['switches'][sw_name][
                    'prefixes'].items():
                host_prefix = topo.get_host_ip(host) + '/24'

                if "customer" in nh and len(nh["customer"]) > 0:
                    # Add the set_meta forwarding rule for the <prefix,customer> tuple
                    add_entry_fwtable(sock, 'meta_fwtable', 'set_meta', \
                        [str(host_prefix), 0], [mapping_dic[host]*2, \
                        0 if len(nh["customer"]) == 1 else 1,\
                        mapping_dic[nh["customer"][0]]])

                    # If only one backup next-hop is avaible, use it two times
                    if len(nh["customer"]) == 2:
                        nh["customer"].append(nh["customer"][-1])

                    i = 0
                    for n in nh["customer"]:
                        do_register_write(sock, 'next_hops_port', mapping_dic[host]*6+i, \
duration = int(sys.argv[1])

send_cmds = []
recv_cmds = []

Popen("sudo killall iperf", shell=True)

num_hosts = 8
num_senders= 4

for src_host in sorted(topo.get_hosts().keys(), key = lambda x: int(x[1:]))[:num_senders]:
    dst_host = 'h' + str((int(src_host[1:]) + 3) % num_hosts + 1)

    src_port = random.randint(1025, 65000)
    dst_port = random.randint(1025, 65000)
    src_ip = topo.get_host_ip(src_host)
    dst_ip = topo.get_host_ip(dst_host)

    send_cmds.append(iperf_send.format(src_host, dst_ip, duration, src_ip, src_port, dst_port))
    recv_cmds.append(iperf_recv.format(dst_host, dst_port))

#start receivers first
for recv_cmd in recv_cmds:
    print "Running:", recv_cmd
    Popen(recv_cmd, shell=True)

time.sleep(1)

for send_cmd in send_cmds:
    print "Running:", send_cmd
    Popen(send_cmd, shell=True)
Exemplo n.º 18
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()