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)],[])
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()
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()
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()
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 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)) ])
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()
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)