summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bp_sim.h32
-rwxr-xr-xsrc/common/basic_utils.cpp38
-rwxr-xr-xsrc/common/basic_utils.h10
-rw-r--r--src/main_dpdk.cpp54
-rw-r--r--src/stateless/rx/trex_stateless_rx_core.cpp47
-rw-r--r--src/stateless/rx/trex_stateless_rx_core.h11
6 files changed, 163 insertions, 29 deletions
diff --git a/src/bp_sim.h b/src/bp_sim.h
index 8a38beb7..05900351 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);
-
};
@@ -679,7 +697,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 <stdio.h>
#include <string>
#include <sstream>
+#include <sys/resource.h>
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 eb65ede3..e98c2305 100644
--- a/src/main_dpdk.cpp
+++ b/src/main_dpdk.cpp
@@ -50,6 +50,7 @@
#include <rte_mbuf.h>
#include <rte_random.h>
#include <rte_version.h>
+
#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;
@@ -2043,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 {
@@ -2803,7 +2813,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);
@@ -2847,7 +2857,7 @@ private:
std::mutex m_cp_lock;
TrexMonitor m_monitor;
-
+
public:
TrexStateless *m_trex_stateless;
@@ -3524,7 +3534,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;
@@ -3534,12 +3544,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();
}
}
@@ -4282,7 +4291,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) {
@@ -4307,7 +4316,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) {
@@ -4702,6 +4711,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 */
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 {