From: Stephen Hemminger <stephen@networkplumber.org>
To: dev@dpdk.org
Cc: Stephen Hemminger <stephen@networkplumber.org>
Subject: [dpdk-dev] [PATCH v5 4/5] mbuf: add a pktmbuf copy routine
Date: Mon, 7 Oct 2019 08:43:42 -0700 [thread overview]
Message-ID: <20191007154343.8556-5-stephen@networkplumber.org> (raw)
In-Reply-To: <20191007154343.8556-1-stephen@networkplumber.org>
This is a commonly used operation that surprisingly the
DPDK has not supported. The new rte_pktmbuf_copy does a
deep copy of packet. This is a complete copy including
meta-data.
It handles the case where the source mbuf comes from a pool
with larger data area than the destination pool. The routine
also has options for skipping data, or truncating at a fixed
length.
This patch also introduces internal inline to copy the
metadata fields of mbuf.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
lib/librte_mbuf/rte_mbuf.c | 69 ++++++++++++++++++++++++++++
lib/librte_mbuf/rte_mbuf.h | 53 +++++++++++++++++----
lib/librte_mbuf/rte_mbuf_version.map | 1 +
3 files changed, 113 insertions(+), 10 deletions(-)
diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c
index 9a1a1b5f9468..d5c9488fa213 100644
--- a/lib/librte_mbuf/rte_mbuf.c
+++ b/lib/librte_mbuf/rte_mbuf.c
@@ -321,6 +321,75 @@ __rte_pktmbuf_linearize(struct rte_mbuf *mbuf)
return 0;
}
+/* Create a deep copy of mbuf */
+struct rte_mbuf *
+rte_pktmbuf_copy(const struct rte_mbuf *m, struct rte_mempool *mp,
+ uint32_t off, uint32_t len)
+{
+ const struct rte_mbuf *seg = m;
+ struct rte_mbuf *mc, *m_last, **prev;
+ uint16_t priv_size;
+
+ if (unlikely(off >= m->pkt_len))
+ return NULL;
+
+ mc = rte_pktmbuf_alloc(mp);
+ if (unlikely(mc == NULL))
+ return NULL;
+
+ if (len > m->pkt_len - off)
+ len = m->pkt_len - off;
+
+ __rte_pktmbuf_copy_hdr(mc, m);
+
+ /* copy private area (can be 0) */
+ priv_size = RTE_MIN(rte_pktmbuf_priv_size(mp),
+ rte_pktmbuf_priv_size(m->pool));
+ rte_memcpy(mc + 1, m + 1, priv_size);
+
+ prev = &mc->next;
+ m_last = mc;
+ while (len > 0) {
+ uint32_t copy_len;
+
+ while (off >= seg->data_len) {
+ off -= seg->data_len;
+ seg = seg->next;
+ }
+
+ /* current buffer is full, chain a new one */
+ if (rte_pktmbuf_tailroom(m_last) == 0) {
+ m_last = rte_pktmbuf_alloc(mp);
+ if (unlikely(m_last == NULL)) {
+ rte_pktmbuf_free(mc);
+ return NULL;
+ }
+ ++mc->nb_segs;
+ *prev = m_last;
+ prev = &m_last->next;
+ }
+
+ copy_len = RTE_MIN(seg->data_len - off, len);
+ if (copy_len > rte_pktmbuf_tailroom(m_last))
+ copy_len = rte_pktmbuf_tailroom(m_last);
+
+ /* append from seg to m_last */
+ rte_memcpy(rte_pktmbuf_mtod_offset(m_last, char *,
+ m_last->data_len),
+ rte_pktmbuf_mtod_offset(seg, char *,
+ off),
+ copy_len);
+
+ m_last->data_len += copy_len;
+ mc->pkt_len += copy_len;
+ off += copy_len;
+ len -= copy_len;
+ }
+
+ __rte_mbuf_sanity_check(mc, 1);
+ return mc;
+}
+
/* dump a mbuf on console */
void
rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len)
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 6133f12172ae..803ddf28496e 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -1684,6 +1684,19 @@ rte_pktmbuf_attach_extbuf(struct rte_mbuf *m, void *buf_addr,
*/
#define rte_pktmbuf_detach_extbuf(m) rte_pktmbuf_detach(m)
+/* internal */
+static inline void
+__rte_pktmbuf_copy_hdr(struct rte_mbuf *mi, const struct rte_mbuf *m)
+{
+ mi->port = m->port;
+ mi->vlan_tci = m->vlan_tci;
+ mi->vlan_tci_outer = m->vlan_tci_outer;
+ mi->tx_offload = m->tx_offload;
+ mi->hash = m->hash;
+ mi->packet_type = m->packet_type;
+ mi->timestamp = m->timestamp;
+}
+
/**
* Attach packet mbuf to another packet mbuf.
*
@@ -1721,23 +1734,17 @@ static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF;
}
- mi->buf_iova = m->buf_iova;
- mi->buf_addr = m->buf_addr;
- mi->buf_len = m->buf_len;
+ __rte_pktmbuf_copy_hdr(mi, m);
mi->data_off = m->data_off;
mi->data_len = m->data_len;
- mi->port = m->port;
- mi->vlan_tci = m->vlan_tci;
- mi->vlan_tci_outer = m->vlan_tci_outer;
- mi->tx_offload = m->tx_offload;
- mi->hash = m->hash;
+ mi->buf_iova = m->buf_iova;
+ mi->buf_addr = m->buf_addr;
+ mi->buf_len = m->buf_len;
mi->next = NULL;
mi->pkt_len = mi->data_len;
mi->nb_segs = 1;
- mi->packet_type = m->packet_type;
- mi->timestamp = m->timestamp;
__rte_mbuf_sanity_check(mi, 1);
__rte_mbuf_sanity_check(m, 0);
@@ -1927,6 +1934,32 @@ static inline void rte_pktmbuf_free(struct rte_mbuf *m)
struct rte_mbuf *
rte_pktmbuf_clone(struct rte_mbuf *md, struct rte_mempool *mp);
+/**
+ * Creates a full copy of a given packet mbuf.
+ *
+ * Copies all the data from a given packet mbuf to a newly allocated
+ * set of mbufs.
+ *
+ * @param m
+ * The packet mbuf to be cloned.
+ * @param mp
+ * The mempool from which the "clone" mbufs are allocated.
+ * @param offset
+ * The number of bytes to skip before copying.
+ * If the mbuf does not have that many bytes, it is an error
+ * and NULL is returned.
+ * @param length
+ * The upper limit on bytes to copy. Passing UINT32_MAX
+ * means all data (after offset).
+ * @return
+ * - The pointer to the new "clone" mbuf on success.
+ * - NULL if allocation fails.
+ */
+__rte_experimental
+struct rte_mbuf *
+rte_pktmbuf_copy(const struct rte_mbuf *m, struct rte_mempool *mp,
+ uint32_t offset, uint32_t length);
+
/**
* Adds given value to the refcnt of all packet mbuf segments.
*
diff --git a/lib/librte_mbuf/rte_mbuf_version.map b/lib/librte_mbuf/rte_mbuf_version.map
index ff5c18a5559b..a50dcb6db9ec 100644
--- a/lib/librte_mbuf/rte_mbuf_version.map
+++ b/lib/librte_mbuf/rte_mbuf_version.map
@@ -57,4 +57,5 @@ EXPERIMENTAL {
global:
rte_mbuf_check;
+ rte_pktmbuf_copy;
} DPDK_18.08;
--
2.20.1
next prev parent reply other threads:[~2019-10-07 15:44 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-28 0:37 [dpdk-dev] [PATCH 0/5] mbuf related patches Stephen Hemminger
2019-09-28 0:37 ` [dpdk-dev] [PATCH 1/5] mbuf: don't generate invalid mbuf in clone test Stephen Hemminger
2019-09-28 0:37 ` [dpdk-dev] [PATCH 2/5] mbuf: delinline rte_pktmbuf_linearize Stephen Hemminger
2019-09-28 15:38 ` Stephen Hemminger
2019-09-30 9:00 ` Morten Brørup
2019-09-28 0:37 ` [dpdk-dev] [PATCH 3/5] mbuf: deinline rte_pktmbuf_clone Stephen Hemminger
2019-09-28 0:37 ` [dpdk-dev] [PATCH 4/5] mbuf: add a pktmbuf copy routine Stephen Hemminger
2019-09-30 13:26 ` Morten Brørup
2019-09-28 0:37 ` [dpdk-dev] [PATCH 5/5] mbuf: add pktmbuf copy test Stephen Hemminger
2019-09-30 15:27 ` [dpdk-dev] [PATCH v2 0/6] mbuf copy related enhancements Stephen Hemminger
2019-09-30 15:27 ` [dpdk-dev] [PATCH v2 1/6] mbuf: don't generate invalid mbuf in clone test Stephen Hemminger
2019-09-30 15:27 ` [dpdk-dev] [PATCH v2 2/6] mbuf: delinline rte_pktmbuf_linearize Stephen Hemminger
2019-09-30 15:27 ` [dpdk-dev] [PATCH v2 3/6] mbuf: deinline rte_pktmbuf_clone Stephen Hemminger
2019-09-30 15:27 ` [dpdk-dev] [PATCH v2 4/6] mbuf: add a pktmbuf copy routine Stephen Hemminger
2019-09-30 15:27 ` [dpdk-dev] [PATCH v2 5/6] mbuf: add pktmbuf copy test Stephen Hemminger
2019-09-30 15:27 ` [dpdk-dev] [PATCH v2 6/6] pdump: use new pktmbuf copy function Stephen Hemminger
2019-09-30 19:20 ` [dpdk-dev] [PATCH v3 0/6] mbuf copy/cloning enhancements Stephen Hemminger
2019-09-30 19:20 ` [dpdk-dev] [PATCH v3 1/6] mbuf: don't generate invalid mbuf in clone test Stephen Hemminger
2019-09-30 19:20 ` [dpdk-dev] [PATCH v3 2/6] mbuf: delinline rte_pktmbuf_linearize Stephen Hemminger
2019-10-01 13:41 ` Andrew Rybchenko
2019-09-30 19:20 ` [dpdk-dev] [PATCH v3 3/6] mbuf: deinline rte_pktmbuf_clone Stephen Hemminger
2019-10-01 13:42 ` Andrew Rybchenko
2019-09-30 19:20 ` [dpdk-dev] [PATCH v3 4/6] mbuf: add a pktmbuf copy routine Stephen Hemminger
2019-10-01 14:03 ` Andrew Rybchenko
2019-10-01 17:36 ` Slava Ovsiienko
2019-10-01 23:29 ` Stephen Hemminger
2019-09-30 19:20 ` [dpdk-dev] [PATCH v3 5/6] mbuf: add pktmbuf copy test Stephen Hemminger
2019-09-30 19:20 ` [dpdk-dev] [PATCH v3 6/6] pdump: use new pktmbuf copy function Stephen Hemminger
2019-10-04 21:47 ` [dpdk-dev] [PATCH v4 0/4] mbuf copy/cloning enhancements Stephen Hemminger
2019-10-04 21:47 ` [dpdk-dev] [PATCH v4 1/4] mbuf: don't generate invalid mbuf in clone test Stephen Hemminger
2019-10-04 21:47 ` [dpdk-dev] [PATCH v4 2/4] mbuf: delinline rte_pktmbuf_linearize Stephen Hemminger
2019-10-04 21:47 ` [dpdk-dev] [PATCH v4 3/4] mbuf: deinline rte_pktmbuf_clone Stephen Hemminger
2019-10-04 21:47 ` [dpdk-dev] [PATCH v4 4/4] mbuf: add a pktmbuf copy routine Stephen Hemminger
2019-10-07 15:43 ` [dpdk-dev] [PATCH v5 0/5] mbuf copy/cloning enhancements Stephen Hemminger
2019-10-07 15:43 ` [dpdk-dev] [PATCH v5 1/5] mbuf: don't generate invalid mbuf in clone test Stephen Hemminger
2019-10-08 8:13 ` Olivier Matz
2019-10-07 15:43 ` [dpdk-dev] [PATCH v5 2/5] mbuf: delinline rte_pktmbuf_linearize Stephen Hemminger
2019-10-08 8:14 ` Olivier Matz
2019-10-07 15:43 ` [dpdk-dev] [PATCH v5 3/5] mbuf: deinline rte_pktmbuf_clone Stephen Hemminger
2019-10-08 8:15 ` Olivier Matz
2019-10-07 15:43 ` Stephen Hemminger [this message]
2019-10-08 9:03 ` [dpdk-dev] [PATCH v5 4/5] mbuf: add a pktmbuf copy routine Olivier Matz
2019-10-08 15:27 ` Stephen Hemminger
2019-10-07 15:43 ` [dpdk-dev] [PATCH v5 5/5] mbuf: add pktmbuf copy test Stephen Hemminger
2019-10-08 9:04 ` Olivier Matz
2019-10-08 16:33 ` [dpdk-dev] [PATCH v6 0/5] mbuf: copy/cloning enhancements Stephen Hemminger
2019-10-08 16:33 ` [dpdk-dev] [PATCH v6 1/5] mbuf: don't generate invalid mbuf in clone test Stephen Hemminger
2019-10-17 5:01 ` David Marchand
2019-10-08 16:33 ` [dpdk-dev] [PATCH v6 2/5] mbuf: delinline rte_pktmbuf_linearize Stephen Hemminger
2019-10-17 5:01 ` David Marchand
2019-10-08 16:33 ` [dpdk-dev] [PATCH v6 3/5] mbuf: deinline rte_pktmbuf_clone Stephen Hemminger
2019-10-17 5:01 ` David Marchand
2019-10-08 16:33 ` [dpdk-dev] [PATCH v6 4/5] mbuf: add a pktmbuf copy routine Stephen Hemminger
2019-10-16 6:58 ` Olivier Matz
2019-10-17 5:01 ` David Marchand
2019-10-08 16:33 ` [dpdk-dev] [PATCH v6 5/5] mbuf: add pktmbuf copy test Stephen Hemminger
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=20191007154343.8556-5-stephen@networkplumber.org \
--to=stephen@networkplumber.org \
--cc=dev@dpdk.org \
/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.