i40e fix of workaround of stuck counters + regression test
authorYaroslav Brustinov <[email protected]>
Mon, 13 Mar 2017 09:01:55 +0000 (11:01 +0200)
committerYaroslav Brustinov <[email protected]>
Mon, 13 Mar 2017 09:01:55 +0000 (11:01 +0200)
Change-Id: I251cb8d346461ccfa4eee8abfda113410160a602
Signed-off-by: Yaroslav Brustinov <[email protected]>
scripts/automation/regression/misc_methods.py
scripts/automation/regression/setups/trex08/config.yaml
scripts/automation/regression/setups/trex09/config.yaml
scripts/automation/regression/stateless_tests/stl_rx_test.py
scripts/automation/regression/trex_unit_test.py
src/bp_sim.h
src/dpdk/drivers/net/i40e/i40e_fdir.c
src/main_dpdk.cpp

index d879b03..e885977 100755 (executable)
@@ -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:
index affe9bc..8199a6d 100644 (file)
@@ -37,4 +37,5 @@ trex:
   hostname       : csi-trex-08
   cores          : 7
   modes          : ['loopback']
+  trex_add_args  : '--x710-reset-threshold 10000000'
 
index 724de6e..7eb2374 100644 (file)
@@ -36,3 +36,4 @@ trex:
   hostname       : csi-trex-09
   cores          : 2
   modes          : ['loopback']
+  trex_add_args  : '--x710-reset-threshold 10000000'
index 4e15e03..347c8e8 100644 (file)
@@ -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] )
+
index f915448..8c07498 100755 (executable)
@@ -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():
index 7346615..24681d4 100755 (executable)
@@ -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);
index eddb2b9..ceac810 100644 (file)
@@ -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,
index 0da245b..1f9dadc 100644 (file)
@@ -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;