def set_fwd_config(test, client_id, action, bind=True): """@brief Helper function to send a set fwd config msg for both the programs tna_32q_multiprogram_a and tna_32q_multiprogram_b. Note, this function cannot be used for sending WARM_INIT_END, since it sends a config with it as well. WARM_INIT_END cannot accept a config. @param test The test object which has its own interface (Program A) @param clinet_id client ID @param action proto enum of VERIFY_AND_WARM_INIT_BEGIN or VERIFY_AND_WARM_INIT_BEGIN_AND_END @param bind If this client needs to bind to the P4 as well """ p4_name_to_put = p4_name_to_pick = p4_name = "tna_32q_multiprogram_a" profile_name_to_put = profile_name_to_pick = "profile_a" config_list = [ gc.ForwardingConfig( p4_name_to_put, create_path_bf_rt(base_pick_path, p4_name_to_pick), [ gc.ProfileInfo( profile_name_to_put, create_path_context(base_pick_path, p4_name_to_pick, profile_name_to_pick), create_path_tofino(base_pick_path, p4_name_to_pick, profile_name_to_pick), external_pipes) ]) ] p4_name_to_put = p4_name_to_pick = "tna_32q_multiprogram_b" profile_name_to_put = profile_name_to_pick = "profile_b" config_list.append( gc.ForwardingConfig( p4_name_to_put, create_path_bf_rt(base_pick_path, p4_name_to_pick), [ gc.ProfileInfo( profile_name_to_put, create_path_context(base_pick_path, p4_name_to_pick, profile_name_to_pick), create_path_tofino(base_pick_path, p4_name_to_pick, profile_name_to_pick), internal_pipes) ])) success = test.interface.send_set_forwarding_pipeline_config_request( action, base_put_path, config_list) if not success: raise RuntimeError("Failed to get response for setfwd") test.p4_name = p4_name if bind: test.interface.bind_pipeline_config(p4_name)
def setUp(self): client_id = 0 p4_name_to_put = p4_name_to_pick = p4_name = "tna_register" profile_name_to_put = profile_name_to_pick = "pipe" # Setup and don't perform bind BfRuntimeTest.setUp(self, client_id, perform_bind=False) # Send a Verify_and_warm_init_begin_and_end logger.info("Sending Verify and warm_init_begin and warm_init_end for %s", p4_name_to_put) action = bfruntime_pb2.SetForwardingPipelineConfigRequest.VERIFY_AND_WARM_INIT_BEGIN_AND_END success = self.interface.send_set_forwarding_pipeline_config_request( action, base_put_path, [gc.ForwardingConfig(p4_name_to_put, create_path_bf_rt(base_pick_path, p4_name_to_pick), [gc.ProfileInfo(profile_name_to_put, create_path_context(base_pick_path, p4_name_to_pick, profile_name_to_pick), create_path_tofino(base_pick_path, p4_name_to_pick, profile_name_to_pick), [0, 1, 2, 3])] )]) if not success: raise RuntimeError("Failed to setFwd") self.p4_name = p4_name self.interface.bind_pipeline_config("tna_register")
def setP4ProgramList(self): cfg_list = [] # By default program is loaded on all TOFINO pipelines pipe_id_list = [0, 1, 2, 3] try: if len(self.p4_name_list) == SINGLE: p4_name = self.p4_name_list[0] logger.warn("Setting config for: %s" % p4_name) cfg_list = [ gc.ForwardingConfig( p4_name, self.bfrt_fp(self.p4_base, p4_name), [ gc.ProfileInfo( self.profile_name, self.cxt_fp(self.p4_base, p4_name, self.profile_name), self.tna_fp(self.p4_base, p4_name, self.profile_name), pipe_id_list) ]) ] logger.warn("p4_base = %s" % self.p4_base) else: pipe_index = 0 for p4_name in self.p4_name_list: logger.warn("Setting config for: %s" % p4_name) pfl_info_list = [ gc.ProfileInfo( self.profile_name, self.cxt_fp(self.p4_base, p4_name, self.profile_name), self.tna_fp(self.p4_base, p4_name, self.profile_name), [pipe_index]) ] fwd_cfg = gc.ForwardingConfig( p4_name, self.bfrt_fp(self.p4_base, p4_name), pfl_info_list) cfg_list.append(fwd_cfg) pipe_index = pipe_index + 1 return cfg_list except Exception as e: logException(sys._getframe().f_code.co_name, e)
def runTest(self): # Only changing the name of the program from a to c # So it will be picked from a but put into c for testing purposes # The server should treat them as different programs p4_name_to_put = new_p4_name = "tna_32q_multiprogram_c" p4_name_to_pick = "tna_32q_multiprogram_a" profile_name_to_put = "profile_c" profile_name_to_pick = "profile_a" # Send a Verify and warm_init_begin and warm_init_end logger.info("Client 1:") action = bfruntime_pb2.SetForwardingPipelineConfigRequest.VERIFY_AND_WARM_INIT_BEGIN_AND_END config_list = [ gc.ForwardingConfig( p4_name_to_put, create_path_bf_rt(base_pick_path, p4_name_to_pick), [ gc.ProfileInfo( profile_name_to_put, create_path_context(base_pick_path, p4_name_to_pick, profile_name_to_pick), create_path_tofino(base_pick_path, p4_name_to_pick, profile_name_to_pick), external_pipes) ]) ] p4_name_to_put = p4_name_to_pick = "tna_32q_multiprogram_b" profile_name_to_put = profile_name_to_pick = "profile_b" config_list.append( gc.ForwardingConfig( p4_name_to_put, create_path_bf_rt(base_pick_path, p4_name_to_pick), [ gc.ProfileInfo( profile_name_to_put, create_path_context(base_pick_path, p4_name_to_pick, profile_name_to_pick), create_path_tofino(base_pick_path, p4_name_to_pick, profile_name_to_pick), internal_pipes) ])) success = self.a.interface.send_set_forwarding_pipeline_config_request( action, base_put_path, config_list) if not success: raise RuntimeError("Failed to get response for setfwd") # Check if client 1 has dropped out exception = self.a.interface.exception_q.get(timeout=5) if exception.grpc_error_get().code() != grpc.StatusCode.CANCELLED: logger.error("Did not receive cancelled for a") assert (0) # client 2 should not drop out logger.info("Client 2:") is_queue_empty = False try: exception = self.b.interface.exception_q.get(timeout=5) except q.Empty: logger.info("Did not receive cancelled for b. Expected behavior") is_queue_empty = True pass if not is_queue_empty: logger.error("Exception_queue was supposed to be empty") assert (0) # Check for WARM_INIT_FINISHED on client 2. success = self.b.interface.is_set_fwd_action_done( bfruntime_pb2.SetForwardingPipelineConfigResponseType.Value( "WARM_INIT_FINISHED"), 5, 5) if not success: raise RuntimeError("Failed to receive set fwd response") # Initiate subscribe and BIND for client 1 logger.info("Client 1:") self.a.setUpBind(1, new_p4_name)
def runTest(self): p4_name_to_put = p4_name_to_pick = new_p4_name = "tna_ternary_match" profile_name_to_put = profile_name_to_pick = "pipe" # Send a Verify and warm_init_begin and warm_init_end logger.info( "Sending Verify and warm_init_begin and warm_init_end for %s", p4_name_to_put) action = bfruntime_pb2.SetForwardingPipelineConfigRequest.VERIFY_AND_WARM_INIT_BEGIN_AND_END success = self.a.interface.send_set_forwarding_pipeline_config_request( action, base_put_path, [ gc.ForwardingConfig( p4_name_to_put, create_path_bf_rt(base_pick_path, p4_name_to_pick), [ gc.ProfileInfo( profile_name_to_put, create_path_context(base_pick_path, p4_name_to_pick, profile_name_to_pick), create_path_tofino(base_pick_path, p4_name_to_pick, profile_name_to_pick), [0, 1, 2, 3]) ]) ]) if not success: raise RuntimeError("Failed to setFwd") # Check if both the clients have dropped out exception = self.a.interface.exception_q.get(timeout=5) if exception.grpc_error_get().code() != grpc.StatusCode.CANCELLED: logger.error("Did not receive cancelled for a") assert (0) exception = self.b.interface.exception_q.get(timeout=5) if exception.grpc_error_get().code() != grpc.StatusCode.CANCELLED: logger.error("Did not receive cancelled for b") assert (0) # Initiate subscribe and BIND for client 1 self.a.setUpBind(1, new_p4_name) # Try inserting a table entry in the new Program and test it target = gc.Target(device_id=0, pipe_id=0xffff) ig_port = get_port_from_pipes(external_pipes) eg_port = get_port_from_pipes(external_pipes) dip = '10.10.0.1' pkt = testutils.simple_tcp_packet(ip_dst=dip) exp_pkt = pkt self.a.bfrt_info = self.a.interface.bfrt_info_get(new_p4_name) self.a.forward_table = self.a.bfrt_info.table_get( "SwitchIngress.forward") self.a.forward_table.info.key_field_annotation_add( "hdr.ipv4.dst_addr", "ipv4") try: key = self.a.forward_table.make_key([ gc.KeyTuple('$MATCH_PRIORITY', 1), gc.KeyTuple('vrf', 0), gc.KeyTuple('hdr.ipv4.dst_addr', dip, '255.255.0.0') ]) data = self.a.forward_table.make_data( [gc.DataTuple('port', eg_port)], 'SwitchIngress.hit') self.a.forward_table.entry_add(target, [key], [data]) # check get resp = self.a.forward_table.entry_get(target, [key], {"from_hw": True}) data_dict = next(resp)[0].to_dict() recv_port = data_dict["port"] if (recv_port != eg_port): logger.error("Error! port sent = %s received port = %s", str(eg_port), str(recv_port)) assert 0 logger.info("Sending packet on port %d", ig_port) testutils.send_packet(self, ig_port, pkt) logger.info("Expecting packet on port %d", eg_port) testutils.verify_packet(self, exp_pkt, eg_port) testutils.verify_no_other_packets(self, timeout=2) except Exception as e: logger.info("!!!! Test Failed!!!!") import traceback traceback.print_exc() raise e finally: self.a.forward_table.entry_del(target, [ self.a.forward_table.make_key([ gc.KeyTuple('$MATCH_PRIORITY', 1), gc.KeyTuple('vrf', 0), gc.KeyTuple('hdr.ipv4.dst_addr', dip, '255.255.0.0') ]) ]) 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)