DPDK patches and discussions
 help / color / mirror / Atom feed
From: Nitin Saxena <nsaxena@marvell.com>
To: Nithin Dabilpuram <ndabilpuram@marvell.com>,
	Pavan Nikhilesh <pbhagavatula@marvell.com>,
	Robin Jarry <rjarry@redhat.com>,
	"Christophe Fontaine" <cfontain@redhat.com>
Cc: <dev@dpdk.org>, Jerin Jacob <jerinj@marvell.com>,
	Nitin Saxena <nsaxena16@gmail.com>
Subject: [PATCH v6 1/2] node: add global node mbuf dynfield
Date: Mon, 28 Apr 2025 16:07:06 +0530	[thread overview]
Message-ID: <20250428103711.3317231-2-nsaxena@marvell.com> (raw)
In-Reply-To: <20250428103711.3317231-1-nsaxena@marvell.com>

This patch defines rte_node specific dynamic field structure
(rte_node_mbuf_dynfield_t)

rte_node_mbuf_dynfield_t structure holds two types of fields
- Persistent data fields which are preserved across graph walk.
  Currently size of persistent data fields is zero.
- Overloadable data fields which are used by any two adjacent nodes.
  Same fields can be repurposed by any other adjacent nodes

This dynfield can be also be used by out-of-tree nodes.

Signed-off-by: Nitin Saxena <nsaxena@marvell.com>
---
 doc/api/doxy-api-index.md              |   2 +
 doc/guides/rel_notes/release_25_07.rst |   6 ++
 lib/node/meson.build                   |   2 +
 lib/node/node_mbuf_dynfield.c          |  59 +++++++++++
 lib/node/rte_node_mbuf_dynfield.h      | 140 +++++++++++++++++++++++++
 5 files changed, 209 insertions(+)
 create mode 100644 lib/node/node_mbuf_dynfield.c
 create mode 100644 lib/node/rte_node_mbuf_dynfield.h

diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 5c425a2cb9..e1c85bcfbd 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -219,6 +219,8 @@ The public API headers are grouped by topics:
     [ip4_node](@ref rte_node_ip4_api.h),
     [ip6_node](@ref rte_node_ip6_api.h),
     [udp4_input_node](@ref rte_node_udp4_input_api.h)
+  * graph_nodes_mbuf:
+    [node_mbuf_dynfield](@ref rte_node_mbuf_dynfield.h)

 - **basic**:
   [bitops](@ref rte_bitops.h),
diff --git a/doc/guides/rel_notes/release_25_07.rst b/doc/guides/rel_notes/release_25_07.rst
index 093b85d206..2dc888e65d 100644
--- a/doc/guides/rel_notes/release_25_07.rst
+++ b/doc/guides/rel_notes/release_25_07.rst
@@ -55,6 +55,12 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================

+* **Added rte_node specific global mbuf dynamic field.**
+
+  Instead each node registering mbuf dynamic field for its own purpose, a
+  global structure is added which can be used/overloaded by all nodes
+  (including out-of-tree nodes). This minimizes footprint of node specific mbuf
+  dynamic field.

 Removed Items
 -------------
