summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Barnea <ibarnea@cisco.com>2016-08-10 15:09:45 +0300
committerIdo Barnea <ibarnea@cisco.com>2016-08-10 15:09:45 +0300
commit92880804c194990c0a2e3201c6179b8c2f6cae7c (patch)
tree6650b767894e35b0090b7e80d8f0371d2ba0f97c
parente61cecf7febc28116507221af6922e252bda89a4 (diff)
Better flow stat parser unit tests, including IPv6
-rwxr-xr-xlinux/ws_main.py1
-rwxr-xr-xlinux_dpdk/ws_main.py1
-rw-r--r--src/debug.cpp204
-rw-r--r--src/flow_stat_parser.cpp203
-rw-r--r--src/flow_stat_parser.h28
-rw-r--r--src/gtest/trex_stateless_gtest.cpp4
-rw-r--r--src/test_pkt_gen.cpp232
-rw-r--r--src/test_pkt_gen.h46
8 files changed, 459 insertions, 260 deletions
diff --git a/linux/ws_main.py b/linux/ws_main.py
index 66d79d13..b1704e5e 100755
--- a/linux/ws_main.py
+++ b/linux/ws_main.py
@@ -113,6 +113,7 @@ main_src = SrcGroup(dir='src',
'rx_check_header.cpp',
'nat_check.cpp',
'nat_check_flow_table.cpp',
+ 'test_pkt_gen.cpp',
'timer_wheel_pq.cpp',
'time_histogram.cpp',
'utl_json.cpp',
diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py
index e6feb219..9e07da05 100755
--- a/linux_dpdk/ws_main.py
+++ b/linux_dpdk/ws_main.py
@@ -110,6 +110,7 @@ main_src = SrcGroup(dir='src',
'tuple_gen.cpp',
'rx_check.cpp',
'rx_check_header.cpp',
+ 'test_pkt_gen.cpp',
'timer_wheel_pq.cpp',
'time_histogram.cpp',
'os_time.cpp',
diff --git a/src/debug.cpp b/src/debug.cpp
index dd07cd05..3cb4e3cb 100644
--- a/src/debug.cpp
+++ b/src/debug.cpp
@@ -27,26 +27,10 @@
#include <rte_pci.h>
#include <rte_ethdev.h>
#include <common/basic_utils.h>
-#include "rx_check_header.h"
+#include "test_pkt_gen.h"
#include "main_dpdk.h"
#include "debug.h"
-enum {
- D_PKT_TYPE_ICMP = 1,
- D_PKT_TYPE_UDP = 2,
- D_PKT_TYPE_TCP = 3,
- D_PKT_TYPE_9k_UDP = 4,
- D_PKT_TYPE_IPV6 = 60,
- D_PKT_TYPE_HW_VERIFY = 100,
-
-};
-
-enum {
- DPF_VLAN = 0x1,
- DPF_QINQ = 0X2,
- DPF_RXCHECK = 0x4
-};
-
const uint8_t udp_pkt[] = {
0x00,0x00,0x00,0x01,0x00,0x00,
0x00,0x00,0x00,0x01,0x00,0x00,
@@ -133,194 +117,40 @@ rte_mbuf_t *CTrexDebug::create_test_pkt(int ip_ver, uint16_t l4_proto, uint8_t t
}
#else
-// For playing around, and testing packet sending in debug mode
rte_mbuf_t *CTrexDebug::create_test_pkt(int ip_ver, uint16_t l4_proto, uint8_t ttl
, uint32_t ip_id, uint16_t flags) {
- int pkt_size = 0;
- // ASA 2
- uint8_t dst_mac[6] = {0x74, 0xa2, 0xe6, 0xd5, 0x39, 0x25};
- uint8_t src_mac[6] = {0xa0, 0x36, 0x9f, 0x38, 0xa4, 0x02};
- uint8_t vlan_header[4] = {0x0a, 0xbc, 0x00, 0x00}; // we set the type below according to if pkt is ipv4 or 6
- uint8_t vlan_header2[4] = {0x0a, 0xbc, 0x88, 0xa8};
- uint16_t l2_proto;
- // ASA 1A
- // uint8_t dst_mac[6] = {0xd4, 0x8c, 0xb5, 0xc9, 0x54, 0x2b};
- // uint8_t src_mac[6] = {0xa0, 0x36, 0x9f, 0x38, 0xa4, 0x0};
- if (flags & DPF_VLAN) {
- l2_proto = 0x0081;
- } else {
- if (ip_ver == 4)
- l2_proto = 0x0008;
- else // IPV6
- l2_proto = 0xdd86;
- }
+ int pkt_size;
+ char *pkt;
+ rte_mbuf_t *m;
+ char *p;
+ CTestPktGen gen;
+ uint16_t l3_type;
- uint8_t ip_header[] = {
- 0x45,0x02,0x00,0x30,
- 0x00,0x00,0x40,0x00,
- 0xff,0x01,0xbd,0x04,
- 0x10,0x0,0x0,0x1, //SIP
- 0x30,0x0,0x0,0x1, //DIP
- // 0x82, 0x0b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // IP option. change 45 to 48 (header len) if using it.
- };
- uint8_t ipv6_header[] = {
- 0x60,0x00,0xff,0x30, // traffic class + flow label
- 0x00,0x00,0x40,0x00, // payload len + next header + hop limit
- 0x10,0x0,0x0,0x1,0x10,0x0,0x0,0x1,0x10,0x0,0x0,0x1,0x10,0x0,0x0,0x1, //SIP
- 0x30,0x0,0x0,0x1,0x10,0x0,0x0,0x1,0x30,0x0,0x0,0x1,0x10,0x0,0x0,0x1, //DIP
- };
- uint8_t udp_header[] = {0x11, 0x11, 0x11,0x11, 0x00, 0x6d, 0x00, 0x00};
- uint8_t udp_data[] = {0x64,0x31,0x3a,0x61,
- 0x64,0x32,0x3a,0x69,0x64,
- 0x32,0x30,0x3a,0xd0,0x0e,
- 0xa1,0x4b,0x7b,0xbd,0xbd,
- 0x16,0xc6,0xdb,0xc4,0xbb,0x43,
- 0xf9,0x4b,0x51,0x68,0x33,0x72,
- 0x20,0x39,0x3a,0x69,0x6e,0x66,0x6f,
- 0x5f,0x68,0x61,0x73,0x68,0x32,0x30,0x3a,0xee,0xc6,0xa3,
- 0xd3,0x13,0xa8,0x43,0x06,0x03,0xd8,0x9e,0x3f,0x67,0x6f,
- 0xe7,0x0a,0xfd,0x18,0x13,0x8d,0x65,0x31,0x3a,0x71,0x39,
- 0x3a,0x67,0x65,0x74,0x5f,0x70,0x65,0x65,0x72,0x73,0x31,
- 0x3a,0x74,0x38,0x3a,0x3d,0xeb,0x0c,0xbf,0x0d,0x6a,0x0d,
- 0xa5,0x31,0x3a,0x79,0x31,0x3a,0x71,0x65,0x87,0xa6,0x7d,
- 0xe7
- };
-
- uint8_t tcp_header[] = {0xab, 0xcd, 0x00, 0x80, // src, dst ports
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // seq num, ack num
- 0x50, 0x00, 0xff, 0xff, // Header size, flags, window size
- 0x00, 0x00, 0x00, 0x00, // checksum ,urgent pointer
- };
-
- uint8_t tcp_data[] = {0x8, 0xa, 0x1, 0x2, 0x3, 0x4, 0x3, 0x4, 0x6, 0x5,
- 0x8, 0xa, 0x1, 0x2, 0x3, 0x4, 0x3, 0x4, 0x6, 0x5};
-
- uint8_t icmp_header[] = {
- 0x08, 0x00,
- 0xb8, 0x21, //checksum
- 0xaa, 0xbb, // id
- 0x00, 0x01, // Sequence number
- };
- uint8_t icmp_data[] = {
- 0xd6, 0x6e, 0x64, 0x34, // magic
- 0x6a, 0xad, 0x0f, 0x00, //64 bit counter
- 0x00, 0x56, 0x34, 0x12,
- 0x78, 0x56, 0x34, 0x12, 0x00, 0x00 // seq
- };
-
- pkt_size = 14;
- switch(ip_ver) {
+ switch (ip_ver) {
case 4:
- pkt_size += sizeof(ip_header);
+ l3_type = EthernetHeader::Protocol::IP;
break;
case 6:
- pkt_size += sizeof(ipv6_header);
- if (flags & DPF_RXCHECK) {
- pkt_size += sizeof(struct CRx_check_header);
- }
- break;
- default:
- printf("Internal error. Wrong ip_ver\n");
- exit(-1);
- }
-
- switch (l4_proto) {
- case IPPROTO_ICMP:
- pkt_size += sizeof(icmp_header) + sizeof (icmp_data);
- break;
- case IPPROTO_UDP:
- pkt_size += sizeof(udp_header) + sizeof (udp_data);
- break;
- case IPPROTO_TCP:
- pkt_size += sizeof(tcp_header) + sizeof (tcp_data);
+ l3_type = EthernetHeader::Protocol::IPv6;
break;
default:
return NULL;
+ break;
}
- rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(0, pkt_size);
+ pkt = gen.create_test_pkt(l3_type, l4_proto, ttl, ip_id, flags, 1000, pkt_size);
+ m = CGlobalInfo::pktmbuf_alloc(0, pkt_size);
if ( unlikely(m == 0) ) {
printf("ERROR no packets \n");
return (NULL);
}
- char *p = rte_pktmbuf_append(m, pkt_size);
- assert(p);
-
- /* set pkt data */
- memcpy(p, dst_mac, sizeof(dst_mac)); p += sizeof(dst_mac);
- memcpy(p, src_mac, sizeof(src_mac)); p += sizeof(src_mac);
- memcpy(p, &l2_proto, sizeof(l2_proto)); p += sizeof(l2_proto);
-
- if (flags & DPF_VLAN) {
- if (flags & DPF_QINQ) {
- memcpy(p, &vlan_header2, sizeof(vlan_header2)); p += sizeof(vlan_header2);
- }
- if (ip_ver == 4) {
- vlan_header[2] = 0x08;
- vlan_header[3] = 0x00;
- } else {
- vlan_header[2] = 0x86;
- vlan_header[3] = 0xdd;
- }
- memcpy(p, &vlan_header, sizeof(vlan_header)); p += sizeof(vlan_header);
- }
-
- struct IPHeader *ip = (IPHeader *)p;
- struct IPv6Header *ipv6 = (IPv6Header *)p;
- if (ip_ver == 4) {
- memcpy(p, ip_header, sizeof(ip_header)); p += sizeof(ip_header);
- ip->setProtocol(l4_proto);
- ip->setTotalLength(pkt_size - 14);
- ip->setId(ip_id);
- } else {
- memcpy(p, ipv6_header, sizeof(ipv6_header)); p += sizeof(ipv6_header);
- if (flags & DPF_RXCHECK) {
- // rx check header
- ipv6->setNextHdr(RX_CHECK_V6_OPT_TYPE);
- if (flags & DPF_RXCHECK) {
- struct CRx_check_header *rxch = (struct CRx_check_header *)p;
- p += sizeof(CRx_check_header);
- rxch->m_option_type = l4_proto;
- rxch->m_option_len = RX_CHECK_V6_OPT_LEN;
- }
- } else {
- ipv6->setNextHdr(l4_proto);
- }
- ipv6->setPayloadLen(pkt_size - 14 - sizeof(ipv6_header));
- ipv6->setFlowLabel(ip_id);
- }
-
- struct TCPHeader *tcp = (TCPHeader *)p;
- struct ICMPHeader *icmp= (ICMPHeader *)p;
- switch (l4_proto) {
- case IPPROTO_ICMP:
- memcpy(p, icmp_header, sizeof(icmp_header)); p += sizeof(icmp_header);
- memcpy(p, icmp_data, sizeof(icmp_data)); p += sizeof(icmp_data);
- icmp->updateCheckSum(sizeof(icmp_header) + sizeof(icmp_data));
- break;
- case IPPROTO_UDP:
- memcpy(p, udp_header, sizeof(udp_header)); p += sizeof(udp_header);
- memcpy(p, udp_data, sizeof(udp_data)); p += sizeof(udp_data);
- break;
- case IPPROTO_TCP:
- memcpy(p, tcp_header, sizeof(tcp_header)); p += sizeof(tcp_header);
- memcpy(p, tcp_data, sizeof(tcp_data)); p += sizeof(tcp_data);
- tcp->setSynFlag(false);
- // printf("Sending TCP header:");
- //tcp->dump(stdout);
- break;
- default:
- return NULL;
- }
+ p = rte_pktmbuf_append(m, pkt_size);
+ memcpy(p, pkt, pkt_size);
+ free(pkt);
- if (ip_ver == 4) {
- ip->setTimeToLive(ttl);
- ip->updateCheckSum();
- } else {
- ipv6->setHopLimit(ttl);
- }
return m;
}
+
#endif
rte_mbuf_t *CTrexDebug::create_pkt(uint8_t *pkt, int pkt_size) {
diff --git a/src/flow_stat_parser.cpp b/src/flow_stat_parser.cpp
index deae7062..29d79b9b 100644
--- a/src/flow_stat_parser.cpp
+++ b/src/flow_stat_parser.cpp
@@ -25,6 +25,7 @@
#include "common/Network/Packet/IPHeader.h"
#include "common/Network/Packet/IPv6Header.h"
#include "common/Network/Packet/TcpHeader.h"
+#include "test_pkt_gen.h"
#include "flow_stat_parser.h"
void CFlowStatParser::reset() {
@@ -38,7 +39,7 @@ void CFlowStatParser::reset() {
int CFlowStatParser::parse(uint8_t *p, uint16_t len) {
EthernetHeader *ether = (EthernetHeader *)p;
- int min_len = ETH_HDR_LEN + IPV4_HDR_LEN;
+ int min_len = ETH_HDR_LEN;
reset();
if (len < min_len)
@@ -46,12 +47,18 @@ int CFlowStatParser::parse(uint8_t *p, uint16_t len) {
switch( ether->getNextProtocol() ) {
case EthernetHeader::Protocol::IP :
+ min_len += IPV4_HDR_LEN;
+ if (len < min_len)
+ return -1;
m_ipv4 = (IPHeader *)(p + ETH_HDR_LEN);
m_l4 = ((uint8_t *)m_ipv4) + m_ipv4->getHeaderLength();
m_l4_proto = m_ipv4->getProtocol();
m_stat_supported = true;
break;
case EthernetHeader::Protocol::IPv6 :
+ min_len += IPV6_HDR_LEN;
+ if (len < min_len)
+ return -1;
m_ipv6 = (IPv6Header *)(p + ETH_HDR_LEN);
m_l4 = ((uint8_t *)m_ipv6) + m_ipv6->getHeaderLength();
m_l4_proto = m_ipv6->getNextHdr();
@@ -64,12 +71,18 @@ int CFlowStatParser::parse(uint8_t *p, uint16_t len) {
return -1;
switch ( ether->getVlanProtocol() ){
case EthernetHeader::Protocol::IP:
+ min_len += IPV4_HDR_LEN;
+ if (len < min_len)
+ return -1;
m_ipv4 = (IPHeader *)(p + ETH_HDR_LEN + 4);
m_l4 = ((uint8_t *)m_ipv4) + m_ipv4->getHeaderLength();
m_l4_proto = m_ipv4->getProtocol();
m_stat_supported = true;
break;
case EthernetHeader::Protocol::IPv6 :
+ min_len += IPV6_HDR_LEN;
+ if (len < min_len)
+ return -1;
m_ipv6 = (IPv6Header *)(p + ETH_HDR_LEN + 4);
m_l4 = ((uint8_t *)m_ipv6) + m_ipv6->getHeaderLength();
m_l4_proto = m_ipv6->getNextHdr();
@@ -169,7 +182,7 @@ uint8_t CFlowStatParser::get_ttl(){
}
// calculate the payload len. Do not want to do this in parse(), since this is required only in
-// specific cases, while parse is used in many places (including on packet RX path, where we want to bo as fast as possible)
+// specific cases, while parse is used in many places (including on packet RX path, where we want to be as fast as possible)
int CFlowStatParser::get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload_len) {
uint16_t l2_header_len;
uint16_t l3_header_len;
@@ -189,6 +202,7 @@ int CFlowStatParser::get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload
l4_proto = m_ipv4->getProtocol();
p_l3 = (uint8_t *)m_ipv4;
} else if (m_ipv6) {
+ //??? fix payload calc in this case
l2_header_len = ((uint8_t *)m_ipv6) - p;
l3_header_len = IPV6_HDR_LEN;
l4_proto = m_ipv6->getNextHdr();
@@ -227,78 +241,129 @@ int CFlowStatParser::get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload
}
static const uint16_t TEST_IP_ID = 0xabcd;
+static const uint16_t TEST_IP_ID2 = 0xabcd;
static const uint8_t TEST_L4_PROTO = IPPROTO_UDP;
-int CFlowStatParser::test() {
- uint32_t ip_id = 0;
- uint8_t l4_proto;
- uint8_t test_pkt[] = {
- // ether header
- 0x74, 0xa2, 0xe6, 0xd5, 0x39, 0x25,
- 0xa0, 0x36, 0x9f, 0x38, 0xa4, 0x02,
- 0x81, 0x00,
- 0x0a, 0xbc, 0x08, 0x00, // vlan
- // IP header
- 0x45,0x02,0x00,0x30,
- 0x01,0x02,0x40,0x00,
- 0xff, TEST_L4_PROTO, 0xbd,0x04,
- 0x10,0x0,0x0,0x1,
- 0x30,0x0,0x0,0x1,
- // TCP heaader
- 0xab, 0xcd, 0x00, 0x80, // src, dst ports
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // seq num, ack num
- 0x50, 0x00, 0xff, 0xff, // Header size, flags, window size
- 0x00, 0x00, 0x00, 0x00, // checksum ,urgent pointer
- // some extra bytes
- 0x1, 0x2, 0x3, 0x4
- };
-
- // good packet
- assert (parse(test_pkt, sizeof(test_pkt)) == 0);
- m_ipv4->updateCheckSum();
- assert(m_ipv4->isChecksumOK() == true);
- set_ip_id(TEST_IP_ID);
- // utl_DumpBuffer(stdout, test_pkt, sizeof(test_pkt), 0);
- get_ip_id(ip_id);
- assert(ip_id == TEST_IP_ID);
- assert(m_ipv4->isChecksumOK() == true);
- assert(get_l4_proto(l4_proto) == 0);
- assert(l4_proto == TEST_L4_PROTO);
- assert(m_stat_supported == true);
-
- // payload len test
- uint16_t payload_len;
+
+int CFlowStatParserTest::verify_pkt_one_parser(uint8_t * p, uint16_t pkt_size, uint16_t payload_len, uint32_t ip_id
+ , uint8_t l4_proto, CFlowStatParser &parser, bool sup_pkt) {
int ret;
- ret = get_payload_len(test_pkt, sizeof(test_pkt), payload_len);
- // UDP packet.
- assert(ret == 0);
- assert(payload_len == 16);
- reset();
- // ICMP packet
- test_pkt[27] = IPPROTO_ICMP;
- assert (parse(test_pkt, sizeof(test_pkt)) == 0);
- ret = get_payload_len(test_pkt, sizeof(test_pkt), payload_len);
- assert(ret == 0);
- assert(payload_len == 16);
- // TCP packet
- test_pkt[27] = IPPROTO_TCP;
- assert (parse(test_pkt, sizeof(test_pkt)) == 0);
- ret = get_payload_len(test_pkt, sizeof(test_pkt), payload_len);
- assert(ret == 0);
- assert(payload_len == 4);
- // Other protocol
- test_pkt[27] = 0xaa;
- assert (parse(test_pkt, sizeof(test_pkt)) == 0);
- ret = get_payload_len(test_pkt, sizeof(test_pkt), payload_len);
- assert(ret == 0);
- assert(payload_len == 24);
+ uint32_t pkt_ip_id = 0;
+ uint8_t pkt_l4_proto;
+ uint16_t pkt_payload_len;
+
+ ret = parser.parse(p, pkt_size);
+ if (sup_pkt) {
+ assert (ret == 0);
+ parser.get_ip_id(pkt_ip_id);
+ assert(pkt_ip_id == ip_id);
+ parser.set_ip_id(TEST_IP_ID2);
+ // utl_DumpBuffer(stdout, test_pkt, sizeof(test_pkt), 0);
+ parser.get_ip_id(ip_id);
+ assert(ip_id == TEST_IP_ID2);
+ if (parser.m_ipv4)
+ assert(parser.m_ipv4->isChecksumOK() == true);
+ assert(parser.get_l4_proto(pkt_l4_proto) == 0);
+ assert(pkt_l4_proto == l4_proto);
+ assert(parser.m_stat_supported == true);
+ ret = parser.get_payload_len(p, pkt_size, pkt_payload_len);
+ assert(ret == 0);
+ assert(pkt_payload_len == payload_len);
+ } else {
+ assert(ret != 0);
+ assert(parser.m_stat_supported == false);
+ }
- reset();
+ return 0;
+}
+
+int CFlowStatParserTest::verify_pkt(uint8_t *p, uint16_t pkt_size, uint16_t payload_len, uint32_t ip_id, uint8_t l4_proto
+ , uint16_t flags) {
+ int ret, ret_val;
+ CFlowStatParser parser;
+ C82599Parser parser82599(false);
+ C82599Parser parser82599_vlan(true);
+
+ printf (" ");
+ if ((flags & P_OK) || (flags & P_BAD)) {
+ printf("general parser");
+ ret = verify_pkt_one_parser(p, pkt_size, payload_len, ip_id, l4_proto, parser, flags & P_OK);
+ ret_val = ret;
+ if (ret == 0)
+ printf("-OK");
+ else {
+ printf("-BAD");
+ }
+ }
+ if ((flags & P82599_OK) || (flags & P82599_BAD)) {
+ printf(", 82599 parser");
+ ret = verify_pkt_one_parser(p, pkt_size, payload_len, ip_id, l4_proto, parser82599, flags & P82599_OK);
+ ret_val |= ret;
+ if (ret == 0)
+ printf("-OK");
+ else {
+ printf("-BAD");
+ }
+ }
+ if ((flags & P82599_VLAN_OK) || (flags & P82599_VLAN_BAD)) {
+ printf(", 82599 vlan parser");
+ ret = verify_pkt_one_parser(p, pkt_size, payload_len, ip_id, l4_proto, parser82599_vlan, flags & P82599_VLAN_OK);
+ ret_val |= ret;
+ if (ret == 0)
+ printf("-OK");
+ else {
+ printf("-BAD");
+ }
+ }
+ printf("\n");
+
+ return 0;
+}
+
+int CFlowStatParserTest::test_one_pkt(const char *name, uint16_t ether_type, uint8_t l4_proto, bool is_vlan
+ , uint16_t verify_flags) {
+ CTestPktGen gen;
+ uint8_t *p;
+ int pkt_size;
+ uint16_t payload_len = 16;
+ uint16_t pkt_flags;
+ int ret = 0;
+
+ printf("%s - ", name);
+
+ if (is_vlan) {
+ pkt_flags = DPF_VLAN;
+ } else {
+ pkt_flags = 0;
+ }
+
+ p = (uint8_t *)gen.create_test_pkt(ether_type, l4_proto, 255, TEST_IP_ID, pkt_flags, payload_len, pkt_size);
+ ret = verify_pkt(p, pkt_size, payload_len, TEST_IP_ID, l4_proto, verify_flags);
+ free(p);
+
+ return ret;
+}
- // bad packet. change eth protocol
- test_pkt[16] = 0xaa;
- assert (parse(test_pkt, sizeof(test_pkt)) == -1);
- assert(m_stat_supported == false);
+int CFlowStatParserTest::test() {
+ bool vlan = true;
+ uint8_t tcp = IPPROTO_TCP, udp = IPPROTO_UDP, icmp = IPPROTO_ICMP;
+ uint16_t ipv4 = EthernetHeader::Protocol::IP, ipv6 = EthernetHeader::Protocol::IPv6;
+
+ test_one_pkt("IPv4 TCP", ipv4, tcp, !vlan, P_OK | P82599_OK | P82599_VLAN_BAD);
+ test_one_pkt("IPv4 TCP VLAN", ipv4, tcp, vlan, P_OK | P82599_BAD | P82599_VLAN_OK);
+ test_one_pkt("IPv4 UDP", ipv4, udp, !vlan, P_OK | P82599_OK | P82599_VLAN_BAD);
+ test_one_pkt("IPv4 UDP VLAN", ipv4, udp, vlan, P_OK | P82599_BAD | P82599_VLAN_OK);
+ test_one_pkt("IPv4 ICMP", ipv4, icmp, !vlan, P_OK | P82599_OK | P82599_VLAN_BAD);
+ test_one_pkt("IPv4 ICMP VLAN", ipv4, icmp, vlan, P_OK | P82599_BAD | P82599_VLAN_OK);
+ test_one_pkt("IPv6 TCP", ipv6, tcp, !vlan, P_OK | P82599_BAD | P82599_VLAN_BAD);
+ test_one_pkt("IPv6 TCP VLAN", ipv6, tcp, vlan, P_OK | P82599_BAD | P82599_VLAN_BAD);
+ test_one_pkt("IPv6 UDP", ipv6, udp, !vlan, P_OK | P82599_BAD | P82599_VLAN_BAD);
+ test_one_pkt("IPv6 UDP VLAN", ipv6, udp, vlan, P_OK | P82599_BAD | P82599_VLAN_BAD);
+ test_one_pkt("IPv6 ICMP", ipv6, icmp, !vlan, P_OK | P82599_BAD | P82599_VLAN_BAD);
+ test_one_pkt("IPv6 ICMP VLAN", ipv6, icmp, vlan, P_OK | P82599_BAD | P82599_VLAN_BAD);
+ test_one_pkt("IPv4 IGMP", ipv4, IPPROTO_IGMP, !vlan, P_OK | P82599_OK | P82599_VLAN_BAD);
+ test_one_pkt("BAD l3 type", 0xaa, icmp, !vlan, P_BAD | P82599_BAD | P82599_VLAN_BAD);
+ test_one_pkt("VLAN + BAD l3 type", 0xaa, icmp, vlan, P_BAD | P82599_BAD | P82599_VLAN_BAD);
return 0;
}
diff --git a/src/flow_stat_parser.h b/src/flow_stat_parser.h
index 8ec5a229..3f729903 100644
--- a/src/flow_stat_parser.h
+++ b/src/flow_stat_parser.h
@@ -30,6 +30,7 @@
// Basic flow stat parser. Relevant for xl710/x710/x350 cards
class CFlowStatParser {
+ friend class CFlowStatParserTest;
public:
virtual ~CFlowStatParser() {}
virtual void reset();
@@ -42,7 +43,6 @@ class CFlowStatParser {
virtual int get_payload_len(uint8_t *p, uint16_t len, uint16_t &payload_len);
virtual uint16_t get_pkt_size();
virtual uint8_t get_ttl();
- virtual int test();
uint8_t *get_l3() {
if (m_ipv4)
return (uint8_t *)m_ipv4;
@@ -72,6 +72,10 @@ class CFlowStatParser {
return true;
}
+ private:
+ char *create_test_pkt(int ip_ver, uint16_t l4_proto, uint8_t ttl
+ , uint32_t ip_id, uint16_t flags, int &pkt_size);
+
protected:
IPHeader *m_ipv4;
IPv6Header *m_ipv6;
@@ -132,7 +136,27 @@ class CSimplePacketParser {
uint16_t m_vlan_offset;
uint8_t * m_l4;
private:
- rte_mbuf_t * m_m ;
+ rte_mbuf_t * m_m;
+};
+
+class CFlowStatParserTest {
+ enum {
+ P_OK = 0x1,
+ P_BAD = 0x2,
+ P82599_OK = 0x4,
+ P82599_BAD = 0x8,
+ P82599_VLAN_OK = 0x10,
+ P82599_VLAN_BAD = 0x20,
+ };
+
+ public:
+ int test();
+
+ private:
+ int test_one_pkt(const char *name, uint16_t ether_type, uint8_t l4_proto, bool is_vlan, uint16_t verify_flags);
+ int verify_pkt(uint8_t *p, uint16_t pkt_size, uint16_t payload_len, uint32_t ip_id, uint8_t l4_proto, uint16_t flags);
+ int verify_pkt_one_parser(uint8_t * p, uint16_t pkt_size, uint16_t payload_len, uint32_t ip_id, uint8_t l4_proto
+ , CFlowStatParser &parser, bool sup_pkt);
};
#endif
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp
index 35254713..376d2454 100644
--- a/src/gtest/trex_stateless_gtest.cpp
+++ b/src/gtest/trex_stateless_gtest.cpp
@@ -3719,8 +3719,8 @@ class flow_stat_pkt_parse : public testing::Test {
};
-TEST_F(flow_stat_pkt_parse, x710_parser) {
- CFlowStatParser parser;
+TEST_F(flow_stat_pkt_parse, parser) {
+ CFlowStatParserTest parser;
parser.test();
}
diff --git a/src/test_pkt_gen.cpp b/src/test_pkt_gen.cpp
new file mode 100644
index 00000000..b16eca37
--- /dev/null
+++ b/src/test_pkt_gen.cpp
@@ -0,0 +1,232 @@
+/*
+ Ido Barnea
+ Cisco Systems, Inc.
+*/
+
+/*
+ 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 <assert.h>
+#include <netinet/in.h>
+#include <common/Network/Packet/TcpHeader.h>
+#include <common/Network/Packet/UdpHeader.h>
+#include <common/Network/Packet/IcmpHeader.h>
+#include <common/Network/Packet/IPHeader.h>
+#include <common/Network/Packet/IPv6Header.h>
+#include <common/Network/Packet/EthernetHeader.h>
+#include "rx_check_header.h"
+#include "test_pkt_gen.h"
+
+// For use in tests
+char *CTestPktGen::create_test_pkt(uint16_t l3_type, uint16_t l4_proto, uint8_t ttl, uint32_t ip_id, uint16_t flags
+ , uint16_t max_payload, int &pkt_size) {
+ // ASA 2
+ uint8_t dst_mac[6] = {0x74, 0xa2, 0xe6, 0xd5, 0x39, 0x25};
+ uint8_t src_mac[6] = {0xa0, 0x36, 0x9f, 0x38, 0xa4, 0x02};
+ uint8_t vlan_header[4] = {0x0a, 0xbc, 0x00, 0x00}; // we set the type below according to if pkt is ipv4 or 6
+ uint8_t vlan_header2[4] = {0x0a, 0xbc, 0x88, 0xa8};
+ uint16_t l2_proto;
+ uint16_t payload_len;
+
+ // ASA 1
+ // uint8_t dst_mac[6] = {0xd4, 0x8c, 0xb5, 0xc9, 0x54, 0x2b};
+ // uint8_t src_mac[6] = {0xa0, 0x36, 0x9f, 0x38, 0xa4, 0x0};
+ if (flags & DPF_VLAN) {
+ l2_proto = 0x0081;
+ } else {
+ l2_proto = htons(l3_type);
+ }
+
+ uint8_t ip_header[] = {
+ 0x45,0x02,0x00,0x30,
+ 0x00,0x00,0x40,0x00,
+ 0xff,0x01,0xbd,0x04,
+ 0x10,0x0,0x0,0x1, //SIP
+ 0x30,0x0,0x0,0x1, //DIP
+ // 0x82, 0x0b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // IP option. change 45 to 48 (header len) if using it.
+ };
+ uint8_t ipv6_header[] = {
+ 0x60,0x00,0xff,0x30, // traffic class + flow label
+ 0x00,0x00,0x40,0x00, // payload len + next header + hop limit
+ 0x10,0x0,0x0,0x1,0x10,0x0,0x0,0x1,0x10,0x0,0x0,0x1,0x10,0x0,0x0,0x1, //SIP
+ 0x30,0x0,0x0,0x1,0x10,0x0,0x0,0x1,0x30,0x0,0x0,0x1,0x10,0x0,0x0,0x1, //DIP
+ };
+ uint8_t udp_header[] = {0x11, 0x11, 0x11,0x11, 0x00, 0x6d, 0x00, 0x00};
+ uint8_t udp_data[] = {0x64,0x31,0x3a,0x61,
+ 0x64,0x32,0x3a,0x69,0x64,
+ 0x32,0x30,0x3a,0xd0,0x0e,
+ 0xa1,0x4b,0x7b,0xbd,0xbd,
+ 0x16,0xc6,0xdb,0xc4,0xbb,0x43,
+ 0xf9,0x4b,0x51,0x68,0x33,0x72,
+ 0x20,0x39,0x3a,0x69,0x6e,0x66,0x6f,
+ 0x5f,0x68,0x61,0x73,0x68,0x32,0x30,0x3a,0xee,0xc6,0xa3,
+ 0xd3,0x13,0xa8,0x43,0x06,0x03,0xd8,0x9e,0x3f,0x67,0x6f,
+ 0xe7,0x0a,0xfd,0x18,0x13,0x8d,0x65,0x31,0x3a,0x71,0x39,
+ 0x3a,0x67,0x65,0x74,0x5f,0x70,0x65,0x65,0x72,0x73,0x31,
+ 0x3a,0x74,0x38,0x3a,0x3d,0xeb,0x0c,0xbf,0x0d,0x6a,0x0d,
+ 0xa5,0x31,0x3a,0x79,0x31,0x3a,0x71,0x65,0x87,0xa6,0x7d,
+ 0xe7
+ };
+
+ uint8_t tcp_header[] = {0xab, 0xcd, 0x00, 0x80, // src, dst ports
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // seq num, ack num
+ 0x50, 0x00, 0xff, 0xff, // Header size, flags, window size
+ 0x00, 0x00, 0x00, 0x00, // checksum ,urgent pointer
+ };
+
+ uint8_t tcp_data[] = {0x8, 0xa, 0x1, 0x2, 0x3, 0x4, 0x3, 0x4, 0x6, 0x5,
+ 0x8, 0xa, 0x1, 0x2, 0x3, 0x4, 0x3, 0x4, 0x6, 0x5};
+
+ uint8_t icmp_header[] = {
+ 0x08, 0x00,
+ 0xb8, 0x21, //checksum
+ 0xaa, 0xbb, // id
+ 0x00, 0x01, // Sequence number
+ };
+ uint8_t icmp_data[] = {
+ 0xd6, 0x6e, 0x64, 0x34, // magic
+ 0x6a, 0xad, 0x0f, 0x00, //64 bit counter
+ 0x00, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12, 0x00, 0x00 // seq
+ };
+
+ pkt_size = 14;
+
+ if (flags & DPF_VLAN) {
+ pkt_size += 4;
+ if (flags & DPF_QINQ) {
+ pkt_size += 4;
+ }
+ }
+
+ switch(l3_type) {
+ case EthernetHeader::Protocol::IP:
+ pkt_size += sizeof(ip_header);
+ break;
+ case EthernetHeader::Protocol::IPv6:
+ pkt_size += sizeof(ipv6_header);
+ if (flags & DPF_RXCHECK) {
+ pkt_size += sizeof(struct CRx_check_header);
+ }
+ break;
+ }
+
+ switch (l4_proto) {
+ case IPPROTO_ICMP:
+ pkt_size += sizeof(icmp_header);
+ payload_len = (max_payload < sizeof(icmp_data)) ? max_payload:sizeof(icmp_data);
+ pkt_size += payload_len;
+ break;
+ case IPPROTO_UDP:
+ pkt_size += sizeof(udp_header);
+ payload_len = (max_payload < sizeof(udp_data)) ? max_payload:sizeof(udp_data);
+ pkt_size += payload_len;
+ break;
+ case IPPROTO_TCP:
+ pkt_size += sizeof(tcp_header);
+ payload_len = (max_payload < sizeof(tcp_data)) ? max_payload:sizeof(tcp_data);
+ pkt_size += payload_len;
+ break;
+ default:
+ payload_len = (max_payload < sizeof(udp_data)) ? max_payload:sizeof(udp_data);
+ pkt_size += payload_len;
+ break;
+ }
+
+ char *p_start = (char *)malloc(pkt_size);
+ assert(p_start);
+ char *p = p_start;
+
+ /* set pkt data */
+ memcpy(p, dst_mac, sizeof(dst_mac)); p += sizeof(dst_mac);
+ memcpy(p, src_mac, sizeof(src_mac)); p += sizeof(src_mac);
+ memcpy(p, &l2_proto, sizeof(l2_proto)); p += sizeof(l2_proto);
+
+ if (flags & DPF_VLAN) {
+ if (flags & DPF_QINQ) {
+ memcpy(p, &vlan_header2, sizeof(vlan_header2)); p += sizeof(vlan_header2);
+ }
+
+ uint16_t l3_type_htons = htons(l3_type);
+ memcpy(&vlan_header[2], &l3_type_htons, sizeof(l3_type));
+ memcpy(p, &vlan_header, sizeof(vlan_header)); p += sizeof(vlan_header);
+ }
+
+ struct IPHeader *ip = (IPHeader *)p;
+ struct IPv6Header *ipv6 = (IPv6Header *)p;
+ switch(l3_type) {
+ case EthernetHeader::Protocol::IP:
+ memcpy(p, ip_header, sizeof(ip_header)); p += sizeof(ip_header);
+ ip->setProtocol(l4_proto);
+ ip->setTotalLength(pkt_size - 14);
+ ip->setId(ip_id);
+ break;
+ case EthernetHeader::Protocol::IPv6:
+ memcpy(p, ipv6_header, sizeof(ipv6_header)); p += sizeof(ipv6_header);
+ if (flags & DPF_RXCHECK) {
+ // rx check header
+ ipv6->setNextHdr(RX_CHECK_V6_OPT_TYPE);
+ if (flags & DPF_RXCHECK) {
+ struct CRx_check_header *rxch = (struct CRx_check_header *)p;
+ p += sizeof(CRx_check_header);
+ rxch->m_option_type = l4_proto;
+ rxch->m_option_len = RX_CHECK_V6_OPT_LEN;
+ }
+ } else {
+ ipv6->setNextHdr(l4_proto);
+ }
+ ipv6->setPayloadLen(pkt_size - 14 - sizeof(ipv6_header));
+ ipv6->setFlowLabel(ip_id);
+ break;
+ }
+
+
+ struct TCPHeader *tcp = (TCPHeader *)p;
+ struct ICMPHeader *icmp= (ICMPHeader *)p;
+ switch (l4_proto) {
+ case IPPROTO_ICMP:
+ memcpy(p, icmp_header, sizeof(icmp_header)); p += sizeof(icmp_header);
+ memcpy(p, icmp_data, payload_len); p += payload_len;
+ icmp->updateCheckSum(sizeof(icmp_header) + sizeof(icmp_data));
+ break;
+ case IPPROTO_UDP:
+ memcpy(p, udp_header, sizeof(udp_header)); p += sizeof(udp_header);
+ memcpy(p, udp_data, payload_len); p += payload_len;
+ break;
+ case IPPROTO_TCP:
+ memcpy(p, tcp_header, sizeof(tcp_header)); p += sizeof(tcp_header);
+ memcpy(p, tcp_data, payload_len); p += payload_len;
+ tcp->setSynFlag(false);
+ // printf("Sending TCP header:");
+ //tcp->dump(stdout);
+ break;
+ default:
+ memcpy(p, udp_data, payload_len); p += payload_len;
+ break;
+ }
+
+ switch(l3_type) {
+ case EthernetHeader::Protocol::IP:
+ ip->setTimeToLive(ttl);
+ ip->updateCheckSum();
+ break;
+ case EthernetHeader::Protocol::IPv6:
+ ipv6->setHopLimit(ttl);
+ break;
+ }
+
+ return p_start;
+}
diff --git a/src/test_pkt_gen.h b/src/test_pkt_gen.h
new file mode 100644
index 00000000..f4ac3a83
--- /dev/null
+++ b/src/test_pkt_gen.h
@@ -0,0 +1,46 @@
+/*
+ Ido Barnea
+ Cisco Systems, Inc.
+*/
+
+/*
+ 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 __TEST_PKT_GEN_H__
+#define __TEST_PKT_GEN_H__
+
+enum {
+ D_PKT_TYPE_ICMP = 1,
+ D_PKT_TYPE_UDP = 2,
+ D_PKT_TYPE_TCP = 3,
+ D_PKT_TYPE_9k_UDP = 4,
+ D_PKT_TYPE_IPV6 = 60,
+ D_PKT_TYPE_HW_VERIFY = 100,
+};
+
+enum {
+ DPF_VLAN = 0x1,
+ DPF_QINQ = 0X2,
+ DPF_RXCHECK = 0x4
+};
+
+class CTestPktGen {
+ public:
+ char *create_test_pkt(uint16_t l3_type, uint16_t l4_proto, uint8_t ttl, uint32_t ip_id, uint16_t flags
+ , uint16_t max_payload, int &pkt_size);
+};
+
+#endif