summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Barnea <ibarnea@cisco.com>2016-08-08 10:35:40 +0300
committerIdo Barnea <ibarnea@cisco.com>2016-08-08 10:35:40 +0300
commit7cecfd8ac5537e2128af95660c19f8bb4955a8a0 (patch)
treef4ca325c152babd92ef1285189c66eafe4600017
parentecc97537fbd9d67fc5f3278dabec49a10943330e (diff)
IPv6 x710 flow stats work. Still not supported: Flow stats for UDP/TCP IPv6 packets with extension header.
-rw-r--r--scripts/automation/regression/stateless_tests/stl_rx_test.py5
-rw-r--r--src/flow_stat.cpp64
-rw-r--r--src/flow_stat.h21
-rw-r--r--src/flow_stat_parser.cpp14
-rw-r--r--src/flow_stat_parser.h1
-rw-r--r--src/internal_api/trex_platform_api.h52
-rw-r--r--src/main_dpdk.cpp122
-rw-r--r--src/main_dpdk.h6
-rw-r--r--src/stateless/cp/trex_exception.h1
9 files changed, 169 insertions, 117 deletions
diff --git a/scripts/automation/regression/stateless_tests/stl_rx_test.py b/scripts/automation/regression/stateless_tests/stl_rx_test.py
index 98600087..cdd138de 100644
--- a/scripts/automation/regression/stateless_tests/stl_rx_test.py
+++ b/scripts/automation/regression/stateless_tests/stl_rx_test.py
@@ -54,7 +54,8 @@ class STLRX_Test(CStlGeneral_Test):
);
self.pkt = STLPktBuilder(pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)/('Your_paylaod_comes_here'))
- self.ipv6pkt = STLPktBuilder(pkt = Ether()/IPv6(dst="2001:0:4137:9350:8000:f12a:b9c8:2815",src="2001:4860:0:2001::68")/UDP(dport=12,sport=1025)/('Your_paylaod_comes_here'))
+ self.ipv6pkt = STLPktBuilder(pkt = Ether()/IPv6(dst="2001:0:4137:9350:8000:f12a:b9c8:2815",src="2001:4860:0:2001::68")
+ /IPv6ExtHdrHopByHop()/ICMP()/('Your_paylaod_comes_here'))
self.large_pkt = STLPktBuilder(pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)/('a'*1000))
self.pkt_9k = STLPktBuilder(pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)/('a'*9000))
self.vm_pkt = STLPktBuilder(pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")
@@ -248,11 +249,11 @@ class STLRX_Test(CStlGeneral_Test):
streams_data = [
{'name': 'Flow stat. No latency', 'pkt': self.pkt, 'lat': False},
{'name': 'Latency, no field engine', 'pkt': self.pkt, 'lat': True},
-#Not supported yet {'name': 'IPv6 flow stat. No latency', 'pkt': self.ipv6pkt, 'lat': False},
{'name': 'Latency, short packet with field engine', 'pkt': self.vm_pkt, 'lat': True},
{'name': 'Latency, large packet field engine', 'pkt': self.vm_large_pkt, 'lat': True}
]
if self.latency_9k_enable:
+ streams_data.append({'name': 'IPv6 flow stat. No latency', 'pkt': self.ipv6pkt, 'lat': False})
streams_data.append({'name': 'Latency, 9k packet with field engine', 'pkt': self.vm_9k_pkt, 'lat': True})
if self.ipv6_support:
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,