From: Nithin Dabilpuram <ndabilpuram@marvell.com>
To: <jerinj@marvell.com>, <ferruh.yigit@intel.com>,
<thomas@monjalon.net>, <ruifeng.wang@arm.com>,
<david.marchand@redhat.com>,
Nithin Dabilpuram <ndabilpuram@marvell.com>,
Pavan Nikhilesh <pbhagavatula@marvell.com>
Cc: <dev@dpdk.org>, Andrzej Ostruszka <amo@semihalf.com>,
<kkanas@marvell.com>
Subject: [dpdk-dev] [PATCH] node: add pkt classifier node
Date: Sun, 7 Jun 2020 22:10:42 +0530 [thread overview]
Message-ID: <20200607164042.24910-1-ndabilpuram@marvell.com> (raw)
This node classifies pkts based on packet type and
sends them to appropriate next node. This is node
helps in distribution of packets from ethdev_rx node
to different next node with a constant overhead for
all packet types.
Currently all except non fragmented IPV4 packets are marked
to be sent to "pkt_drop" node.
Performance difference on ARM64 Octeontx2 is -4.9% due to
addition of new node in the path.
Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
---
lib/librte_node/Makefile | 1 +
lib/librte_node/ethdev_rx.c | 20 +++-
lib/librte_node/ethdev_rx_priv.h | 2 +
lib/librte_node/ip4_lookup_neon.h | 1 -
lib/librte_node/meson.build | 2 +-
lib/librte_node/node_private.h | 2 +
lib/librte_node/pkt_cls.c | 225 ++++++++++++++++++++++++++++++++++++++
lib/librte_node/pkt_cls_priv.h | 27 +++++
8 files changed, 273 insertions(+), 7 deletions(-)
create mode 100644 lib/librte_node/pkt_cls.c
create mode 100644 lib/librte_node/pkt_cls_priv.h
diff --git a/lib/librte_node/Makefile b/lib/librte_node/Makefile
index 9dee8b4..3ec0210 100644
--- a/lib/librte_node/Makefile
+++ b/lib/librte_node/Makefile
@@ -23,6 +23,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_NODE) += ethdev_tx.c
SRCS-$(CONFIG_RTE_LIBRTE_NODE) += ethdev_ctrl.c
SRCS-$(CONFIG_RTE_LIBRTE_NODE) += ip4_lookup.c
SRCS-$(CONFIG_RTE_LIBRTE_NODE) += ip4_rewrite.c
+SRCS-$(CONFIG_RTE_LIBRTE_NODE) += pkt_cls.c
SRCS-$(CONFIG_RTE_LIBRTE_NODE) += pkt_drop.c
# install header files
diff --git a/lib/librte_node/ethdev_rx.c b/lib/librte_node/ethdev_rx.c
index 5cc7365..4c23961 100644
--- a/lib/librte_node/ethdev_rx.c
+++ b/lib/librte_node/ethdev_rx.c
@@ -16,9 +16,14 @@ static struct ethdev_rx_node_main ethdev_rx_main;
static __rte_always_inline uint16_t
ethdev_rx_node_process_inline(struct rte_graph *graph, struct rte_node *node,
- uint16_t port, uint16_t queue)
+ ethdev_rx_node_ctx_t *ctx)
{
- uint16_t count, next_index = ETHDEV_RX_NEXT_IP4_LOOKUP;
+ uint16_t count, next_index;
+ uint16_t port, queue;
+
+ port = ctx->port_id;
+ queue = ctx->queue_id;
+ next_index = ctx->cls_next;
/* Get pkts from port */
count = rte_eth_rx_burst(port, queue, (struct rte_mbuf **)node->objs,
@@ -43,8 +48,7 @@ ethdev_rx_node_process(struct rte_graph *graph, struct rte_node *node,
RTE_SET_USED(objs);
RTE_SET_USED(cnt);
- n_pkts = ethdev_rx_node_process_inline(graph, node, ctx->port_id,
- ctx->queue_id);
+ n_pkts = ethdev_rx_node_process_inline(graph, node, ctx);
return n_pkts;
}
@@ -191,6 +195,8 @@ ethdev_rx_node_init(const struct rte_graph *graph, struct rte_node *node)
RTE_VERIFY(elem != NULL);
+ ctx->cls_next = ETHDEV_RX_NEXT_PKT_CLS;
+
/* Check and setup ptype */
return ethdev_ptype_setup(ctx->port_id, ctx->queue_id);
}
@@ -209,7 +215,11 @@ static struct rte_node_register ethdev_rx_node_base = {
.init = ethdev_rx_node_init,
.nb_edges = ETHDEV_RX_NEXT_MAX,
- .next_nodes = {[ETHDEV_RX_NEXT_IP4_LOOKUP] = "ip4_lookup"},
+ .next_nodes = {
+ /* Default pkt classification node */
+ [ETHDEV_RX_NEXT_PKT_CLS] = "pkt_cls",
+ [ETHDEV_RX_NEXT_IP4_LOOKUP] = "ip4_lookup",
+ },
};
struct rte_node_register *
diff --git a/lib/librte_node/ethdev_rx_priv.h b/lib/librte_node/ethdev_rx_priv.h
index 2d7195a..efcd66d 100644
--- a/lib/librte_node/ethdev_rx_priv.h
+++ b/lib/librte_node/ethdev_rx_priv.h
@@ -23,6 +23,7 @@ typedef struct ethdev_rx_node_ctx ethdev_rx_node_ctx_t;
struct ethdev_rx_node_ctx {
uint16_t port_id; /**< Port identifier of the Rx node. */
uint16_t queue_id; /**< Queue identifier of the Rx node. */
+ uint16_t cls_next;
};
/**
@@ -41,6 +42,7 @@ struct ethdev_rx_node_elem {
enum ethdev_rx_next_nodes {
ETHDEV_RX_NEXT_IP4_LOOKUP,
+ ETHDEV_RX_NEXT_PKT_CLS,
ETHDEV_RX_NEXT_MAX,
};
diff --git a/lib/librte_node/ip4_lookup_neon.h b/lib/librte_node/ip4_lookup_neon.h
index dd21cb2..5e5a7d8 100644
--- a/lib/librte_node/ip4_lookup_neon.h
+++ b/lib/librte_node/ip4_lookup_neon.h
@@ -37,7 +37,6 @@ ip4_lookup_node_process(struct rte_graph *graph, struct rte_node *node,
from = objs;
n_left_from = nb_objs;
-#define OBJS_PER_CLINE (RTE_CACHE_LINE_SIZE / sizeof(void *))
for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += OBJS_PER_CLINE)
rte_prefetch0(&objs[i]);
diff --git a/lib/librte_node/meson.build b/lib/librte_node/meson.build
index 17f1316..3d582f6 100644
--- a/lib/librte_node/meson.build
+++ b/lib/librte_node/meson.build
@@ -2,7 +2,7 @@
# Copyright(C) 2020 Marvell International Ltd.
sources = files('null.c', 'log.c', 'ethdev_rx.c', 'ethdev_tx.c', 'ip4_lookup.c',
- 'ip4_rewrite.c', 'pkt_drop.c', 'ethdev_ctrl.c')
+ 'ip4_rewrite.c', 'pkt_drop.c', 'ethdev_ctrl.c', 'pkt_cls.c')
headers = files('rte_node_ip4_api.h', 'rte_node_eth_api.h')
# Strict-aliasing rules are violated by uint8_t[] to context size casts.
cflags += '-fno-strict-aliasing'
diff --git a/lib/librte_node/node_private.h b/lib/librte_node/node_private.h
index 975b9aa..ab7941c 100644
--- a/lib/librte_node/node_private.h
+++ b/lib/librte_node/node_private.h
@@ -46,6 +46,8 @@ struct node_mbuf_priv2 {
#define NODE_MBUF_PRIV2_SIZE sizeof(struct node_mbuf_priv2)
+#define OBJS_PER_CLINE (RTE_CACHE_LINE_SIZE / sizeof(void *))
+
/**
* Get mbuf_priv1 pointer from rte_mbuf.
*
diff --git a/lib/librte_node/pkt_cls.c b/lib/librte_node/pkt_cls.c
new file mode 100644
index 0000000..b95454d
--- /dev/null
+++ b/lib/librte_node/pkt_cls.c
@@ -0,0 +1,225 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2020 Marvell.
+ */
+
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_mbuf.h>
+#include <rte_graph.h>
+#include <rte_graph_worker.h>
+
+#include "pkt_cls_priv.h"
+#include "node_private.h"
+
+/* Next node for each ptype, default is '0' is "pkt_drop" */
+static const uint8_t p_nxt[256] __rte_cache_aligned = {
+ [RTE_PTYPE_L3_IPV4] = PKT_CLS_NEXT_IP4_LOOKUP,
+
+ [RTE_PTYPE_L3_IPV4_EXT] = PKT_CLS_NEXT_IP4_LOOKUP,
+
+ [RTE_PTYPE_L3_IPV4_EXT_UNKNOWN] = PKT_CLS_NEXT_IP4_LOOKUP,
+
+ [RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L2_ETHER] =
+ PKT_CLS_NEXT_IP4_LOOKUP,
+
+ [RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L2_ETHER] =
+ PKT_CLS_NEXT_IP4_LOOKUP,
+
+ [RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L2_ETHER] =
+ PKT_CLS_NEXT_IP4_LOOKUP,
+};
+
+static uint16_t
+pkt_cls_node_process(struct rte_graph *graph, struct rte_node *node,
+ void **objs, uint16_t nb_objs)
+{
+ struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts;
+ uint8_t l0, l1, l2, l3, last_type;
+ uint16_t next_index, n_left_from;
+ uint16_t held = 0, last_spec = 0;
+ struct pkt_cls_node_ctx *ctx;
+ void **to_next, **from;
+ uint32_t i;
+
+ pkts = (struct rte_mbuf **)objs;
+ from = objs;
+ n_left_from = nb_objs;
+
+ for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += OBJS_PER_CLINE)
+ rte_prefetch0(&objs[i]);
+
+#if RTE_GRAPH_BURST_SIZE > 64
+ for (i = 0; i < 4 && i < n_left_from; i++)
+ rte_prefetch0(pkts[i]);
+#endif
+
+ ctx = (struct pkt_cls_node_ctx *)node->ctx;
+ last_type = ctx->l2l3_type;
+ next_index = p_nxt[last_type];
+
+ /* Get stream for the speculated next node */
+ to_next = rte_node_next_stream_get(graph, node,
+ next_index, nb_objs);
+ while (n_left_from >= 4) {
+#if RTE_GRAPH_BURST_SIZE > 64
+ if (likely(n_left_from > 7)) {
+ rte_prefetch0(pkts[4]);
+ rte_prefetch0(pkts[5]);
+ rte_prefetch0(pkts[6]);
+ rte_prefetch0(pkts[7]);
+ }
+#endif
+
+ mbuf0 = pkts[0];
+ mbuf1 = pkts[1];
+ mbuf2 = pkts[2];
+ mbuf3 = pkts[3];
+ pkts += 4;
+ n_left_from -= 4;
+
+ l0 = mbuf0->packet_type &
+ (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
+ l1 = mbuf1->packet_type &
+ (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
+ l2 = mbuf2->packet_type &
+ (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
+ l3 = mbuf3->packet_type &
+ (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
+
+ /* Check if they are destined to same
+ * next node based on l2l3 packet type.
+ */
+ uint8_t fix_spec = (last_type ^ l0) | (last_type ^ l1) |
+ (last_type ^ l2) | (last_type ^ l3);
+
+ if (unlikely(fix_spec)) {
+ /* Copy things successfully speculated till now */
+ rte_memcpy(to_next, from,
+ last_spec * sizeof(from[0]));
+ from += last_spec;
+ to_next += last_spec;
+ held += last_spec;
+ last_spec = 0;
+
+ /* l0 */
+ if (p_nxt[l0] == next_index) {
+ to_next[0] = from[0];
+ to_next++;
+ held++;
+ } else {
+ rte_node_enqueue_x1(graph, node,
+ p_nxt[l0], from[0]);
+ }
+
+ /* l1 */
+ if (p_nxt[l1] == next_index) {
+ to_next[0] = from[1];
+ to_next++;
+ held++;
+ } else {
+ rte_node_enqueue_x1(graph, node,
+ p_nxt[l1], from[1]);
+ }
+
+ /* l2 */
+ if (p_nxt[l2] == next_index) {
+ to_next[0] = from[2];
+ to_next++;
+ held++;
+ } else {
+ rte_node_enqueue_x1(graph, node,
+ p_nxt[l2], from[2]);
+ }
+
+ /* l3 */
+ if (p_nxt[l3] == next_index) {
+ to_next[0] = from[3];
+ to_next++;
+ held++;
+ } else {
+ rte_node_enqueue_x1(graph, node,
+ p_nxt[l3], from[3]);
+ }
+
+ /* Update speculated ptype */
+ if ((last_type != l3) && (l2 == l3) &&
+ (next_index != p_nxt[l3])) {
+ /* Put the current stream for
+ * speculated ltype.
+ */
+ rte_node_next_stream_put(graph, node,
+ next_index, held);
+
+ held = 0;
+
+ /* Get next stream for new ltype */
+ next_index = p_nxt[l3];
+ last_type = l3;
+ to_next = rte_node_next_stream_get(graph, node,
+ next_index,
+ nb_objs);
+ } else if (next_index == p_nxt[l3]) {
+ last_type = l3;
+ }
+
+ from += 4;
+ } else {
+ last_spec += 4;
+ }
+ }
+
+ while (n_left_from > 0) {
+ mbuf0 = pkts[0];
+
+ pkts += 1;
+ n_left_from -= 1;
+
+ l0 = mbuf0->packet_type &
+ (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
+ if (unlikely((l0 != last_type) &&
+ (p_nxt[l0] != next_index))) {
+ /* Copy things successfully speculated till now */
+ rte_memcpy(to_next, from,
+ last_spec * sizeof(from[0]));
+ from += last_spec;
+ to_next += last_spec;
+ held += last_spec;
+ last_spec = 0;
+
+ rte_node_enqueue_x1(graph, node,
+ p_nxt[l0], from[0]);
+ from += 1;
+ } else {
+ last_spec += 1;
+ }
+ }
+
+ /* !!! Home run !!! */
+ if (likely(last_spec == nb_objs)) {
+ rte_node_next_stream_move(graph, node, next_index);
+ return nb_objs;
+ }
+
+ held += last_spec;
+ /* Copy things successfully speculated till now */
+ rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
+ rte_node_next_stream_put(graph, node, next_index, held);
+
+ ctx->l2l3_type = last_type;
+ return nb_objs;
+}
+
+/* Packet Classification Node */
+struct rte_node_register pkt_cls_node = {
+ .process = pkt_cls_node_process,
+ .name = "pkt_cls",
+
+ .nb_edges = PKT_CLS_NEXT_MAX,
+ .next_nodes = {
+ /* Pkt drop node starts at '0' */
+ [PKT_CLS_NEXT_PKT_DROP] = "pkt_drop",
+ [PKT_CLS_NEXT_IP4_LOOKUP] = "ip4_lookup",
+ },
+};
+RTE_NODE_REGISTER(pkt_cls_node);
diff --git a/lib/librte_node/pkt_cls_priv.h b/lib/librte_node/pkt_cls_priv.h
new file mode 100644
index 0000000..3f2bb04
--- /dev/null
+++ b/lib/librte_node/pkt_cls_priv.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2020 Marvell.
+ */
+#ifndef __INCLUDE_PKT_CLS_PRIV_H__
+#define __INCLUDE_PKT_CLS_PRIV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_common.h>
+
+struct pkt_cls_node_ctx {
+ uint16_t l2l3_type;
+};
+
+enum pkt_cls_next_nodes {
+ PKT_CLS_NEXT_PKT_DROP,
+ PKT_CLS_NEXT_IP4_LOOKUP,
+ PKT_CLS_NEXT_MAX,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_PKT_CLS_PRIV_H__ */
--
2.8.4
next reply other threads:[~2020-06-07 16:41 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-07 16:40 Nithin Dabilpuram [this message]
2020-07-21 23:01 ` Thomas Monjalon
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=20200607164042.24910-1-ndabilpuram@marvell.com \
--to=ndabilpuram@marvell.com \
--cc=amo@semihalf.com \
--cc=david.marchand@redhat.com \
--cc=dev@dpdk.org \
--cc=ferruh.yigit@intel.com \
--cc=jerinj@marvell.com \
--cc=kkanas@marvell.com \
--cc=pbhagavatula@marvell.com \
--cc=ruifeng.wang@arm.com \
--cc=thomas@monjalon.net \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).