All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bernard Iremonger <bernard.iremonger@intel.com>
To: dev@dpdk.org, ferruh.yigit@intel.com,
	konstantin.ananyev@intel.com, cristian.dumitrescu@intel.com,
	adrien.mazarguil@6wind.com
Cc: Bernard Iremonger <bernard.iremonger@intel.com>
Subject: [PATCH v6 2/4] examples/flow_classify: flow classify sample application
Date: Fri, 29 Sep 2017 10:18:55 +0100	[thread overview]
Message-ID: <1506676737-23900-3-git-send-email-bernard.iremonger@intel.com> (raw)
In-Reply-To: <1504802598-27296-1-git-send-email-bernard.iremonger@intel.com>

The flow_classify sample application exercises the following
librte_flow_classify API's:

rte_flow_classify_create
rte_flow_classify_validate
rte_flow_classify_destroy
rte_flow_classify_query

It sets up the IPv4 ACL field definitions.
It creates table_acl and adds and deletes rules using the
librte_table API.

It uses a file of IPv4 five tuple rules for input.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 examples/flow_classify/Makefile            |  57 ++
 examples/flow_classify/flow_classify.c     | 897 +++++++++++++++++++++++++++++
 examples/flow_classify/ipv4_rules_file.txt |  14 +
 3 files changed, 968 insertions(+)
 create mode 100644 examples/flow_classify/Makefile
 create mode 100644 examples/flow_classify/flow_classify.c
 create mode 100644 examples/flow_classify/ipv4_rules_file.txt

