diff options
author | Yaroslav Brustinov <ybrustin@cisco.com> | 2017-03-13 11:01:55 +0200 |
---|---|---|
committer | Yaroslav Brustinov <ybrustin@cisco.com> | 2017-03-13 11:01:55 +0200 |
commit | dbff547f4d9360d3c48c7b269255234cd31271df (patch) | |
tree | 1bbee86b5a4d9d54fa20140f96ea62b7474f8db2 | |
parent | c8d1f318e2d322626e401c9599ba75006d2e8e6c (diff) |
i40e fix of workaround of stuck counters + regression test
Change-Id: I251cb8d346461ccfa4eee8abfda113410160a602
Signed-off-by: Yaroslav Brustinov <ybrustin@cisco.com>
-rwxr-xr-x | scripts/automation/regression/misc_methods.py | 12 | ||||
-rw-r--r-- | scripts/automation/regression/setups/trex08/config.yaml | 1 | ||||
-rw-r--r-- | scripts/automation/regression/setups/trex09/config.yaml | 1 | ||||
-rw-r--r-- | scripts/automation/regression/stateless_tests/stl_rx_test.py | 27 | ||||
-rwxr-xr-x | scripts/automation/regression/trex_unit_test.py | 3 | ||||
-rwxr-xr-x | src/bp_sim.h | 10 | ||||
-rw-r--r-- | src/dpdk/drivers/net/i40e/i40e_fdir.c | 7 | ||||
-rw-r--r-- | src/main_dpdk.cpp | 18 |
8 files changed, 62 insertions, 17 deletions
diff --git a/scripts/automation/regression/misc_methods.py b/scripts/automation/regression/misc_methods.py index d879b038..e8859779 100755 --- a/scripts/automation/regression/misc_methods.py +++ b/scripts/automation/regression/misc_methods.py @@ -129,15 +129,13 @@ def load_complete_config_file (filepath): try: with open(filepath, 'r') as f: config = yaml.safe_load(f) - + # Handle TRex configuration trex_config['trex_name'] = config["trex"]["hostname"] - trex_config['trex_password'] = config["trex"].get("password") - #trex_config['trex_is_dual'] = config["trex"]["is_dual"] trex_config['trex_cores'] = int(config["trex"]["cores"]) - #trex_config['trex_latency'] = int(config["trex"]["latency"]) -# trex_config['trex_version_path'] = config["trex"]["version_path"] trex_config['modes'] = config['trex'].get('modes', []) + for key, val in config['trex'].items(): + trex_config[key] = val if 'loopback' not in trex_config['modes']: trex_config['router_interface'] = config["router"]["ip_address"] @@ -225,10 +223,10 @@ def load_benchmark_config_file (filepath): """ # create response dictionary - benchmark_config = {} + benchmark_config = {} try: - with open(filepath, 'r') as f: + with open(filepath) as f: benchmark_config = yaml.safe_load(f) except Exception as inst: diff --git a/scripts/automation/regression/setups/trex08/config.yaml b/scripts/automation/regression/setups/trex08/config.yaml index affe9bc9..8199a6dc 100644 --- a/scripts/automation/regression/setups/trex08/config.yaml +++ b/scripts/automation/regression/setups/trex08/config.yaml @@ -37,4 +37,5 @@ trex: hostname : csi-trex-08 cores : 7 modes : ['loopback'] + trex_add_args : '--x710-reset-threshold 10000000' diff --git a/scripts/automation/regression/setups/trex09/config.yaml b/scripts/automation/regression/setups/trex09/config.yaml index 724de6e7..7eb23743 100644 --- a/scripts/automation/regression/setups/trex09/config.yaml +++ b/scripts/automation/regression/setups/trex09/config.yaml @@ -36,3 +36,4 @@ trex: hostname : csi-trex-09 cores : 2 modes : ['loopback'] + trex_add_args : '--x710-reset-threshold 10000000' diff --git a/scripts/automation/regression/stateless_tests/stl_rx_test.py b/scripts/automation/regression/stateless_tests/stl_rx_test.py index 4e15e03b..347c8e8b 100644 --- a/scripts/automation/regression/stateless_tests/stl_rx_test.py +++ b/scripts/automation/regression/stateless_tests/stl_rx_test.py @@ -100,6 +100,7 @@ class STLRX_Test(CStlGeneral_Test): self.cap = cap drv_name = port_info['driver'] + self.drv_name = drv_name if drv_name == 'net_ixgbe': self.ipv6_support = False else: @@ -613,3 +614,29 @@ class STLRX_Test(CStlGeneral_Test): except STLError as e: assert False , '{0}'.format(e) + + + # counters get stuck in i40e when they are getting to limit. + # this test checks our workaround to this issue + def test_x710_counters_wraparound(self): + if self.drv_name != 'net_i40e': + self.skip('Test is only for i40e.') + + percent = min(20, self.speed * 0.8) # 8G at X710 and 20G at XL710 + total_pkts = 300000000 # send 300 million packets to ensure getting to threshold of reset several times + + s1 = STLStream(name = 'wrapping_stream', + packet = self.pkt, + flow_stats = STLFlowStats(pg_id = 5), + mode = STLTXSingleBurst(total_pkts = total_pkts, + percentage = percent)) + + # add both streams to ports + self.c.add_streams([s1], ports = [self.tx_port]) + + print("\ninjecting {0} packets on port {1}\n".format(total_pkts, self.tx_port)) + + exp = {'pg_id': 5, 'total_pkts': total_pkts, 'pkt_len': s1.get_pkt_len()} + + self.__rx_iteration( [exp] ) + diff --git a/scripts/automation/regression/trex_unit_test.py b/scripts/automation/regression/trex_unit_test.py index f915448d..8c07498a 100755 --- a/scripts/automation/regression/trex_unit_test.py +++ b/scripts/automation/regression/trex_unit_test.py @@ -394,11 +394,12 @@ class CTRexTestConfiguringPlugin(Plugin): CTRexScenario.server_logs = self.server_logs CTRexScenario.debug_image = options.debug_image CTRexScenario.json_verbose = self.json_verbose + additional_args = self.configuration.trex.get('trex_add_args', '') if not self.no_daemon: CTRexScenario.trex = CTRexClient(trex_host = self.configuration.trex['trex_name'], verbose = self.json_verbose, debug_image = options.debug_image, - trex_args = options.trex_args) + trex_args = options.trex_args + ' ' + additional_args) if self.pkg or self.restart_daemon: if not CTRexScenario.trex.check_master_connectivity(): diff --git a/src/bp_sim.h b/src/bp_sim.h index 7346615a..24681d4b 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -775,6 +775,9 @@ public: out_file = ""; prefix = ""; set_tw_bucket_time_in_usec(20.0); + // we read every 0.5 second. We want to catch the counter when it approach the maximum (where it will stuck, + // and we will start losing packets). + x710_fdir_reset_threshold = 0xffffffff - 1000000000/8/64*40; } CParserOption(){ @@ -819,6 +822,7 @@ public: CMacAddrCfg m_mac_addr[TREX_MAX_PORTS]; double m_tw_bucket_time_sec; double m_tw_bucket_time_sec_level1; + uint32_t x710_fdir_reset_threshold; public: uint8_t * get_src_mac_addr(int if_index){ @@ -857,6 +861,12 @@ public: void set_rx_enabled() { m_rx_thread_enabled = true; } + uint32_t get_x710_fdir_reset_threshold() { + return (x710_fdir_reset_threshold); + } + void set_x710_fdir_reset_threshold(uint32_t val) { + x710_fdir_reset_threshold = val; + } inline double get_tw_bucket_time_in_sec(void){ return (m_tw_bucket_time_sec); diff --git a/src/dpdk/drivers/net/i40e/i40e_fdir.c b/src/dpdk/drivers/net/i40e/i40e_fdir.c index eddb2b9f..ceac810f 100644 --- a/src/dpdk/drivers/net/i40e/i40e_fdir.c +++ b/src/dpdk/drivers/net/i40e/i40e_fdir.c @@ -1145,11 +1145,18 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev, memset(&check_filter, 0, sizeof(check_filter)); i40e_fdir_filter_convert(filter, &check_filter); node = i40e_sw_fdir_filter_lookup(fdir_info, &check_filter.fdir.input); + +#ifndef TREX_PATCH +/* +We use same rule at different filters, for example to overcome "stuck counters" issue: +https://trex-tgn.cisco.com/youtrack/issue/trex-199 + */ if (add && node) { PMD_DRV_LOG(ERR, "Conflict with existing flow director rules!"); return -EINVAL; } +#endif if (!add && !node) { PMD_DRV_LOG(ERR, diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 0da245ba..1f9dadcd 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -708,6 +708,7 @@ enum { OPT_HELP, OPT_L_PKT_MODE, OPT_NO_FLOW_CONTROL, OPT_NO_HW_FLOW_STAT, + OPT_X710_RESET_THRESHOLD, OPT_VLAN, OPT_RX_CHECK_HOPS, OPT_CLIENT_CFG_FILE, @@ -770,6 +771,7 @@ static CSimpleOpt::SOption parser_options[] = { OPT_L_PKT_MODE, "--l-pkt-mode", SO_REQ_SEP }, { OPT_NO_FLOW_CONTROL, "--no-flow-control-change", SO_NONE }, { OPT_NO_HW_FLOW_STAT, "--no-hw-flow-stat", SO_NONE }, + { OPT_X710_RESET_THRESHOLD, "--x710-reset-threshold", SO_REQ_SEP }, { OPT_VLAN, "--vlan", SO_NONE }, { OPT_CLIENT_CFG_FILE, "--client_cfg", SO_REQ_SEP }, { OPT_CLIENT_CFG_FILE, "--client-cfg", SO_REQ_SEP }, @@ -831,7 +833,7 @@ static int usage(){ printf(" 1 In case of TCP flow, use TCP ACK in first SYN to pass NAT translation information. Initial SYN packet must be first packet in the TCP flow \n"); printf(" In case of UDP stream, NAT translation information will pass in IP ID field of first packet in flow. This means that this field is changed by TRex\n"); printf(" 2 Add special IP option to pass NAT translation information to first packet of each flow. Will not work on certain firewalls if they drop packets with IP options \n"); - printf(" 3 Like 1, but without support for sequence number randomization in server->clien direction. Performance (flow/second) better than 1 \n"); + printf(" 3 Like 1, but without support for sequence number randomization in server->client direction. Performance (flow/second) better than 1 \n"); printf(" --learn-verify : Test the NAT translation mechanism. Should be used when there is no NAT in the setup \n"); printf(" --limit-ports : Limit number of ports used. Must be even number (TRex always uses port pairs) \n"); printf(" --lm : Hex mask of cores that should send traffic \n"); @@ -1014,6 +1016,9 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t case OPT_NO_FLOW_CONTROL: po->preview.set_disable_flow_control_setting(true); break; + case OPT_X710_RESET_THRESHOLD: + po->set_x710_fdir_reset_threshold(atoi(args.OptionArg())); + break; case OPT_VLAN: opt_vlan_was_set = true; break; @@ -6740,9 +6745,6 @@ void CTRexExtendedDriverBase40G::reset_rx_stats(CPhyEthIF * _if, uint32_t *stats // instead of adding this to rte_ethdev.h extern "C" int rte_eth_fdir_stats_get(uint8_t port_id, uint32_t *stats, uint32_t start, uint32_t len); -// we read every 0.5 second. We want to catch the counter when it approach the maximum (where it will stuck, -// and we will start losing packets). -const uint32_t X710_FDIR_RESET_THRESHOLD = 0xffffffff - 1000000000/8/64*40; // get rx stats on _if, between min and max // prev_pkts should be the previous values read from the hardware. @@ -6759,21 +6761,19 @@ int CTRexExtendedDriverBase40G::get_rx_stats(CPhyEthIF * _if, uint32_t *pkts, ui rte_eth_fdir_stats_get(port_id, hw_stats, start, len); for (int i = loop_start; i < loop_start + len; i++) { - if (unlikely(hw_stats[i - min] > X710_FDIR_RESET_THRESHOLD)) { - // When x710 fdir counters reach max of 32 bits (4G), the get stuck. To handle this, we temporarily + if (unlikely(hw_stats[i - min] > CGlobalInfo::m_options.get_x710_fdir_reset_threshold())) { + // When x710 fdir counters reach max of 32 bits (4G), they get stuck. To handle this, we temporarily // move to temp counter, reset the counter in danger, and go back to using it. // see trex-199 for more details - uint32_t counter, temp_count; + uint32_t counter, temp_count=0; uint32_t hw_id = start - min + i; add_del_rules( RTE_ETH_FILTER_ADD, port_id, fdir_hw_id_rule_params[hw_id].rule_type, 0 , IP_ID_RESERVE_BASE + i, fdir_hw_id_rule_params[hw_id].l4_proto, MAIN_DPDK_DROP_Q , FDIR_TEMP_HW_ID); - delay(100); rte_eth_fdir_stats_reset(port_id, &counter, hw_id, 1); add_del_rules( RTE_ETH_FILTER_ADD, port_id, fdir_hw_id_rule_params[hw_id].rule_type, 0 , IP_ID_RESERVE_BASE + i, fdir_hw_id_rule_params[hw_id].l4_proto, MAIN_DPDK_DROP_Q, hw_id); - delay(100); rte_eth_fdir_stats_reset(port_id, &temp_count, FDIR_TEMP_HW_ID, 1); pkts[i] = counter + temp_count - prev_pkts[i]; prev_pkts[i] = 0; |