diff options
author | Ido Barnea <ibarnea@cisco.com> | 2016-08-08 10:35:40 +0300 |
---|---|---|
committer | Ido Barnea <ibarnea@cisco.com> | 2016-08-08 10:35:40 +0300 |
commit | 7cecfd8ac5537e2128af95660c19f8bb4955a8a0 (patch) | |
tree | f4ca325c152babd92ef1285189c66eafe4600017 /src | |
parent | ecc97537fbd9d67fc5f3278dabec49a10943330e (diff) |
IPv6 x710 flow stats work. Still not supported: Flow stats for UDP/TCP IPv6 packets with extension header.
Diffstat (limited to 'src')
-rw-r--r-- | src/flow_stat.cpp | 64 | ||||
-rw-r--r-- | src/flow_stat.h | 21 | ||||
-rw-r--r-- | src/flow_stat_parser.cpp | 14 | ||||
-rw-r--r-- | src/flow_stat_parser.h | 1 | ||||
-rw-r--r-- | src/internal_api/trex_platform_api.h | 52 | ||||
-rw-r--r-- | src/main_dpdk.cpp | 122 | ||||
-rw-r--r-- | src/main_dpdk.h | 6 | ||||
-rw-r--r-- | src/stateless/cp/trex_exception.h | 1 |
8 files changed, 166 insertions, 115 deletions
diff --git a/src/flow_stat.cpp b/src/flow_stat.cpp index a9451e17..58ff65a4 100644 --- a/src/flow_stat.cpp +++ b/src/flow_stat.cpp @@ -87,13 +87,15 @@ inline std::string methodName(const std::string& prettyFunction) #endif /************** class CFlowStatUserIdInfo ***************/ -CFlowStatUserIdInfo::CFlowStatUserIdInfo(uint8_t proto) { +CFlowStatUserIdInfo::CFlowStatUserIdInfo(uint16_t l3_proto, uint8_t l4_proto, uint8_t ipv6_next_h) { memset(m_rx_cntr, 0, sizeof(m_rx_cntr)); memset(m_rx_cntr_base, 0, sizeof(m_rx_cntr)); memset(m_tx_cntr, 0, sizeof(m_tx_cntr)); memset(m_tx_cntr_base, 0, sizeof(m_tx_cntr)); m_hw_id = UINT16_MAX; - m_proto = proto; + m_l3_proto = l3_proto; + m_l4_proto = l4_proto; + m_ipv6_next_h = ipv6_next_h; m_ref_count = 1; m_trans_ref_count = 0; m_was_sent = false; @@ -105,7 +107,7 @@ CFlowStatUserIdInfo::CFlowStatUserIdInfo(uint8_t proto) { } std::ostream& operator<<(std::ostream& os, const CFlowStatUserIdInfo& cf) { - os << "hw_id:" << cf.m_hw_id << " proto:" << (uint16_t) cf.m_proto << " ref(" + os << "hw_id:" << cf.m_hw_id << " l3 proto:" << (uint16_t) cf.m_l3_proto << " ref(" << (uint16_t) cf.m_ref_count << "," << (uint16_t) cf.m_trans_ref_count << ")"; os << " rx count ("; os << cf.m_rx_cntr[0]; @@ -141,7 +143,7 @@ void CFlowStatUserIdInfo::add_stream(uint8_t proto) { std::cout << __METHOD_NAME__ << " proto:" << (uint16_t)proto << std::endl; #endif - if (proto != m_proto) + if (proto != m_l4_proto) throw TrexFStatEx("Can't use same pg_id for streams with different l4 protocol", TrexException::T_FLOW_STAT_PG_ID_DIFF_L4); @@ -221,7 +223,7 @@ CFlowStatUserIdMap::find_user_id(uint32_t user_id) { } CFlowStatUserIdInfo * -CFlowStatUserIdMap::add_user_id(uint32_t user_id, uint8_t proto) { +CFlowStatUserIdMap::add_user_id(uint32_t user_id, uint16_t l3_proto, uint8_t l4_proto, uint8_t ipv6_next_h) { #ifdef __DEBUG_FUNC_ENTRY__ std::cout << __METHOD_NAME__ << " user id:" << user_id << " proto:" << (uint16_t)proto << std::endl; @@ -229,10 +231,10 @@ CFlowStatUserIdMap::add_user_id(uint32_t user_id, uint8_t proto) { CFlowStatUserIdInfo *new_id; - if (proto == PAYLOAD_RULE_PROTO) { - new_id = new CFlowStatUserIdInfoPayload(proto); + if (l4_proto == PAYLOAD_RULE_PROTO) { + new_id = new CFlowStatUserIdInfoPayload(l3_proto, l4_proto, ipv6_next_h); } else { - new_id = new CFlowStatUserIdInfo(proto); + new_id = new CFlowStatUserIdInfo(l3_proto, l4_proto, ipv6_next_h); } if (new_id != NULL) { std::pair<flow_stat_user_id_map_it_t, bool> ret; @@ -249,9 +251,10 @@ CFlowStatUserIdMap::add_user_id(uint32_t user_id, uint8_t proto) { } } -void CFlowStatUserIdMap::add_stream(uint32_t user_id, uint8_t proto) { +void CFlowStatUserIdMap::add_stream(uint32_t user_id, uint16_t l3_proto, uint8_t l4_proto, uint8_t ipv6_next_h) { #ifdef __DEBUG_FUNC_ENTRY__ - std::cout << __METHOD_NAME__ << " user id:" << user_id << " proto:" << (uint16_t)proto + std::cout << __METHOD_NAME__ << " user id:" << user_id << " l3 proto:" << (uint16_t)l3_proto + << " l4 proto:" << (uint16_t)l4_proto << " IPv6 next header:" << (uint16_t)ipv6_next_h << std::endl; #endif @@ -259,9 +262,10 @@ void CFlowStatUserIdMap::add_stream(uint32_t user_id, uint8_t proto) { c_user_id = find_user_id(user_id); if (! c_user_id) { - c_user_id = add_user_id(user_id, proto); // throws exception on error + // throws exception on error + c_user_id = add_user_id(user_id, l3_proto, l4_proto, ipv6_next_h); } else { - c_user_id->add_stream(proto); + c_user_id->add_stream(l4_proto); } } @@ -360,17 +364,6 @@ bool CFlowStatUserIdMap::is_started(uint32_t user_id) { return c_user_id->is_started(); } -uint8_t CFlowStatUserIdMap::l4_proto(uint32_t user_id) { - CFlowStatUserIdInfo *c_user_id; - - c_user_id = find_user_id(user_id); - if (! c_user_id) { - return 0; - } - - return c_user_id->get_proto(); -} - uint16_t CFlowStatUserIdMap::unmap(uint32_t user_id) { #ifdef __DEBUG_FUNC_ENTRY__ std::cout << __METHOD_NAME__ << " user id:" << user_id << std::endl; @@ -557,7 +550,7 @@ int CFlowStatRuleMgr::add_stream(TrexStream * stream) { return add_stream_internal(stream, true); } -/* +/* * Helper function for adding/verifying streams * stream - stream to act on * do_action - if false, just verify. Do not change any state, or add to database. @@ -589,14 +582,20 @@ 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_parser->get_l3_proto(l3_proto) < 0) { + throw TrexFStatEx("Failed determining l3 proto for packet", TrexException::T_FLOW_STAT_FAILED_FIND_L3); + } uint8_t l4_proto; if (m_parser->get_l4_proto(l4_proto) < 0) { throw TrexFStatEx("Failed determining l4 proto for packet", TrexException::T_FLOW_STAT_FAILED_FIND_L4); } + // throws exception if there is error if (do_action) { - m_user_id_map.add_stream(stream->m_rx_check.m_pg_id, l4_proto); + 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); } break; case TrexPlatformApi::IF_STAT_PAYLOAD: @@ -610,7 +609,7 @@ int CFlowStatRuleMgr::add_stream_internal(TrexStream * stream, bool do_action) { , TrexException::T_FLOW_STAT_PAYLOAD_TOO_SHORT); } if (do_action) { - m_user_id_map.add_stream(stream->m_rx_check.m_pg_id, PAYLOAD_RULE_PROTO); + m_user_id_map.add_stream(stream->m_rx_check.m_pg_id, 0, PAYLOAD_RULE_PROTO, 0); } break; default: @@ -759,7 +758,10 @@ int CFlowStatRuleMgr::start_stream(TrexStream * stream) { m_max_hw_id = hw_id; } m_hw_id_map.map(hw_id, user_id); - add_hw_rule(hw_id, m_user_id_map.l4_proto(user_id)); + CFlowStatUserIdInfo *uid_info = m_user_id_map.find_user_id(user_id); + if (uid_info != NULL) { + add_hw_rule(hw_id, uid_info->get_l3_proto(), uid_info->get_l4_proto(), uid_info->get_ipv6_next_h()); + } } else { if (hw_id > m_max_hw_id_payload) { m_max_hw_id_payload = hw_id; @@ -821,9 +823,9 @@ int CFlowStatRuleMgr::start_stream(TrexStream * stream) { return 0; } -int CFlowStatRuleMgr::add_hw_rule(uint16_t hw_id, uint8_t proto) { +int CFlowStatRuleMgr::add_hw_rule(uint16_t hw_id, uint16_t l3_proto, uint8_t l4_proto, uint8_t ipv6_next_h) { for (int port = 0; port < m_num_ports; port++) { - m_api->add_rx_flow_stat_rule(port, FLOW_STAT_RULE_TYPE_IPV4_ID, proto, hw_id); + m_api->add_rx_flow_stat_rule(port, l3_proto, l4_proto, ipv6_next_h, hw_id); } return 0; @@ -862,7 +864,6 @@ int CFlowStatRuleMgr::stop_stream(TrexStream * stream) { if (m_user_id_map.stop_stream(stream->m_rx_check.m_pg_id) == 0) { // last stream associated with the entry stopped transmittig. // remove user_id <--> hw_id mapping - uint8_t proto = m_user_id_map.l4_proto(stream->m_rx_check.m_pg_id); uint16_t hw_id = m_user_id_map.get_hw_id(stream->m_rx_check.m_pg_id); if (hw_id >= MAX_FLOW_STATS) { throw TrexFStatEx("Internal error in stop_stream. Got bad hw_id" + std::to_string(hw_id) @@ -881,7 +882,8 @@ int CFlowStatRuleMgr::stop_stream(TrexStream * stream) { rfc2544_info_t rfc2544_info; for (uint8_t port = 0; port < m_num_ports; port++) { if (rule_type == TrexPlatformApi::IF_STAT_IPV4_ID) { - m_api->del_rx_flow_stat_rule(port, FLOW_STAT_RULE_TYPE_IPV4_ID, proto, hw_id); + m_api->del_rx_flow_stat_rule(port, p_user_id->get_l3_proto(), p_user_id->get_l4_proto() + , p_user_id->get_ipv6_next_h(), hw_id); } m_api->get_flow_stats(port, &rx_cntr, (void *)&tx_cntr, hw_id, hw_id, true, rule_type); // when stopping, always send counters for stopped stream one last time diff --git a/src/flow_stat.h b/src/flow_stat.h index 05b94f04..dee1acc8 100644 --- a/src/flow_stat.h +++ b/src/flow_stat.h @@ -268,7 +268,7 @@ class CFlowStatParser; class CFlowStatUserIdInfo { public: - CFlowStatUserIdInfo(uint8_t proto); + CFlowStatUserIdInfo(uint16_t l3_proto, uint8_t l4_proto, uint8_t ipv6_next_h); virtual ~CFlowStatUserIdInfo() {}; friend std::ostream& operator<<(std::ostream& os, const CFlowStatUserIdInfo& cf); void set_rx_cntr(uint8_t port, rx_per_flow_t val) {m_rx_cntr[port] = val;} @@ -279,7 +279,9 @@ class CFlowStatUserIdInfo { uint16_t get_hw_id() {return m_hw_id;} virtual void reset_hw_id(); bool is_hw_id() {return (m_hw_id != UINT16_MAX);} - uint64_t get_proto() {return m_proto;} + uint16_t get_l3_proto() {return m_l3_proto;} + uint8_t get_l4_proto() {return m_l4_proto;} + uint8_t get_ipv6_next_h() {return m_ipv6_next_h;} uint8_t get_ref_count() {return m_ref_count;} virtual void add_stream(uint8_t proto); int del_stream() {m_ref_count--; return m_ref_count;} @@ -309,7 +311,9 @@ class CFlowStatUserIdInfo { tx_per_flow_t m_tx_cntr[TREX_MAX_PORTS]; // How many packets transmitted with this user id since stream start // How many packets transmitted with this user id, since stream creation, before stream start. tx_per_flow_t m_tx_cntr_base[TREX_MAX_PORTS]; - uint8_t m_proto; // protocol (UDP, TCP, other), associated with this user id. + uint16_t m_l3_proto; // L3 protocol (IPv4, IPv6), associated with this user id. + uint8_t m_l4_proto; // L4 protocol (UDP, TCP, other), associated with this user id. + uint8_t m_ipv6_next_h; // In case of IPv6, what is the type of the first extension header uint8_t m_ref_count; // How many streams with this user id exists uint8_t m_trans_ref_count; // How many streams with this user id currently transmit bool m_was_sent; // Did we send this info to clients once? @@ -320,7 +324,9 @@ typedef std::map<uint32_t, class CFlowStatUserIdInfo *>::iterator flow_stat_user class CFlowStatUserIdInfoPayload : public CFlowStatUserIdInfo { public: - CFlowStatUserIdInfoPayload(uint8_t proto) : CFlowStatUserIdInfo(proto){m_rfc2544_support = true; clear();}; + CFlowStatUserIdInfoPayload(uint16_t l3_proto, uint8_t l4_proto, uint8_t ipv6_next_h) + : CFlowStatUserIdInfo(l3_proto, l4_proto, ipv6_next_h) + {m_rfc2544_support = true; clear();} virtual void add_stream(uint8_t proto); void clear() { @@ -408,14 +414,13 @@ class CFlowStatUserIdMap { bool is_empty() {return (m_map.empty() == true);}; uint16_t get_hw_id(uint32_t user_id); CFlowStatUserIdInfo * find_user_id(uint32_t user_id); - CFlowStatUserIdInfo * add_user_id(uint32_t user_id, uint8_t proto); - void add_stream(uint32_t user_id, uint8_t proto); + CFlowStatUserIdInfo * add_user_id(uint32_t user_id, uint16_t l3_proto, uint8_t l4_proto, uint8_t ipv6_next_h); + void add_stream(uint32_t user_id, uint16_t l3_proto, uint8_t l4_proto, uint8_t ipv6_next_h); int del_stream(uint32_t user_id); int start_stream(uint32_t user_id, uint16_t hw_id); int start_stream(uint32_t user_id); int stop_stream(uint32_t user_id); bool is_started(uint32_t user_id); - uint8_t l4_proto(uint32_t user_id); uint16_t unmap(uint32_t user_id); flow_stat_user_id_map_it_t begin() {return m_map.begin();} flow_stat_user_id_map_it_t end() {return m_map.end();} @@ -464,7 +469,7 @@ class CFlowStatRuleMgr { void create(); int compile_stream(const TrexStream * stream, CFlowStatParser *parser); int add_stream_internal(TrexStream * stream, bool do_action); - int add_hw_rule(uint16_t hw_id, uint8_t proto); + int add_hw_rule(uint16_t hw_id, uint16_t l3_proto, uint8_t l4_proto, uint8_t ipv6_next_h); void send_start_stop_msg_to_rx(bool is_start); private: diff --git a/src/flow_stat_parser.cpp b/src/flow_stat_parser.cpp index 602ef310..deae7062 100644 --- a/src/flow_stat_parser.cpp +++ b/src/flow_stat_parser.cpp @@ -119,6 +119,20 @@ int CFlowStatParser::set_ip_id(uint32_t new_id) { return -1; } +int CFlowStatParser::get_l3_proto(uint16_t &proto) { + if (m_ipv4) { + proto = EthernetHeader::Protocol::IP; + return 0; + } + + if (m_ipv6) { + proto = EthernetHeader::Protocol::IPv6; + return 0; + } + + return -1; +} + int CFlowStatParser::get_l4_proto(uint8_t &proto) { if (m_ipv4) { proto = m_ipv4->getProtocol(); diff --git a/src/flow_stat_parser.h b/src/flow_stat_parser.h index d44c8a7f..8ec5a229 100644 --- a/src/flow_stat_parser.h +++ b/src/flow_stat_parser.h @@ -37,6 +37,7 @@ class CFlowStatParser { virtual bool is_stat_supported() {return m_stat_supported == true;} virtual int get_ip_id(uint32_t &ip_id); virtual int set_ip_id(uint32_t ip_id); + virtual int get_l3_proto(uint16_t &proto); virtual int get_l4_proto(uint8_t &proto); virtual int get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload_len); virtual uint16_t get_pkt_size(); diff --git a/src/internal_api/trex_platform_api.h b/src/internal_api/trex_platform_api.h index c9247130..7a2a0c8a 100644 --- a/src/internal_api/trex_platform_api.h +++ b/src/internal_api/trex_platform_api.h @@ -32,7 +32,7 @@ limitations under the License. /** * Global stats - * + * * @author imarom (06-Oct-15) */ @@ -48,23 +48,23 @@ public: double m_rx_cpu_util; double m_tx_bps; double m_rx_bps; - + double m_tx_pps; double m_rx_pps; - + uint64_t m_total_tx_pkts; uint64_t m_total_rx_pkts; - + uint64_t m_total_tx_bytes; uint64_t m_total_rx_bytes; - + uint64_t m_tx_rx_errors; } m_stats; }; /** * Per Interface stats - * + * * @author imarom (26-Oct-15) */ class TrexPlatformInterfaceStats { @@ -80,16 +80,16 @@ public: double m_tx_bps; double m_rx_bps; - + double m_tx_pps; double m_rx_pps; - + uint64_t m_total_tx_pkts; uint64_t m_total_rx_pkts; - + uint64_t m_total_tx_bytes; uint64_t m_total_rx_bytes; - + uint64_t m_tx_rx_errors; } m_stats; }; @@ -97,8 +97,8 @@ public: /** * low level API interface - * can be implemented by DPDK or mock - * + * can be implemented by DPDK or mock + * * @author imarom (25-Oct-15) */ @@ -110,7 +110,7 @@ public: IF_STAT_IPV6_FLOW_LABEL = 4, IF_STAT_RX_BYTES_COUNT = 8, // Card support counting rx bytes }; - + enum driver_speed_e { SPEED_INVALID, SPEED_1G, @@ -126,7 +126,7 @@ public: /** * interface static info - * + * */ struct intf_info_st { std::string driver_name; @@ -152,8 +152,10 @@ public: virtual int get_rx_err_cntrs(void *rx_err_cntrs) const = 0; virtual int reset_hw_flow_stats(uint8_t port_id) const = 0; virtual void get_port_num(uint8_t &port_num) const = 0; - virtual int add_rx_flow_stat_rule(uint8_t port_id, uint8_t type, uint16_t proto, uint16_t id) const = 0; - virtual int del_rx_flow_stat_rule(uint8_t port_id, uint8_t type, uint16_t proto, uint16_t id) const = 0; + virtual int add_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto + , uint8_t ipv6_next_h, uint16_t id) const = 0; + virtual int del_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto + , uint8_t ipv6_next_h, uint16_t id) const = 0; virtual void set_promiscuous(uint8_t port_id, bool enabled) const = 0; virtual bool get_promiscuous(uint8_t port_id) const = 0; virtual void flush_dp_messages() const = 0; @@ -169,7 +171,7 @@ public: /** * DPDK implementation of the platform API - * + * * @author imarom (26-Oct-15) */ class TrexDpdkPlatformApi : public TrexPlatformApi { @@ -189,8 +191,10 @@ public: int get_rx_err_cntrs(void *rx_err_cntrs) const; int reset_hw_flow_stats(uint8_t port_id) const; void get_port_num(uint8_t &port_num) const; - int add_rx_flow_stat_rule(uint8_t port_id, uint8_t type, uint16_t proto, uint16_t id) const; - int del_rx_flow_stat_rule(uint8_t port_id, uint8_t type, uint16_t proto, uint16_t id) const; + virtual int add_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto + , uint8_t ipv6_next_h, uint16_t id) const; + virtual int del_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto + , uint8_t ipv6_next_h, uint16_t id) const; void set_promiscuous(uint8_t port_id, bool enabled) const; bool get_promiscuous(uint8_t port_id) const; void flush_dp_messages() const; @@ -204,7 +208,7 @@ public: /** * for simulation - * + * * @author imarom (25-Feb-16) */ class SimPlatformApi : public TrexPlatformApi { @@ -250,12 +254,12 @@ public: virtual int get_rx_err_cntrs(void *rx_err_cntrs) const {return 0;}; virtual int reset_hw_flow_stats(uint8_t port_id) const {return 0;}; virtual void get_port_num(uint8_t &port_num) const {port_num = 2;}; - virtual int add_rx_flow_stat_rule(uint8_t port_id, uint8_t type, uint16_t proto, uint16_t id) const {return 0;} - virtual int del_rx_flow_stat_rule(uint8_t port_id, uint8_t type, uint16_t proto, uint16_t id) const {return 0;} - + virtual int add_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto + , uint8_t ipv6_next_h, uint16_t id) const {return 0;}; + virtual int del_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto + , uint8_t ipv6_next_h, uint16_t id) const {return 0;}; void set_promiscuous(uint8_t port_id, bool enabled) const { } - bool get_promiscuous(uint8_t port_id) const { return false; } diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index f5261f8d..e5884f93 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -136,7 +136,8 @@ public: return(false); } virtual int configure_rx_filter_rules(CPhyEthIF * _if)=0; - virtual int add_del_rx_flow_stat_rule(uint8_t port_id, enum rte_filter_op op, uint8_t type, uint16_t proto, uint16_t id) {return -1;}; + virtual int add_del_rx_flow_stat_rule(uint8_t port_id, enum rte_filter_op op, uint16_t l3, uint8_t l4 + , uint8_t ipv6_next_h, uint16_t id) {return -1;}; virtual bool is_hardware_support_drop_queue(){ return(false); } @@ -316,11 +317,10 @@ public: virtual void update_global_config_fdir(port_cfg_t * cfg){ } - virtual void update_configuration(port_cfg_t * cfg); - virtual int configure_rx_filter_rules(CPhyEthIF * _if); - virtual int add_del_rx_flow_stat_rule(uint8_t port_id, enum rte_filter_op op, uint8_t type, uint16_t proto, uint16_t id); + virtual int add_del_rx_flow_stat_rule(uint8_t port_id, enum rte_filter_op op, uint16_t l3_proto + , uint8_t l4_proto, uint8_t ipv6_next_h, uint16_t id); virtual bool is_hardware_filter_is_supported(){ return (true); } @@ -1339,17 +1339,17 @@ void CPhyEthIF::configure(uint16_t nb_rx_queue, rte_eth_dev_info_get(m_port_id, &m_dev_info); if (CGlobalInfo::m_options.preview.getChecksumOffloadEnable()) { - /* check if the device supports TCP and UDP checksum offloading */ - if ((m_dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) == 0) { - rte_exit(EXIT_FAILURE, "Device does not support UDP checksum offload: " - "port=%u\n", - m_port_id); - } - if ((m_dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) == 0) { - rte_exit(EXIT_FAILURE, "Device does not support TCP checksum offload: " - "port=%u\n", - m_port_id); - } + /* check if the device supports TCP and UDP checksum offloading */ + if ((m_dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) == 0) { + rte_exit(EXIT_FAILURE, "Device does not support UDP checksum offload: " + "port=%u\n", + m_port_id); + } + if ((m_dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) == 0) { + rte_exit(EXIT_FAILURE, "Device does not support TCP checksum offload: " + "port=%u\n", + m_port_id); + } } } @@ -2176,7 +2176,7 @@ void CCoreEthIF::apply_client_cfg(const ClientCfg *cfg, rte_mbuf_t *m, pkt_dir_t /* VLAN */ if (cfg_dir.has_vlan()) { add_vlan(m, cfg_dir.get_vlan()); - } + } } @@ -2188,11 +2188,11 @@ void CCoreEthIF::add_vlan(rte_mbuf_t *m, uint16_t vlan_id) { /** * slow path features goes here (avoid multiple IFs) - * + * */ void CCoreEthIF::handle_slowpath_features(CGenNode *node, rte_mbuf_t *m, uint8_t *p, pkt_dir_t dir) { - + /* MAC ovverride */ if ( unlikely( CGlobalInfo::m_options.preview.get_mac_ip_overide_enable() ) ) { /* client side */ @@ -2231,7 +2231,7 @@ int CCoreEthIF::send_node(CGenNode * node) { dir = node->cur_interface_dir(); single_port = node->get_is_all_flow_from_same_dir() ; - + if ( unlikely( CGlobalInfo::m_options.preview.get_vlan_mode_enable() ) ){ /* which vlan to choose 0 or 1*/ uint8_t vlan_port = (node->m_src_ip &1); @@ -2259,7 +2259,7 @@ int CCoreEthIF::send_node(CGenNode * node) { /* update mac addr dest/src 12 bytes */ uint8_t *p = rte_pktmbuf_mtod(m, uint8_t*); uint8_t p_id = lp_port->m_port->get_port_id(); - + memcpy(p,CGlobalInfo::m_options.get_dst_src_mac_addr(p_id),12); /* when slowpath features are on */ @@ -2267,7 +2267,7 @@ int CCoreEthIF::send_node(CGenNode * node) { handle_slowpath_features(node, m, p, dir); } - + if ( unlikely( node->is_rx_check_enabled() ) ) { lp_stats->m_tx_rx_check_pkt++; lp->do_generate_new_mbuf_rxcheck(m, node, single_port); @@ -2829,9 +2829,9 @@ public: int reset_counters(); /** - * mark for shutdown - * on the next check - the control plane will - * call shutdown() + * mark for shutdown + * on the next check - the control plane will + * call shutdown() */ void mark_for_shutdown(shutdown_rc_e rc) { @@ -2858,7 +2858,7 @@ private: /** * shutdown sequence - * + * */ void shutdown(); @@ -4114,14 +4114,14 @@ CGlobalTRex::handle_fast_path() { /** * shutdown sequence - * + * */ void CGlobalTRex::shutdown() { std::stringstream ss; ss << " *** TRex is shutting down - cause: '"; switch (m_mark_for_shutdown) { - + case SHUTDOWN_TEST_ENDED: ss << "test has ended'"; break; @@ -4133,7 +4133,7 @@ void CGlobalTRex::shutdown() { case SHUTDOWN_SIGINT: ss << "received signal SIGINT'"; break; - + case SHUTDOWN_SIGTERM: ss << "received signal SIGTERM'"; break; @@ -4220,7 +4220,7 @@ int CGlobalTRex::run_in_master() { /* shutdown everything gracefully */ shutdown(); - + return (0); } @@ -5635,22 +5635,42 @@ extern "C" int rte_eth_fdir_stats_reset(uint8_t port_id, uint32_t *stats, uint32 // type - rule type. Currently we only support rules in IP ID. // proto - Packet protocol: UDP or TCP // id - Counter id in HW. We assume it is in the range 0..MAX_FLOW_STATS -int CTRexExtendedDriverBase40G::add_del_rx_flow_stat_rule(uint8_t port_id, enum rte_filter_op op, uint8_t type, uint16_t proto, uint16_t id) { +int CTRexExtendedDriverBase40G::add_del_rx_flow_stat_rule(uint8_t port_id, enum rte_filter_op op, uint16_t l3_proto + , uint8_t l4_proto, uint8_t ipv6_next_h, uint16_t id) { uint32_t rule_id = (port_id % m_if_per_card) * MAX_FLOW_STATS + id; uint16_t rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_OTHER; + uint8_t next_proto; - switch(proto) { - case IPPROTO_TCP: - rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_TCP; - break; - case IPPROTO_UDP: - rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_UDP; - break; - default: - rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_OTHER; - break; + if (l3_proto == EthernetHeader::Protocol::IP) { + next_proto = l4_proto; + switch(l4_proto) { + case IPPROTO_TCP: + rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_TCP; + break; + case IPPROTO_UDP: + rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_UDP; + break; + default: + rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_OTHER; + break; + } + } else { + // IPv6 + next_proto = ipv6_next_h; + switch(l4_proto) { + case IPPROTO_TCP: + rte_type = RTE_ETH_FLOW_NONFRAG_IPV6_TCP; + break; + case IPPROTO_UDP: + rte_type = RTE_ETH_FLOW_NONFRAG_IPV6_UDP; + break; + default: + rte_type = RTE_ETH_FLOW_NONFRAG_IPV6_OTHER; + break; + } } - add_del_rules(op, port_id, rte_type, 0, IP_ID_RESERVE_BASE + id, proto, MAIN_DPDK_DATA_Q, rule_id); + + add_del_rules(op, port_id, rte_type, 0, IP_ID_RESERVE_BASE + id, next_proto, MAIN_DPDK_DATA_Q, rule_id); return 0; } @@ -5909,10 +5929,10 @@ struct rte_mbuf * rte_mbuf_convert_to_one_seg(struct rte_mbuf *m){ /** * handle a signal for termination - * + * * @author imarom (7/27/2016) - * - * @param signum + * + * @param signum */ static void trex_termination_handler(int signum) { std::stringstream ss; @@ -5932,7 +5952,7 @@ static void trex_termination_handler(int signum) { default: assert(0); } - + } /*********************************************************** @@ -6061,14 +6081,16 @@ int TrexDpdkPlatformApi::reset_hw_flow_stats(uint8_t port_id) const { return g_trex.m_ports[port_id].reset_hw_flow_stats(); } -int TrexDpdkPlatformApi::add_rx_flow_stat_rule(uint8_t port_id, uint8_t type, uint16_t proto, uint16_t id) const { +int TrexDpdkPlatformApi::add_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto + , uint8_t ipv6_next_h, uint16_t id) const { return CTRexExtendedDriverDb::Ins()->get_drv() - ->add_del_rx_flow_stat_rule(port_id, RTE_ETH_FILTER_ADD, type, proto, id); + ->add_del_rx_flow_stat_rule(port_id, RTE_ETH_FILTER_ADD, l3_type, l4_proto, ipv6_next_h, id); } -int TrexDpdkPlatformApi::del_rx_flow_stat_rule(uint8_t port_id, uint8_t type, uint16_t proto, uint16_t id) const { +int TrexDpdkPlatformApi::del_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto + , uint8_t ipv6_next_h, uint16_t id) const { return CTRexExtendedDriverDb::Ins()->get_drv() - ->add_del_rx_flow_stat_rule(port_id, RTE_ETH_FILTER_DELETE, type, proto, id); + ->add_del_rx_flow_stat_rule(port_id, RTE_ETH_FILTER_DELETE, l3_type, l4_proto, ipv6_next_h, id); } void TrexDpdkPlatformApi::set_promiscuous(uint8_t port_id, bool enabled) const { @@ -6107,7 +6129,7 @@ CFlowStatParser *TrexDpdkPlatformApi::get_flow_stat_parser() const { /** * marks the control plane for a total server shutdown - * + * * @author imarom (7/27/2016) */ void TrexDpdkPlatformApi::mark_for_shutdown() const { diff --git a/src/main_dpdk.h b/src/main_dpdk.h index c2169eea..f8c35732 100644 --- a/src/main_dpdk.h +++ b/src/main_dpdk.h @@ -125,8 +125,10 @@ class CPhyEthIF { } void flush_dp_rx_queue(void); void flush_rx_queue(void); - int add_rx_flow_stat_rule(uint8_t type, uint16_t proto, uint16_t id); - int del_rx_flow_stat_rule(uint8_t type, uint16_t proto, uint16_t id); + int add_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto + , uint8_t ipv6_next_h, uint16_t id) const; + int del_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto + , uint8_t ipv6_next_h, uint16_t id) const; inline uint16_t tx_burst(uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { return rte_eth_tx_burst(m_port_id, queue_id, tx_pkts, nb_pkts); } diff --git a/src/stateless/cp/trex_exception.h b/src/stateless/cp/trex_exception.h index ff3179f9..3984e7e3 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_FAILED_FIND_L3, T_FLOW_STAT_FAILED_FIND_L4, T_FLOW_STAT_PAYLOAD_TOO_SHORT, T_FLOW_STAT_NO_STREAMS_EXIST, |