diff options
-rw-r--r-- | scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py | 27 | ||||
-rw-r--r-- | src/flow_stat.cpp | 30 | ||||
-rw-r--r-- | src/flow_stat.h | 11 | ||||
-rw-r--r-- | src/stateless/rx/trex_stateless_rx_core.cpp | 6 | ||||
-rw-r--r-- | src/stateless/rx/trex_stateless_rx_core.h | 52 | ||||
-rwxr-xr-x | src/time_histogram.cpp | 41 | ||||
-rwxr-xr-x | src/time_histogram.h | 6 |
7 files changed, 81 insertions, 92 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 94a45577..0ec98a0d 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 @@ -1020,19 +1020,20 @@ class CLatencyStats(CTRexStats): output[int_pg_id]['err_cntrs'] = current_pg['err_cntrs'] output[int_pg_id]['latency'] = {} - output[int_pg_id]['latency']['last_max'] = current_pg['latency']['last_max'] - output[int_pg_id]['latency']['jitter'] = current_pg['latency']['jitter'] - if current_pg['latency']['h'] != "": - output[int_pg_id]['latency']['average'] = current_pg['latency']['h']['s_avg'] - output[int_pg_id]['latency']['total_max'] = current_pg['latency']['h']['max_usec'] - output[int_pg_id]['latency']['histogram'] = {elem['key']: elem['val'] - for elem in current_pg['latency']['h']['histogram']} - zero_count = current_pg['latency']['h']['cnt'] - current_pg['latency']['h']['high_cnt'] - if zero_count != 0: - output[int_pg_id]['latency']['total_min'] = 1 - output[int_pg_id]['latency']['histogram'][0] = zero_count - elif output[int_pg_id]['latency']['histogram']: - output[int_pg_id]['latency']['total_min'] = min(output[int_pg_id]['latency']['histogram'].keys()) + if 'latency' in current_pg: + for field in ['jitter', 'average', 'total_max', 'last_max']: + if field in current_pg['latency']: + output[int_pg_id]['latency'][field] = current_pg['latency'][field] + else: + output[int_pg_id]['latency'][field] = StatNotAvailable(field) + + if 'histogram' in current_pg['latency']: + output[int_pg_id]['latency']['histogram'] = {int(elem): current_pg['latency']['histogram'][elem] + for elem in current_pg['latency']['histogram']} + min_val = min(output[int_pg_id]['latency']['histogram'].keys()) + if min_val == 0: + min_val = 2 + output[int_pg_id]['latency']['total_min'] = min_val else: output[int_pg_id]['latency']['total_min'] = StatNotAvailable('total_min') diff --git a/src/flow_stat.cpp b/src/flow_stat.cpp index 2385e03f..98b9494b 100644 --- a/src/flow_stat.cpp +++ b/src/flow_stat.cpp @@ -464,6 +464,8 @@ CFlowStatRuleMgr::CFlowStatRuleMgr() { m_rx_core = NULL; m_hw_id_map.create(MAX_FLOW_STATS); m_hw_id_map_payload.create(MAX_FLOW_STATS_PAYLOAD); + memset(m_rx_cant_count_err, 0, sizeof(m_rx_cant_count_err)); + memset(m_tx_cant_count_err, 0, sizeof(m_tx_cant_count_err)); } CFlowStatRuleMgr::~CFlowStatRuleMgr() { @@ -959,6 +961,7 @@ bool CFlowStatRuleMgr::dump_json(std::string & s_json, std::string & l_json, boo p_user_id->set_need_to_send_rx(port); } } else { + m_rx_cant_count_err[port] += rx_pkts.get_pkts(); std::cerr << __METHOD_NAME__ << i << ":Could not count " << rx_pkts << " rx packets, on port " << (uint16_t)port << ", because no mapping was found." << std::endl; } @@ -972,6 +975,7 @@ bool CFlowStatRuleMgr::dump_json(std::string & s_json, std::string & l_json, boo p_user_id->set_need_to_send_tx(port); } } else { + m_tx_cant_count_err[port] += tx_pkts.get_pkts();; std::cerr << __METHOD_NAME__ << i << ":Could not count " << tx_pkts << " tx packets on port " << (uint16_t)port << ", because no mapping was found." << std::endl; } @@ -990,6 +994,7 @@ bool CFlowStatRuleMgr::dump_json(std::string & s_json, std::string & l_json, boo p_user_id->set_need_to_send_rx(port); } } else { + m_rx_cant_count_err[port] += rx_pkts.get_pkts();; std::cerr << __METHOD_NAME__ << i << ":Could not count " << rx_pkts << " rx payload packets, on port " << (uint16_t)port << ", because no mapping was found." << std::endl; } @@ -1003,6 +1008,7 @@ bool CFlowStatRuleMgr::dump_json(std::string & s_json, std::string & l_json, boo p_user_id->set_need_to_send_tx(port); } } else { + m_tx_cant_count_err[port] += tx_pkts.get_pkts();; std::cerr << __METHOD_NAME__ << i << ":Could not count " << tx_pkts << " tx packets on port " << (uint16_t)port << ", because no mapping was found." << std::endl; } @@ -1011,6 +1017,15 @@ bool CFlowStatRuleMgr::dump_json(std::string & s_json, std::string & l_json, boo } // build json report + // general per port data + for (uint8_t port = 0; port < m_num_ports; port++) { + std::string str_port = static_cast<std::ostringstream*>( &(std::ostringstream() << int(port) ) )->str(); + if (m_rx_cant_count_err[port] != 0) + s_data_section["port_data"][str_port]["rx_err"] = m_rx_cant_count_err[port]; + if (m_tx_cant_count_err[port] != 0) + s_data_section["port_data"][str_port]["tx_err"] = m_tx_cant_count_err[port]; + } + flow_stat_user_id_map_it_t it; for (it = m_user_id_map.begin(); it != m_user_id_map.end(); it++) { bool send_empty = true; @@ -1022,6 +1037,7 @@ bool CFlowStatRuleMgr::dump_json(std::string & s_json, std::string & l_json, boo user_id_info->set_was_sent(true); send_empty = false; } + // flow stat json for (uint8_t port = 0; port < m_num_ports; port++) { std::string str_port = static_cast<std::ostringstream*>( &(std::ostringstream() << int(port) ) )->str(); if (user_id_info->need_to_send_rx(port) || baseline) { @@ -1042,10 +1058,11 @@ bool CFlowStatRuleMgr::dump_json(std::string & s_json, std::string & l_json, boo s_data_section[str_user_id] = Json::objectValue; } + // latency info json if (user_id_info->rfc2544_support()) { CFlowStatUserIdInfoPayload *user_id_info_p = (CFlowStatUserIdInfoPayload *)user_id_info; // payload object. Send also latency, jitter... - Json::Value lat_hist; + Json::Value lat_hist = Json::arrayValue; if (user_id_info->is_hw_id()) { // if mapped to hw_id, take info from what we just got from rx core uint16_t hw_id = user_id_info->get_hw_id(); @@ -1055,17 +1072,16 @@ bool CFlowStatRuleMgr::dump_json(std::string & s_json, std::string & l_json, boo user_id_info_p->set_dup_cnt(rfc2544_info[hw_id].get_dup_cnt()); user_id_info_p->set_seq_err_big_cnt(rfc2544_info[hw_id].get_seq_err_ev_big()); user_id_info_p->set_seq_err_low_cnt(rfc2544_info[hw_id].get_seq_err_ev_low()); - l_data_section[str_user_id]["latency"]["h"] = lat_hist; - l_data_section[str_user_id]["latency"]["last_max"] = rfc2544_info[hw_id].get_last_max_usec(); + l_data_section[str_user_id]["latency"] = lat_hist; l_data_section[str_user_id]["latency"]["jitter"] = rfc2544_info[hw_id].get_jitter_usec(); } else { // Not mapped to hw_id. Get saved info. user_id_info_p->get_latency_json(lat_hist); - l_data_section[str_user_id]["latency"]["h"] = lat_hist; - l_data_section[str_user_id]["latency"]["last_max"] = 0; - l_data_section[str_user_id]["latency"]["jitter"] = user_id_info_p->get_jitter_usec(); + if (lat_hist != Json::nullValue) { + l_data_section[str_user_id]["latency"] = lat_hist; + l_data_section[str_user_id]["latency"]["jitter"] = user_id_info_p->get_jitter_usec(); + } } - //todo: add last 10 samples l_data_section[str_user_id]["err_cntrs"]["dropped"] = Json::Value::UInt64(user_id_info_p->get_seq_err_cnt()); l_data_section[str_user_id]["err_cntrs"]["out_of_order"] diff --git a/src/flow_stat.h b/src/flow_stat.h index 3387c2d3..8671b228 100644 --- a/src/flow_stat.h +++ b/src/flow_stat.h @@ -24,11 +24,12 @@ #include <stdio.h> #include <string> #include <map> +#include <json/json.h> #include "trex_defs.h" #include "trex_exception.h" #include "trex_stream.h" #include "msg_manager.h" -#include <internal_api/trex_platform_api.h> +#include "internal_api/trex_platform_api.h" // range reserved for rx stat measurement is from IP_ID_RESERVE_BASE to 0xffff // Do not change this value. In i350 cards, we filter according to first byte of IP ID @@ -132,7 +133,7 @@ class rfc2544_info_t_ { m_seq_err_ev_big = 0; m_seq_err_ev_low = 0; m_jitter = 0; - m_latency = Json::Value(""); + m_latency = Json::nullValue; m_last_max_latency = 0; } @@ -332,7 +333,7 @@ class CFlowStatUserIdInfoPayload : public CFlowStatUserIdInfo { json = m_rfc2544_info.m_latency; } - inline void set_latency_json(Json::Value json) { + inline void set_latency_json(const Json::Value &json) { m_rfc2544_info.m_latency = json; } @@ -474,7 +475,9 @@ class CFlowStatRuleMgr { uint32_t m_num_started_streams; // How many started (transmitting) streams we have CNodeRing *m_ring_to_rx; // handle for sending messages to Rx core CFlowStatParser *m_parser; - uint16_t m_cap; + uint16_t m_cap; // capabilities of the NIC driver we are using + uint32_t m_rx_cant_count_err[TREX_MAX_PORTS]; + uint32_t m_tx_cant_count_err[TREX_MAX_PORTS]; }; #endif diff --git a/src/stateless/rx/trex_stateless_rx_core.cpp b/src/stateless/rx/trex_stateless_rx_core.cpp index 8f2f5d64..b3555c13 100644 --- a/src/stateless/rx/trex_stateless_rx_core.cpp +++ b/src/stateless/rx/trex_stateless_rx_core.cpp @@ -52,12 +52,8 @@ void CRFC2544Info::export_data(rfc2544_info_t_ &obj) { obj.set_err_cntrs(m_seq_err, m_ooo, m_dup, m_seq_err_events_too_big, m_seq_err_events_too_low); obj.set_jitter(m_jitter.get_jitter()); - json_str = ""; - m_latency.dump_json("", json_str); - // This is a hack. We need to make the dump_json return json object. - reader.parse( json_str.c_str(), json); + m_latency.dump_json(json); obj.set_latency_json(json); - obj.set_last_max(m_last_max.getMax()); }; void CCPortLatencyStl::reset() { diff --git a/src/stateless/rx/trex_stateless_rx_core.h b/src/stateless/rx/trex_stateless_rx_core.h index 1528a7e1..ce1bc1ad 100644 --- a/src/stateless/rx/trex_stateless_rx_core.h +++ b/src/stateless/rx/trex_stateless_rx_core.h @@ -28,55 +28,6 @@ class TrexStatelessCpToRxMsgBase; -class CLastMax { - public: - CLastMax() { - m_max1 = 0; - m_max1 = 1; - m_choose = true; - } - - void update(dsec_t val) { - if (m_choose) { - if (val > m_max1) { - m_max1 = val; - sanb_smp_memory_barrier(); - } - } else { - if (val > m_max2) { - m_max2 = val; - sanb_smp_memory_barrier(); - } - } - } - - dsec_t getMax() { - if (m_choose) - return m_max2; - else - return m_max1; - } - - void switchMax() { - if (m_choose) { - m_max2 = 0; - m_choose = false; - sanb_smp_memory_barrier(); - } - else { - m_max1 = 0; - m_choose = true; - sanb_smp_memory_barrier(); - } - } - - private: - dsec_t m_max1; - dsec_t m_max2; - bool m_choose; -}; - - class CCPortLatencyStl { public: void reset(); @@ -112,12 +63,10 @@ class CRFC2544Info { void export_data(rfc2544_info_t_ &obj); inline void add_sample(double stime) { m_latency.Add(stime); - m_last_max.update(stime); m_jitter.calc(stime); } inline void sample_period_end() { m_latency.update(); - m_last_max.switchMax(); } inline uint32_t get_seq() {return m_seq;} inline void set_seq(uint32_t val) {m_seq = val;} @@ -136,7 +85,6 @@ 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 - CLastMax m_last_max; // maximum for last measurement period (reset whenever we read it). }; class CRxCoreStateless { diff --git a/src/time_histogram.cpp b/src/time_histogram.cpp index 8a92cb6f..fefa59d6 100755 --- a/src/time_histogram.cpp +++ b/src/time_histogram.cpp @@ -66,10 +66,6 @@ bool CTimeHistogram::Add(dsec_t dt) { return false; } period_elem.inc_high_cnt(); - - if ( m_max_dt < dt) { - m_max_dt = dt; - } period_elem.update_max(dt); uint32_t d_10usec = (uint32_t)(dt*100000.0); @@ -118,6 +114,9 @@ void CTimeHistogram::update() { update_average(period_elem); m_total_cnt += period_elem.get_cnt(); m_total_cnt_high += period_elem.get_high_cnt(); + if ( m_max_dt < period_elem.get_max()) { + m_max_dt = period_elem.get_max(); + } } void CTimeHistogram::update_average(CTimeHistogramPerPeriodData &period_elem) { @@ -180,11 +179,7 @@ void CTimeHistogram::Dump(FILE *fd) { } } -/* - { "histogram" : [ {} ,{} ] } - -*/ - +// Used in statefull void CTimeHistogram::dump_json(std::string name,std::string & json ) { char buff[200]; if (name != "") @@ -222,3 +217,31 @@ void CTimeHistogram::dump_json(std::string name,std::string & json ) { } json+=" ] } ,"; } + +// Used in stateless +void CTimeHistogram::dump_json(Json::Value & json, bool add_histogram) { + int i, j; + uint32_t base=10; + CTimeHistogramPerPeriodData &period_elem = m_period_data[get_read_period_index()]; + + json["total_max"] = get_usec(m_max_dt); + json["last_max"] = get_usec(period_elem.get_max()); + json["average"] = get_average_latency(); + + if (add_histogram) { + for (j = 0; j < HISTOGRAM_SIZE_LOG; j++) { + for (i = 0; i < HISTOGRAM_SIZE; i++) { + if (m_hcnt[j][i] > 0) { + std::string key = static_cast<std::ostringstream*>( &(std::ostringstream() + << int(base * (i + 1)) ) )->str(); + json["histogram"][key] = Json::Value::UInt64(m_hcnt[j][i]); + } + } + base = base * 10; + } + if (m_total_cnt != m_total_cnt_high) { + json["histogram"]["0"] = Json::Value::UInt64(m_total_cnt - m_total_cnt_high); + } + } +} + diff --git a/src/time_histogram.h b/src/time_histogram.h index da70e677..0d532f1b 100755 --- a/src/time_histogram.h +++ b/src/time_histogram.h @@ -24,11 +24,12 @@ limitations under the License. #include <stdint.h> -#include "os_time.h" #include <stdio.h> #include <math.h> -#include "mbuf.h" #include <string> +#include <json/json.h> +#include "mbuf.h" +#include "os_time.h" class CTimeHistogramPerPeriodData { public: @@ -85,6 +86,7 @@ public: return period_elem.get_max_usec(); } void dump_json(std::string name,std::string & json ); + void dump_json(Json::Value & json, bool add_histogram = true); uint64_t get_count() {return m_total_cnt;} uint64_t get_high_count() {return m_total_cnt_high;} |