Exemplo n.º 1
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]
topo = Topology(db="topology.db")

iperf_send = "mx {0} iperf -M 9000 -c {1} -t {2} --bind {3} -p {5} 2>&1 >/dev/null"
iperf_recv = "mx {0} iperf -s -p {1} 2>&1 >/dev/null"
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)
Exemplo n.º 3
0
class RerouteController(object):
    """Controller for the fast rerouting exercise."""
    def __init__(self):
        """Initializes the topology and data structures."""

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

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

        # Preconfigure all MAC addresses
        self.install_macs()

        # Install nexthop indices and populate registers.
        self.install_nexthop_indices()
        self.update_nexthops()

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

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

    def install_macs(self):
        """Install the port-to-mac map on all switches.

        You do not need to change this.

        Note: Real switches would rely on L2 learning to achieve this.
        """
        for switch, control in self.controllers.items():
            print "Installing MAC addresses for switch '%s'." % switch
            print "=========================================\n"
            for neighbor in self.topo.get_neighbors(switch):
                mac = self.topo.node_to_node_mac(neighbor, switch)
                port = self.topo.node_to_node_port_num(switch, neighbor)
                control.table_add('rewrite_mac', 'rewriteMac', [str(port)],
                                  [str(mac)])

    def install_nexthop_indices(self):
        """Install the mapping from prefix to nexthop ids for all switches."""
        for switch, control in self.controllers.items():
            print "Installing nexthop indices for switch '%s'." % switch
            print "===========================================\n"
            control.table_clear('ipv4_lpm')
            for host in self.topo.get_hosts():
                subnet = self.get_host_net(host)
                index = self.get_nexthop_index(host)
                control.table_add('ipv4_lpm', 'read_port', [subnet],
                                  [str(index)])

    def get_host_net(self, host):
        """Return ip and subnet of a host.

        Args:
            host (str): The host for which the net will be retruned.

        Returns:
            str: IP and subnet in the format "address/mask".
        """
        gateway = self.topo.get_host_gateway_name(host)
        return self.topo[host][gateway]['ip']

    def get_nexthop_index(self, host):
        """Return the nexthop index for a destination.

        Args:
            host (str): Name of destination node (host).

        Returns:
            int: nexthop index, used to look up nexthop ports.
        """
        # For now, give each host an individual nexthop id.
        host_list = sorted(list(self.topo.get_hosts().keys()))
        return host_list.index(host)

    def get_port(self, node, nexthop_node):
        """Return egress port for nexthop from the view of node.

        Args:
            node (str): Name of node for which the port is determined.
            nexthop_node (str): Name of node to reach.

        Returns:
            int: nexthop port
        """
        return self.topo.node_to_node_port_num(node, nexthop_node)

    def failure_notification(self, failures):
        """Called if a link fails.

        Args:
            failures (list(tuple(str, str))): List of failed links.
        """
        self.update_nexthops(failures=failures)

    # Helpers to update nexthops.
    # ===========================

    def dijkstra(self, failures=None):
        """Compute shortest paths and distances.

        Args:
            failures (list(tuple(str, str))): List of failed links.

        Returns:
            tuple(dict, dict): First dict: distances, second: paths.
        """
        graph = self.topo.network_graph

        if failures is not None:
            graph = graph.copy()
            for failure in failures:
                graph.remove_edge(*failure)

        # Compute the shortest paths from switches to hosts.
        dijkstra = dict(all_pairs_dijkstra(graph, weight='weight'))

        distances = {node: data[0] for node, data in dijkstra.items()}
        paths = {node: data[1] for node, data in dijkstra.items()}

        return distances, paths

    def compute_nexthops(self, failures=None):
        """Compute the best nexthops for all switches to each host.

        Optionally, a link can be marked as failed. This link will be excluded
        when computing the shortest paths.

        Args:
            failures (list(tuple(str, str))): List of failed links.

        Returns:
            dict(str, list(str, str, int))):
                Mapping from all switches to subnets, MAC, port.
        """
        # Compute the shortest paths from switches to hosts.
        all_shortest_paths = self.dijkstra(failures=failures)[1]

        # Translate shortest paths to mapping from host to nexthop node
        # (per switch).
        results = {}
        for switch in self.controllers:
            switch_results = results[switch] = []
            for host in self.topo.network_graph.get_hosts():
                try:
                    path = all_shortest_paths[switch][host]
                except KeyError:
                    print "WARNING: The graph is not connected!"
                    print "'%s' cannot reach '%s'." % (switch, host)
                    continue
                nexthop = path[1]  # path[0] is the switch itself.
                switch_results.append((host, nexthop))

        return results

    # Update nexthops.
    # ================

    def update_nexthops(self, failures=None):
        """Install nexthops in all switches."""
        nexthops = self.compute_nexthops(failures=failures)

        for switch, destinations in nexthops.items():
            print "Updating nexthops for switch '%s'." % switch
            control = self.controllers[switch]
            for host, nexthop in destinations:
                nexthop_id = self.get_nexthop_index(host)
                port = self.get_port(switch, nexthop)
                # Write the port in the nexthop lookup register.
                control.register_write('primaryNH', nexthop_id, port)

        #######################################################################
        # Compute loop-free alternate nexthops and install them below.
        #######################################################################

        pass
