diff options
author | 2016-07-04 12:55:42 +0300 | |
---|---|---|
committer | 2016-07-04 12:55:42 +0300 | |
commit | 7f58dadbd502f6fe504170c443505c7ad2eb3785 (patch) | |
tree | 1f86a439d24565332a7a286841913d080fb0be74 /src | |
parent | a76479bc269cad96475f9c71381b4f826d47709f (diff) | |
parent | 582e6dddb5693d5fa7576c19b0ef7c1c0723ff59 (diff) |
Merge branch 'master' into cpu_per_core
Diffstat (limited to 'src')
-rwxr-xr-x | src/bp_sim.h | 32 | ||||
-rwxr-xr-x | src/common/basic_utils.cpp | 38 | ||||
-rwxr-xr-x | src/common/basic_utils.h | 10 | ||||
-rw-r--r-- | src/main_dpdk.cpp | 54 | ||||
-rw-r--r-- | src/stateless/rx/trex_stateless_rx_core.cpp | 47 | ||||
-rw-r--r-- | src/stateless/rx/trex_stateless_rx_core.h | 11 |
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 { |