From bc3c25d78a3aa8051d7247465181c5afd6ac8ca2 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Thu, 23 Jun 2016 10:53:41 +0300 Subject: skip 9k_latency test until defect will be solved --- scripts/automation/regression/stateless_tests/stl_rx_test.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/scripts/automation/regression/stateless_tests/stl_rx_test.py b/scripts/automation/regression/stateless_tests/stl_rx_test.py index 84f32081..d8a25564 100644 --- a/scripts/automation/regression/stateless_tests/stl_rx_test.py +++ b/scripts/automation/regression/stateless_tests/stl_rx_test.py @@ -261,7 +261,7 @@ class STLRX_Test(CStlGeneral_Test): - def __test_9k_stream(self,pgid,ports,precet,max_latency,avg_latency,duration,pkt_size): + def __9k_stream(self,pgid,ports,precet,max_latency,avg_latency,duration,pkt_size): my_pg_id=pgid s_ports=ports; all_ports=list(CTRexScenario.stl_ports_map['map'].keys()); @@ -314,6 +314,8 @@ class STLRX_Test(CStlGeneral_Test): # check low latency when you have stream of 9K stream def test_9k_stream(self): + self.skip('Skip due to bug trex-215') + if self.latency_9k_enable == False: print("SKIP") return @@ -330,18 +332,14 @@ class STLRX_Test(CStlGeneral_Test): s_port=sorted(s_port) if self.speed == 40 : # the NIC does not support all full rate in case both port works let's filter odd ports - tmp_l=[] - for port in s_port: - if ((int(port) % 2) ==0): - tmp_l.append(port); - s_port=tmp_l; + s_port=list(filter(lambda x: x % 2==0, s_port)) if len(s_port)==0: s_port=[0]; error=1; for j in range(0,5): print(" {4} - duration {0} pgid {1} pkt_size {2} s_port {3} ".format(duration,pgid,pkt_size,s_port,j)); - if self.__test_9k_stream(pgid, + if self.__9k_stream(pgid, s_port,90, self.latency_9k_max_latency, self.latency_9k_max_average, -- cgit 1.2.3-korg From e43c2856b2aec77c70a5c70d9ea0b87cf7d34eea Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Thu, 23 Jun 2016 11:10:28 +0300 Subject: minor update for the stats doc --- .../stl/trex_stl_lib/trex_stl_client.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py index 6dec6fa7..c1833754 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py @@ -1284,18 +1284,20 @@ class STLClient(object): **total** and per port statistics contain dictionary with following format. + Most of the bytes counters (unless specified otherwise) are in L2 layer including the FCS. e.g. minimum packet size in 64 bytes + =============================== =============== key Meaning =============================== =============== - ibytes Number of input bytes + ibytes Number of input bytes ierrors Number of input errors - ipackets Number of input packets - obytes Number of output bytes + ipackets Number of input packets + obytes Number of output bytes oerrors Number of output errors opackets Number of output packets - rx_bps Receive bytes per second rate + rx_bps Receive bytes per second rate (L2 layer) rx_pps Receive packet per second rate - tx_bps Transmit bytes per second rate + tx_bps Transmit bytes per second rate (L2 layer) tx_pps Transmit packet per second rate =============================== =============== @@ -1327,8 +1329,8 @@ class STLClient(object): ================= =============== bw_per_core Estimated byte rate Trex can support per core. This is calculated by extrapolation of current rate and load on transmitting cores. cpu_util Estimate of the average utilization percentage of the transimitting cores - queue_full Total number of packets we could not transmit because NIC TX queue was full. This usually indicates that the rate we trying to transmit is too high for this port - rx_cpu_util Estimate of the utilization percentage of the core handling RX traffic + queue_full Total number of packets transmitted while the NIC TX queue was full. The packets will be transmitted, eventually, but will create high CPU%due to polling the queue. This usually indicates that the rate we trying to transmit is too high for this port. + rx_cpu_util Estimate of the utilization percentage of the core handling RX traffic. Too high value of this CPU utilization could cause drop of latency streams. rx_drop_bps Received bytes per second drop rate rx_bps Received bytes per second rate rx_pps Received packets per second rate @@ -1356,7 +1358,7 @@ class STLClient(object): ================= =============== key Meaning (see better explanation below the table) ================= =============== - dropped How many packets were dropped. + dropped How many packets were dropped (estimation) dup How many packets were duplicated. out_of_order How many packets we received out of order. seq_too_high How many events of packet with sequence number too high we saw. @@ -1384,10 +1386,10 @@ class STLClient(object): ================= =============== key Meaning ================= =============== - average Average latency over the stream lifetime (usec). Total average is computed each sampling period by following formula: = /2 + /2 + average Average latency over the stream lifetime (usec).Low pass filter is applied to the last window average.It is computed each sampling period by following formula: = /2 + /2 histogram Dictionary describing logarithmic distribution histogram of packet latencies. Keys in the dictionary represent range of latencies (in usec). Values are the total number of packets received in this latency range. For example, an entry {100:13} would mean that we saw 13 packets with latency in the range between 100 and 200 usec. jitter Jitter of latency samples, computed as described in :rfc:`3550#appendix-A.8` - last_max Maximum latency measured between last two data reads from server. + last_max Maximum latency measured between last two data reads from server (0.5 sec window). total_max Maximum latency measured over the stream lifetime (in usec). total_min Minimum latency measured over the stream lifetime (in usec). ================= =============== -- cgit 1.2.3-korg From f672c6c1ac980fa248298b679603da3645735787 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 22 Jun 2016 18:03:43 +0300 Subject: FLOW_STATS: removed line_util fields --- .../stl/trex_stl_lib/trex_stl_stats.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py index 88a94865..3effa1f0 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py @@ -1047,12 +1047,7 @@ class CRxStats(CTRexStats): def __init__(self, ports): super(CRxStats, self).__init__() self.ports = ports - self.ports_speed = {} - def get_ports_speed(self): - for port in self.ports: - self.ports_speed[str(port)] = self.ports[port].get_speed_bps() - self.ports_speed['total'] = sum(self.ports_speed.values()) # calculates a diff between previous snapshot # and current one @@ -1170,8 +1165,8 @@ class CRxStats(CTRexStats): return # TX - self.get_ports_speed() for port in pg_current['tx_pkts'].keys(): + prev_tx_pps = pg_prev['tx_pps'].get(port) now_tx_pkts = pg_current['tx_pkts'].get(port) prev_tx_pkts = pg_prev['tx_pkts'].get(port) @@ -1180,19 +1175,20 @@ class CRxStats(CTRexStats): prev_tx_bps = pg_prev['tx_bps'].get(port) now_tx_bytes = pg_current['tx_bytes'].get(port) prev_tx_bytes = pg_prev['tx_bytes'].get(port) + pg_current['tx_bps'][port], pg_current['tx_bps_lpf'][port] = self.calc_bps(prev_tx_bps, now_tx_bytes, prev_tx_bytes, diff_sec) if pg_current['tx_bps'].get(port) != None and pg_current['tx_pps'].get(port) != None: pg_current['tx_bps_L1'][port] = calc_bps_L1(pg_current['tx_bps'][port], pg_current['tx_pps'][port]) pg_current['tx_bps_L1_lpf'][port] = calc_bps_L1(pg_current['tx_bps_lpf'][port], pg_current['tx_pps_lpf'][port]) - pg_current['tx_line_util'][port] = 100.0 * pg_current['tx_bps_L1'][port] / self.ports_speed[port] else: pg_current['tx_bps_L1'][port] = None pg_current['tx_bps_L1_lpf'][port] = None - pg_current['tx_line_util'][port] = None + # RX for port in pg_current['rx_pkts'].keys(): + prev_rx_pps = pg_prev['rx_pps'].get(port) now_rx_pkts = pg_current['rx_pkts'].get(port) prev_rx_pkts = pg_prev['rx_pkts'].get(port) @@ -1205,11 +1201,9 @@ class CRxStats(CTRexStats): if pg_current['rx_bps'].get(port) != None and pg_current['rx_pps'].get(port) != None: pg_current['rx_bps_L1'][port] = calc_bps_L1(pg_current['rx_bps'][port], pg_current['rx_pps'][port]) pg_current['rx_bps_L1_lpf'][port] = calc_bps_L1(pg_current['rx_bps_lpf'][port], pg_current['rx_pps_lpf'][port]) - pg_current['rx_line_util'][port] = 100.0 * pg_current['rx_bps_L1'][port] / self.ports_speed[port] else: pg_current['rx_bps_L1'][port] = None pg_current['rx_bps_L1_lpf'][port] = None - pg_current['rx_line_util'][port] = None def calc_pps (self, prev_bw, now, prev, diff_sec): @@ -1272,7 +1266,7 @@ class CRxStats(CTRexStats): stats[int(pg_id)][field][int(port)] = val if val != 'N/A' else StatNotAvailable(field) # BW values - for field in ['tx_pps', 'tx_bps', 'tx_bps_L1', 'rx_pps', 'rx_bps', 'rx_bps_L1', 'tx_line_util', 'rx_line_util']: + for field in ['tx_pps', 'tx_bps', 'tx_bps_L1', 'rx_pps', 'rx_bps', 'rx_bps_L1']: val = self.get([pg_id, field, 'total']) stats[int(pg_id)][field] = {'total': val if val != 'N/A' else StatNotAvailable(field)} for port in value[field].keys(): -- cgit 1.2.3-korg From 5f84648529772a4b0b52eedfbf3669c6e45d653f Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 23 Jun 2016 11:27:05 +0300 Subject: allow coredump for TRex with --alow-coredump by default, huge pages will not be mapped to the core --- src/bp_sim.h | 6 ++++++ src/common/basic_utils.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/common/basic_utils.h | 10 ++++++++++ src/main_dpdk.cpp | 24 ++++++++++++++++++++++-- 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/bp_sim.h b/src/bp_sim.h index 1f35faba..42ea2178 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -679,7 +679,13 @@ public: return (btGetMaskBit32(m_flags1,6,6) ? true:false); } + void setCoreDumpEnable(bool enable) { + btSetMaskBit32(m_flags1, 7, 7, (enable ? 1 : 0) ); + } + bool getCoreDumpEnable(){ + return (btGetMaskBit32(m_flags1, 7, 7) ? true : false); + } public: void Dump(FILE *fd); diff --git a/src/common/basic_utils.cpp b/src/common/basic_utils.cpp index 4f5578a6..b2277697 100755 --- a/src/common/basic_utils.cpp +++ b/src/common/basic_utils.cpp @@ -18,6 +18,7 @@ limitations under the License. #include #include #include +#include bool utl_is_file_exists (const std::string& name) { if (FILE *file = fopen(name.c_str(), "r")) { @@ -198,3 +199,40 @@ utl_generate_random_str(unsigned int &seed, int len) { return (ss.str()); } +/** + * define the coredump size + * allowed when crashing + * + * @param size - -1 means unlimited + * @param map_huge_pages - should the core map the huge TLB + * pages + */ +void utl_set_coredump_size(long size, bool map_huge_pages) { + int mask; + struct rlimit core_limits; + + if (size == -1) { + core_limits.rlim_cur = core_limits.rlim_max = RLIM_INFINITY; + } else { + core_limits.rlim_cur = core_limits.rlim_max = size; + } + + setrlimit(RLIMIT_CORE, &core_limits); + + /* set core dump mask */ + FILE *fp = fopen("/proc/self/coredump_filter", "wb"); + if (!fp) { + printf("failed to open /proc/self/coredump_filter\n"); + exit(-1); + } + + /* huge pages is the 5th bit */ + if (map_huge_pages) { + mask = 0x33; + } else { + mask = 0x13; + } + + fprintf(fp, "%08x\n", mask); + fclose(fp); +} diff --git a/src/common/basic_utils.h b/src/common/basic_utils.h index 63e858ab..1884e896 100755 --- a/src/common/basic_utils.h +++ b/src/common/basic_utils.h @@ -87,6 +87,16 @@ void utl_macaddr_to_str(const uint8_t *macaddr, std::string &output); std::string utl_generate_random_str(unsigned int &seed, int len); +/** + * define the coredump size + * allowed when crashing + * + * @param size - -1 means unlimited + * @param map_huge_pages - should the core map the huge TLB + * pages + */ +void utl_set_coredump_size(long size, bool map_huge_pages = false); + #endif diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index dcef2f38..4f8d8937 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -50,6 +50,7 @@ #include #include #include + #include "bp_sim.h" #include "os_time.h" #include "common/arg/SimpleGlob.h" @@ -553,7 +554,9 @@ enum { OPT_HELP, OPT_PREFIX, OPT_MAC_SPLIT, OPT_SEND_DEBUG_PKT, - OPT_NO_WATCHDOG + OPT_NO_WATCHDOG, + OPT_ALLOW_COREDUMP + }; @@ -615,7 +618,8 @@ static CSimpleOpt::SOption parser_options[] = { OPT_MAC_SPLIT, "--mac-spread", SO_REQ_SEP }, { OPT_SEND_DEBUG_PKT, "--send-debug-pkt", SO_REQ_SEP }, { OPT_MBUF_FACTOR , "--mbuf-factor", SO_REQ_SEP }, - { OPT_NO_WATCHDOG , "--no-watchdog", SO_NONE }, + { OPT_NO_WATCHDOG , "--no-watchdog", SO_NONE }, + { OPT_ALLOW_COREDUMP , "--allow-coredump", SO_NONE }, SO_END_OF_OPTIONS @@ -718,6 +722,8 @@ static int usage(){ printf(" \n"); printf(" --no-watchdog : disable watchdog \n"); printf(" \n"); + printf(" --allow-coredump : allow a creation of core dump \n"); + printf(" \n"); printf(" --vm-sim : simulate vm with driver of one input queue and one output queue \n"); printf(" \n"); printf(" Examples: "); @@ -935,6 +941,10 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t po->preview.setWDDisable(true); break; + case OPT_ALLOW_COREDUMP : + po->preview.setCoreDumpEnable(true); + break; + case OPT_LATENCY_PREVIEW : sscanf(args.OptionArg(),"%d", &po->m_latency_prev); break; @@ -4703,6 +4713,15 @@ int main_test(int argc , char * argv[]){ exit(-1); } + /* enable core dump if requested */ + if (CGlobalInfo::m_options.preview.getCoreDumpEnable()) { + utl_set_coredump_size(-1); + } + else { + utl_set_coredump_size(0); + } + + update_global_info_from_platform_file(); /* It is not a mistake. Give the user higher priorty over the configuration file */ @@ -5779,3 +5798,4 @@ int TrexDpdkPlatformApi::get_active_pgids(flow_stat_active_t &result) const { CFlowStatParser *TrexDpdkPlatformApi::get_flow_stat_parser() const { return CTRexExtendedDriverDb::Ins()->get_drv()->get_flow_stat_parser(); } + -- cgit 1.2.3-korg From 6ea7b686a00192fc7e1e8e34160ec18e3de61d1a Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 23 Jun 2016 14:00:35 +0300 Subject: enabling efence --- linux_dpdk/ws_main.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index 12a2fd89..dde94dc4 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -714,8 +714,7 @@ def build_prog (bld, build_obj): debug_file_list=''; if not build_obj.isRelease (): #debug - #debug_file_list +=ef_src.file_list(top) - pass + debug_file_list +=ef_src.file_list(top) bld.objects( -- cgit 1.2.3-korg From 6b2fddc208846e404f0eb7a42c745fa004aa1c9a Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Thu, 23 Jun 2016 14:10:24 +0300 Subject: ef is back for debug --- linux_dpdk/ws_main.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index 12a2fd89..dde94dc4 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -714,8 +714,7 @@ def build_prog (bld, build_obj): debug_file_list=''; if not build_obj.isRelease (): #debug - #debug_file_list +=ef_src.file_list(top) - pass + debug_file_list +=ef_src.file_list(top) bld.objects( -- cgit 1.2.3-korg From a36aff0da82e5391049559017ab9afb38b084d81 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Thu, 23 Jun 2016 17:10:19 +0300 Subject: add 64byte FCS test --- .../regression/stateless_tests/stl_rx_test.py | 93 ++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/scripts/automation/regression/stateless_tests/stl_rx_test.py b/scripts/automation/regression/stateless_tests/stl_rx_test.py index d8a25564..0dbc7f31 100644 --- a/scripts/automation/regression/stateless_tests/stl_rx_test.py +++ b/scripts/automation/regression/stateless_tests/stl_rx_test.py @@ -354,8 +354,101 @@ class STLRX_Test(CStlGeneral_Test): print("===>Iteration {0} PASS {1}".format(i,j)); + def check_stats (self,stats,a,b,err): + if a != b: + tmp = 'ERROR field : {0}, read : {1} != expected : {2} '.format(err,a,b) + pprint.pprint(stats) + assert False,tmp + + def send_1_burst(self,from_port,is_latency,pkts): + + pid = from_port + base_pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025) + + pad = (60 - len(base_pkt)) * 'x' + + stream_pkt = STLPktBuilder(pkt = base_pkt/pad) + + all_ports=list(CTRexScenario.stl_ports_map['map'].keys()); + + dpid = CTRexScenario.stl_ports_map['map'][pid] + + s_ports =[pid] + + try: + # reset all ports + self.c.reset(ports = all_ports) + + + for pid in s_ports: + if is_latency: + s1 = STLStream(name = 'rx', + packet = stream_pkt, + flow_stats = STLFlowLatencyStats(pg_id = 5 + pid), + mode = STLTXSingleBurst(total_pkts = pkts,pps = 1000)) + else: + s1 = STLStream(name = 'rx', + packet = stream_pkt, + mode = STLTXSingleBurst(total_pkts = pkts,pps = 1000)) + + + # add both streams to ports + self.c.add_streams(s1, ports = [pid]) + + self.c.clear_stats() + + self.c.start(ports = s_ports) + self.c.wait_on_traffic(ports = s_ports) + + stats = self.c.get_stats() + + ips = stats[dpid] + ops = stats[pid] + tps = stats['total'] + tbytes = pkts*64 + + self.check_stats (stats,ops["obytes"], tbytes,"ops[obytes]") + self.check_stats (stats,ops["opackets"], pkts,"ops[opackets]") + + self.check_stats (stats,ips["ibytes"], tbytes,"ips[ibytes]") + self.check_stats (stats,ips["ipackets"], pkts,"ips[ipackets]") + + self.check_stats (stats,tps['ibytes'], tbytes,"tps[ibytes]") + self.check_stats (stats,tps['obytes'], tbytes,"tps[obytes]") + self.check_stats (stats,tps['ipackets'], pkts,"tps[ipackets]") + self.check_stats (stats,tps['opackets'], pkts,"tps[opackets]") + + if is_latency: + ls=stats['flow_stats'][5+ pid] + self.check_stats (stats,ls['rx_pkts']['total'], pkts,"ls['rx_pkts']['total']") + self.check_stats (stats,ls['rx_pkts'][dpid], pkts,"ls['rx_pkts'][dpid]") + + self.check_stats (stats,ls['tx_pkts']['total'], pkts,"ls['tx_pkts']['total']") + self.check_stats (stats,ls['tx_pkts'][pid], pkts,"ls['tx_pkts'][pid]") + + self.check_stats (stats,ls['tx_bytes']['total'], tbytes,"ls['tx_bytes']['total']") + self.check_stats (stats,ls['tx_bytes'][pid], pkts+1,"ls['tx_bytes'][pid]") + + + return 0 + + except STLError as e: + assert False , '{0}'.format(e) + + + + def test_fcs_stream(self): + """ this test send 1 64 byte packet with latency and check that all counters are reported as 64 bytes""" + self.skip('Skip due to bug trex-213') + + all_ports=list(CTRexScenario.stl_ports_map['map'].keys()); + for port in all_ports: + for l in [True,False]: + print(" test port {0} latency : {1} ".format(port,l)) + self.send_1_burst(port,l,100) + # this test adds more and more latency streams and re-test with incremental def test_incremental_latency_streams (self): -- cgit 1.2.3-korg From 021f0d49b2607baa05d13f8badfc8f8e51edc43b Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Thu, 23 Jun 2016 17:23:45 +0300 Subject: enable fcs test --- scripts/automation/regression/stateless_tests/stl_rx_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/automation/regression/stateless_tests/stl_rx_test.py b/scripts/automation/regression/stateless_tests/stl_rx_test.py index 0dbc7f31..2b6684fd 100644 --- a/scripts/automation/regression/stateless_tests/stl_rx_test.py +++ b/scripts/automation/regression/stateless_tests/stl_rx_test.py @@ -441,13 +441,13 @@ class STLRX_Test(CStlGeneral_Test): def test_fcs_stream(self): """ this test send 1 64 byte packet with latency and check that all counters are reported as 64 bytes""" - self.skip('Skip due to bug trex-213') + #self.skip('Skip due to bug trex-213') all_ports=list(CTRexScenario.stl_ports_map['map'].keys()); for port in all_ports: for l in [True,False]: print(" test port {0} latency : {1} ".format(port,l)) - self.send_1_burst(port,l,100) + self.send_1_burst(port,False,100) # this test adds more and more latency streams and re-test with incremental -- cgit 1.2.3-korg From 83170bb32b9bdbbe63a9f2b301b19bcd1d7eaa60 Mon Sep 17 00:00:00 2001 From: Ido Barnea Date: Thu, 23 Jun 2016 18:06:39 +0300 Subject: Fix latency stats issues of fast stop/start, and starting from different cores --- src/bp_sim.h | 26 +++++++++++++--- src/main_dpdk.cpp | 32 +++++++++----------- src/stateless/rx/trex_stateless_rx_core.cpp | 47 ++++++++++++++++++++++++----- src/stateless/rx/trex_stateless_rx_core.h | 11 +++++++ 4 files changed, 88 insertions(+), 28 deletions(-) diff --git a/src/bp_sim.h b/src/bp_sim.h index 42ea2178..56e37272 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -256,7 +256,23 @@ void on_node_last(uint8_t plugin_id,CGenNode * node); rte_mbuf_t * on_node_generate_mbuf(uint8_t plugin_id,CGenNode * node,CFlowPktInfo * pkt_info); class CPreviewMode ; -struct CGenNode; + +class CLatencyPktData { + public: + CLatencyPktData() {m_magic = 0xaa;} + inline uint32_t get_seq_num() {return m_seq_num;} + inline void inc_seq_num() {m_seq_num++;} + inline uint32_t get_magic() {return m_magic;} + void reset() { + m_seq_num = UINT32_MAX - 1; // catch wrap around issues early + m_magic++; + } + + private: + uint32_t m_seq_num; // seq num to put in packet for payload rules + uint16_t m_magic; // magic to put in packet for payload rules +}; + /* represent the virtual interface */ @@ -275,7 +291,7 @@ public: uint64_t m_tx_queue_full; uint64_t m_tx_alloc_error; tx_per_flow_t m_tx_per_flow[MAX_FLOW_STATS + MAX_FLOW_STATS_PAYLOAD]; - uint32_t m_seq_num[MAX_FLOW_STATS_PAYLOAD]; // seq num to put in packet for payload rules + CLatencyPktData m_lat_data[MAX_FLOW_STATS_PAYLOAD]; CPerTxthreadTemplateInfo m_template; public: @@ -299,12 +315,14 @@ public: m_tx_queue_full=0; m_template.Clear(); for (int i = 0; i < MAX_FLOW_STATS_PAYLOAD; i++) { - m_seq_num[i] = UINT32_MAX - 1; // catch wrap around issues early + m_lat_data[i].reset(); + } + for (int i = 0; i < sizeof(m_tx_per_flow) / sizeof(m_tx_per_flow[0]); i++) { + m_tx_per_flow[i].clear(); } } inline void Dump(FILE *fd); - }; diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 4f8d8937..906aa2b7 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -2053,17 +2053,17 @@ int CCoreEthIFStateless::send_node_flow_stat(rte_mbuf *m, CGenNodeStateless * no } mi = node_sl->alloc_flow_stat_mbuf(m, fsp_head, is_const); - fsp_head->seq = lp_stats->m_seq_num[hw_id_payload]; + fsp_head->seq = lp_stats->m_lat_data[hw_id_payload].get_seq_num(); fsp_head->hw_id = hw_id_payload; - fsp_head->magic = FLOW_STAT_PAYLOAD_MAGIC; + fsp_head->magic = lp_stats->m_lat_data[hw_id_payload].get_magic(); - lp_stats->m_seq_num[hw_id_payload]++; + lp_stats->m_lat_data[hw_id_payload].inc_seq_num(); #ifdef ERR_CNTRS_TEST if (temp % 10 == 0) { - fsp_head->seq = lp_stats->m_seq_num[hw_id_payload]++; + fsp_head->seq = lp_stats->m_lat_data[hw_id_payload].inc_seq_num(); } if ((temp - 1) % 100 == 0) { - fsp_head->seq = lp_stats->m_seq_num[hw_id_payload] - 4; + fsp_head->seq = lp_stats->m_lat_data[hw_id_payload].get_seq_num() - 4; } #endif } else { @@ -2815,7 +2815,7 @@ public: bool sanity_check(); void update_stats(void); tx_per_flow_t get_flow_tx_stats(uint8_t port, uint16_t hw_id); - tx_per_flow_t clear_flow_tx_stats(uint8_t port, uint16_t index); + tx_per_flow_t clear_flow_tx_stats(uint8_t port, uint16_t index, bool is_lat); void get_stats(CGlobalStats & stats); void dump_post_test_stats(FILE *fd); void dump_config(FILE *fd); @@ -2859,7 +2859,7 @@ private: std::mutex m_cp_lock; TrexMonitor m_monitor; - + public: TrexStateless *m_trex_stateless; @@ -3536,7 +3536,7 @@ tx_per_flow_t CGlobalTRex::get_flow_tx_stats(uint8_t port, uint16_t index) { } // read stats. Return read value, and clear. -tx_per_flow_t CGlobalTRex::clear_flow_tx_stats(uint8_t port, uint16_t index) { +tx_per_flow_t CGlobalTRex::clear_flow_tx_stats(uint8_t port, uint16_t index, bool is_lat) { uint8_t port0; CFlowGenListPerThread * lpt; tx_per_flow_t ret; @@ -3546,12 +3546,11 @@ tx_per_flow_t CGlobalTRex::clear_flow_tx_stats(uint8_t port, uint16_t index) { for (int i=0; i < get_cores_tx(); i++) { lpt = m_fl.m_threads_info[i]; port0 = lpt->getDualPortId() * 2; - if (port == port0) { - m_stats.m_port[port0].m_tx_per_flow[index] += - lpt->m_node_gen.m_v_if->m_stats[0].m_tx_per_flow[index]; - } else if (port == port0 + 1) { - m_stats.m_port[port0 + 1].m_tx_per_flow[index] += - lpt->m_node_gen.m_v_if->m_stats[1].m_tx_per_flow[index]; + if ((port == port0) || (port == port0 + 1)) { + m_stats.m_port[port].m_tx_per_flow[index] += + lpt->m_node_gen.m_v_if->m_stats[port - port0].m_tx_per_flow[index]; + if (is_lat) + lpt->m_node_gen.m_v_if->m_stats[port - port0].m_lat_data[index - MAX_FLOW_STATS].reset(); } } @@ -4293,7 +4292,7 @@ int CPhyEthIF::get_flow_stats(rx_per_flow_t *rx_stats, tx_per_flow_t *tx_stats, } if (tx_stats != NULL) { - tx_stats[i - min] = g_trex.clear_flow_tx_stats(m_port_id, i); + tx_stats[i - min] = g_trex.clear_flow_tx_stats(m_port_id, i, false); } } else { if (hw_rx_stat_supported) { @@ -4318,7 +4317,7 @@ int CPhyEthIF::get_flow_stats_payload(rx_per_flow_t *rx_stats, tx_per_flow_t *tx for (int i = min; i <= max; i++) { if ( reset ) { if (tx_stats != NULL) { - tx_stats[i - min] = g_trex.clear_flow_tx_stats(m_port_id, i + MAX_FLOW_STATS); + tx_stats[i - min] = g_trex.clear_flow_tx_stats(m_port_id, i + MAX_FLOW_STATS, true); } } else { if (tx_stats != NULL) { @@ -5798,4 +5797,3 @@ int TrexDpdkPlatformApi::get_active_pgids(flow_stat_active_t &result) const { CFlowStatParser *TrexDpdkPlatformApi::get_flow_stat_parser() const { return CTRexExtendedDriverDb::Ins()->get_drv()->get_flow_stat_parser(); } - diff --git a/src/stateless/rx/trex_stateless_rx_core.cpp b/src/stateless/rx/trex_stateless_rx_core.cpp index a622ee7a..e5831129 100644 --- a/src/stateless/rx/trex_stateless_rx_core.cpp +++ b/src/stateless/rx/trex_stateless_rx_core.cpp @@ -29,13 +29,21 @@ void CRFC2544Info::create() { m_latency.Create(); - // This is the seq num value we expect next packet to have. - // Init value should match m_seq_num in CVirtualIFPerSideStats - m_seq = UINT32_MAX - 1; // catch wrap around issues early + m_exp_magic = 0; + m_prev_magic = 0; reset(); } +// after calling stop, packets still arriving will be considered error +void CRFC2544Info::stop() { + m_prev_magic = m_exp_magic; + m_exp_magic = FLOW_STAT_PAYLOAD_MAGIC_NONE; +} + void CRFC2544Info::reset() { + // This is the seq num value we expect next packet to have. + // Init value should match m_seq_num in CVirtualIFPerSideStats + m_seq = UINT32_MAX - 1; // catch wrap around issues early m_seq_err = 0; m_seq_err_events_too_big = 0; m_seq_err_events_too_low = 0; @@ -97,7 +105,7 @@ bool CRxCoreStateless::periodic_check_for_cp_messages() { /* tickle the watchdog */ tickle(); - + /* fast path */ if ( likely ( m_ring_from_cp->isEmpty() ) ) { return false; @@ -187,13 +195,32 @@ void CRxCoreStateless::handle_rx_pkt(CLatencyManagerPerPortStl *lp, rte_mbuf_t * if (parser.get_ip_id(ip_id) == 0) { if (is_flow_stat_id(ip_id)) { uint16_t hw_id; + bool good_packet = true; if (is_flow_stat_payload_id(ip_id)) { uint8_t *p = rte_pktmbuf_mtod(m, uint8_t*); struct flow_stat_payload_header *fsp_head = (struct flow_stat_payload_header *) (p + m->pkt_len - sizeof(struct flow_stat_payload_header)); - if (fsp_head->magic == FLOW_STAT_PAYLOAD_MAGIC) { - hw_id = fsp_head->hw_id; - CRFC2544Info &curr_rfc2544 = m_rfc2544[hw_id]; + hw_id = fsp_head->hw_id; + CRFC2544Info &curr_rfc2544 = m_rfc2544[hw_id]; + if (unlikely(fsp_head->magic != curr_rfc2544.get_exp_magic())) { + // bad magic. + // Might be the first packet of a new flow, packet from an old flow or just garbage. + if (fsp_head->magic == curr_rfc2544.get_prev_magic()) { + // packet from previous flow using this hw_id that arrived late + good_packet = false; + } else { + if (curr_rfc2544.no_magic()) { + // first packet we see from this flow + good_packet = true; + curr_rfc2544.set_exp_magic(fsp_head->magic); + } else { + // garbage packet + good_packet = false; + } + } + } + + if (good_packet) { uint32_t pkt_seq = fsp_head->seq; uint32_t exp_seq = curr_rfc2544.get_seq(); if (unlikely(pkt_seq != exp_seq)) { @@ -388,6 +415,12 @@ int CRxCoreStateless::get_rx_stats(uint8_t port_id, rx_per_flow_t *rx_stats, int int CRxCoreStateless::get_rfc2544_info(rfc2544_info_t *rfc2544_info, int min, int max, bool reset) { for (int hw_id = min; hw_id <= max; hw_id++) { CRFC2544Info &curr_rfc2544 = m_rfc2544[hw_id]; + + if (reset) { + // need to stop first, so count will be consistent + curr_rfc2544.stop(); + } + curr_rfc2544.sample_period_end(); curr_rfc2544.export_data(rfc2544_info[hw_id - min]); diff --git a/src/stateless/rx/trex_stateless_rx_core.h b/src/stateless/rx/trex_stateless_rx_core.h index dfc56e4d..140fedf4 100644 --- a/src/stateless/rx/trex_stateless_rx_core.h +++ b/src/stateless/rx/trex_stateless_rx_core.h @@ -59,6 +59,7 @@ class CRxSlCfg { class CRFC2544Info { public: void create(); + void stop(); void reset(); void export_data(rfc2544_info_t_ &obj); inline void add_sample(double stime) { @@ -76,7 +77,14 @@ class CRFC2544Info { inline void inc_seq_err_too_low() {m_seq_err_events_too_low++;} inline void inc_dup() {m_dup++;} inline void inc_ooo() {m_ooo++;} + inline uint16_t get_exp_magic() {return m_exp_magic;} + inline void set_exp_magic(uint16_t magic) {m_exp_magic = magic;} + inline uint16_t get_prev_magic() {return m_prev_magic;} + inline bool no_magic() {return (m_exp_magic == FLOW_STAT_PAYLOAD_MAGIC_NONE) ? true : false;} private: + enum payload_e { + FLOW_STAT_PAYLOAD_MAGIC_NONE = 0 + }; uint32_t m_seq; // expected next seq num CTimeHistogram m_latency; // latency info CJitter m_jitter; @@ -85,6 +93,9 @@ class CRFC2544Info { uint64_t m_seq_err_events_too_low; // How many packet seq num lower than expected events we had uint64_t m_ooo; // Packets we got with seq num lower than expected (We guess they are out of order) uint64_t m_dup; // Packets we got with same seq num + uint16_t m_exp_magic; // magic number we should see in latency header + // magic number previously used with this id. We use this to catch packets arriving late from old flow + uint16_t m_prev_magic; }; class CRxCoreStateless { -- cgit 1.2.3-korg From ff5799ae624b6e74faf26e821558964a08f33577 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Fri, 24 Jun 2016 13:09:04 +0300 Subject: v2.04 --- VERSION | 3 ++- scripts/automation/regression/stateless_tests/stl_rx_test.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index f85ec405..d73be704 100755 --- a/VERSION +++ b/VERSION @@ -1,4 +1,5 @@ -v2.03 +v2.04 + diff --git a/scripts/automation/regression/stateless_tests/stl_rx_test.py b/scripts/automation/regression/stateless_tests/stl_rx_test.py index 2b6684fd..23ebf081 100644 --- a/scripts/automation/regression/stateless_tests/stl_rx_test.py +++ b/scripts/automation/regression/stateless_tests/stl_rx_test.py @@ -74,7 +74,7 @@ class STLRX_Test(CStlGeneral_Test): pprint.pprint(err_latency) tmp = 'RX pkts ERROR - one of the error is on' print(tmp) - #assert False, tmp + assert False, tmp if latency['average']> max_average: pprint.pprint(latency_stats) @@ -314,7 +314,7 @@ class STLRX_Test(CStlGeneral_Test): # check low latency when you have stream of 9K stream def test_9k_stream(self): - self.skip('Skip due to bug trex-215') + #self.skip('Skip due to bug trex-215') if self.latency_9k_enable == False: print("SKIP") -- cgit 1.2.3-korg From efcae8fa373bf0ea6ceac051a698f621d5d65aa1 Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Fri, 24 Jun 2016 18:54:36 +0300 Subject: run_regression: fix passing argument with spaces --- scripts/run_regression | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/run_regression b/scripts/run_regression index bdc2f185..407b7f84 100755 --- a/scripts/run_regression +++ b/scripts/run_regression @@ -1,6 +1,9 @@ #!/bin/bash -INPUT_ARGS=${@//--python[23]/} +ARGS=() +for var in "$@"; do + [[ "$var" != '--python2' && "$var" != '--python3' ]] && ARGS+=("$var") +done if [[ $@ =~ '--python2' || ! $@ =~ '--python3' ]]; then source find_python.sh --python2 @@ -8,7 +11,7 @@ if [[ $@ =~ '--python2' || ! $@ =~ '--python3' ]]; then # Python 2 echo Python2 test - $PYTHON trex_unit_test.py $INPUT_ARGS + $PYTHON trex_unit_test.py "${ARGS[@]}" if [ $? -eq 0 ]; then printf "\n$PYTHON test succeeded\n\n" else @@ -24,7 +27,7 @@ if [[ $@ =~ '--python3' ]]; then # Python 3 echo Python3 test - $PYTHON trex_unit_test.py $INPUT_ARGS + $PYTHON trex_unit_test.py "${ARGS[@]}" if [ $? -eq 0 ]; then printf "\n$PYTHON test succeeded\n\n" else -- cgit 1.2.3-korg From 582e6dddb5693d5fa7576c19b0ef7c1c0723ff59 Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Sun, 26 Jun 2016 14:22:04 +0300 Subject: stf api: don't fail if no histogram in result --- .../stf/trex_stf_lib/trex_client.py | 31 +++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py index a13fe31f..f044f623 100755 --- a/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py +++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py @@ -1480,21 +1480,22 @@ class CTRexResult(object): @staticmethod def __get_filtered_max_latency (src_dict, filtered_latency_amount = 0.001): result = {} - for port, data in src_dict.items(): - if not port.startswith('port-'): - continue - max_port = 'max-%s' % port[5:] - res = data['hist'] - if not len(res['histogram']): - result[max_port] = 0 - continue - result[max_port] = 5 # if sum below will not get to filtered amount, use this value - sum_high = 0.0 - for elem in reversed(res['histogram']): - sum_high += elem['val'] - if sum_high >= filtered_latency_amount * res['cnt']: - result[max_port] = elem['key'] + int('5' + repr(elem['key'])[2:]) - break + if src_dict: + for port, data in src_dict.items(): + if not port.startswith('port-'): + continue + max_port = 'max-%s' % port[5:] + res = data['hist'] + if not len(res['histogram']): + result[max_port] = 0 + continue + result[max_port] = 5 # if sum below will not get to filtered amount, use this value + sum_high = 0.0 + for elem in reversed(res['histogram']): + sum_high += elem['val'] + if sum_high >= filtered_latency_amount * res['cnt']: + result[max_port] = elem['key'] + int('5' + repr(elem['key'])[2:]) + break return result -- cgit 1.2.3-korg