diff --git a/lib/node/meson.build b/lib/node/meson.build
index 0bed97a96c..152fe41129 100644
--- a/lib/node/meson.build
+++ b/lib/node/meson.build
@@ -8,6 +8,7 @@ if is_windows
 endif

 sources = files(
+        'node_mbuf_dynfield.c',
         'ethdev_ctrl.c',
         'ethdev_rx.c',
         'ethdev_tx.c',
@@ -30,6 +31,7 @@ headers = files(
         'rte_node_ip4_api.h',
         'rte_node_ip6_api.h',
         'rte_node_udp4_input_api.h',
+        'rte_node_mbuf_dynfield.h',
 )

 # Strict-aliasing rules are violated by uint8_t[] to context size casts.
diff --git a/lib/node/node_mbuf_dynfield.c b/lib/node/node_mbuf_dynfield.c
new file mode 100644
index 0000000000..6fbbf9604c
--- /dev/null
+++ b/lib/node/node_mbuf_dynfield.c
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2025 Marvell International Ltd.
+ */
+#include <rte_memzone.h>
+#include <rte_node_mbuf_dynfield.h>
+#include <node_private.h>
+#include <eal_export.h>
+#include <rte_errno.h>
+
+#define NODE_MBUF_DYNFIELD_MEMZONE_NAME "__rte_node_mbuf_dynfield"
+
+struct node_mbuf_dynfield_mz {
+	int dynfield_offset;
+};
+
+static const struct rte_mbuf_dynfield node_mbuf_dynfield_desc = {
+	.name = "rte_node_mbuf_dynfield",
+	.size = sizeof(rte_node_mbuf_dynfield_t),
+	.align = alignof(rte_node_mbuf_dynfield_t),
+};
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_mbuf_dynfield_register, 25.07);
+int rte_node_mbuf_dynfield_register(void)
+{
+	struct node_mbuf_dynfield_mz *f = NULL;
+	const struct rte_memzone *mz = NULL;
+	int dyn_offset;
+
+	RTE_BUILD_BUG_ON(sizeof(rte_node_mbuf_dynfield_t) < RTE_NODE_MBUF_DYNFIELD_SIZE);
+	RTE_BUILD_BUG_ON(sizeof(rte_node_mbuf_overload_fields_t) <
+			 RTE_NODE_MBUF_OVERLOADABLE_FIELDS_SIZE);
+
+	mz = rte_memzone_lookup(NODE_MBUF_DYNFIELD_MEMZONE_NAME);
+
+	if (!mz) {
+		mz = rte_memzone_reserve_aligned(NODE_MBUF_DYNFIELD_MEMZONE_NAME,
+						 sizeof(struct node_mbuf_dynfield_mz),
+						 SOCKET_ID_ANY, 0,
+						 RTE_CACHE_LINE_SIZE);
+		if (!mz) {
+			node_err("node_mbuf_dyn", "rte_memzone_reserve_aligned failed");
+			rte_errno = ENOMEM;
+			return -1;
+		}
+		dyn_offset = rte_mbuf_dynfield_register(&node_mbuf_dynfield_desc);
+		if (dyn_offset < 0) {
+			node_err("node_mbuf_dyn", "rte_mbuf_dynfield_register failed");
+			return dyn_offset;
+		}
+		f = (struct node_mbuf_dynfield_mz *)mz->addr;
+		f->dynfield_offset = dyn_offset;
+
+		node_dbg("node_mbuf_dyn", "memzone: %s of size: %zu at offset : %d",
+			 mz->name, mz->len, f->dynfield_offset);
+	} else {
+		f = (struct node_mbuf_dynfield_mz *)mz->addr;
+	}
+	return f->dynfield_offset;
+}
diff --git a/lib/node/rte_node_mbuf_dynfield.h b/lib/node/rte_node_mbuf_dynfield.h
new file mode 100644
index 0000000000..4db5382f91
--- /dev/null
+++ b/lib/node/rte_node_mbuf_dynfield.h
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2025 Marvell International Ltd.
+ */
+
+#ifndef _RTE_GRAPH_MBUF_DYNFIELD_H_
+#define _RTE_GRAPH_MBUF_DYNFIELD_H_
+
+#include <rte_common.h>
+#include <rte_mbuf.h>
+#include <rte_mbuf_dyn.h>
+
+/**
+ * @file: rte_node_mbuf_dynfield.h
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Defines rte_node specific mbuf dynamic field region [rte_node_mbuf_dynfield_t] which
+ * can used by both DPDK in-built and out-of-tree nodes for storing per-mbuf
+ * fields for graph walk
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Size of persistent mbuf fields */
+#define RTE_NODE_MBUF_PERSISTENT_FIELDS_SIZE          (0)
+/** Size of overloadable mbuf fields */
+#define RTE_NODE_MBUF_OVERLOADABLE_FIELDS_SIZE        (8)
+/** Size of node mbuf dynamic field */
+#define RTE_NODE_MBUF_DYNFIELD_SIZE     \
+	(RTE_NODE_MBUF_PERSISTENT_FIELDS_SIZE + RTE_NODE_MBUF_OVERLOADABLE_FIELDS_SIZE)
+
+/**
+ * Node mbuf overloadable data.
+ *
+ * Out-of-tree nodes can repurpose overloadable fields via
+ * rte_node_mbuf_overload_fields_get(mbuf). Overloadable fields are not
+ * preserved and typically can be used with-in two adjacent nodes in the graph.
+ */
+typedef struct rte_node_mbuf_overload_fields {
+	union {
+		uint8_t data[RTE_NODE_MBUF_OVERLOADABLE_FIELDS_SIZE];
+	};
+} rte_node_mbuf_overload_fields_t;
+
+/**
+ * rte_node specific mbuf dynamic field structure [rte_node_mbuf_dynfield_t]
+ *
+ * It holds two types of fields:
+ * 1. Persistent fields: Fields which are preserved across nodes during graph walk.
+ *    - Eg: rx/tx interface etc
+ * 2. Overloadable fields: Fields which can be repurposed by two adjacent nodes.
+ */
+typedef struct rte_node_mbuf_dynfield {
+	/**
+	 * Persistent mbuf region across nodes in graph walk
+	 *
+	 * These fields are preserved across graph walk and can be accessed by
+	 * rte_node_mbuf_dynfield_get() in fast path.
+	 */
+	union {
+		uint8_t persistent_data[RTE_NODE_MBUF_PERSISTENT_FIELDS_SIZE];
+	};
+	/**
+	 * Overloadable mbuf fields across graph walk. Fields which can change
+	 *
+	 * Two adjacent nodes (producer, consumer) can use this memory region for
+	 * sharing per-mbuf specific information. Once mbuf leaves a consumer node,
+	 * this region can be repurposed by another sets of [producer, consumer] node.
+	 *
+	 * In fast path, this region can be accessed by rte_node_mbuf_overload_fields_get()
+	 */
+	rte_node_mbuf_overload_fields_t overloadable_data;
+} rte_node_mbuf_dynfield_t;
+
+/**
+ * For a given mbuf and dynamic offset, return pointer to rte_node_mbuf_dynfield_t *
+ *
+ * @param m
+ *   Mbuf
+ * @param offset
+ *   Dynamic offset returned by @ref rte_node_mbuf_dynfield_register()
+ * @return
+ *  Pointer to node specific mbuf dynamic field structure
+ */
+__rte_experimental
+static __rte_always_inline rte_node_mbuf_dynfield_t *
+rte_node_mbuf_dynfield_get(struct rte_mbuf *m, const int offset)
+{
+	return RTE_MBUF_DYNFIELD(m, offset, struct rte_node_mbuf_dynfield *);
+}
+
+/**
+ * For a given mbuf and dynamic offset, return pointer to overloadable fields
+ * Nodes can typecast returned pointer to reuse for their own purpose
+ *
+ * @param m
+ *   Mbuf
+ * @param offset
+ *   Dynamic offset returned by @ref rte_node_mbuf_dynfield_register()
+ * @return
+ * Pointer to node mbuf overloadable fields
+ */
+__rte_experimental
+static __rte_always_inline rte_node_mbuf_overload_fields_t *
+rte_node_mbuf_overload_fields_get(struct rte_mbuf *m, const int offset)
+{
+	rte_node_mbuf_dynfield_t *f = NULL;
+
+	f = RTE_MBUF_DYNFIELD(m, offset, rte_node_mbuf_dynfield_t *);
+
+	return &(f->overloadable_data);
+}
+
+/**
+ *  Register rte_node specific common mbuf dynamic field region. Can be called
+ *  in rte_node_register()->init() function to save offset in node->ctx
+ *
+ *  In process() function, node->ctx can be passed to
+ *  - rte_node_mbuf_dynfield_get(mbuf, offset)
+ *  - rte_node_mbuf_overload_fields_get(mbuf, offset)
+ *
+ *  Can be called multiple times by any number of nodes in init() function.
+ *  - Very first call registers dynamic field and returns offset
+ *  - Subsequent calls return same offset
+ *
+ *  @return
+ *   <0 on error: rte_errno set to one of:
+ *    - ENOMEM - no memory
+ *   >=0 on success: dynamic field offset
+ */
+__rte_experimental
+int rte_node_mbuf_dynfield_register(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--
2.43.0


  reply	other threads:[~2025-04-28 10:37 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-01  4:20 [PATCH 0/2] node: add mbuf dynamic field for nodes Nitin Saxena
2025-04-01  4:20 ` [PATCH 1/2] node: add global node mbuf dynfield Nitin Saxena
2025-04-01 14:15   ` Stephen Hemminger
2025-04-03 10:27     ` Nitin Saxena
2025-04-04  8:11       ` [EXTERNAL] " Pavan Nikhilesh Bhagavatula
2025-04-04 15:21         ` Stephen Hemminger
2025-04-07  6:01           ` Nitin Saxena
2025-04-01  4:20 ` [PATCH 2/2] node: use node mbuf dynfield in ip4 nodes Nitin Saxena
2025-04-03 10:17 ` [PATCH v2 0/2] node: add mbuf dynamic field for nodes Nitin Saxena
2025-04-03 10:17   ` [PATCH v2 1/2] node: add global node mbuf dynfield Nitin Saxena
2025-04-03 10:17   ` [PATCH v2 2/2] node: use node mbuf dynfield in ip4 nodes Nitin Saxena
2025-04-04  7:12 ` [PATCH v3 0/2] node: add mbuf dynamic field for nodes Nitin Saxena
2025-04-04  7:12   ` [PATCH v3 1/2] node: add global node mbuf dynfield Nitin Saxena
2025-04-04 21:35     ` Stephen Hemminger
2025-04-04  7:12   ` [PATCH v3 2/2] node: use node mbuf dynfield in ip4 nodes Nitin Saxena
2025-04-07  7:47 ` [PATCH v4 0/2] node: add mbuf dynamic field for nodes Nitin Saxena
2025-04-07  7:47   ` [PATCH v4 1/2] node: add global node mbuf dynfield Nitin Saxena
2025-04-07  7:47   ` [PATCH v4 2/2] node: use node mbuf dynfield in ip4 nodes Nitin Saxena
2025-04-08  7:35   ` [PATCH v4 0/2] node: add mbuf dynamic field for nodes David Marchand
2025-04-08  8:42     ` Nitin Saxena
2025-04-09 13:55 ` [PATCH v5 " Nitin Saxena
2025-04-09 13:55   ` [PATCH v5 1/2] node: add global node mbuf dynfield Nitin Saxena
2025-04-18 19:03     ` Pavan Nikhilesh Bhagavatula
2025-04-28 10:42       ` Nitin Saxena
2025-04-09 13:55   ` [PATCH v5 2/2] node: use node mbuf dynfield in ip4 nodes Nitin Saxena
2025-04-28 10:37 ` [PATCH v6 0/2] node: add mbuf dynamic field for nodes Nitin Saxena
2025-04-28 10:37   ` Nitin Saxena [this message]
2025-04-28 10:37   ` [PATCH v6 2/2] node: use node mbuf dynfield in ip4 nodes Nitin Saxena

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=20250428103711.3317231-2-nsaxena@marvell.com \
    --to=nsaxena@marvell.com \
    --cc=cfontain@redhat.com \
    --cc=dev@dpdk.org \
    --cc=jerinj@marvell.com \
    --cc=ndabilpuram@marvell.com \
    --cc=nsaxena16@gmail.com \
    --cc=pbhagavatula@marvell.com \
    --cc=rjarry@redhat.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 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).