diff --git a/examples/flow_classify/Makefile b/examples/flow_classify/Makefile
new file mode 100644
index 0000000..eecdde1
--- /dev/null
+++ b/examples/flow_classify/Makefile
@@ -0,0 +1,57 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 Intel Corporation. All rights reserved.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# binary name
+APP = flow_classify
+
+
+# all source are stored in SRCS-y
+SRCS-y := flow_classify.c
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+# workaround for a gcc bug with noreturn attribute
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+CFLAGS_main.o += -Wno-return-type
+endif
+
+include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/examples/flow_classify/flow_classify.c b/examples/flow_classify/flow_classify.c
new file mode 100644
index 0000000..651fa8f
--- /dev/null
+++ b/examples/flow_classify/flow_classify.c
@@ -0,0 +1,897 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <getopt.h>
+
+#include <rte_eal.h>
+#include <rte_ethdev.h>
+#include <rte_cycles.h>
+#include <rte_lcore.h>
+#include <rte_mbuf.h>
+#include <rte_flow.h>
+#include <rte_flow_classify.h>
+#include <rte_table_acl.h>
+
+#define RX_RING_SIZE 128
+#define TX_RING_SIZE 512
+
+#define NUM_MBUFS 8191
+#define MBUF_CACHE_SIZE 250
+#define BURST_SIZE 32
+#define MAX_NUM_CLASSIFY 30
+#define FLOW_CLASSIFY_MAX_RULE_NUM 91
+#define FLOW_CLASSIFY_MAX_PRIORITY 8
+#define PROTO_TCP 6
+#define PROTO_UDP 17
+#define PROTO_SCTP 132
+
+#define COMMENT_LEAD_CHAR	('#')
+#define OPTION_RULE_IPV4	"rule_ipv4"
+#define RTE_LOGTYPE_FLOW_CLASSIFY	RTE_LOGTYPE_USER3
+#define flow_classify_log(format, ...) \
+		RTE_LOG(ERR, FLOW_CLASSIFY, format, ##__VA_ARGS__)
+
+#define uint32_t_to_char(ip, a, b, c, d) do {\
+		*a = (unsigned char)(ip >> 24 & 0xff);\
+		*b = (unsigned char)(ip >> 16 & 0xff);\
+		*c = (unsigned char)(ip >> 8 & 0xff);\
+		*d = (unsigned char)(ip & 0xff);\
+	} while (0)
+
+enum {
+	CB_FLD_SRC_ADDR,
+	CB_FLD_DST_ADDR,
+	CB_FLD_SRC_PORT,
+	CB_FLD_SRC_PORT_DLM,
+	CB_FLD_SRC_PORT_MASK,
+	CB_FLD_DST_PORT,
+	CB_FLD_DST_PORT_DLM,
+	CB_FLD_DST_PORT_MASK,
+	CB_FLD_PROTO,
+	CB_FLD_PRIORITY,
+	CB_FLD_NUM,
+};
+
+static struct{
+	const char *rule_ipv4_name;
+} parm_config;
+const char cb_port_delim[] = ":";
+
+static const struct rte_eth_conf port_conf_default = {
+	.rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
+};
+
+static void *table_acl;
+uint32_t entry_size;
+static int udp_num_classify;
+static int tcp_num_classify;
+static int sctp_num_classify;
+
+/* ACL field definitions for IPv4 5 tuple rule */
+
+enum {
+	PROTO_FIELD_IPV4,
+	SRC_FIELD_IPV4,
+	DST_FIELD_IPV4,
+	SRCP_FIELD_IPV4,
+	DSTP_FIELD_IPV4,
+	NUM_FIELDS_IPV4
+};
+
+enum {
+	PROTO_INPUT_IPV4,
+	SRC_INPUT_IPV4,
+	DST_INPUT_IPV4,
+	SRCP_DESTP_INPUT_IPV4
+};
+
+static struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
+	/* first input field - always one byte long. */
+	{
+		.type = RTE_ACL_FIELD_TYPE_BITMASK,
+		.size = sizeof(uint8_t),
+		.field_index = PROTO_FIELD_IPV4,
+		.input_index = PROTO_INPUT_IPV4,
+		.offset = sizeof(struct ether_hdr) +
+			offsetof(struct ipv4_hdr, next_proto_id),
+	},
+	/* next input field (IPv4 source address) - 4 consecutive bytes. */
+	{
+		/* rte_flow uses a bit mask for IPv4 addresses */
+		.type = RTE_ACL_FIELD_TYPE_BITMASK,
+		.size = sizeof(uint32_t),
+		.field_index = SRC_FIELD_IPV4,
+		.input_index = SRC_INPUT_IPV4,
+		.offset = sizeof(struct ether_hdr) +
+			offsetof(struct ipv4_hdr, src_addr),
+	},
+	/* next input field (IPv4 destination address) - 4 consecutive bytes. */
+	{
+		/* rte_flow uses a bit mask for IPv4 addresses */
+		.type = RTE_ACL_FIELD_TYPE_BITMASK,
+		.size = sizeof(uint32_t),
+		.field_index = DST_FIELD_IPV4,
+		.input_index = DST_INPUT_IPV4,
+		.offset = sizeof(struct ether_hdr) +
+			offsetof(struct ipv4_hdr, dst_addr),
+	},
+	/*
+	 * Next 2 fields (src & dst ports) form 4 consecutive bytes.
+	 * They share the same input index.
+	 */
+	{
+		/* rte_flow uses a bit mask for protocol ports */
+		.type = RTE_ACL_FIELD_TYPE_BITMASK,
+		.size = sizeof(uint16_t),
+		.field_index = SRCP_FIELD_IPV4,
+		.input_index = SRCP_DESTP_INPUT_IPV4,
+		.offset = sizeof(struct ether_hdr) +
+			sizeof(struct ipv4_hdr) +
+			offsetof(struct tcp_hdr, src_port),
+	},
+	{
+		/* rte_flow uses a bit mask for protocol ports */
+		.type = RTE_ACL_FIELD_TYPE_BITMASK,
+		.size = sizeof(uint16_t),
+		.field_index = DSTP_FIELD_IPV4,
+		.input_index = SRCP_DESTP_INPUT_IPV4,
+		.offset = sizeof(struct ether_hdr) +
+			sizeof(struct ipv4_hdr) +
+			offsetof(struct tcp_hdr, dst_port),
+	},
+};
+
+/* flow classify data */
+static struct rte_flow_classify *udp_flow_classify[MAX_NUM_CLASSIFY];
+static struct rte_flow_classify *tcp_flow_classify[MAX_NUM_CLASSIFY];
+static struct rte_flow_classify *sctp_flow_classify[MAX_NUM_CLASSIFY];
+
+static struct rte_flow_classify_5tuple_stats udp_ntuple_stats;
+static struct rte_flow_classify_stats udp_classify_stats = {
+		.available_space = BURST_SIZE,
+		.used_space = 0,
+		.stats = (void **)&udp_ntuple_stats
+};
+
+static struct rte_flow_classify_5tuple_stats tcp_ntuple_stats;
+static struct rte_flow_classify_stats tcp_classify_stats = {
+		.available_space = BURST_SIZE,
+		.used_space = 0,
+		.stats = (void **)&tcp_ntuple_stats
+};
+
+static struct rte_flow_classify_5tuple_stats sctp_ntuple_stats;
+static struct rte_flow_classify_stats sctp_classify_stats = {
+		.available_space = BURST_SIZE,
+		.used_space = 0,
+		.stats = (void **)&sctp_ntuple_stats
+};
+
+/* parameters for rte_flow_classify_validate and rte_flow_classify_create */
+
+static struct rte_flow_item  eth_item = { RTE_FLOW_ITEM_TYPE_ETH,
+	0, 0, 0 };
+static struct rte_flow_item  end_item = { RTE_FLOW_ITEM_TYPE_END,
+	0, 0, 0 };
+
+/* sample actions:
+ * "actions count / end"
+ */
+static struct rte_flow_action count_action = { RTE_FLOW_ACTION_TYPE_COUNT, 0};
+static struct rte_flow_action end_action = { RTE_FLOW_ACTION_TYPE_END, 0};
+static struct rte_flow_action actions[2];
+
+/* sample attributes */
+static struct rte_flow_attr attr;
+
+/* flow_classify.c: * Based on DPDK skeleton forwarding example. */
+
+/*
+ * Initializes a given port using global settings and with the RX buffers
+ * coming from the mbuf_pool passed as a parameter.
+ */
+static inline int
+port_init(uint8_t port, struct rte_mempool *mbuf_pool)
+{
+	struct rte_eth_conf port_conf = port_conf_default;
+	struct ether_addr addr;
+	const uint16_t rx_rings = 1, tx_rings = 1;
+	int retval;
+	uint16_t q;
+
+	if (port >= rte_eth_dev_count())
+		return -1;
+
+	/* Configure the Ethernet device. */
+	retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
+	if (retval != 0)
+		return retval;
+
+	/* Allocate and set up 1 RX queue per Ethernet port. */
+	for (q = 0; q < rx_rings; q++) {
+		retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
+				rte_eth_dev_socket_id(port), NULL, mbuf_pool);
+		if (retval < 0)
+			return retval;
+	}
+
+	/* Allocate and set up 1 TX queue per Ethernet port. */
+	for (q = 0; q < tx_rings; q++) {
+		retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
+				rte_eth_dev_socket_id(port), NULL);
+		if (retval < 0)
+			return retval;
+	}
+
+	/* Start the Ethernet port. */
+	retval = rte_eth_dev_start(port);
+	if (retval < 0)
+		return retval;
+
+	/* Display the port MAC address. */
+	rte_eth_macaddr_get(port, &addr);
+	printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
+			   " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
+			port,
+			addr.addr_bytes[0], addr.addr_bytes[1],
+			addr.addr_bytes[2], addr.addr_bytes[3],
+			addr.addr_bytes[4], addr.addr_bytes[5]);
+
+	/* Enable RX in promiscuous mode for the Ethernet device. */
+	rte_eth_promiscuous_enable(port);
+
+	return 0;
+}
+
+/*
+ * The lcore main. This is the main thread that does the work, reading from
+ * an input port classifying the packets and writing to an output port.
+ */
+static __attribute__((noreturn)) void
+lcore_main(void)
+{
+	struct rte_flow_error error;
+	const uint8_t nb_ports = rte_eth_dev_count();
+	uint8_t port;
+	int ret;
+	int i;
+
+	/*
+	 * Check that the port is on the same NUMA node as the polling thread
+	 * for best performance.
+	 */
+	for (port = 0; port < nb_ports; port++)
+		if (rte_eth_dev_socket_id(port) > 0 &&
+				rte_eth_dev_socket_id(port) !=
+						(int)rte_socket_id())
+			printf("\n\n");
+			printf("WARNING: port %u is on remote NUMA node\n",
+			       port);
+			printf("to polling thread.\n");
+			printf("Performance will not be optimal.\n");
+
+	printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n",
+			rte_lcore_id());
+
+	/* Run until the application is quit or killed. */
+	for (;;) {
+		/*
+		 * Receive packets on a port, classify them and forward them
+		 * on the paired port.
+		 * The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc.
+		 */
+		for (port = 0; port < nb_ports; port++) {
+
+			/* Get burst of RX packets, from first port of pair. */
+			struct rte_mbuf *bufs[BURST_SIZE];
+			const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
+					bufs, BURST_SIZE);
+
+			if (unlikely(nb_rx == 0))
+				continue;
+
+			for (i = 0; i < MAX_NUM_CLASSIFY; i++) {
+				if (udp_flow_classify[i]) {
+					ret = rte_flow_classify_query(
+						table_acl,
+						udp_flow_classify[i],
+						bufs, nb_rx,
+						&udp_classify_stats, &error);
+					if (ret)
+						printf(
+						"udp flow classify[%d] query failed port=%u\n\n",
+						i, port);
+					else
+						printf(
+						"udp rule [%d] counter1=%lu used_space=%d\n\n",
+						i, udp_ntuple_stats.counter1,
+						udp_classify_stats.used_space);
+				}
+			}
+
+			for (i = 0; i < MAX_NUM_CLASSIFY; i++) {
+				if (tcp_flow_classify[i]) {
+					ret = rte_flow_classify_query(
+						table_acl,
+						tcp_flow_classify[i],
+						bufs, nb_rx,
+						&tcp_classify_stats, &error);
+					if (ret)
+						printf(
+						"tcp flow classify[%d] query failed port=%u\n\n",
+						i, port);
+					else
+						printf(
+						"tcp rule [%d] counter1=%lu used_space=%d\n\n",
+						i, tcp_ntuple_stats.counter1,
+						tcp_classify_stats.used_space);
+				}
+			}
+
+			for (i = 0; i < MAX_NUM_CLASSIFY; i++) {
+				if (sctp_flow_classify[i]) {
+					ret = rte_flow_classify_query(
+						table_acl,
+						sctp_flow_classify[i],
+						bufs, nb_rx,
+						&sctp_classify_stats, &error);
+					if (ret)
+						printf(
+						"sctp flow classify[%d] query failed port=%u\n\n",
+						i, port);
+					else
+						printf(
+						"sctp rule [%d] counter1=%lu used_space=%d\n\n",
+						i, sctp_ntuple_stats.counter1,
+						sctp_classify_stats.used_space);
+				}
+			}
+
+			/* Send burst of TX packets, to second port of pair. */
+			const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
+					bufs, nb_rx);
+
+			/* Free any unsent packets. */
+			if (unlikely(nb_tx < nb_rx)) {
+				uint16_t buf;
+
+				for (buf = nb_tx; buf < nb_rx; buf++)
+					rte_pktmbuf_free(bufs[buf]);
+			}
+		}
+	}
+}
+
+/*
+ * Parse IPv4 5 tuple rules file, ipv4_rules_file.txt.
+ * Expected format:
+ * <src_ipv4_addr>'/'<masklen> <space> \
+ * <dst_ipv4_addr>'/'<masklen> <space> \
+ * <src_port> <space> ":" <src_port_mask> <space> \
+ * <dst_port> <space> ":" <dst_port_mask> <space> \
+ * <proto>'/'<proto_mask> <space> \
+ * <priority>
+ */
+
+static int
+get_cb_field(char **in, uint32_t *fd, int base, unsigned long lim,
+		char dlm)
+{
+	unsigned long val;
+	char *end;
+
+	errno = 0;
+	val = strtoul(*in, &end, base);
+	if (errno != 0 || end[0] != dlm || val > lim)
+		return -EINVAL;
+	*fd = (uint32_t)val;
+	*in = end + 1;
+	return 0;
+}
+
+static int
+parse_ipv4_net(char *in, uint32_t *addr, uint32_t *mask_len)
+{
+	uint32_t a, b, c, d, m;
+
+	if (get_cb_field(&in, &a, 0, UINT8_MAX, '.'))
+		return -EINVAL;
+	if (get_cb_field(&in, &b, 0, UINT8_MAX, '.'))
+		return -EINVAL;
+	if (get_cb_field(&in, &c, 0, UINT8_MAX, '.'))
+		return -EINVAL;
+	if (get_cb_field(&in, &d, 0, UINT8_MAX, '/'))
+		return -EINVAL;
+	if (get_cb_field(&in, &m, 0, sizeof(uint32_t) * CHAR_BIT, 0))
+		return -EINVAL;
+
+	addr[0] = IPv4(a, b, c, d);
+	mask_len[0] = m;
+	return 0;
+}
+
+static int
+parse_ipv4_5tuple_rule(char *str, struct rte_eth_ntuple_filter *ntuple_filter)
+{
+	int i, ret;
+	char *s, *sp, *in[CB_FLD_NUM];
+	static const char *dlm = " \t\n";
+	int dim = CB_FLD_NUM;
+	uint32_t temp;
+
+	s = str;
+	for (i = 0; i != dim; i++, s = NULL) {
+		in[i] = strtok_r(s, dlm, &sp);
+		if (in[i] == NULL)
+			return -EINVAL;
+	}
+
+	ret = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
+			&ntuple_filter->src_ip,
+			&ntuple_filter->src_ip_mask);
+	if (ret != 0) {
+		flow_classify_log("failed to read source address/mask: %s\n",
+			in[CB_FLD_SRC_ADDR]);
+		return ret;
+	}
+
+	ret = parse_ipv4_net(in[CB_FLD_DST_ADDR],
+			&ntuple_filter->dst_ip,
+			&ntuple_filter->dst_ip_mask);
+	if (ret != 0) {
+		flow_classify_log("failed to read source address/mask: %s\n",
+			in[CB_FLD_DST_ADDR]);
+		return ret;
+	}
+
+	if (get_cb_field(&in[CB_FLD_SRC_PORT], &temp, 0, UINT16_MAX, 0))
+		return -EINVAL;
+	ntuple_filter->src_port = (uint16_t)temp;
+
+	if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,
+			sizeof(cb_port_delim)) != 0)
+		return -EINVAL;
+
+	if (get_cb_field(&in[CB_FLD_SRC_PORT_MASK], &temp, 0, UINT16_MAX, 0))
+		return -EINVAL;
+	ntuple_filter->src_port_mask = (uint16_t)temp;
+
+	if (get_cb_field(&in[CB_FLD_DST_PORT], &temp, 0, UINT16_MAX, 0))
+		return -EINVAL;
+	ntuple_filter->dst_port = (uint16_t)temp;
+
+	if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,
+			sizeof(cb_port_delim)) != 0)
+		return -EINVAL;
+
+	if (get_cb_field(&in[CB_FLD_DST_PORT_MASK], &temp, 0, UINT16_MAX, 0))
+		return -EINVAL;
+	ntuple_filter->dst_port_mask = (uint16_t)temp;
+
+	if (get_cb_field(&in[CB_FLD_PROTO], &temp, 0, UINT8_MAX, '/'))
+		return -EINVAL;
+	ntuple_filter->proto = (uint8_t)temp;
+
+	if (get_cb_field(&in[CB_FLD_PROTO], &temp, 0, UINT8_MAX, 0))
+		return -EINVAL;
+	ntuple_filter->proto_mask = (uint8_t)temp;
+
+	if (get_cb_field(&in[CB_FLD_PRIORITY], &temp, 0, UINT16_MAX, 0))
+		return -EINVAL;
+	ntuple_filter->priority = (uint16_t)temp;
+	if (ntuple_filter->priority > FLOW_CLASSIFY_MAX_PRIORITY)
+		ret = -EINVAL;
+
+	return ret;
+}
+
+/* Bypass comment and empty lines */
+static inline int
+is_bypass_line(char *buff)
+{
+	int i = 0;
+
+	/* comment line */
+	if (buff[0] == COMMENT_LEAD_CHAR)
+		return 1;
+	/* empty line */
+	while (buff[i] != '\0') {
+		if (!isspace(buff[i]))
+			return 0;
+		i++;
+	}
+	return 1;
+}
+
+static uint32_t
+convert_depth_to_bitmask(uint32_t depth_val)
+{
+	uint32_t bitmask = 0;
+	int i, j;
+
+	for (i = depth_val, j = 0; i > 0; i--, j++)
+		bitmask |= (1 << (31 - j));
+	return bitmask;
+}
+
+static int
+add_classify_rule(struct rte_eth_ntuple_filter *ntuple_filter)
+{
+	int ret = 0;
+	struct rte_flow_error error;
+	struct rte_flow_item_ipv4 ipv4_spec;
+	struct rte_flow_item_ipv4 ipv4_mask;
+	struct rte_flow_item ipv4_udp_item;
+	struct rte_flow_item ipv4_tcp_item;
+	struct rte_flow_item ipv4_sctp_item;
+	struct rte_flow_item_udp udp_spec;
+	struct rte_flow_item_udp udp_mask;
+	struct rte_flow_item udp_item;
+	struct rte_flow_item_tcp tcp_spec;
+	struct rte_flow_item_tcp tcp_mask;
+	struct rte_flow_item tcp_item;
+	struct rte_flow_item_sctp sctp_spec;
+	struct rte_flow_item_sctp sctp_mask;
+	struct rte_flow_item sctp_item;
+	struct rte_flow_item pattern_ipv4_5tuple[4];
+	struct rte_flow_classify *flow_classify;
+	uint8_t ipv4_proto;
+
+	/* set up parameters for validate and create */
+	memset(&ipv4_spec, 0, sizeof(ipv4_spec));
+	ipv4_spec.hdr.next_proto_id = ntuple_filter->proto;
+	ipv4_spec.hdr.src_addr = ntuple_filter->src_ip;
+	ipv4_spec.hdr.dst_addr = ntuple_filter->dst_ip;
+	ipv4_proto = ipv4_spec.hdr.next_proto_id;
+
+	memset(&ipv4_mask, 0, sizeof(ipv4_mask));
+	ipv4_mask.hdr.next_proto_id = ntuple_filter->proto_mask;
+	ipv4_mask.hdr.src_addr = ntuple_filter->src_ip_mask;
+	ipv4_mask.hdr.src_addr =
+		convert_depth_to_bitmask(ipv4_mask.hdr.src_addr);
+	ipv4_mask.hdr.dst_addr = ntuple_filter->dst_ip_mask;
+	ipv4_mask.hdr.dst_addr =
+		convert_depth_to_bitmask(ipv4_mask.hdr.dst_addr);
+
+	switch (ipv4_proto) {
+	case PROTO_UDP:
+		if (udp_num_classify >= MAX_NUM_CLASSIFY) {
+			printf(
+				"\nINFO: UDP classify rule capacity %d reached\n",
+				udp_num_classify);
+			ret = -1;
+			break;
+		}
+		ipv4_udp_item.type = RTE_FLOW_ITEM_TYPE_IPV4;
+		ipv4_udp_item.spec = &ipv4_spec;
+		ipv4_udp_item.mask = &ipv4_mask;
+		ipv4_udp_item.last = NULL;
+
+		udp_spec.hdr.src_port = ntuple_filter->src_port;
+		udp_spec.hdr.dst_port = ntuple_filter->dst_port;
+		udp_spec.hdr.dgram_len = 0;
+		udp_spec.hdr.dgram_cksum = 0;
+
+		udp_mask.hdr.src_port = ntuple_filter->src_port_mask;
+		udp_mask.hdr.dst_port = ntuple_filter->dst_port_mask;
+		udp_mask.hdr.dgram_len = 0;
+		udp_mask.hdr.dgram_cksum = 0;
+
+		udp_item.type = RTE_FLOW_ITEM_TYPE_UDP;
+		udp_item.spec = &udp_spec;
+		udp_item.mask = &udp_mask;
+		udp_item.last = NULL;
+
+		attr.priority = ntuple_filter->priority;
+		pattern_ipv4_5tuple[1] = ipv4_udp_item;
+		pattern_ipv4_5tuple[2] = udp_item;
+		break;
+	case PROTO_TCP:
+		if (tcp_num_classify >= MAX_NUM_CLASSIFY) {
+			printf(
+				"\nINFO: TCP classify rule capacity %d reached\n",
+				tcp_num_classify);
+			ret = -1;
+			break;
+		}
+		ipv4_tcp_item.type = RTE_FLOW_ITEM_TYPE_IPV4;
+		ipv4_tcp_item.spec = &ipv4_spec;
+		ipv4_tcp_item.mask = &ipv4_mask;
+		ipv4_tcp_item.last = NULL;
+
+		memset(&tcp_spec, 0, sizeof(tcp_spec));
+		tcp_spec.hdr.src_port = ntuple_filter->src_port;
+		tcp_spec.hdr.dst_port = ntuple_filter->dst_port;
+
+		memset(&tcp_mask, 0, sizeof(tcp_mask));
+		tcp_mask.hdr.src_port = ntuple_filter->src_port_mask;
+		tcp_mask.hdr.dst_port = ntuple_filter->dst_port_mask;
+
+		tcp_item.type = RTE_FLOW_ITEM_TYPE_TCP;
+		tcp_item.spec = &tcp_spec;
+		tcp_item.mask = &tcp_mask;
+		tcp_item.last = NULL;
+
+		attr.priority = ntuple_filter->priority;
+		pattern_ipv4_5tuple[1] = ipv4_tcp_item;
+		pattern_ipv4_5tuple[2] = tcp_item;
+		break;
+	case PROTO_SCTP:
+		if (sctp_num_classify >= MAX_NUM_CLASSIFY) {
+			printf(
+				"\nINFO: SCTP classify rule capacity %d reached\n",
+				sctp_num_classify);
+			ret = -1;
+			break;
+		}
+		ipv4_sctp_item.type = RTE_FLOW_ITEM_TYPE_IPV4;
+		ipv4_sctp_item.spec = &ipv4_spec;
+		ipv4_sctp_item.mask = &ipv4_mask;
+		ipv4_sctp_item.last = NULL;
+
+		sctp_spec.hdr.src_port = ntuple_filter->src_port;
+		sctp_spec.hdr.dst_port = ntuple_filter->dst_port;
+		sctp_spec.hdr.cksum = 0;
+		sctp_spec.hdr.tag = 0;
+
+		sctp_mask.hdr.src_port = ntuple_filter->src_port_mask;
+		sctp_mask.hdr.dst_port = ntuple_filter->dst_port_mask;
+		sctp_mask.hdr.cksum = 0;
+		sctp_mask.hdr.tag = 0;
+
+		sctp_item.type = RTE_FLOW_ITEM_TYPE_SCTP;
+		sctp_item.spec = &sctp_spec;
+		sctp_item.mask = &sctp_mask;
+		sctp_item.last = NULL;
+
+		attr.priority = ntuple_filter->priority;
+		pattern_ipv4_5tuple[1] = ipv4_sctp_item;
+		pattern_ipv4_5tuple[2] = sctp_item;
+		break;
+	default:
+		break;
+	}
+
+	if (ret == -1)
+		return 0;
+
+	attr.ingress = 1;
+	pattern_ipv4_5tuple[0] = eth_item;
+	pattern_ipv4_5tuple[3] = end_item;
+	actions[0] = count_action;
+	actions[1] = end_action;
+
+	ret = rte_flow_classify_validate(table_acl, &attr, pattern_ipv4_5tuple,
+			actions, &error);
+	if (ret)
+		rte_exit(EXIT_FAILURE,
+			"flow classify validate failed ipv4_proto = %u\n",
+			ipv4_proto);
+
+	flow_classify = rte_flow_classify_create(
+			table_acl, entry_size, &attr, pattern_ipv4_5tuple,
+			actions, &error);
+	if (flow_classify == NULL)
+		rte_exit(EXIT_FAILURE,
+			"flow classify create failed ipv4_proto = %u\n",
+			ipv4_proto);
+
+	switch (ipv4_proto) {
+	case PROTO_UDP:
+		udp_flow_classify[udp_num_classify] = flow_classify;
+		udp_num_classify++;
+		break;
+	case PROTO_TCP:
+		tcp_flow_classify[tcp_num_classify] = flow_classify;
+		tcp_num_classify++;
+		break;
+	case PROTO_SCTP:
+		sctp_flow_classify[sctp_num_classify] = flow_classify;
+		sctp_num_classify++;
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int
+add_rules(const char *rule_path)
+{
+	FILE *fh;
+	char buff[LINE_MAX];
+	unsigned int i = 0;
+	unsigned int total_num = 0;
+	struct rte_eth_ntuple_filter ntuple_filter;
+
+	fh = fopen(rule_path, "rb");
+	if (fh == NULL)
+		rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__,
+			rule_path);
+
+	fseek(fh, 0, SEEK_SET);
+
+	i = 0;
+	while (fgets(buff, LINE_MAX, fh) != NULL) {
+		i++;
+
+		if (is_bypass_line(buff))
+			continue;
+
+		if (total_num >= FLOW_CLASSIFY_MAX_RULE_NUM - 1) {
+			printf("\nINFO: classify rule capacity %d reached\n",
+				total_num);
+			break;
+		}
+
+		if (parse_ipv4_5tuple_rule(buff, &ntuple_filter) != 0)
+			rte_exit(EXIT_FAILURE,
+				"%s Line %u: parse rules error\n",
+				rule_path, i);
+
+		if (add_classify_rule(&ntuple_filter) != 0)
+			rte_exit(EXIT_FAILURE, "add rule error\n");
+
+		total_num++;
+	}
+
+	fclose(fh);
+	return 0;
+}
+
+/* display usage */
+static void
+print_usage(const char *prgname)
+{
+	printf("%s usage:\n", prgname);
+	printf("[EAL options] --  --"OPTION_RULE_IPV4"=FILE: ");
+	printf("specify the ipv4 rules file.\n");
+	printf("Each rule occupies one line in the file.\n");
+}
+
+/* Parse the argument given in the command line of the application */
+static int
+parse_args(int argc, char **argv)
+{
+	int opt, ret;
+	char **argvopt;
+	int option_index;
+	char *prgname = argv[0];
+	static struct option lgopts[] = {
+		{OPTION_RULE_IPV4, 1, 0, 0},
+		{NULL, 0, 0, 0}
+	};
+
+	argvopt = argv;
+
+	while ((opt = getopt_long(argc, argvopt, "",
+				lgopts, &option_index)) != EOF) {
+
+		switch (opt) {
+		/* long options */
+		case 0:
+			if (!strncmp(lgopts[option_index].name,
+					OPTION_RULE_IPV4,
+					sizeof(OPTION_RULE_IPV4)))
+				parm_config.rule_ipv4_name = optarg;
+			break;
+		default:
+			print_usage(prgname);
+			return -1;
+		}
+	}
+
+	if (optind >= 0)
+		argv[optind-1] = prgname;
+
+	ret = optind-1;
+	optind = 1; /* reset getopt lib */
+	return ret;
+}
+
+/*
+ * The main function, which does initialization and calls the per-lcore
+ * functions.
+ */
+int
+main(int argc, char *argv[])
+{
+	struct rte_mempool *mbuf_pool;
+	uint8_t nb_ports;
+	uint8_t portid;
+	int ret;
+	int socket_id;
+	struct rte_table_acl_params table_acl_params;
+
+	/* Initialize the Environment Abstraction Layer (EAL). */
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
+
+	argc -= ret;
+	argv += ret;
+
+	/* parse application arguments (after the EAL ones) */
+	ret = parse_args(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Invalid flow_classify parameters\n");
+
+	/* Check that there is an even number of ports to send/receive on. */
+	nb_ports = rte_eth_dev_count();
+	if (nb_ports < 2 || (nb_ports & 1))
+		rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n");
+
+	/* Creates a new mempool in memory to hold the mbufs. */
+	mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports,
+		MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+
+	if (mbuf_pool == NULL)
+		rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
+
+	/* Initialize all ports. */
+	for (portid = 0; portid < nb_ports; portid++)
+		if (port_init(portid, mbuf_pool) != 0)
+			rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n",
+					portid);
+
+	if (rte_lcore_count() > 1)
+		printf("\nWARNING: Too many lcores enabled. Only 1 used.\n");
+
+	socket_id = rte_eth_dev_socket_id(0);
+
+	/* initialise ACL table params */
+	table_acl_params.n_rule_fields = RTE_DIM(ipv4_defs);
+	table_acl_params.name = "table_acl_ipv4_5tuple";
+	table_acl_params.n_rules = FLOW_CLASSIFY_MAX_RULE_NUM;
+	memcpy(table_acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
+	entry_size = RTE_ACL_RULE_SZ(RTE_DIM(ipv4_defs));
+
+	table_acl = rte_table_acl_ops.f_create(&table_acl_params, socket_id,
+						entry_size);
+	if (table_acl == NULL)
+		rte_exit(EXIT_FAILURE, "Failed to create table_acl\n");
+
+	/* read file of IPv4 5 tuple rules and initialise parameters
+	 * for rte_flow_classify_validate and rte_flow_classify_create
+	 */
+
+	if (add_rules(parm_config.rule_ipv4_name))
+		rte_exit(EXIT_FAILURE, "Failed to add rules\n");
+
+	/* Call lcore_main on the master core only. */
+	lcore_main();
+
+	return 0;
+}
diff --git a/examples/flow_classify/ipv4_rules_file.txt b/examples/flow_classify/ipv4_rules_file.txt
new file mode 100644
index 0000000..262763d
--- /dev/null
+++ b/examples/flow_classify/ipv4_rules_file.txt
@@ -0,0 +1,14 @@
+#file format:
+#src_ip/masklen dstt_ip/masklen src_port : mask dst_port : mask proto/mask priority
+#
+2.2.2.3/24 2.2.2.7/24 32 : 0xffff 33 : 0xffff 17/0xff 0
+9.9.9.3/24 9.9.9.7/24 32 : 0xffff 33 : 0xffff 17/0xff 1
+9.9.9.3/24 9.9.9.7/24 32 : 0xffff 33 : 0xffff 6/0xff 2
+9.9.8.3/24 9.9.8.7/24 32 : 0xffff 33 : 0xffff 6/0xff 3
+6.7.8.9/24 2.3.4.5/24 32 : 0xffff 33 : 0xffff 132/0xff 4
+6.7.8.9/32 192.168.0.36/32 10 : 0xffff 11 : 0xffff 6/0xfe 5
+6.7.8.9/24 192.168.0.36/24 10 : 0xffff 11 : 0xffff 6/0xfe 6
+6.7.8.9/16 192.168.0.36/16 10 : 0xffff 11 : 0xffff 6/0xfe 7
+6.7.8.9/8 192.168.0.36/8 10 : 0xffff 11 : 0xffff 6/0xfe 8
+#error rules
+#9.8.7.6/8 192.168.0.36/8 10 : 0xffff 11 : 0xffff 6/0xfe 9
\ No newline at end of file
-- 
1.9.1

  parent reply	other threads:[~2017-09-29  9:19 UTC|newest]

Thread overview: 145+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-20 18:54 [RFC 17.08] Flow classification library Ferruh Yigit
2017-04-20 18:54 ` [RFC 17.08] flow_classify: add librte_flow_classify library Ferruh Yigit
2017-05-04 11:35   ` Mcnamara, John
2017-05-16 22:19     ` Thomas Monjalon
2017-05-17 14:54   ` Ananyev, Konstantin
2017-05-17 15:37     ` Ferruh Yigit
2017-05-17 16:10       ` Ananyev, Konstantin
2017-05-18 12:12         ` Ferruh Yigit
2017-05-17 16:02     ` Ferruh Yigit
2017-05-17 16:18       ` Ananyev, Konstantin
2017-05-17 16:38       ` Gaëtan Rivet
2017-05-18 11:33         ` Ferruh Yigit
2017-05-18 20:31           ` Thomas Monjalon
2017-05-19  8:57             ` Ananyev, Konstantin
2017-05-19  9:11               ` Gaëtan Rivet
2017-05-19  9:40                 ` Ananyev, Konstantin
2017-05-19 10:11                 ` Thomas Monjalon
2017-05-22  9:13                   ` Adrien Mazarguil
2017-04-21 10:38 ` [RFC 17.08] Flow classification library Gaëtan Rivet
2017-05-03  9:15   ` Mcnamara, John
2017-05-06 14:04     ` Morten Brørup
2017-05-09 13:37       ` Ferruh Yigit
2017-05-09 19:24         ` Morten Brørup
2017-05-17 11:26           ` Ferruh Yigit
2017-05-09 13:26   ` Ferruh Yigit
2017-05-18 18:12 ` [RFC v2] " Ferruh Yigit
2017-05-18 18:12   ` [RFC v2] flow_classify: add librte_flow_classify library Ferruh Yigit
2017-05-19 16:30   ` [RFC v2] Flow classification library Iremonger, Bernard
2017-05-22 13:53     ` Ferruh Yigit
2017-05-23 12:26       ` Adrien Mazarguil
2017-05-23 12:58         ` Ferruh Yigit
2017-05-23 13:30           ` Adrien Mazarguil
2017-05-23 16:42             ` Ferruh Yigit
2017-05-25 15:46   ` [RFC v3] " Ferruh Yigit
2017-05-25 15:46     ` [RFC v3] flow_classify: add librte_flow_classify library Ferruh Yigit
2017-05-30 12:59       ` Iremonger, Bernard
2017-08-23 13:51     ` [PATCH v1 0/6] Flow classification library Bernard Iremonger
2017-08-25 16:10       ` [PATCH v2 0/6] flow " Bernard Iremonger
2017-08-31 14:54         ` [PATCH v3 0/5] " Bernard Iremonger
2017-09-06 10:27           ` [PATCH v4 " Bernard Iremonger
2017-09-07 16:43             ` [PATCH v5 0/6] " Bernard Iremonger
2017-09-29  9:18               ` [PATCH v6 0/4] " Bernard Iremonger
2017-10-02  9:31                 ` [PATCH v7 " Bernard Iremonger
2017-10-17 20:26                   ` [PATCH v8 " Bernard Iremonger
2017-10-22 13:32                     ` [PATCH v9 " Bernard Iremonger
2017-10-23 15:16                       ` [PATCH v10 " Bernard Iremonger
2017-10-23 20:59                         ` Thomas Monjalon
2017-10-24  8:40                           ` Iremonger, Bernard
2017-10-24  9:23                             ` Mcnamara, John
2017-10-24  9:38                               ` Thomas Monjalon
2017-10-24  9:53                                 ` Iremonger, Bernard
2017-10-24 10:25                                   ` Thomas Monjalon
2017-10-24 17:27                         ` [PATCH v11 " Bernard Iremonger
2017-10-24 20:33                           ` Thomas Monjalon
2017-10-25  8:47                             ` Iremonger, Bernard
2017-10-25  8:56                               ` Thomas Monjalon
2017-10-24 17:28                         ` [PATCH v11 1/4] flow_classify: add flow classify library Bernard Iremonger
2017-10-24 19:39                           ` Thomas Monjalon
2017-10-25 11:10                             ` Iremonger, Bernard
2017-10-25 12:13                               ` Thomas Monjalon
2017-10-24 19:41                           ` Thomas Monjalon
2017-10-24 19:43                           ` Thomas Monjalon
2017-10-24 20:05                           ` Thomas Monjalon
2017-10-24 20:16                           ` Thomas Monjalon
2017-10-24 20:18                           ` Thomas Monjalon
2017-10-24 17:28                         ` [PATCH v11 2/4] examples/flow_classify: flow classify sample application Bernard Iremonger
2017-10-24 20:13                           ` Thomas Monjalon
2017-10-24 17:28                         ` [PATCH v11 3/4] test: add packet burst generator functions Bernard Iremonger
2017-10-24 17:28                         ` [PATCH v11 4/4] test: flow classify library unit tests Bernard Iremonger
2017-10-23 15:16                       ` [PATCH v10 1/4] librte_flow_classify: add flow classify library Bernard Iremonger
2017-10-23 16:03                         ` Singh, Jasvinder
2017-10-24  9:50                         ` Thomas Monjalon
2017-10-24 10:09                           ` Iremonger, Bernard
2017-10-23 15:16                       ` [PATCH v10 2/4] examples/flow_classify: flow classify sample application Bernard Iremonger
2017-10-23 16:04                         ` Singh, Jasvinder
2017-10-23 15:16                       ` [PATCH v10 3/4] test: add packet burst generator functions Bernard Iremonger
2017-10-23 16:05                         ` Singh, Jasvinder
2017-10-23 15:16                       ` [PATCH v10 4/4] test: flow classify library unit tests Bernard Iremonger
2017-10-23 16:06                         ` Singh, Jasvinder
2017-10-22 13:32                     ` [PATCH v9 1/4] librte_flow_classify: add flow classify library Bernard Iremonger
2017-10-23 13:21                       ` Singh, Jasvinder
2017-10-23 13:37                         ` Iremonger, Bernard
2017-10-22 13:32                     ` [PATCH v9 2/4] examples/flow_classify: flow classify sample application Bernard Iremonger
2017-10-22 13:32                     ` [PATCH v9 3/4] test: add packet burst generator functions Bernard Iremonger
2017-10-22 13:32                     ` [PATCH v9 4/4] test: flow classify library unit tests Bernard Iremonger
2017-10-17 20:26                   ` [PATCH v8 1/4] librte_flow_classify: add flow classify library Bernard Iremonger
2017-10-19 14:22                     ` Singh, Jasvinder
2017-10-20 16:59                       ` Iremonger, Bernard
2017-10-21 12:07                         ` Iremonger, Bernard
2017-10-17 20:26                   ` [PATCH v8 2/4] examples/flow_classify: flow classify sample application Bernard Iremonger
2017-10-17 20:26                   ` [PATCH v8 3/4] test: add packet burst generator functions Bernard Iremonger
2017-10-17 20:26                   ` [PATCH v8 4/4] test: flow classify library unit tests Bernard Iremonger
2017-10-02  9:31                 ` [PATCH v7 1/4] librte_flow_classify: add librte_flow_classify library Bernard Iremonger
2017-10-06 15:00                   ` Singh, Jasvinder
2017-10-09  9:28                     ` Mcnamara, John
2017-10-13 15:39                     ` Iremonger, Bernard
2017-10-02  9:31                 ` [PATCH v7 2/4] examples/flow_classify: flow classify sample application Bernard Iremonger
2017-10-02  9:31                 ` [PATCH v7 3/4] test: add packet burst generator functions Bernard Iremonger
2017-10-02  9:31                 ` [PATCH v7 4/4] test: flow classify library unit tests Bernard Iremonger
2017-09-29  9:18               ` [PATCH v6 1/4] librte_flow_classify: add librte_flow_classify library Bernard Iremonger
2017-09-29  9:18               ` Bernard Iremonger [this message]
2017-09-29  9:18               ` [PATCH v6 3/4] test: add packet burst generator functions Bernard Iremonger
2017-09-29  9:18               ` [PATCH v6 4/4] test: flow classify library unit tests Bernard Iremonger
2017-09-07 16:43             ` [PATCH v5 1/6] librte_table: fix acl entry add and delete functions Bernard Iremonger
2017-09-18 15:29               ` Singh, Jasvinder
2017-09-20 12:21                 ` Dumitrescu, Cristian
2017-09-29  8:25                   ` Iremonger, Bernard
2017-09-07 16:43             ` [PATCH v5 2/6] librte_table: fix acl lookup function Bernard Iremonger
2017-09-20 12:24               ` Dumitrescu, Cristian
2017-09-29  8:27                 ` Iremonger, Bernard
2017-09-07 16:43             ` [PATCH v5 3/6] librte_flow_classify: add librte_flow_classify library Bernard Iremonger
2017-09-07 16:43             ` [PATCH v5 4/6] examples/flow_classify: flow classify sample application Bernard Iremonger
2017-09-07 16:43             ` [PATCH v5 5/6] test: add packet burst generator functions Bernard Iremonger
2017-09-07 16:43             ` [PATCH v5 6/6] test: flow classify library unit tests Bernard Iremonger
2017-09-06 10:27           ` [PATCH v4 1/5] librte_table: fix acl entry add and delete functions Bernard Iremonger
2017-09-06 10:27           ` [PATCH v4 2/5] librte_table: fix acl lookup function Bernard Iremonger
2017-09-06 10:27           ` [PATCH v4 3/5] librte_flow_classify: add librte_flow_classify library Bernard Iremonger
2017-09-06 10:27           ` [PATCH v4 4/5] examples/flow_classify: flow classify sample application Bernard Iremonger
2017-09-06 10:27           ` [PATCH v4 5/5] test: flow classify library unit tests Bernard Iremonger
2017-08-31 14:54         ` [PATCH v3 1/5] librte_table: fix acl entry add and delete functions Bernard Iremonger
2017-08-31 15:09           ` Pavan Nikhilesh Bhagavatula
2017-08-31 14:54         ` [PATCH v3 2/5] librte_table: fix acl lookup function Bernard Iremonger
2017-08-31 14:54         ` [PATCH v3 3/5] librte_flow_classify: add librte_flow_classify library Bernard Iremonger
2017-08-31 15:18           ` Pavan Nikhilesh Bhagavatula
2017-08-31 14:54         ` [PATCH v3 4/5] examples/flow_classify: flow classify sample application Bernard Iremonger
2017-08-31 14:54         ` [PATCH v3 5/5] test: flow classify library unit tests Bernard Iremonger
2017-08-25 16:10       ` [PATCH v2 1/6] librte_table: fix acl entry add and delete functions Bernard Iremonger
2017-08-25 16:10       ` [PATCH v2 2/6] librte_table: fix acl lookup function Bernard Iremonger
2017-08-25 16:10       ` [PATCH v2 3/6] librte_ether: initialise IPv4 protocol mask for rte_flow Bernard Iremonger
2017-08-30 12:39         ` Adrien Mazarguil
2017-08-30 13:28           ` Iremonger, Bernard
2017-08-30 14:39             ` Adrien Mazarguil
2017-08-30 15:12               ` Iremonger, Bernard
2017-08-25 16:10       ` [PATCH v2 4/6] librte_flow_classify: add librte_flow_classify library Bernard Iremonger
2017-08-25 16:10       ` [PATCH v2 5/6] examples/flow_classify: flow classify sample application Bernard Iremonger
2017-08-25 16:10       ` [PATCH v2 6/6] test: flow classify library unit tests Bernard Iremonger
2017-08-23 13:51     ` [PATCH v1 1/6] librte_table: move structure to header file Bernard Iremonger
2017-08-23 14:13       ` Dumitrescu, Cristian
2017-08-23 14:32         ` Iremonger, Bernard
2017-08-28  8:48           ` Iremonger, Bernard
2017-08-23 13:51     ` [PATCH v1 2/6] librte_table: fix acl entry add and delete functions Bernard Iremonger
2017-08-23 13:51     ` [PATCH v1 3/6] librte_ether: initialise IPv4 protocol mask for rte_flow Bernard Iremonger
2017-08-23 13:51     ` [PATCH v1 4/6] librte_flow_classify: add librte_flow_classify library Bernard Iremonger
2017-08-23 13:51     ` [PATCH v1 5/6] examples/flow_classify: flow classify sample application Bernard Iremonger
2017-08-23 13:51     ` [PATCH v1 6/6] test: flow classify library unit tests Bernard Iremonger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1506676737-23900-3-git-send-email-bernard.iremonger@intel.com \
    --to=bernard.iremonger@intel.com \
    --cc=adrien.mazarguil@6wind.com \
    --cc=cristian.dumitrescu@intel.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=konstantin.ananyev@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.