def setUp(self): self.client_id = 0 self.p4_name = "switchml" self.dev = 0 self.dev_tgt = gc.Target(self.dev, pipe_id=0xFFFF) BfRuntimeTest.setUp(self, self.client_id, self.p4_name) self.bfrt_info = self.interface.bfrt_info_get() self.target = gc.Target(device_id=0, pipe_id=0xffff) self.job = None
def runTest(self): target = gc.Target(device_id=0, pipe_id=0xffff) # Get bfrt_info and set it as part of the test bfrt_info = self.interface.bfrt_info_get(p4_program_name) # Set default output port table_output_port = bfrt_info.table_get("SwitchIngress.output_port") action_data = table_output_port.make_data( action_name="SwitchIngress.set_output_port", data_field_list_in=[gc.DataTuple(name="port_id", val=swports[1])]) table_output_port.default_entry_set(target=target, data=action_data) try: ipkt = testutils.simple_tcp_packet(eth_dst='11:11:11:11:11:11', eth_src='22:33:44:55:66:77', ip_src='1.2.3.4', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, tcp_sport=0x1234, tcp_dport=0xabcd, with_tcp_chksum=True) epkt = ipkt testutils.send_packet(self, swports[0], ipkt) testutils.verify_packet(self, epkt, swports[1]) finally: table_output_port.default_entry_reset(target)
def CfgPortTableClearTest(self, port1): target = client.Target(device_id=0, pipe_id=0xffff) self.port_table.entry_del(target, key_list=None) self.port_table.entry_add( target, [self.port_table.make_key([client.KeyTuple('$DEV_PORT', port1)])], [ self.port_table.make_data([ client.DataTuple('$SPEED', str_val="BF_SPEED_100G"), client.DataTuple('$FEC', str_val="BF_FEC_TYP_NONE") ]) ]) self.port_table.entry_del(target, key_list=None) try: get_data_list = self.port_table.make_data([client.DataTuple("$SPEED")]) resp = self.port_table.entry_get( target, [self.port_table.make_key([client.KeyTuple('$DEV_PORT', port1)])], {"from_hw": False}, get_data_list) data_dict = next(resp)[0].to_dict() # since we have deleted all the ports, the above API call should have # failed. Assert if not logger.error("Unable to clear port cfg table") assert (0) except: logger.info("Cleared port cfg table successfully")
def table_add(table_name, match_key_names_list, match_key_values_list, action_name, action_data_names_list, action_data_values_list): # simply a wrapper t = bfrt_info.table_dict[table_name] def table_add_gen_kd(table_name, match_key_names_list, match_key_values_list, action_name, action_data_names_list, action_data_values_list): # prepare to add a single match-action table rule t = bfrt_info.table_dict[table_name] # prepare KeyTuple KeyTuple_list = [] for keyName, keyValue in zip(match_key_names_list, match_key_values_list): KeyTuple_list.append(client.KeyTuple(name=keyName, value=keyValue)) tKey = t.make_key(KeyTuple_list) DataTuple_List = [] for dataName, dataValue in zip(action_data_names_list, action_data_values_list): DataTuple_List.append( client.DataTuple(name=dataName, val=dataValue)) tData = t.make_data(DataTuple_List, action_name=action_name) return tKey, tData tKey, tData = table_add_gen_kd(table_name, match_key_names_list, match_key_values_list, action_name, action_data_names_list, action_data_values_list) return t.entry_add(target=client.Target(), key_list=[tKey], data_list=[tData])
def modify_grp(self, sel_table, members, member_status): target = gc.Target(device_id=dev_id, pipe_id=0xffff) # Modify group sel_table.entry_mod(target, [ sel_table.make_key( [gc.KeyTuple('$SELECTOR_GROUP_ID', self.group_id)]) ], [ sel_table.make_data([ gc.DataTuple('$ACTION_MEMBER_ID', int_arr_val=members), gc.DataTuple('$ACTION_MEMBER_STATUS', bool_arr_val=member_status) ]) ]) # Verify member_dict = { members[i]: member_status[i] for i in range(len(members)) } get_resp = sel_table.entry_get(target, [ sel_table.make_key( [gc.KeyTuple('$SELECTOR_GROUP_ID', self.group_id)]) ], {"from_hw": False}) data_dict = next(get_resp)[0].to_dict() member_dict_recv = { data_dict["$ACTION_MEMBER_ID"][i]: data_dict["$ACTION_MEMBER_STATUS"][i] for i in range(len(data_dict["$ACTION_MEMBER_ID"])) } assert member_dict == member_dict_recv
def lpfGetTestHelper(self, num_entries, table, key_fields, action_name): target = client.Target(device_id=0, pipe_id=0xffff) gain_time = [ float(random.randint(1, 200) * 1000) for x in range(num_entries) ] # decay_time = [random.randint(50, 100)*1000 for x in range(num_entries)] decay_time = gain_time out_scale = [random.randint(1, 10) for x in range(num_entries)] logger.info("Inserting %d entries to the lpf table", num_entries) data_list = [] for x in range(num_entries): data_list.append( table.make_data([ client.DataTuple('$LPF_SPEC_TYPE', str_val="RATE"), client.DataTuple('$LPF_SPEC_GAIN_TIME_CONSTANT_NS', float_val=gain_time[x]), client.DataTuple('$LPF_SPEC_DECAY_TIME_CONSTANT_NS', float_val=decay_time[x]), client.DataTuple('$LPF_SPEC_OUT_SCALE_DOWN_FACTOR', out_scale[x]) ], action_name)) table.entry_add(target, key_fields, data_list) for x in range(num_entries): resp = table.entry_get(target, [key_fields[x]], {"from_hw": False}) data_dict = next(resp)[0].to_dict() assert (data_dict["$LPF_SPEC_TYPE"] == "RATE") assert (data_dict["$LPF_SPEC_GAIN_TIME_CONSTANT_NS"] <= gain_time[x]) assert (data_dict["$LPF_SPEC_DECAY_TIME_CONSTANT_NS"] <= decay_time[x]) assert (data_dict["$LPF_SPEC_OUT_SCALE_DOWN_FACTOR"] == out_scale[x])
def cross_check_entries(self): # Apply table operations to sync the registers on the indirect register table logger.info("Syncing indirect stful registers") target = gc.Target(device_id=0, pipe_id=0xffff) self.test_reg_table.operations_execute(target, 'Sync') # Get from sw and check its value. logger.info("Reading back the register table entries") resp = self.test_reg_table.entry_get( target, None, {"from_hw": False}) # The values read back should match the initialized values logger.info("Verifying read back indirect register values") i = 0 for data, key in resp: data_dict = data.to_dict() key_dict = key.to_dict() VerifyReadRegisters(self, "SwitchIngress.test_reg.first", "SwitchIngress.test_reg.second", resp, [self.register_value_lo[i]] * 4, [self.register_value_hi[i]] * 4, data_dict) assert key_dict["$REGISTER_INDEX"]['value'] == i logger.info("Indirect Register values matched for idx %d", i) i += 1 pass
def runTest(self): target = client.Target(device_id=0, pipe_id=0xffff) bfrt_info = self.interface.bfrt_info_get("tna_meter_lpf_wred") table = bfrt_info.table_get("SwitchIngress.direct_meter_color") table.info.key_field_annotation_add("hdr.ethernet.src_addr", "mac") entry_key = table.make_key( [client.KeyTuple('hdr.ethernet.src_addr', '00:11:22:33:44:55')]) entry_data = table.make_data([], "SwitchIngress.set_color_direct") table.entry_add(target, [entry_key], [entry_data]) for data, key in table.entry_get(target, [entry_key], {"from_hw": False}): data_dict = data.to_dict() if g_is_tofino and testutils.test_param_get("target") is not "hw": self.assertEqual(data_dict["$METER_SPEC_CIR_KBPS"], 5195848221) self.assertEqual(data_dict["$METER_SPEC_PIR_KBPS"], 5195848221) elif g_is_tofino2: self.assertEqual(data_dict["$METER_SPEC_CIR_KBPS"], 4087999890) self.assertEqual(data_dict["$METER_SPEC_PIR_KBPS"], 4087999890) self.assertEqual(data_dict["$METER_SPEC_CBS_KBITS"], 4380866642) self.assertEqual(data_dict["$METER_SPEC_PBS_KBITS"], 4380866642) table.entry_del(target, [entry_key])
def __init__(self, program, retries, addr='localhost:50052', client_id=0, device_id=0): ## Due to a bug in client.py, the num_tries parameter is currently ## fixed at 5. re_retries = int((retries - 1) / 5) + 1 for i in range(0, re_retries): ## The "is_master" argument has been removed in SED 9.4.0 args = dict(client_id=client_id, num_tries=retries, device_id=device_id) if "is_master" in inspect.getargspec( gc.ClientInterface.__init__).args: args["is_master"] = True try: self.intf = gc.ClientInterface(addr, **args) except: if i < re_retries - 1: continue else: raise Exception("connection attempts exceeded") else: break self.intf.bind_pipeline_config(program) self.target = gc.Target(device_id=device_id, pipe_id=0xffff) self.info = self.intf.bfrt_info_get()
def runTest(self): target = gc.Target(device_id=0, pipe_id=0xffff) # Get bfrt_info and set it as part of the test bfrt_info = self.interface.bfrt_info_get(p4_program_name) # Set default output port ipv4_match_regular = bfrt_info.table_get("SwitchIngress.ipv4_match_regular") action_data = ipv4_match_regular.make_data( action_name="SwitchIngress.set_output_port", data_field_list_in=[gc.DataTuple(name="port_id", val=swports[0])] ) ipv4_match_regular.default_entry_set( target=target, data=action_data) try: ipkt = testutils.simple_udp_packet(eth_dst='11:11:11:11:11:11', eth_src='22:22:22:22:22:22', ip_src='1.2.3.4', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, udp_sport=0x1234, udp_dport=0xabcd) testutils.send_packet(self, swports[0], ipkt) testutils.verify_packet(self, ipkt, swports[0]) finally: ipv4_match_regular.default_entry_reset(target)
def runTest(self): self.p4_name = "tna_32q_multiprogram_b" # Keep BINDing to the program till success while (True): try: time.sleep(1) logger.info("Client W2: Binding to %s", self.p4_name) self.interface.bind_pipeline_config( "tna_32q_multiprogram_b") self.bfrt_info = self.interface.bfrt_info_get(self.p4_name) break except gc.BfruntimeRpcException as e: # Errors tolerated -> # 1. Device is locked, try again # 2. Already_exists because this client is already bound # to the same P4, break if e.grpc_error_get().code( ) == grpc.StatusCode.UNAVAILABLE: logger.info( "Failed to BIND because device is locked %s", e.grpc_error_get().code()) continue elif e.grpc_error_get().code( ) == grpc.StatusCode.ALREADY_EXISTS: logger.info( "This client is already connected to this P4 %s", e.grpc_error_get().code()) break logger.error("Failed to BIND %s", e.grpc_error_get().code()) raise e except Exception as e: raise e # Write a few entries logger.info("Writing to Table: SwitchIngress_b.forward") target = gc.Target(device_id=0, pipe_id=0xffff) dip = "5.6.7.8" self.e_forward_table = self.bfrt_info.table_get( "SwitchEgress_b.forward") self.e_forward_table.info.key_field_annotation_add( "hdr.ipv4.dst_addr", "ipv4") for i in range(10): try: self.e_forward_table.entry_add(target, [ self.e_forward_table.make_key([ gc.KeyTuple( 'hdr.ipv4.dst_addr', dip, prefix_len=31), gc.KeyTuple('hdr.ipv4.ttl', i), gc.KeyTuple('hdr.custom_metadata.custom_tag', i) ]) ], [ self.e_forward_table.make_data([], 'SwitchEgress_b.hit') ]) except gc.BfruntimeRpcException as e: # All errors tolerated here since we just want to try and write entries logger.info("%s", e) pass except Exception as e: raise e
def runTest(self): target = gc.Target(device_id=0, pipe_id=0xffff) # Get bfrt_info and set it as part of the test bfrt_info = self.interface.bfrt_info_get(p4_program_name) # Set default output port table_output_port = bfrt_info.table_get("SwitchIngress.output_port") action_data = table_output_port.make_data( action_name="SwitchIngress.set_output_port", data_field_list_in=[gc.DataTuple(name="port_id", val=swports[1])]) table_output_port.default_entry_set(target=target, data=action_data) # Set a default entry in the rewrite table so all packets get # their checksum updated. table_translate = bfrt_info.table_get("SwitchIngress.translate") action_data = table_translate.make_data( action_name="SwitchIngress.snupat", data_field_list_in=[ gc.DataTuple(name="src_addr", val=gc.ipv4_to_bytes("4.3.2.1")), gc.DataTuple(name="src_port", val=gc.to_bytes(0x4321, 2)), gc.DataTuple(name="update", val=0x0) ], ) table_translate.default_entry_set(target=target, data=action_data) try: ipkt = testutils.simple_udp_packet(eth_dst='11:11:11:11:11:11', eth_src='00:00:00:00:00:00', ip_src='1.2.3.4', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, udp_sport=0x1234, udp_dport=0xabcd, with_udp_chksum=True) epkt = testutils.simple_udp_packet(eth_dst='11:11:11:11:11:11', eth_src='00:00:00:00:00:00', ip_src='4.3.2.1', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, udp_sport=0x4321, udp_dport=0xabcd, with_udp_chksum=False) # We expect the packet to have the same TCP checksum as the packet # we sent in. Calling str forces scapy to calculate the checksum # for the given layer. epkt[scapy.all.IP].chksum = ipkt[scapy.all.IP].__class__( str(ipkt[scapy.all.IP])).chksum epkt[scapy.all.UDP].chksum = ipkt[scapy.all.UDP].__class__( str(ipkt[scapy.all.UDP])).chksum testutils.send_packet(self, swports[0], ipkt) testutils.verify_packet(self, epkt, swports[1]) finally: table_output_port.default_entry_reset(target) table_translate.default_entry_reset(target)
def main(): print("Starting...") grpc_addr = 'localhost:50052' client_id = 1 is_master = False p4_name = "netassay_tunnel_j8" interface = gc.ClientInterface(grpc_addr, client_id=client_id, device_id=0, is_master=is_master) interface.bind_pipeline_config(p4_name) target = gc.Target(device_id=0, pipe_id=0xffff) bfrt_info = interface.bfrt_info_get(p4_name) def signal_handler(sig, frame): print('You pressed Ctrl+C! Tearing down gRPC connection...') interface._tear_down_stream() sys.exit(0) signal.signal(signal.SIGINT, signal_handler) while 1: # pull regsiters 1 client_reg_pair_1 = bfrt_info.table_get( "SwitchEgress.client_reg_pair_1") entries_list = client_reg_pair_1.entry_get(target) ip_count_pair_list_1 = get_index_and_value_tunnel( entries_list, "SwitchEgress.client_reg_pair_1.cip", "SwitchEgress.client_reg_pair_1.counter") # pull regsiters 2 client_reg_pair_2 = bfrt_info.table_get( "SwitchEgress.client_reg_pair_2") entries_list = client_reg_pair_2.entry_get(target) ip_count_pair_list_2 = get_index_and_value_tunnel( entries_list, "SwitchEgress.client_reg_pair_2.cip", "SwitchEgress.client_reg_pair_2.counter") # combine ip_count_pair_list_all = ip_count_pair_list_1 + ip_count_pair_list_2 # print print("Suspected clients using DNS tunneling...(w/ counter value):") for i in ip_count_pair_list_all: ip_addr = socket.inet_ntoa(struct.pack("!I", int(i[0]))) print("- {}: {}".format(str(ip_addr), str(i[1]))) print("\n\n") # sleep time.sleep(INTERVAL_SECONDS) # Tear down. interface._tear_down_stream() exit() interface._tear_down_stream()
def add_default_entries(self): self.logger.info("Clearing worker count register...") # target all pipes on device 0 target = gc.Target(device_id=0, pipe_id=0xffff) # all handled in the p4 code pass
def clear_registers(self): self.logger.info("Clearing exponent registers...") # target all pipes on device 0 target = gc.Target(device_id=0, pipe_id=0xffff) # clear all register entries self.register.entry_del(target)
def getCntr(self, index): t = self.bfrt_info.table_get('cntr') resp = t.entry_get( gc.Target(device_id=dev_id, pipe_id=0xffff), [t.make_key([gc.KeyTuple('$COUNTER_INDEX', index)])], {"from_hw": True}, None) data_dict = next(resp)[0].to_dict() return data_dict['$COUNTER_SPEC_PKTS']
def runTest(self): # Get bfrt_info and set it as part of the test target = client.Target(device_id=0, pipe_id=0xffff) # Insert 100 entries num_entries = 100 phase0_igr_ports = {} try: logger.info("Inserting %d entries in the phase0 table", num_entries) for i in range(num_entries): igr_port = 0 phase0data = 0 while True: igr_pipe = random.randint(0, 3) igr_local_port = random.randint(0, 63) igr_port = (igr_pipe << 7) | (igr_local_port) if igr_port not in phase0_igr_ports: field1 = random.randint(1, 0xffff) # 16 bit field2 = random.randint(1, 0xffffff) # 24 bits field3 = random.randint(1, 0xffff) # 16 bits field4 = random.randint(1, 0xff) # 8 bits phase0data = make_phase0_data(field1, field2, field3, field4) phase0_igr_ports[igr_port] = phase0data break self.port_metadata_table.entry_add( target, [self.port_metadata_table.make_key( [client.KeyTuple('ig_intr_md.ingress_port', igr_port)])], [self.port_metadata_table.make_data( [client.DataTuple('$DEFAULT_FIELD', phase0data)])]) # Read back the entries logger.info("Reading back %d entries", num_entries) for key, value in list(phase0_igr_ports.items()): igr_port = key phase0data = value resp = self.port_metadata_table.entry_get( target, [self.port_metadata_table.make_key( [client.KeyTuple('ig_intr_md.ingress_port', igr_port)])], {"from_hw": True}) fields = next(resp)[0].to_dict() logger.info("Verifying %d entry for igr port %d", i, igr_port) recv_data = fields["$DEFAULT_FIELD"] if recv_data != phase0data: logger.info("Exp data : %s : Rcv data : %s", phase0data, recv_data) assert(0) finally: logger.info("Cleaning up entries") self.port_metadata_table.entry_del(target)
def runTest(self): target = gc.Target(device_id=0, pipe_id=0xffff) # Get bfrt_info bfrt_info = self.interface.bfrt_info_get(p4_program_name) # Set default output port table_output_port = bfrt_info.table_get("SwitchIngress.output_port") action_data = table_output_port.make_data( action_name="SwitchIngress.set_output_port", data_field_list_in=[gc.DataTuple(name="port_id", val=swports[1])]) table_output_port.default_entry_set(target=target, data=action_data) # Add bridge_md to ig_intr_md table_bridge_md_ctl = bfrt_info.table_get( "SwitchIngress.bridge_md_ctrl") action_data = table_bridge_md_ctl.make_data( [ gc.DataTuple(name="dst_mac_addr_low", val=0xffeeddcc), gc.DataTuple(name="src_mac_addr_low", val=0x11223344), ], action_name="SwitchIngress.bridge_add_example_hdr") table_bridge_md_ctl.default_entry_set(target=target, data=action_data) try: ipkt = testutils.simple_tcp_packet(eth_dst='11:11:11:11:11:11', eth_src='22:22:22:22:22:22', ip_src='1.2.3.4', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, tcp_sport=0x1234, tcp_dport=0xabcd, with_tcp_chksum=True) epkt = testutils.simple_tcp_packet(eth_dst='00:00:ff:ee:dd:cc', eth_src='00:00:11:22:33:44', ip_src='1.2.3.4', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, tcp_sport=0x1234, tcp_dport=0xabcd, with_tcp_chksum=True) testutils.send_packet(self, swports[0], ipkt) testutils.verify_packet(self, epkt, swports[1]) finally: table_output_port.default_entry_reset(target) table_bridge_md_ctl.default_entry_reset(target)
def clear_registers(self): self.logger.info("Clearing significand registers...") # target all pipes on device 0 target = gc.Target(device_id=0, pipe_id=0xffff) # for each register in stage start = timer() for register in self.registers: register.entry_del(target) end = timer() self.logger.info("Cleared four registers in {} seconds per register...".format((end-start)/4))
def runTest(self): target = client.Target(device_id=0, pipe_id=0xffff) num_entries = random.randint(1, 100) wred_indices = [x + 1 for x in range(num_entries)] random.shuffle(wred_indices) key_dict = {} ip_addrs = [] # Get bfrt_info and set it as part of the test bfrt_info = self.interface.bfrt_info_get("tna_meter_lpf_wred") wred_match_table = bfrt_info.table_get("SwitchIngress.wred_match_tbl") wred_match_table.info.key_field_annotation_add("hdr.ipv4.src_addr", "ipv4") for i in range(num_entries): ip_addr = "%d.%d.%d.%d" % (random.randint( 1, 255), random.randint(0, 255), random.randint( 0, 255), random.randint(0, 255)) while ip_addr in key_dict: ip_addr = "%d.%d.%d.%d" % (random.randint( 1, 255), random.randint(0, 255), random.randint( 0, 255), random.randint(0, 255)) ip_addrs.append(ip_addr) key_dict[ip_addr] = True logger.info( "Inserting %d entries to the match table with random WRED indices", num_entries) for x in range(num_entries): wred_match_table.entry_add(target, [ wred_match_table.make_key( [client.KeyTuple('hdr.ipv4.src_addr', ip_addrs[x])]) ], [ wred_match_table.make_data( [client.DataTuple('wred_idx', wred_indices[x])], 'SwitchIngress.mark_wred') ]) for x in range(num_entries): resp = wred_match_table.entry_get(target, [ wred_match_table.make_key( [client.KeyTuple('hdr.ipv4.src_addr', ip_addrs[x])]) ], {"from_hw": False}) data_dict = next(resp)[0].to_dict() assert data_dict["wred_idx"] == wred_indices[x] for x in range(num_entries): wred_match_table.entry_del(target, [ wred_match_table.make_key( [client.KeyTuple('hdr.ipv4.src_addr', ip_addrs[x])]) ])
def getEntry(self, register_idx): # Please note that grpc server is always going to return all instances of the register # i.e. one per pipe and stage the table exists in. The asymmetric suport for indirect # register tables is limited only to the insertion of the entries. Thus even if we # made the indirect register table asymmetric, we need to pass in the device target # as consisting of all the pipes while reading the entry target = gc.Target(device_id=0, pipe_id=0xffff) resp = self.register_bool_table.entry_get(target, [ self.register_bool_table.make_key( [gc.KeyTuple('$REGISTER_INDEX', register_idx)]) ], {"from_hw": True}) return resp
def runTest(self): target = gc.Target(device_id=0, pipe_id=0xffff) # Get bfrt_info and set it as part of the test bfrt_info = self.interface.bfrt_info_get(p4_program_name) # Set default output port table_output_port = bfrt_info.table_get("SwitchIngress.output_port") action_data = table_output_port.make_data( action_name="SwitchIngress.set_output_port", data_field_list_in=[gc.DataTuple(name="port_id", val=swports[1])]) table_output_port.default_entry_set(target=target, data=action_data) # Set a default entry in the rewrite table so all packets get # their checksum updated. table_translate = bfrt_info.table_get("SwitchIngress.translate") action_data = table_translate.make_data( action_name="SwitchIngress.sntpat", data_field_list_in=[ gc.DataTuple(name="src_addr", val=gc.ipv4_to_bytes("4.3.2.1")), gc.DataTuple(name="src_port", val=gc.to_bytes(0x4321, 2)), gc.DataTuple(name="update", val=0x1) ], ) table_translate.default_entry_set(target=target, data=action_data) try: ipkt = testutils.simple_tcp_packet(eth_dst='11:11:11:11:11:11', eth_src='00:00:00:00:00:00', ip_src='1.2.3.4', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, tcp_sport=0x1234, tcp_dport=0xabcd, with_tcp_chksum=True) epkt = testutils.simple_tcp_packet(eth_dst='11:11:11:11:11:11', eth_src='00:00:00:00:00:00', ip_src='4.3.2.1', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, tcp_sport=0x4321, tcp_dport=0xabcd, with_tcp_chksum=True) testutils.send_packet(self, swports[0], ipkt) testutils.verify_packet(self, epkt, swports[1]) finally: table_output_port.default_entry_reset(target) table_translate.default_entry_reset(target)
def runTest(self): eg_port = swports[2] dmac = '22:22:22:22:22:22' dkey = '22:22:22:22:22:23' dmask = 'ff:ff:ff:ff:ff:f0' port_mask = 0 pkt = testutils.simple_tcp_packet(eth_dst=dmac) pkt2 = testutils.simple_tcp_packet(eth_dst=dkey) exp_pkt = pkt exp_pkt2 = pkt2 # Get bfrt_info and set it as part of the test bfrt_info = self.interface.bfrt_info_get("tna_dkm") # Set the scope of the table to ALL_PIPES logger.info("=============== Testing Dyn Key Mask ===============") target = gc.Target(device_id=0, pipe_id=0xffff) logger.info("set dyn key mask") forward_table = bfrt_info.table_get("SwitchIngress.forward") forward_table.info.key_field_annotation_add("hdr.ethernet.dst_addr", "mac") key_mask = forward_table.make_key( [gc.KeyTuple('hdr.ethernet.dst_addr', dmask), gc.KeyTuple('ig_intr_md.ingress_port', port_mask)]) forward_table.attribute_dyn_key_mask_set(target, key_mask) resp = forward_table.attribute_get(target, "DynamicKeyMask") for d in resp: assert d["fields"].to_dict()["ig_intr_md.ingress_port"]["value"] == port_mask assert d["fields"].to_dict()["hdr.ethernet.dst_addr"]["value"] == dmask logger.info("Add entry") key_list = [forward_table.make_key( [gc.KeyTuple('hdr.ethernet.dst_addr', dmac), gc.KeyTuple('ig_intr_md.ingress_port', swports_0[0])])] data_list = [forward_table.make_data([gc.DataTuple('port', eg_port)], "SwitchIngress.hit")] forward_table.entry_add(target, key_list, data_list) self.send_and_verify_packet(swports_0[0], eg_port, pkt2, exp_pkt2) self.send_and_verify_packet(swports_1[0], eg_port, pkt2, exp_pkt2) if int(testutils.test_param_get('num_pipes')) > 2: self.send_and_verify_packet(swports_2[0], eg_port, pkt2, exp_pkt2) if int(testutils.test_param_get('num_pipes')) > 3: self.send_and_verify_packet(swports_3[0], eg_port, pkt2, exp_pkt2) self.send_and_verify_packet(swports_0[0], eg_port, pkt, exp_pkt) self.send_and_verify_packet(swports_1[0], eg_port, pkt, exp_pkt) if int(testutils.test_param_get('num_pipes')) > 2: self.send_and_verify_packet(swports_2[0], eg_port, pkt, exp_pkt) if int(testutils.test_param_get('num_pipes')) > 3: self.send_and_verify_packet(swports_3[0], eg_port, pkt, exp_pkt) testutils.verify_no_other_packets(self, timeout=2) logger.info("Delete the entry") forward_table.entry_del(target, key_list)
def runTest(self): self.p4_name = "tna_32q_multiprogram_a" # Keep BINDing to the program till success or 5 tries while (True): try: time.sleep(1) logger.info("Client W1: Binding to %s", self.p4_name) self.interface.bind_pipeline_config( "tna_32q_multiprogram_a") self.bfrt_info = self.interface.bfrt_info_get(self.p4_name) break except gc.BfruntimeRpcException as e: # Errors tolerated -> # 1. Device is locked # 2. Already_exists because this client is already bound # to the same P4 if e.grpc_error_get().code( ) == grpc.StatusCode.UNAVAILABLE: logger.info( "Failed to BIND because device is locked %s", e.grpc_error_get().code()) continue elif e.grpc_error_get().code( ) == grpc.StatusCode.ALREADY_EXISTS: logger.info( "This client is already connected to this P4 %s", e.grpc_error_get().code()) break logger.error("Failed to BIND %s", e.grpc_error_get().code()) raise e except Exception as e: raise e # Write a few entries logger.info("Writing to Table: SwitchIngress_a.storm_control") target = gc.Target(device_id=0, pipe_id=0xffff) self.storm_control_table = self.bfrt_info.table_get( "SwitchIngress_a.storm_control") for i in range(10): try: self.storm_control_table.entry_add(target, [ self.storm_control_table.make_key( [gc.KeyTuple('ig_intr_md.ingress_port', i)]) ], [ self.storm_control_table.make_data( [gc.DataTuple('index', i)], 'SwitchIngress_a.set_color') ]) except gc.BfruntimeRpcException as e: # All errors tolerated here since we just want to try and write entries logger.info("%s", e) pass
def runTest(self): target = gc.Target(device_id=0, pipe_id=0xffff) # Get bfrt_info and set it as part of the test bfrt_info = self.interface.bfrt_info_get(p4_program_name) ipv4_match_regular = bfrt_info.table_get("SwitchIngress.ipv4_match_regular") ipv4_match_regular.info.key_field_annotation_add('hdr.ethernet.dst_addr', 'mac') ipv4_match_regular.info.key_field_annotation_add('hdr.ethernet.src_addr', 'mac') ipv4_match_regular.info.key_field_annotation_add('hdr.ipv4.dst_addr', 'ipv4') ipv4_match_regular.info.key_field_annotation_add('hdr.ipv4.src_addr', 'ipv4') key_data_regular = ipv4_match_regular.make_key([ gc.KeyTuple(name='hdr.ethernet.dst_addr', value='11:11:11:11:11:11'), gc.KeyTuple(name='hdr.ethernet.src_addr', value='22:22:22:22:22:22'), gc.KeyTuple(name='hdr.ipv4.dst_addr', value='100.99.98.97'), gc.KeyTuple(name='hdr.ipv4.src_addr', value='1.2.3.4'), ]) action_data_regular = ipv4_match_regular.make_data( [gc.DataTuple(name='port_id', val=swports[3])], 'SwitchIngress.set_output_port' ) ipv4_match_regular.entry_add( target, [key_data_regular], [action_data_regular]) try: ipkt = testutils.simple_udp_packet(eth_dst='11:11:11:11:11:11', eth_src='22:22:22:22:22:22', ip_src='1.2.3.4', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, udp_sport=0x1234, udp_dport=0xabcd) testutils.send_packet(self, swports[0], ipkt) testutils.verify_packet(self, ipkt, swports[3]) finally: ipv4_match_regular.default_entry_reset(target) ipv4_match_regular.entry_del(target, [key_data_regular])
def add_udp_entry(self, worker_rid, worker_mac, worker_ip): self.logger.info("Adding worker {} {} at rid {}".format(worker_mac, worker_ip, worker_rid)) # target all pipes on device 0 target = gc.Target(device_id=0, pipe_id=0xffff) self.table.entry_add( target, [self.table.make_key([gc.KeyTuple('eg_md.switchml_md.worker_id', worker_rid)])], [self.table.make_data([gc.DataTuple('eth_dst_addr', worker_mac), gc.DataTuple('ip_dst_addr', worker_ip)], 'Egress.set_dst_addr.set_dst_addr_for_SwitchML_UDP')])
def runTest(self): target = gc.Target(device_id=0, pipe_id=0xffff) # Get bfrt_info and set it as part of the test bfrt_info = self.interface.bfrt_info_get(p4_program_name) # Set default output port table_output_port = bfrt_info.table_get("SwitchIngress.output_port") action_data = table_output_port.make_data( action_name="SwitchIngress.set_output_port", data_field_list_in=[gc.DataTuple(name="port_id", val=swports[1])]) table_output_port.default_entry_set(target=target, data=action_data) # Set a default entry in the rewrite table so all packets get # their checksum updated. table_translate = bfrt_info.table_get("SwitchIngress.translate") action_data = table_translate.make_data( action_name="SwitchIngress.checksum_upd_ipv4_tcp_udp", data_field_list_in=[gc.DataTuple(name="update", val=0x1)]) table_translate.default_entry_set(target=target, data=action_data) try: ipkt = testutils.simple_tcp_packet(eth_dst='11:11:11:11:11:11', eth_src='00:00:00:00:00:00', ip_src='1.2.3.4', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, tcp_sport=0x1234, tcp_dport=0xabcd, with_tcp_chksum=True) # Set incorrect checksum ipkt[scapy.all.IP].chksum = 0x4321 # We expect the program to correct the IPv4 checksum. epkt = testutils.simple_tcp_packet(eth_dst='00:00:de:ad:be:ef', eth_src='00:00:00:00:00:00', ip_src='1.2.3.4', ip_dst='100.99.98.97', ip_id=101, ip_ttl=64, tcp_sport=0x1234, tcp_dport=0xabcd, with_tcp_chksum=True) testutils.send_packet(self, swports[0], ipkt) testutils.verify_packet(self, epkt, swports[1]) finally: table_output_port.default_entry_reset(target) table_translate.default_entry_reset(target)
def runTest(self): ig_port = self.swports(1) eg_port = ig_port meter_config = get_one_meter_config() entity = self.add_to_t_mtr_0(ig_port, eg_port, meter_config) # read table entry over p4runtime rentity = self.read_one(entity) self.assertProtoEqual(rentity, entity) # Set up Bfruntime interface bri = self.BriInterface("$SHARED") target = client.Target(device_id=0, pipe_id=0xffff) # Add an entry to the node table bri.node_table.entry_add(target, [ bri.node_table.make_key([client.KeyTuple('$MULTICAST_NODE_ID', 1)]) ], [ bri.node_table.make_data([ client.DataTuple('$MULTICAST_RID', 2), client.DataTuple('$MULTICAST_LAG_ID', int_arr_val=[10]), client.DataTuple('$DEV_PORT', int_arr_val=[20]) ]) ]) # Add an entry to the MGID table key = bri.mgid_table.make_key([client.KeyTuple('$MGID', 1)]) data = bri.mgid_table.make_data([ client.DataTuple('$MULTICAST_NODE_ID', int_arr_val=[1]), client.DataTuple('$MULTICAST_NODE_L1_XID_VALID', bool_arr_val=[True]), client.DataTuple('$MULTICAST_NODE_L1_XID', int_arr_val=[2]) ]) bri.mgid_table.entry_add(target, [key], [data]) # Read the entry back and ensure that it was the same for data_ret, key_ret in bri.mgid_table.entry_get(target, [key]): data_ret_dict = data_ret.to_dict() data_dict = data.to_dict() assert data_ret_dict["$MULTICAST_NODE_ID"] == data_dict[ "$MULTICAST_NODE_ID"] assert data_ret_dict["$MULTICAST_NODE_L1_XID_VALID"] == data_dict[ "$MULTICAST_NODE_L1_XID_VALID"] assert data_ret_dict["$MULTICAST_NODE_L1_XID"] == data_dict[ "$MULTICAST_NODE_L1_XID"] # Delete the entries bri.mgid_table.entry_del(target, [key]) bri.node_table.entry_del(target, [ bri.node_table.make_key([client.KeyTuple('$MULTICAST_NODE_ID', 1)]) ]) bri.tearDown()
def runTest(self): ig_port = swports[1] eg_port = swports[2] dmac = '22:22:22:22:22:22' target = client.Target(device_id=0, pipe_id=0xffff) # Get bfrt_info and set it as part of the test bfrt_info = self.interface.bfrt_info_get("tna_action_profile") forward_table = bfrt_info.table_get("SwitchIngress.forward") action_profile = bfrt_info.table_get("SwitchIngress.action_profile") ap_key = action_profile.make_key( [client.KeyTuple('$ACTION_MEMBER_ID', 1)]) action_profile.entry_add(target, [ap_key], [ action_profile.make_data([client.DataTuple('port', eg_port)], 'SwitchIngress.set_port') ]) fwd_key = forward_table.make_key([ client.KeyTuple('ig_intr_md.ingress_port', ig_port), client.KeyTuple('vid', 0) ]) forward_table.entry_add(target, [fwd_key], [ forward_table.make_data([client.DataTuple('$ACTION_MEMBER_ID', 1)]) ]) try: pkt = testutils.simple_tcp_packet(eth_dst=dmac) logger.info("Sending packet on port %d", ig_port) testutils.send_packet(self, ig_port, pkt) exp_pkt = pkt logger.info("Expecting packet on port %d", eg_port) testutils.verify_packets(self, exp_pkt, [eg_port]) finally: forward_table.entry_del(target, [fwd_key]) action_profile.entry_del(target, [ap_key]) try: logger.info("Sending packet on port %d", ig_port) testutils.send_packet(self, ig_port, pkt) logger.info("Packet is expected to get dropped.") testutils.verify_no_other_packets(self) finally: pass
def __init__(self, client, bfrt_info): # get logging, client, and global program info self.logger = logging.getLogger('Table') self.gc = client self.bfrt_info = bfrt_info # target all pipes on device 0 self.target = gc.Target(device_id=0, pipe_id=0xffff) # child clases must set table self.table = None # lowest possible priority for ternary match rules self.lowest_priority = 1 << 24