diff options
author | Ido Barnea <ibarnea@cisco.com> | 2016-09-08 12:04:59 +0300 |
---|---|---|
committer | Ido Barnea <ibarnea@cisco.com> | 2016-09-13 11:54:20 +0300 |
commit | 58f1ee52761a489322036f111793ddd8e85e197a (patch) | |
tree | 0381145a5b44e685c94a9723f6d75e3cfe924004 | |
parent | 34a6b9050f9179e8000e54b0b3c07f054322c5a2 (diff) |
APIs and functions in preparation for receive all mode. XL710/i350 mode toggling work.
-rwxr-xr-x | linux_dpdk/ws_main.py | 1 | ||||
-rw-r--r-- | src/debug.cpp | 61 | ||||
-rw-r--r-- | src/debug.h | 2 | ||||
-rw-r--r-- | src/dpdk/drivers/net/i40e/i40e_ethdev.c | 64 | ||||
-rw-r--r-- | src/dpdk_funcs.c | 94 | ||||
-rw-r--r-- | src/dpdk_funcs.h | 29 | ||||
-rw-r--r-- | src/flow_stat.cpp | 37 | ||||
-rw-r--r-- | src/flow_stat.h | 7 | ||||
-rw-r--r-- | src/flow_stat_parser.cpp | 11 | ||||
-rw-r--r-- | src/flow_stat_parser.h | 11 | ||||
-rw-r--r-- | src/main_dpdk.cpp | 190 | ||||
-rw-r--r-- | src/stateless/cp/trex_exception.h | 1 | ||||
-rw-r--r-- | src/stateless/rx/trex_stateless_rx_core.cpp | 20 | ||||
-rw-r--r-- | src/stateless/rx/trex_stateless_rx_core.h | 6 | ||||
-rw-r--r-- | src/test_pkt_gen.h | 2 |
15 files changed, 392 insertions, 144 deletions
diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index f208fa9c..f895204c 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -247,6 +247,7 @@ version_src = SrcGroup( dpdk_src = SrcGroup(dir='src/dpdk/', src_list=[ + '../dpdk_funcs.c', 'drivers/net/af_packet/rte_eth_af_packet.c', 'drivers/net/cxgbe/base/t4_hw.c', 'drivers/net/cxgbe/cxgbe_ethdev.c', diff --git a/src/debug.cpp b/src/debug.cpp index 3cb4e3cb..2e7eb5db 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -133,6 +133,9 @@ rte_mbuf_t *CTrexDebug::create_test_pkt(int ip_ver, uint16_t l4_proto, uint8_t t case 6: l3_type = EthernetHeader::Protocol::IPv6; break; + case 1: + l3_type = EthernetHeader::Protocol::ARP; + break; default: return NULL; break; @@ -280,6 +283,8 @@ struct pkt_params { }; struct pkt_params test_pkts[] = { + {"ARP", 1, IPPROTO_UDP, 255, 5, 0, ZERO}, + {"VLAN ARP", 1, IPPROTO_UDP, 255, 5, DPF_VLAN, ZERO}, {"ipv4 TCP ttl 255", 4, IPPROTO_TCP, 255, 5, 0, STF}, {"ipv4 TCP ttl 254", 4, IPPROTO_TCP, 254, 5, 0, STF}, {"ipv4 TCP ttl 253", 4, IPPROTO_TCP, 253, 5, 0, ZERO}, @@ -330,7 +335,7 @@ struct pkt_params test_pkts[] = { // unit test for verifying hw queues rule configuration. Can be run by: // for stateful: --send-debug-pkt 100 -f cap2/dns.yaml -l 1 // for stateless: --setnd-debug-pkt 100 -i -int CTrexDebug::verify_hw_rules() { +int CTrexDebug::verify_hw_rules(bool recv_all) { rte_mbuf_t *m = NULL; CPhyEthIF * lp; rte_mbuf_t * rx_pkts[32]; @@ -345,30 +350,34 @@ int CTrexDebug::verify_hw_rules() { uint8_t exp_q; uint16_t pkt_flags = test_pkts[pkt_num].pkt_flags; debug_expected_q_t expected_q = test_pkts[pkt_num].expected_q; - switch (expected_q) { - case ZERO: - exp_q = 0; - break; - case ONE: - exp_q = 1; - break; - case STL: - if ( CGlobalInfo::m_options.is_stateless() ) { - exp_q = 1; - } else { - exp_q = 0; - } - break; - case STF: - if ( CGlobalInfo::m_options.is_stateless() ) { - exp_q = 0; - } else { - exp_q = 1; + if (recv_all) { + exp_q = MAIN_DPDK_RX_Q; + } else { + switch (expected_q) { + case ZERO: + exp_q = MAIN_DPDK_DATA_Q; + break; + case ONE: + exp_q = MAIN_DPDK_RX_Q; + break; + case STL: + if ( CGlobalInfo::m_options.is_stateless() ) { + exp_q = MAIN_DPDK_RX_Q; + } else { + exp_q = MAIN_DPDK_DATA_Q; + } + break; + case STF: + if ( CGlobalInfo::m_options.is_stateless() ) { + exp_q = MAIN_DPDK_DATA_Q; + } else { + exp_q = MAIN_DPDK_RX_Q; + } + break; + default: + exp_q = MAIN_DPDK_DATA_Q; + break; } - break; - default: - exp_q = 0; - break; } m = create_test_pkt(ip_ver, l4_proto, ttl, ip_id, pkt_flags); @@ -412,7 +421,9 @@ int CTrexDebug::test_send(uint pkt_type) { rte_mbuf_t *m, *d; if (pkt_type == D_PKT_TYPE_HW_VERIFY) { - return verify_hw_rules(); + return verify_hw_rules(false); + } else if (pkt_type == D_PKT_TYPE_HW_VERIFY_RCV_ALL) { + return verify_hw_rules(true); } if (! (pkt_type >= 1 && pkt_type <= 4) && !(pkt_type >= 61 && pkt_type <= 63)) { diff --git a/src/debug.h b/src/debug.h index 3ecc3604..d178e3af 100644 --- a/src/debug.h +++ b/src/debug.h @@ -33,7 +33,7 @@ class CTrexDebug { int set_promisc_all(bool enable); int test_send_pkts(rte_mbuf_t *, uint16_t queue_id, int pkt, int port); rte_mbuf_t *create_test_pkt(int ip_ver, uint16_t l4_proto, uint8_t ttl, uint32_t ip_id, uint16_t flags); - int verify_hw_rules(); + int verify_hw_rules(bool recv_all); public: CTrexDebug(CPhyEthIF *m_ports_arg, int max_ports); diff --git a/src/dpdk/drivers/net/i40e/i40e_ethdev.c b/src/dpdk/drivers/net/i40e/i40e_ethdev.c index 778c1eca..ca1a4808 100644 --- a/src/dpdk/drivers/net/i40e/i40e_ethdev.c +++ b/src/dpdk/drivers/net/i40e/i40e_ethdev.c @@ -757,66 +757,6 @@ static inline void i40e_flex_payload_reg_init(struct i40e_hw *hw) #define TREX_PATCH #define TREX_PATCH_LOW_LATENCY -#ifdef TREX_PATCH - -// 0 - statfull mode. 1 stateless. -static int trex_mode=0; -void i40e_set_trex_mode(int mode) { - trex_mode = mode; -} - -static void i40e_dump_filter_regs(struct i40e_hw *hw) -{ - int reg_nums[] = {31, 33, 34, 35, 41, 43}; - int i; - uint32_t reg; - - for (i =0; i < sizeof (reg_nums)/sizeof(int); i++) { - reg = I40E_READ_REG(hw,I40E_PRTQF_FD_INSET(reg_nums[i], 0)); - printf("I40E_PRTQF_FD_INSET(%d, 0): 0x%08x\n", reg_nums[i], reg); - reg = I40E_READ_REG(hw,I40E_PRTQF_FD_INSET(reg_nums[i], 1)); - printf("I40E_PRTQF_FD_INSET(%d, 1): 0x%08x\n", reg_nums[i], reg); - } -} - -static inline void i40e_filter_fields_reg_init(struct i40e_hw *hw) -{ - uint32_t reg; - - I40E_WRITE_REG(hw, I40E_GLQF_ORT(12), 0x00000062); - I40E_WRITE_REG(hw, I40E_GLQF_PIT(2), 0x000024A0); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, 0), 0); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, 0), 0); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER, 0), 0); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, 0), 0); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, 0), 0); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER, 0), 0); - if (trex_mode == 1) { - // stateless - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, 1), 0x00100000); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, 1), 0x00100000); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER, 1), 0x00100000); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, 1), 0x0000000000200000ULL); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, 1), 0x0000000000200000ULL); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER, 1), 0x0000000000200000ULL); - } else { - //stateful - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, 1), 0x00040000); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, 1), 0x00040000); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER, 1), 0x00040000); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, 1), 0x00080000); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, 1), 0x00080000); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER, 1), 0x00080000); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_SCTP, 0), 0); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_SCTP, 1), 0x00040000); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_SCTP, 0), 0); - I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_SCTP, 1), 0x00080000); - } - I40E_WRITE_REG(hw, I40E_GLQF_FD_MSK(0, 34), 0x000DFF00); - I40E_WRITE_REG(hw, I40E_GLQF_FD_MSK(0,44), 0x000C00FF); - I40E_WRITE_FLUSH(hw); -} -#endif //TREX_PATCH /* * Add a ethertype filter to drop all flow control frames transmitted @@ -1069,14 +1009,10 @@ eth_i40e_dev_init(struct rte_eth_dev *dev) * for flexible payload by software. * It should be removed once issues are fixed in NVM. */ -#ifdef TREX_PATCH - i40e_filter_fields_reg_init(hw); -#else i40e_flex_payload_reg_init(hw); /* Initialize the input set for filters (hash and fd) to default value */ i40e_filter_input_set_init(pf); -#endif /* Initialize the parameters for adminq */ i40e_init_adminq_parameter(hw); diff --git a/src/dpdk_funcs.c b/src/dpdk_funcs.c new file mode 100644 index 00000000..99d23276 --- /dev/null +++ b/src/dpdk_funcs.c @@ -0,0 +1,94 @@ +/* + Copyright (c) 2016-2016 Cisco Systems, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include <stdint.h> +#include <rte_byteorder.h> +#include <rte_ethdev.h> +#include "dpdk/drivers/net/i40e/base/i40e_register.h" +#include "dpdk/drivers/net/i40e/base/i40e_status.h" +#include "dpdk/drivers/net/i40e/base/i40e_osdep.h" +#include "dpdk/drivers/net/i40e/base/i40e_type.h" +#include "dpdk/drivers/net/i40e/i40e_ethdev.h" +#include "dpdk_funcs.h" + +void i40e_trex_dump_fdir_regs(struct i40e_hw *hw) +{ + int reg_nums[] = {31, 33, 34, 35, 41, 43}; + int i; + uint32_t reg; + + for (i =0; i < sizeof (reg_nums)/sizeof(int); i++) { + reg = I40E_READ_REG(hw,I40E_PRTQF_FD_INSET(reg_nums[i], 0)); + printf("I40E_PRTQF_FD_INSET(%d, 0): 0x%08x\n", reg_nums[i], reg); + reg = I40E_READ_REG(hw,I40E_PRTQF_FD_INSET(reg_nums[i], 1)); + printf("I40E_PRTQF_FD_INSET(%d, 1): 0x%08x\n", reg_nums[i], reg); + } +} + +void i40e_trex_fdir_reg_init(int port_id, int mode) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + I40E_WRITE_REG(hw, I40E_GLQF_ORT(12), 0x00000062); + I40E_WRITE_REG(hw, I40E_GLQF_PIT(2), 0x000024A0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, 0), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, 0), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER, 0), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, 0), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, 0), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER, 0), 0); + switch(mode) { + case I40E_TREX_INIT_STL: + // stateless - filter according to IP id or IPv6 identification + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, 1), 0x00100000); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, 1), 0x00100000); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER, 1), 0x00100000); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, 1), 0x0000000000200000ULL); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, 1), 0x0000000000200000ULL); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER, 1), 0x0000000000200000ULL); + break; + case I40E_TREX_INIT_RCV_ALL: + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, 1), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, 1), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER, 1), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, 1), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, 1), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER, 1), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_SCTP, 0), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_SCTP, 1), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_SCTP, 0), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_SCTP, 1), 0); + break; + case I40E_TREX_INIT_STF: + default: + // stateful - Filter according to TTL or IPv6 hop limit + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, 1), 0x00040000); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, 1), 0x00040000); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER, 1), 0x00040000); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, 1), 0x00080000); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, 1), 0x00080000); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER, 1), 0x00080000); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_SCTP, 0), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV4_SCTP, 1), 0x00040000); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_SCTP, 0), 0); + I40E_WRITE_REG(hw, I40E_PRTQF_FD_INSET(I40E_FILTER_PCTYPE_NONF_IPV6_SCTP, 1), 0x00080000); + break; + } + I40E_WRITE_REG(hw, I40E_GLQF_FD_MSK(0, 34), 0x000DFF00); + I40E_WRITE_REG(hw, I40E_GLQF_FD_MSK(0,44), 0x000C00FF); + I40E_WRITE_FLUSH(hw); +} diff --git a/src/dpdk_funcs.h b/src/dpdk_funcs.h new file mode 100644 index 00000000..2db905ff --- /dev/null +++ b/src/dpdk_funcs.h @@ -0,0 +1,29 @@ +/* + Copyright (c) 2016-2016 Cisco Systems, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef __DPDK_FUNCS__ +#define __DPDK_FUNCS__ + +enum i40e_trex_init_mode_ { + I40E_TREX_INIT_STL, + I40E_TREX_INIT_STF, + I40E_TREX_INIT_RCV_ALL, +}; + +void i40e_trex_dump_fdir_regs(struct i40e_hw *hw); +void i40e_trex_fdir_reg_init(int port_id, int mode); + +#endif diff --git a/src/flow_stat.cpp b/src/flow_stat.cpp index 58ff65a4..84be590f 100644 --- a/src/flow_stat.cpp +++ b/src/flow_stat.cpp @@ -583,6 +583,11 @@ int CFlowStatRuleMgr::add_stream_internal(TrexStream * stream, bool do_action) { switch(rule_type) { case TrexPlatformApi::IF_STAT_IPV4_ID: uint16_t l3_proto; + + if (m_mode == FLOW_STAT_MODE_PASS_ALL) { + throw TrexFStatEx("Can not add flow stat stream in 'receive all' mode", TrexException::T_FLOW_STAT_BAD_RULE_TYPE_FOR_MODE); + } + if (m_parser->get_l3_proto(l3_proto) < 0) { throw TrexFStatEx("Failed determining l3 proto for packet", TrexException::T_FLOW_STAT_FAILED_FIND_L3); } @@ -594,8 +599,8 @@ int CFlowStatRuleMgr::add_stream_internal(TrexStream * stream, bool do_action) { // throws exception if there is error if (do_action) { - uint8_t ipv6_next_h = l4_proto; //??? just for now - m_user_id_map.add_stream(stream->m_rx_check.m_pg_id, l3_proto, l4_proto, ipv6_next_h); + // passing 0 in ipv6_next_h. This is not used currently in stateless. + m_user_id_map.add_stream(stream->m_rx_check.m_pg_id, l3_proto, l4_proto, 0); } break; case TrexPlatformApi::IF_STAT_PAYLOAD: @@ -930,6 +935,34 @@ int CFlowStatRuleMgr::get_active_pgids(flow_stat_active_t &result) { return 0; } +int CFlowStatRuleMgr::set_mode(enum flow_stat_mode_e mode) { + if ( ! m_user_id_map.is_empty() ) + return -1; + + if (! m_api ) { + create(); + } + + switch (mode) { + case FLOW_STAT_MODE_PASS_ALL: + delete m_parser; + m_parser = new CPassAllParser; + break; + case FLOW_STAT_MODE_NORMAL: + delete m_parser; + m_parser = m_api->get_flow_stat_parser(); + assert(m_parser); + break; + default: + return -1; + + } + + m_mode = mode; + + return 0; +} + extern bool rx_should_stop; void CFlowStatRuleMgr::send_start_stop_msg_to_rx(bool is_start) { TrexStatelessCpToRxMsgBase *msg; diff --git a/src/flow_stat.h b/src/flow_stat.h index dee1acc8..e0c995ab 100644 --- a/src/flow_stat.h +++ b/src/flow_stat.h @@ -452,6 +452,11 @@ class CFlowStatRuleMgr { FLOW_STAT_RULE_TYPE_IPV6_FLOW_LABEL, }; + enum flow_stat_mode_e { + FLOW_STAT_MODE_NORMAL, + FLOW_STAT_MODE_PASS_ALL, + }; + CFlowStatRuleMgr(); ~CFlowStatRuleMgr(); friend std::ostream& operator<<(std::ostream& os, const CFlowStatRuleMgr& cf); @@ -463,6 +468,7 @@ class CFlowStatRuleMgr { int start_stream(TrexStream * stream); int stop_stream(TrexStream * stream); int get_active_pgids(flow_stat_active_t &result); + int set_mode(enum flow_stat_mode_e mode); bool dump_json(std::string & s_json, std::string & l_json, bool baseline); private: @@ -484,6 +490,7 @@ class CFlowStatRuleMgr { int 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; + enum flow_stat_mode_e m_mode; 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]; diff --git a/src/flow_stat_parser.cpp b/src/flow_stat_parser.cpp index 2ab273a6..fd0fb80a 100644 --- a/src/flow_stat_parser.cpp +++ b/src/flow_stat_parser.cpp @@ -433,6 +433,17 @@ int C82599Parser::parse(uint8_t *p, uint16_t len) { return 0; } +int CPassAllParser::parse(uint8_t *pkt, uint16_t len) { + reset(); + + if (len < ETH_HDR_LEN) + return -1; + + m_len = len; + + return 0; +} + bool CSimplePacketParser::Parse(){ rte_mbuf_t * m=m_m; diff --git a/src/flow_stat_parser.h b/src/flow_stat_parser.h index 78bc1e6a..df70e4ec 100644 --- a/src/flow_stat_parser.h +++ b/src/flow_stat_parser.h @@ -98,6 +98,17 @@ class C82599Parser : public CFlowStatParser { bool m_vlan_supported; }; +class CPassAllParser : public CFlowStatParser { + public: + virtual int parse(uint8_t *pkt, uint16_t len); + virtual bool is_stat_supported() {return true;} + virtual int get_ip_id(uint32_t &ip_id) { ip_id = 0; return 0;} + virtual int set_ip_id(uint32_t ip_id){return 0;} + virtual int get_l3_proto(uint16_t &proto){proto = 0; return 0;} + virtual int get_l4_proto(uint8_t &proto) {proto = 0; return 0;} + virtual int get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload_len) {payload_len = m_len; return 0;} +}; + // Used for latency statefull packets. Need to be merged with above parser class CSimplePacketParser { public: diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 1e31f3df..8a92237d 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -66,6 +66,7 @@ #include "../linux_dpdk/version.h" extern "C" { #include "dpdk/drivers/net/ixgbe/base/ixgbe_type.h" +#include "dpdk_funcs.h" } #include "dpdk/drivers/net/e1000/base/e1000_regs.h" #include "global_io_mode.h" @@ -74,6 +75,7 @@ extern "C" { #include "platform_cfg.h" #include "latency.h" #include "debug.h" +#include "test_pkt_gen.h" #include "internal_api/trex_platform_api.h" #include "main_dpdk.h" #include "trex_watchdog.h" @@ -98,7 +100,6 @@ extern "C" { typedef struct rte_mbuf * (*rte_mbuf_convert_to_one_seg_t)(struct rte_mbuf *m); struct rte_mbuf * rte_mbuf_convert_to_one_seg(struct rte_mbuf *m); -extern "C" void i40e_set_trex_mode(int mode); extern "C" int rte_eth_dev_get_port_by_addr(const struct rte_pci_addr *addr, uint8_t *port_id); void reorder_dpdk_ports(); @@ -140,7 +141,7 @@ public: return(false); } - virtual int configure_drop_queue(CPhyEthIF * _if); + virtual int stop_queue(CPhyEthIF * _if, uint16_t q_num); virtual void get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats)=0; virtual void clear_extended_stats(CPhyEthIF * _if)=0; virtual int wait_for_stable_link(); @@ -155,6 +156,7 @@ public: virtual int get_rx_stat_capabilities() {return 0;} virtual int verify_fw_ver(int i) {return 0;} virtual CFlowStatParser *get_flow_stat_parser(); + virtual int set_rcv_all(CPhyEthIF * _if, bool set_on)=0; }; @@ -179,17 +181,16 @@ public: return (true); } - virtual int configure_drop_queue(CPhyEthIF * _if); + virtual int stop_queue(CPhyEthIF * _if, uint16_t q_num); virtual int configure_rx_filter_rules(CPhyEthIF * _if); virtual int configure_rx_filter_rules_statefull(CPhyEthIF * _if); virtual int configure_rx_filter_rules_stateless(CPhyEthIF * _if); - + virtual void clear_rx_filter_rules(CPhyEthIF * _if); virtual bool is_hardware_support_drop_queue(){ return(true); } virtual void get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats); - virtual void clear_extended_stats(CPhyEthIF * _if); virtual int dump_fdir_global_stats(CPhyEthIF * _if, FILE *fd) {return 0;} virtual int get_stat_counters_num() {return MAX_FLOW_STATS;} @@ -199,6 +200,7 @@ public: } virtual int wait_for_stable_link(); virtual void wait_after_link_up(); + virtual int set_rcv_all(CPhyEthIF * _if, bool set_on); }; class CTRexExtendedDriverBase1GVm : public CTRexExtendedDriverBase { @@ -236,19 +238,16 @@ public: return(false); } - virtual int configure_drop_queue(CPhyEthIF * _if); - - + virtual int stop_queue(CPhyEthIF * _if, uint16_t q_num); virtual void get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats); - virtual void clear_extended_stats(CPhyEthIF * _if); - virtual int wait_for_stable_link(); virtual int get_stat_counters_num() {return MAX_FLOW_STATS;} virtual int get_rx_stat_capabilities() { return TrexPlatformApi::IF_STAT_IPV4_ID | TrexPlatformApi::IF_STAT_RX_BYTES_COUNT | TrexPlatformApi::IF_STAT_PAYLOAD; } + virtual int set_rcv_all(CPhyEthIF * _if, bool set_on) {return 0;} }; @@ -286,6 +285,7 @@ public: | TrexPlatformApi::IF_STAT_PAYLOAD; } virtual CFlowStatParser *get_flow_stat_parser(); + virtual int set_rcv_all(CPhyEthIF * _if, bool set_on) {return 0;} }; class CTRexExtendedDriverBase40G : public CTRexExtendedDriverBase10G { @@ -329,11 +329,13 @@ public: virtual bool hw_rx_stat_supported(){return true;} virtual int verify_fw_ver(int i); virtual CFlowStatParser *get_flow_stat_parser(); + virtual int set_rcv_all(CPhyEthIF * _if, bool set_on); private: virtual void add_del_rules(enum rte_filter_op op, uint8_t port_id, uint16_t type, uint8_t ttl , uint16_t ip_id, uint16_t l4_proto, int queue, uint16_t stat_idx); - virtual int configure_rx_filter_rules_statfull(CPhyEthIF * _if); + virtual int add_del_eth_type_rule(uint8_t port_id, enum rte_filter_op op, uint16_t eth_type); + virtual int configure_rx_filter_rules_statefull(CPhyEthIF * _if); private: uint8_t m_if_per_card; @@ -1386,7 +1388,7 @@ void CPhyEthIF::configure_rx_drop_queue(){ exit(1); } } - get_ex_drv()->configure_drop_queue(this); + get_ex_drv()->stop_queue(this, MAIN_DPDK_DATA_Q); } @@ -5024,9 +5026,6 @@ int main_test(int argc , char * argv[]){ return (-1); } - // We init i40e fdir registers differently in case of stateless. Must set this before rte_eal_init which initiates the registers - i40e_set_trex_mode(get_is_stateless() ? 1:0 ); - ret = rte_eal_init(global_dpdk_args_num, (char **)global_dpdk_args); if (ret < 0){ printf(" You might need to run ./trex-cfg once \n"); @@ -5081,10 +5080,50 @@ int main_test(int argc , char * argv[]){ g_trex.start_master_statefull(); } + // For unit testing of HW rules and queues configuration. Just send some packets and exit. if (CGlobalInfo::m_options.m_debug_pkt_proto != 0) { CTrexDebug debug = CTrexDebug(g_trex.m_ports, g_trex.m_max_ports); - debug.test_send(CGlobalInfo::m_options.m_debug_pkt_proto); - exit(1); + int ret; + + if (CGlobalInfo::m_options.m_debug_pkt_proto == D_PKT_TYPE_HW_TOGGLE_TEST) { + // Unit test: toggle many times between receive all and stateless/stateful modes, + // to test resiliency of add/delete fdir filters + printf("Starting receive all/normal mode toggle unit test\n"); + for (int i = 0; i < 100; i++) { + for (int port_id = 0; port_id < g_trex.m_max_ports; port_id++) { + CPhyEthIF *pif = &g_trex.m_ports[port_id]; + CTRexExtendedDriverDb::Ins()->get_drv()->set_rcv_all(pif, true); + } + ret = debug.test_send(D_PKT_TYPE_HW_VERIFY_RCV_ALL); + if (ret != 0) { + printf("Iteration %d: Receive all mode failed\n", i); + exit(ret); + } + + for (int port_id = 0; port_id < g_trex.m_max_ports; port_id++) { + CPhyEthIF *pif = &g_trex.m_ports[port_id]; + CTRexExtendedDriverDb::Ins()->get_drv()->configure_rx_filter_rules(pif); + } + + ret = debug.test_send(D_PKT_TYPE_HW_VERIFY); + if (ret != 0) { + printf("Iteration %d: Normal mode failed\n", i); + exit(ret); + } + + printf("Iteration %d OK\n", i); + } + exit(0); + } else { + if (CGlobalInfo::m_options.m_debug_pkt_proto == D_PKT_TYPE_HW_VERIFY_RCV_ALL) { + for (int port_id = 0; port_id < g_trex.m_max_ports; port_id++) { + CPhyEthIF *pif = &g_trex.m_ports[port_id]; + CTRexExtendedDriverDb::Ins()->get_drv()->set_rcv_all(pif, true); + } + } + ret = debug.test_send(CGlobalInfo::m_options.m_debug_pkt_proto); + exit(ret); + } } if ( CGlobalInfo::m_options.preview.getOnlyLatency() ){ @@ -5165,9 +5204,9 @@ void reorder_dpdk_ports() { ////////////////////////////////////////////////////////////////////////////////////////////// // driver section ////////////////////////////////////////////////////////////////////////////////////////////// -int CTRexExtendedDriverBase::configure_drop_queue(CPhyEthIF * _if) { +int CTRexExtendedDriverBase::stop_queue(CPhyEthIF * _if, uint16_t q_num) { uint8_t port_id=_if->get_rte_port_id(); - return (rte_eth_dev_rx_queue_stop(port_id, 0)); + return (rte_eth_dev_rx_queue_stop(port_id, q_num)); } int CTRexExtendedDriverBase::wait_for_stable_link() { @@ -5206,14 +5245,15 @@ void CTRexExtendedDriverBase1G::update_global_config_fdir(port_cfg_t * cfg){ // Configuration is done in configure_rx_filter_rules by writing to registers } -// e1000 driver does not support the generic stop queue API, so we need to implement ourselves -int CTRexExtendedDriverBase1G::configure_drop_queue(CPhyEthIF * _if) { - // Drop packets coming to RX queue 0 - _if->pci_reg_write( E1000_RXDCTL(0) , 0); +#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 +// e1000 driver does not support the generic stop/start queue API, so we need to implement ourselves +int CTRexExtendedDriverBase1G::stop_queue(CPhyEthIF * _if, uint16_t q_num) { + uint32_t reg_val = _if->pci_reg_read( E1000_RXDCTL(q_num)); + reg_val &= ~E1000_RXDCTL_QUEUE_ENABLE; + _if->pci_reg_write( E1000_RXDCTL(q_num), reg_val); return 0; } - int CTRexExtendedDriverBase1G::configure_rx_filter_rules(CPhyEthIF * _if){ if ( get_is_stateless() ) { return configure_rx_filter_rules_stateless(_if); @@ -5274,6 +5314,8 @@ int CTRexExtendedDriverBase1G::configure_rx_filter_rules_statefull(CPhyEthIF * _ num_rules = sizeof(ff_rules_v4)/sizeof(ff_rules_v4[0]); } + clear_rx_filter_rules(_if); + uint8_t len = 24; for (rule_id=0; rule_id<num_rules; rule_id++ ) { /* clear rule all */ @@ -5326,12 +5368,7 @@ int CTRexExtendedDriverBase1G::configure_rx_filter_rules_stateless(CPhyEthIF * _ uint32_t mask = 0; int rule_id; - // clear registers of rules. Just in case. - for (rule_id = 0 ; rule_id < 8; rule_id++) { - for (int i=0; i<0xff; i+=4) { - _if->pci_reg_write( (E1000_FHFT(rule_id)+i) , 0); - } - } + clear_rx_filter_rules(_if); rule_id = 0; mask |= 0x1 << rule_id; @@ -5394,6 +5431,39 @@ int CTRexExtendedDriverBase1G::configure_rx_filter_rules_stateless(CPhyEthIF * _ return (0); } +// clear registers of rules +void CTRexExtendedDriverBase1G::clear_rx_filter_rules(CPhyEthIF * _if) { + for (int rule_id = 0 ; rule_id < 8; rule_id++) { + for (int i = 0; i < 0xff; i += 4) { + _if->pci_reg_write( (E1000_FHFT(rule_id) + i) , 0); + } + } +} + +int CTRexExtendedDriverBase1G::set_rcv_all(CPhyEthIF * _if, bool set_on) { + // byte 12 equals 08 - for IPv4 and ARP + // 86 - For IPv6 + // 81 - For VLAN + // 88 - For MPLS + uint8_t eth_types[] = {0x08, 0x86, 0x81, 0x88}; + uint32_t mask = 0; + + clear_rx_filter_rules(_if); + + if (! set_on) + return 0; + + for (int rule_id = 0; rule_id < sizeof(eth_types); rule_id++) { + mask |= 0x1 << rule_id; + // Filter for byte 12 of packet + _if->pci_reg_write( (E1000_FHFT(rule_id)+(1*16) + 4) , 0x000000 | eth_types[rule_id]); + _if->pci_reg_write( (E1000_FHFT(rule_id)+(1*16) + 8) , 0x10); /* MASK */ + // FLEX_PRIO[[18:16] = 1, RQUEUE[10:8] = 1, len = 24 + _if->pci_reg_write( (E1000_FHFT(rule_id) + 0xFC) , (1 << 16) | (1 << 8) | 24); + } + + return 0; +} void CTRexExtendedDriverBase1G::get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats){ @@ -5694,16 +5764,26 @@ void CTRexExtendedDriverBase40G::add_del_rules(enum rte_filter_op op, uint8_t po break; } - ret=rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR, - op, (void*)&filter); - - if ( ret !=0 ){ - rte_exit(EXIT_FAILURE, "rte_eth_dev_filter_ctrl" - "err=%d, port=%u \n", + ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR, op, (void*)&filter); + if ( ret != 0 ) { + rte_exit(EXIT_FAILURE, "rte_eth_dev_filter_ctrl: err=%d, port=%u\n", ret, port_id); } } +int CTRexExtendedDriverBase40G::add_del_eth_type_rule(uint8_t port_id, enum rte_filter_op op, uint16_t eth_type) { + int ret; + struct rte_eth_ethertype_filter filter; + + memset(&filter, 0, sizeof(filter)); + filter.ether_type = eth_type; + filter.flags = 0; + filter.queue = MAIN_DPDK_RX_Q; + ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_ETHERTYPE, op, (void *) &filter); + + return ret; +} + extern "C" int rte_eth_fdir_stats_reset(uint8_t port_id, uint32_t *stats, uint32_t start, uint32_t len); // type - rule type. Currently we only support rules in IP ID. @@ -5748,7 +5828,7 @@ int CTRexExtendedDriverBase40G::add_del_rx_flow_stat_rule(uint8_t port_id, enum return 0; } -int CTRexExtendedDriverBase40G::configure_rx_filter_rules_statfull(CPhyEthIF * _if) { +int CTRexExtendedDriverBase40G::configure_rx_filter_rules_statefull(CPhyEthIF * _if) { uint32_t port_id = _if->get_port_id(); uint16_t hops = get_rx_check_hops(); int i; @@ -5772,25 +5852,31 @@ const uint32_t FDIR_TEMP_HW_ID = 511; const uint32_t FDIR_PAYLOAD_RULES_HW_ID = 510; extern const uint32_t FLOW_STAT_PAYLOAD_IP_ID; int CTRexExtendedDriverBase40G::configure_rx_filter_rules(CPhyEthIF * _if) { + uint32_t port_id = _if->get_port_id(); + + set_rcv_all(_if, false); + if (get_is_stateless()) { - uint32_t port_id = _if->get_port_id(); + i40e_trex_fdir_reg_init(port_id, I40E_TREX_INIT_STL); + add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV4_UDP, 0 , FLOW_STAT_PAYLOAD_IP_ID, 0, MAIN_DPDK_RX_Q, FDIR_PAYLOAD_RULES_HW_ID); add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV4_TCP, 0 , FLOW_STAT_PAYLOAD_IP_ID, 0, MAIN_DPDK_RX_Q, FDIR_PAYLOAD_RULES_HW_ID); add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV4_OTHER, 0 , FLOW_STAT_PAYLOAD_IP_ID, IPPROTO_ICMP, MAIN_DPDK_RX_Q, FDIR_PAYLOAD_RULES_HW_ID); - rte_eth_fdir_stats_reset(_if->get_port_id(), NULL, FDIR_TEMP_HW_ID, 1); - add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV6_UDP, 0 , FLOW_STAT_PAYLOAD_IP_ID, 0, MAIN_DPDK_RX_Q, 0); add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV6_TCP, 0 , FLOW_STAT_PAYLOAD_IP_ID, 0, MAIN_DPDK_RX_Q, 0); add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV6_OTHER, 0 , FLOW_STAT_PAYLOAD_IP_ID, 0, MAIN_DPDK_RX_Q, 0); + + rte_eth_fdir_stats_reset(_if->get_port_id(), NULL, FDIR_TEMP_HW_ID, 1); return 0; // Other rules are configured dynamically in stateless } else { - return configure_rx_filter_rules_statfull(_if); + i40e_trex_fdir_reg_init(port_id, I40E_TREX_INIT_STF); + return configure_rx_filter_rules_statefull(_if); } } @@ -5927,6 +6013,25 @@ CFlowStatParser *CTRexExtendedDriverBase40G::get_flow_stat_parser() { return parser; } +int CTRexExtendedDriverBase40G::set_rcv_all(CPhyEthIF * _if, bool set_on) { + uint32_t port_id = _if->get_port_id(); + enum rte_filter_op op = set_on ? RTE_ETH_FILTER_ADD : RTE_ETH_FILTER_DELETE; + + add_del_eth_type_rule(port_id, op, EthernetHeader::Protocol::ARP); + + if (set_on) { + i40e_trex_fdir_reg_init(port_id, I40E_TREX_INIT_RCV_ALL); + // In order to receive packets, we also need to configure rules for each type. + add_del_rules(op, port_id, RTE_ETH_FLOW_NONFRAG_IPV4_UDP, 10, 0, 0, MAIN_DPDK_RX_Q, 0); + add_del_rules(op, port_id, RTE_ETH_FLOW_NONFRAG_IPV4_TCP, 10, 0, 0, MAIN_DPDK_RX_Q, 0); + add_del_rules(op, port_id, RTE_ETH_FLOW_NONFRAG_IPV4_OTHER, 10, 0, 0, MAIN_DPDK_RX_Q, 0); + add_del_rules(op, port_id, RTE_ETH_FLOW_NONFRAG_IPV6_UDP, 10, 0, 0, MAIN_DPDK_RX_Q, 0); + add_del_rules(op, port_id, RTE_ETH_FLOW_NONFRAG_IPV6_TCP, 10, 0, 0, MAIN_DPDK_RX_Q, 0); + add_del_rules(op, port_id, RTE_ETH_FLOW_NONFRAG_IPV6_OTHER, 10, 0, 0, MAIN_DPDK_RX_Q, 0); + } + return 0; +} + ///////////////////////////////////////////////////////////////////// @@ -5952,7 +6057,7 @@ void CTRexExtendedDriverBase1GVm::clear_extended_stats(CPhyEthIF * _if){ } -int CTRexExtendedDriverBase1GVm::configure_drop_queue(CPhyEthIF * _if){ +int CTRexExtendedDriverBase1GVm::stop_queue(CPhyEthIF * _if, uint16_t q_num) { return (0); } @@ -6239,4 +6344,3 @@ CFlowStatParser *TrexDpdkPlatformApi::get_flow_stat_parser() const { void TrexDpdkPlatformApi::mark_for_shutdown() const { g_trex.mark_for_shutdown(CGlobalTRex::SHUTDOWN_RPC_REQ); } - diff --git a/src/stateless/cp/trex_exception.h b/src/stateless/cp/trex_exception.h index 3984e7e3..c12732ef 100644 --- a/src/stateless/cp/trex_exception.h +++ b/src/stateless/cp/trex_exception.h @@ -44,6 +44,7 @@ class TrexException : public std::runtime_error T_FLOW_STAT_UNSUPP_PKT_FORMAT, T_FLOW_STAT_BAD_RULE_TYPE, T_FLOW_STAT_BAD_RULE_TYPE_FOR_IF, + T_FLOW_STAT_BAD_RULE_TYPE_FOR_MODE, T_FLOW_STAT_FAILED_FIND_L3, T_FLOW_STAT_FAILED_FIND_L4, T_FLOW_STAT_PAYLOAD_TOO_SHORT, diff --git a/src/stateless/rx/trex_stateless_rx_core.cpp b/src/stateless/rx/trex_stateless_rx_core.cpp index 577f5992..e61fb448 100644 --- a/src/stateless/rx/trex_stateless_rx_core.cpp +++ b/src/stateless/rx/trex_stateless_rx_core.cpp @@ -72,6 +72,8 @@ void CCPortLatencyStl::reset() { } void CRxCoreStateless::create(const CRxSlCfg &cfg) { + m_rcv_all = false; + m_capture = false; m_max_ports = cfg.m_max_ports; CMessagingManager * cp_rx = CMsgIns::Ins()->getCpRx(); @@ -190,13 +192,12 @@ void CRxCoreStateless::start() { void CRxCoreStateless::handle_rx_pkt(CLatencyManagerPerPortStl *lp, rte_mbuf_t *m) { CFlowStatParser parser; - if (parser.parse(rte_pktmbuf_mtod(m, uint8_t *), m->pkt_len) == 0) { + if (m_rcv_all || parser.parse(rte_pktmbuf_mtod(m, uint8_t *), m->pkt_len) == 0) { uint32_t ip_id; - if (parser.get_ip_id(ip_id) == 0) { - if (is_flow_stat_id(ip_id)) { + if (m_rcv_all || (parser.get_ip_id(ip_id) == 0)) { + if (m_rcv_all || is_flow_stat_id(ip_id)) { uint16_t hw_id; - - if (is_flow_stat_payload_id(ip_id)) { + if (m_rcv_all || is_flow_stat_payload_id(ip_id)) { bool good_packet = true; uint8_t *p = rte_pktmbuf_mtod(m, uint8_t*); struct flow_stat_payload_header *fsp_head = (struct flow_stat_payload_header *) @@ -206,7 +207,8 @@ void CRxCoreStateless::handle_rx_pkt(CLatencyManagerPerPortStl *lp, rte_mbuf_t * if (unlikely(fsp_head->magic != FLOW_STAT_PAYLOAD_MAGIC) || hw_id >= MAX_FLOW_STATS_PAYLOAD) { good_packet = false; - m_err_cntrs.m_bad_header++; + if (!m_rcv_all) + m_err_cntrs.m_bad_header++; } else { curr_rfc2544 = &m_rfc2544[hw_id]; @@ -291,6 +293,10 @@ void CRxCoreStateless::handle_rx_pkt(CLatencyManagerPerPortStl *lp, rte_mbuf_t * } } +void CRxCoreStateless::capture_pkt(rte_mbuf_t *m) { + +} + // In VM setup, handle packets coming as messages from DP cores. void CRxCoreStateless::handle_rx_queue_msgs(uint8_t thread_id, CNodeRing * r) { while ( true ) { @@ -314,6 +320,8 @@ void CRxCoreStateless::handle_rx_queue_msgs(uint8_t thread_id, CNodeRing * r) { assert( rx_port_index < m_max_ports ); lp = &m_ports[rx_port_index]; handle_rx_pkt(lp, (rte_mbuf_t *)l_msg->m_pkt); + if (m_capture) + capture_pkt((rte_mbuf_t *)l_msg->m_pkt); rte_pktmbuf_free((rte_mbuf_t *)l_msg->m_pkt); break; default: diff --git a/src/stateless/rx/trex_stateless_rx_core.h b/src/stateless/rx/trex_stateless_rx_core.h index e86e0eea..39af8199 100644 --- a/src/stateless/rx/trex_stateless_rx_core.h +++ b/src/stateless/rx/trex_stateless_rx_core.h @@ -147,6 +147,7 @@ class CRxCoreStateless { void tickle(); void idle_state_loop(); void handle_rx_pkt(CLatencyManagerPerPortStl * lp, rte_mbuf_t * m); + void capture_pkt(rte_mbuf_t *m); void handle_rx_queue_msgs(uint8_t thread_id, CNodeRing * r); void flush_rx(); int try_rx(); @@ -156,11 +157,10 @@ class CRxCoreStateless { uint16_t get_hw_id(uint16_t id); private: - TrexMonitor m_monitor; - uint32_t m_max_ports; - bool m_has_streams; + bool m_capture; + bool m_rcv_all; CLatencyManagerPerPortStl m_ports[TREX_MAX_PORTS]; state_e m_state; CNodeRing *m_ring_from_cp; diff --git a/src/test_pkt_gen.h b/src/test_pkt_gen.h index f4ac3a83..49e8e7b0 100644 --- a/src/test_pkt_gen.h +++ b/src/test_pkt_gen.h @@ -29,6 +29,8 @@ enum { D_PKT_TYPE_9k_UDP = 4, D_PKT_TYPE_IPV6 = 60, D_PKT_TYPE_HW_VERIFY = 100, + D_PKT_TYPE_HW_VERIFY_RCV_ALL = 101, + D_PKT_TYPE_HW_TOGGLE_TEST = 102, }; enum { |