[dpdk-dev] performance-thread: add software packet type parsing

Message ID 1481901316-48216-1-git-send-email-tomaszx.kulasek@intel.com (mailing list archive)
State Accepted, archived
Delegated to: Thomas Monjalon
Headers

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel compilation success Compilation OK

Commit Message

Tomasz Kulasek Dec. 16, 2016, 3:15 p.m. UTC
  Last changes in Niantic and Fortville NIC drivers causes that
vector Rx path is chosen by default in l3fwd-thread application.
This path doesn't support propagation of hw packet type recognition
to the packet_type field in mbuf, and packets cannot be classified
properly.

The approach to solve this problem is similar to the commit: 71a7e2424e07
("examples/l3fwd: fix using packet type blindly").

To use sw packet analizer, new command line option "--parse-ptype" is
introduced.

Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 doc/guides/sample_app_ug/performance_thread.rst |    4 +
 examples/performance-thread/l3fwd-thread/main.c |  100 ++++++++++++++++++++++-
 2 files changed, 101 insertions(+), 3 deletions(-)
  

Comments

Thomas Monjalon Jan. 17, 2017, 5:39 p.m. UTC | #1
2016-12-16 16:15, Tomasz Kulasek:
> Last changes in Niantic and Fortville NIC drivers causes that
> vector Rx path is chosen by default in l3fwd-thread application.
> This path doesn't support propagation of hw packet type recognition
> to the packet_type field in mbuf, and packets cannot be classified
> properly.
> 
> The approach to solve this problem is similar to the commit: 71a7e2424e07
> ("examples/l3fwd: fix using packet type blindly").
> 
> To use sw packet analizer, new command line option "--parse-ptype" is
> introduced.
> 
> Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>

Applied, thanks
  

Patch

diff --git a/doc/guides/sample_app_ug/performance_thread.rst b/doc/guides/sample_app_ug/performance_thread.rst
index d7d9b08..0a655af 100644
--- a/doc/guides/sample_app_ug/performance_thread.rst
+++ b/doc/guides/sample_app_ug/performance_thread.rst
@@ -107,6 +107,7 @@  The application has a number of command line options::
         --tx(lcore,thread)[,(lcore,thread)]
         [--enable-jumbo] [--max-pkt-len PKTLEN]]  [--no-numa]
         [--hash-entry-num] [--ipv6] [--no-lthreads] [--stat-lcore lcore]
+        [--parse-ptype]
 
 Where:
 
@@ -142,6 +143,9 @@  Where:
 * ``--stat-lcore``: optional, run CPU load stats collector on the specified
   lcore.
 
+* ``--parse-ptype:`` optional, set to use software to analyze packet type.
+  Without this option, hardware will check the packet type.
+
 The parameters of the ``--rx`` and ``--tx`` options are:
 
 * ``--rx`` parameters
diff --git a/examples/performance-thread/l3fwd-thread/main.c b/examples/performance-thread/l3fwd-thread/main.c
index fdc90b2..336f88c 100644
--- a/examples/performance-thread/l3fwd-thread/main.c
+++ b/examples/performance-thread/l3fwd-thread/main.c
@@ -1,7 +1,7 @@ 
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -90,6 +90,64 @@ 
 #define APP_LOOKUP_METHOD             APP_LOOKUP_LPM
 #endif
 
+static int
+check_ptype(int portid)
+{
+	int i, ret;
+	int ipv4 = 0, ipv6 = 0;
+
+	ret = rte_eth_dev_get_supported_ptypes(portid, RTE_PTYPE_L3_MASK, NULL,
+			0);
+	if (ret <= 0)
+		return 0;
+
+	uint32_t ptypes[ret];
+
+	ret = rte_eth_dev_get_supported_ptypes(portid, RTE_PTYPE_L3_MASK,
+			ptypes, ret);
+	for (i = 0; i < ret; ++i) {
+		if (ptypes[i] & RTE_PTYPE_L3_IPV4)
+			ipv4 = 1;
+		if (ptypes[i] & RTE_PTYPE_L3_IPV6)
+			ipv6 = 1;
+	}
+
+	if (ipv4 && ipv6)
+		return 1;
+
+	return 0;
+}
+
+static inline void
+parse_ptype(struct rte_mbuf *m)
+{
+	struct ether_hdr *eth_hdr;
+	uint32_t packet_type = RTE_PTYPE_UNKNOWN;
+	uint16_t ether_type;
+
+	eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+	ether_type = eth_hdr->ether_type;
+	if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4))
+		packet_type |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
+	else if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv6))
+		packet_type |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
+
+	m->packet_type = packet_type;
+}
+
+static uint16_t
+cb_parse_ptype(__rte_unused uint8_t port, __rte_unused uint16_t queue,
+		struct rte_mbuf *pkts[], uint16_t nb_pkts,
+		__rte_unused uint16_t max_pkts, __rte_unused void *user_param)
+{
+	unsigned int i;
+
+	for (i = 0; i < nb_pkts; i++)
+		parse_ptype(pkts[i]);
+
+	return nb_pkts;
+}
+
 /*
  *  When set to zero, simple forwaring path is eanbled.
  *  When set to one, optimized forwarding path is enabled.
@@ -170,8 +228,9 @@ 
 
 /* mask of enabled ports */
 static uint32_t enabled_port_mask;
