def __init__(self, sw_name): self.topo = load_topo('topology.json') 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 = SimpleSwitchThriftAPI(self.thrift_port) self.init()
class FillRegisters(object): def __init__(self, sw_name): self.topo = load_topo('topology.json') self.sw_name = sw_name self.thrift_port = self.topo.get_thrift_port(sw_name) self.controller = SimpleSwitchThriftAPI(self.thrift_port) def fill_registers(self): for i in range(128): self.controller.register_write("recirculate_register", i, i)
def reset_states(self): """Resets registers, tables, etc. """ for p4rtswitch, controller in self.controllers.items(): # Reset grpc server controller.reset_state() # Connect to thrift server thrift_port = self.topo.get_thrift_port(p4rtswitch) controller_thrift = SimpleSwitchThriftAPI(thrift_port) # Reset forwarding states controller_thrift.reset_state()
class ReadCounters(object): def __init__(self, sw_name): self.topo = load_topo('topology.json') self.sw_name = sw_name self.thrift_port = self.topo.get_thrift_port(sw_name) self.controller = SimpleSwitchThriftAPI(self.thrift_port) def direct(self): entries = self.controller.table_num_entries('count_table') for i in range(0, 4): self.controller.counter_read('direct_port_counter', i) def indirect(self): for i in range(1, 5): self.controller.counter_read('port_counter', i)
def connect_to_switches(self): """Connects to all the switches in the topology and saves them in self.controllers. """ for p4switch in self.topo.get_p4switches(): thrift_port = self.topo.get_thrift_port(p4switch) self.controllers[p4switch] = SimpleSwitchThriftAPI(thrift_port)
def reset(self): # Reset grpc server self.controller.reset_state() # Due to a bug in the way the grpc switch reset its states with the message # SetForwardingPipelineConfigRequest and Action VERIFY_AND_COMMIT (this is # a problem in the implementation of the server), subsequent initializations # (i.e. those which happen after the switch reset) of multicast groups # (with the same multicast id) are appended to the previous ones # (i.e. those present before the reset), which are supposed to be erased by the reset, but # they actually are not. This leads to duplicate packets sent to the same port. # This seems to be caused by the fact that, even if the grpc server is reset, the # switch forwarding states are not completely erased. In order to overcome this, # a complete reset can be achieved by resetting the switch via thrift. thrift_port = self.topo.get_thrift_port(self.sw_name) controller_thrift = SimpleSwitchThriftAPI(thrift_port) # Reset forwarding states controller_thrift.reset_state()
def connect_to_switches(self): for p4switch in self.topo.get_p4switches(): thrift_port = self.topo.get_thrift_port(p4switch) self.controllers[p4switch] = SimpleSwitchThriftAPI(thrift_port)
class FloodingController(object): def __init__(self, sw_name): self.topo = load_topo('topology.json') 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 = SimpleSwitchThriftAPI(self.thrift_port) self.init() def init(self): self.controller.reset_state() self.fill_dmac_table() self.add_boadcast_groups() def fill_dmac_table(self): self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:01'], ['1']) self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:02'], ['2']) self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:03'], ['3']) self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:04'], ['4']) self.controller.table_set_default("dmac", "broadcast", []) def add_boadcast_groups(self): interfaces_to_port = self.topo.get_node_intfs[ self.sw_name]["interfaces_to_port"].copy() #filter lo and cpu port interfaces_to_port.pop('lo', None) interfaces_to_port.pop(self.topo.get_cpu_port_intf(self.sw_name), None) mc_grp_id = 1 rid = 0 for ingress_port in interfaces_to_port.values(): port_list = list(interfaces_to_port.values()) del (port_list[port_list.index(ingress_port)]) #add multicast group self.controller.mc_mgrp_create(mc_grp_id) #add multicast node group handle = self.controller.mc_node_create(rid, port_list) #associate with mc grp self.controller.mc_node_associate(mc_grp_id, handle) #fill broadcast table self.controller.table_add("select_mcast_grp", "set_mcast_grp", [str(ingress_port)], [str(mc_grp_id)]) mc_grp_id += 1 rid += 1
class L2Controller(object): def __init__(self, sw_name): self.topo = load_topo('topology.json') 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 = SimpleSwitchThriftAPI(self.thrift_port) self.init() def init(self): self.controller.reset_state() self.add_boadcast_groups() self.add_mirror() #self.fill_table_test() def add_mirror(self): if self.cpu_port: self.controller.mirroring_add(100, self.cpu_port) def add_boadcast_groups(self): interfaces_to_port = self.topo.get_node_intfs(fields=['port'])[self.sw_name].copy() # Filter lo and cpu port interfaces_to_port.pop('lo', None) interfaces_to_port.pop(self.topo.get_cpu_port_intf(self.sw_name), None) mc_grp_id = 1 rid = 0 for ingress_port in interfaces_to_port.values(): port_list = list(interfaces_to_port.values()) del(port_list[port_list.index(ingress_port)]) #add multicast group self.controller.mc_mgrp_create(mc_grp_id) #add multicast node group handle = self.controller.mc_node_create(rid, port_list) #associate with mc grp self.controller.mc_node_associate(mc_grp_id, handle) #fill broadcast table self.controller.table_add("broadcast", "set_mcast_grp", [str(ingress_port)], [str(mc_grp_id)]) mc_grp_id +=1 rid +=1 def fill_table_test(self): self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:01'], ['1']) self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:02'], ['2']) self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:03'], ['3']) self.controller.table_add("dmac", "forward", ['00:00:0a:00:00:04'], ['4']) def learn(self, learning_data): for mac_addr, ingress_port in learning_data: print("mac: %012X ingress_port: %s " % (mac_addr, ingress_port)) self.controller.table_add("smac", "NoAction", [str(mac_addr)]) self.controller.table_add("dmac", "forward", [str(mac_addr)], [str(ingress_port)]) def unpack_digest(self, msg, num_samples): digest = [] starting_index = 32 for sample in range(num_samples): mac0, mac1, ingress_port = struct.unpack(">LHH", msg[starting_index:starting_index+8]) starting_index +=8 mac_addr = (mac0 << 16) + mac1 digest.append((mac_addr, ingress_port)) return digest def recv_msg_digest(self, msg): topic, device_id, ctx_id, list_id, buffer_id, num = struct.unpack("<iQiiQi", msg[:32]) digest = self.unpack_digest(msg, num) self.learn(digest) #Acknowledge digest self.controller.client.bm_learning_ack_buffer(ctx_id, list_id, buffer_id) def run_digest_loop(self): sub = nnpy.Socket(nnpy.AF_SP, nnpy.SUB) notifications_socket = self.controller.client.bm_mgmt_get_info().notifications_socket sub.connect(notifications_socket) sub.setsockopt(nnpy.SUB, nnpy.SUB_SUBSCRIBE, '') while True: msg = sub.recv() self.recv_msg_digest(msg) def recv_msg_cpu(self, pkt): packet = Ether(raw(pkt)) if packet.type == 0x1234: cpu_header = CpuHeader(bytes(packet.load)) self.learn([(cpu_header.macAddr, cpu_header.ingress_port)]) def run_cpu_port_loop(self): cpu_port_intf = str(self.topo.get_cpu_port_intf(self.sw_name).replace("eth0", "eth1")) sniff(iface=cpu_port_intf, prn=self.recv_msg_cpu)