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)
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
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 = ''
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')
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)
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']
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()