-static int promiscuous_on; /**< $et in promiscuous mode off by default. */
+static int promiscuous_on; /**< Set in promiscuous mode off by default. */
 static int numa_on = 1;    /**< NUMA is enabled by default. */
+static int parse_ptype_on;
 
 #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
 static int ipv6;           /**< ipv6 is false by default. */
@@ -2610,6 +2669,7 @@  static inline __attribute__((always_inline)) uint16_t
 		"  [--rx (port,queue,lcore,thread)[,(port,queue,lcore,thread]]"
 		"  [--tx (lcore,thread)[,(lcore,thread]]"
 		"  [--enable-jumbo [--max-pkt-len PKTLEN]]\n"
+		"  [--parse-ptype]\n\n"
 		"  -p PORTMASK: hexadecimal bitmask of ports to configure\n"
 		"  -P : enable promiscuous mode\n"
 		"  --rx (port,queue,lcore,thread): rx queues configuration\n"
@@ -2621,7 +2681,8 @@  static inline __attribute__((always_inline)) uint16_t
 		"  --enable-jumbo: enable jumbo frame"
 		" which max packet len is PKTLEN in decimal (64-9600)\n"
 		"  --hash-entry-num: specify the hash entry number in hexadecimal to be setup\n"
-		"  --no-lthreads: turn off lthread model\n",
+		"  --no-lthreads: turn off lthread model\n"
+		"  --parse-ptype: set to use software to analyze packet type\n\n",
 		prgname);
 }
 
@@ -2840,6 +2901,7 @@  static int parse_max_pkt_len(const char *pktlen)
 #define CMD_LINE_OPT_ENABLE_JUMBO "enable-jumbo"
 #define CMD_LINE_OPT_HASH_ENTRY_NUM "hash-entry-num"
 #define CMD_LINE_OPT_NO_LTHREADS "no-lthreads"
+#define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype"
 
 /* Parse the argument given in the command line of the application */
 static int
@@ -2859,6 +2921,7 @@  static int parse_max_pkt_len(const char *pktlen)
 		{CMD_LINE_OPT_ENABLE_JUMBO, 0, 0, 0},
 		{CMD_LINE_OPT_HASH_ENTRY_NUM, 1, 0, 0},
 		{CMD_LINE_OPT_NO_LTHREADS, 0, 0, 0},
+		{CMD_LINE_OPT_PARSE_PTYPE, 0, 0, 0},
 		{NULL, 0, 0, 0}
 	};
 
@@ -2935,6 +2998,12 @@  static int parse_max_pkt_len(const char *pktlen)
 				lthreads_on = 0;
 			}
 
+			if (!strncmp(lgopts[option_index].name, CMD_LINE_OPT_PARSE_PTYPE,
+					sizeof(CMD_LINE_OPT_PARSE_PTYPE))) {
+				printf("software packet type parsing enabled\n");
+				parse_ptype_on = 1;
+			}
+
 			if (!strncmp(lgopts[option_index].name, CMD_LINE_OPT_ENABLE_JUMBO,
 				sizeof(CMD_LINE_OPT_ENABLE_JUMBO))) {
 				struct option lenopts = {"max-pkt-len", required_argument, 0,
@@ -3623,6 +3692,31 @@  static void convert_ipv6_5tuple(struct ipv6_5tuple *key1,
 			rte_eth_promiscuous_enable(portid);
 	}
 
+	for (i = 0; i < n_rx_thread; i++) {
+		lcore_id = rx_thread[i].conf.lcore_id;
+		if (rte_lcore_is_enabled(lcore_id) == 0)
+			continue;
+
+		/* check if hw packet type is supported */
+		for (queue = 0; queue < rx_thread[i].n_rx_queue; ++queue) {
+			portid = rx_thread[i].rx_queue_list[queue].port_id;
+			queueid = rx_thread[i].rx_queue_list[queue].queue_id;
+
+			if (parse_ptype_on) {
+				if (!rte_eth_add_rx_callback(portid, queueid,
+						cb_parse_ptype, NULL))
+					rte_exit(EXIT_FAILURE,
+						"Failed to add rx callback: "
+						"port=%d\n", portid);
+			} else if (!check_ptype(portid))
+				rte_exit(EXIT_FAILURE,
+					"Port %d cannot parse packet type.\n\n"
+					"Please add --parse-ptype to use sw "
+					"packet type analyzer.\n\n",
+					portid);
+		}
+	}
+
 	check_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask);
 
 	if (lthreads_on) {