Exemplo n.º 4
0
topo_db = args.topo_db
routing_file = args.routing_file
threshold = args.threshold

# Logger for the controller
logger.setup_logger('controller', log_dir + '/controller.log', level=log_level)
log = logging.getLogger('controller')

log.info(str(port)+'\t'+str(log_dir)+'\t'+str(log_level)+'\t'+str(routing_file)+ \
'\t'+str(threshold))

# Read the topology
topo = Topology(db=topo_db)

mapping_dic = {}
tmp = list(topo.get_hosts()) + list(topo.get_p4switches())
mapping_dic = {k: v for v, k in enumerate(tmp)}
log.info(str(mapping_dic))
"""
    This function adds an entry in a match+action table of the switch
"""


def add_entry_fwtable(connection, fwtable_name, action_name, match_list,
                      args_list):
    args_str = ''
    for a in args_list:
        args_str += str(a) + ' '
    args_str = args_str[:-1]

    match_str = ''
Exemplo n.º 5
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.º 6
0
class P4CLI(CLI):

    def __init__(self, *args, **kwargs):
        self.conf_file = kwargs.get("conf_file", None)
        self.import_last_modifications = {}

        self.last_compilation_state = False

        if not self.conf_file:
            log.warn("No configuration given to the CLI. P4 functionalities are disabled.")
        else:
            self.config = load_conf(self.conf_file)
            # class CLI from mininet.cli does not have config parameter, thus remove it
            kwargs.__delitem__("conf_file")
        CLI.__init__(self, *args, **kwargs)

    def failed_status(self):
        self.last_compilation_state = False
        return FAILED_STATUS

    def do_load_topo_conf(self, line= ""):

        """
        Updates the topo config
        Args:
            line:

        Returns:

        """
        args = line.split()
        if args:
            conf_file = args[0]
            self.conf_file = conf_file

        #re-load conf file
        self.config = load_conf(self.conf_file)

    def do_set_p4conf(self, line=""):
        """Updates configuration file location, and reloads it."""
        args = line.split()
        conf = args[0]
        if not os.path.exists(conf):
            warn('Configuratuion file %s does not exist' % conf)
            return
        self.conf_file = conf
        self.config = load_conf(conf)

    def do_test_p4(self, line=""):
        """Tests start stop functionalities."""
        self.do_p4switch_stop("s1")
        self.do_p4switch_start("s1")
        self.do_p4switch_reboot("s1")
        self.do_p4switches_reboot()

    def do_p4switch_stop(self, line=""):
        """Stop simple switch from switch namespace."""
        switch_name = line.split()
        if not switch_name or len(switch_name) > 1:
            error('usage: p4switch_stop <p4switch name>\n')
        else:
            switch_name = switch_name[0]
            if switch_name not in self.mn:
                error("p4switch %s not in the network\n" % switch_name)
            else:
                p4switch = self.mn[switch_name]
                p4switch.stop_p4switch()

    def do_p4switch_start(self, line=""):
        """Start again simple switch from namespace."""
        args = line.split()

        # check args validity
        if len(args) > 5:
            error('usage: p4switch_start <p4switch name> [--p4src <path>] [--cmds path]\n')
            return self.failed_status()

        switch_name = args[0]

        if switch_name not in self.mn:
            error('usage: p4switch_start <p4switch name> [--p4src <path>] [--cmds path]\n')
            return self.failed_status()

        p4switch = self.mn[switch_name]

        # check if switch is running
        if p4switch.check_switch_started():
            error('P4 Switch already running, stop it first: p4switch_stop %s \n' % switch_name)
            return self.failed_status()

        #load default configuration
        # mandatory defaults if not defined we should complain
        default_p4 = self.config.get("program", None)
        default_options = self.config.get("options", None)

        # non mandatory defaults.
        default_compiler = self.config.get("compiler", DEFAULT_COMPILER)

        default_config = {"program": default_p4, "options": default_options, "compiler": default_compiler}
        #merge with switch conf
        switch_conf = default_config.copy()
        switch_conf.update(self.config['topology']['switches'][switch_name])

        if "--p4src" in args:
            p4source_path = args[args.index("--p4src")+1]
            switch_conf['program'] = p4source_path
            # check if file exists
            if not os.path.exists(p4source_path):
                warn('File Error: p4source %s does not exist\n' % p4source_path)
                return self.failed_status()
            #check if its not a file
            if not os.path.isfile(p4source_path):
                warn('File Error: p4source %s is not a file\n' % p4source_path)
                return self.failed_status()

        p4source_path_source = switch_conf['program']

        # generate output file name
        output_file = p4source_path_source.replace(".p4", "") + ".json"

        program_flag = last_modified(p4source_path_source, output_file)
        includes_flag = check_imports_last_modified(p4source_path_source,
                                                    self.import_last_modifications)

        log.debug("%s %s %s %s\n" % (p4source_path_source, output_file, program_flag, includes_flag))

        if program_flag or includes_flag or (not self.last_compilation_state):
            # compile program
            try:
                compile_p4_to_bmv2(switch_conf)
                self.last_compilation_state = True
            except CompilationError:
                log.error('Compilation failed\n')
                return self.failed_status()

            # update output program
            p4switch.json_path = output_file

        # start switch
        p4switch.start()

        # load command entries
        if "--cmds" in args:
            commands_path = args[args.index("--cmds")+1]
            # check if file exists

        else:
            commands_path = switch_conf.get('cli_input', None)

        if commands_path:
            if not os.path.exists(commands_path):
                error('File Error: commands file %s does not exist\n' % commands_path)
                return self.failed_status()
            entries = read_entries(commands_path)
            add_entries(p4switch.thrift_port, entries)

        return SUCCESS_STATUS

    def do_printSwitches(self, line=""):
        """Print names of all switches."""
        for sw in self.mn.p4switches:
            print((sw.name))   

    def do_p4switches_reboot(self, line=""):
        """Reboot all P4 switches with new program.

        Note:
            If you provide a P4 source code or cmd, all switches will have the same.
        """
        self.config = load_conf(self.conf_file)

        for sw in self.mn.p4switches:
            switch_name = sw.name
            self.do_p4switch_stop(line=switch_name)

            tmp_line = switch_name + " " +line
            self.do_p4switch_start(line=tmp_line)

        #run scripts
        if isinstance(self.config.get('exec_scripts', None), list):
            for script in self.config.get('exec_scripts'):
                if script["reboot_run"]:
                    info("Exec Script: {}\n".format(script["cmd"]))
                    run_command(script["cmd"])

    def do_p4switch_reboot(self, line=""):
        """Reboot a P4 switch with a new program."""
        self.config = load_conf(self.conf_file)
        if not line or len(line.split()) > 5:
            error('usage: p4switch_reboot <p4switch name> [--p4src <path>] [--cmds path]\n')
        else:
            switch_name = line.split()[0]
            self.do_p4switch_stop(line=switch_name)
            self.do_p4switch_start(line=line)

    def do_pingset(self ,line=""):
        hosts_names = line.strip().split()
        hosts = [x for x in self.mn.hosts if x.name in hosts_names]
        self.mn.ping(hosts=hosts, timeout=1)


    def do_printNetInfo(self, line=""):
        """Prints Topology Info"""

        self.topo = Topology(db="topology.db")
   
        print("\n*********************")
        print("Network Information:")
        print("*********************\n")
        
        switches = self.topo.get_switches()

        for sw in sorted(switches.keys()):
            
            # skip linux bridge
            if sw == "sw-cpu":
                continue

            thrift_port = self.topo.get_thrift_port(sw)
            switch_id = self.topo[sw].get("sw_id", "N/A")
            cpu_index = self.topo.get_cpu_port_index(sw, quiet=True)
            header = "{}(thirft->{}, cpu_port->{})".format(sw, thrift_port, cpu_index)

            header2 = "{:>4} {:>15} {:>8} {:>20} {:>16} {:>8} {:>8} {:>8} {:>8} {:>8}".format("port", "intf", "node", "mac", "ip", "bw", "weight", "delay", "loss","queue")                                                                                     

            print(header)
            print((len(header2)*"-")) 
            print(header2)
            
            for intf,port_number  in sorted(list(self.topo.get_interfaces_to_port(sw).items()), key=lambda x: x[1]):
                if intf == "lo":
                    continue
                
                other_node = self.topo.get_interfaces_to_node(sw)[intf]
                mac = self.topo[sw][other_node]['mac']
                ip = self.topo[sw][other_node]['ip'].split("/")[0]
                bw = self.topo[sw][other_node]['bw']
                weight = self.topo[sw][other_node]['weight']
                delay = self.topo[sw][other_node]['delay']
                loss = self.topo[sw][other_node]['loss']
                queue_length = self.topo[sw][other_node]['queue_length']
                print(("{:>4} {:>15} {:>8} {:>20} {:>16} {:>8} {:>8} {:>8} {:>8} {:>8}".format(port_number, intf, other_node, mac, ip, bw, weight, delay, loss, queue_length)))

            print((len(header2)*"-")) 
            print("")

        # HOST INFO
        print("Hosts Info")

        header = "{:>4} {:>15} {:>8} {:>20} {:>16} {:>8} {:>8} {:>8} {:>8} {:>8}".format(
            "name", "intf", "node", "mac", "ip", "bw", "weight", "delay", "loss","queue")    
        
        print((len(header)*"-")) 
        print(header)

        for host in sorted(self.topo.get_hosts()):           
            for intf,port_number  in sorted(list(self.topo.get_interfaces_to_port(host).items()), key=lambda x: x[1]):
                
                other_node = self.topo.get_interfaces_to_node(host)[intf]
                mac = self.topo[host][other_node]['mac']
                ip = self.topo[host][other_node]['ip'].split("/")[0]
                bw = self.topo[host][other_node]['bw']
                weight = self.topo[host][other_node]['weight']
                delay = self.topo[host][other_node]['delay']
                loss = self.topo[host][other_node]['loss']
                queue_length = self.topo[host][other_node]['queue_length']
                print(("{:>4} {:>15} {:>8} {:>20} {:>16} {:>8} {:>8} {:>8} {:>8} {:>8}".format(host, intf, other_node, mac, ip, bw, weight, delay, loss, queue_length)))

        print((len(header)*"-")) 
        print("")

#def describe(self, sw_addr=None, sw_mac=None):
#    print "**********"
#    print "Network configuration for: %s" % self.name
#    print "Default interface: %s\t%s\t%s" %(
#        self.defaultIntf().name,
#        self.defaultIntf().IP(),
#        self.defaultIntf().MAC()
#    )
#    if sw_addr is not None or sw_mac is not None:
#        print "Default route to switch: %s (%s)" % (sw_addr, sw_mac)
#    print "**********"
#    
#def describe(self):
#    print "%s -> Thrift port: %d" % (self.name, self.thrift_port)
Exemplo n.º 7
0
topo = Topology(db="topology.db")

iperf_send = "mx {0} iperf3 -M 9000 -c {1} -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"
duration = int(sys.argv[1])

send_cmds = []
recv_cmds = []

Popen("sudo killall iperf iperf3", 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:
from p4utils.utils.topology import Topology

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

for host in sorted(topo.get_hosts().keys(), key=lambda x: int(x[1:])):

    host_intf = topo.get_host_first_interface(host)
    sw = topo.interface_to_node(host, host_intf)
    print host, topo[sw][host]['intf']
Exemplo n.º 9
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()