DPDK patches and discussions
 help / color / mirror / Atom feed
From: Olivier Matz <olivier.matz@6wind.com>
To: Stephen Hemminger <stephen@networkplumber.org>
Cc: dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH v5 4/5] mbuf: add a pktmbuf copy routine
Date: Tue, 8 Oct 2019 11:03:34 +0200	[thread overview]
Message-ID: <20191008090334.GS7277@glumotte.dev.6wind.com> (raw)
In-Reply-To: <20191007154343.8556-5-stephen@networkplumber.org>

Hi Stephen,

Thank you for this patch. Few comments below.

On Mon, Oct 07, 2019 at 08:43:42AM -0700, Stephen Hemminger wrote:
> 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);

I think ol_flags should be copied too.
Take care to not copy the IND_ATTACHED_MBUF bit.

> +
> +	/* 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);

I'm not sure doing the copy on the MIN() length is a good solution.
Nothing states that the priv area of different mbuf pools are compatible.

I suggest to drop the priv copy, like it's done for the clone. An
application can provide its own functions for copy and clone, and can
adapt the priv copy to its needs.

An alternative is to allocate from the same pool than m, but I prefer
the first solution.

> +
> +	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;
> +			}

For segments 2 to n, the headroom is useless. An optimization could
be to remove the headroom here.

> +			++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;
> +}
> +

The names "dst" and "src" looks clearer than "mi" (for indirect mbuf)
and "m", knowing that this function can deal with 2 direct mbufs.


>  /**
>   * 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.

Although it's not consistent everywhere, I think the imperative
form is preferred ("Create" instead of "Creates").

> + * Copies all the data from a given packet mbuf to a newly allocated
> + * set of mbufs.

Same here

> + *
> + * @param m
> + *   The packet mbuf to be cloned.

cloned -> copied (there are some other occurrences of "clone" below)

> + * @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
> 

  reply	other threads:[~2019-10-08  9:03 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   ` [dpdk-dev] [PATCH v5 4/5] mbuf: add a pktmbuf copy routine Stephen Hemminger
2019-10-08  9:03     ` Olivier Matz [this message]
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=20191008090334.GS7277@glumotte.dev.6wind.com \
    --to=olivier.matz@6wind.com \
    --cc=dev@dpdk.org \
    --cc=stephen@networkplumber.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 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).