summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Barnea <ibarnea@cisco.com>2016-06-02 15:17:46 +0300
committerIdo Barnea <ibarnea@cisco.com>2016-06-02 15:18:06 +0300
commitf26d353e820577c133d26b283bea66c4febeecc3 (patch)
tree16aa0decfacdce57b0c4bdc1b7026f190fd263a9
parent825a35322828e53080549c4f09bb9469d7806387 (diff)
flow latency json changes
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py27
-rw-r--r--src/flow_stat.cpp30
-rw-r--r--src/flow_stat.h11
-rw-r--r--src/stateless/rx/trex_stateless_rx_core.cpp6
-rw-r--r--src/stateless/rx/trex_stateless_rx_core.h52
-rwxr-xr-xsrc/time_histogram.cpp41
-rwxr-xr-xsrc/time_histogram.h6
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;}