[v2] linux-dpdk: packet: implement zero-copy concat

Message ID 1493367230-15468-1-git-send-email-matias.elo@nokia.com
State New
Headers show

Commit Message

Matias Elo April 28, 2017, 8:13 a.m.
Implement zero-copy packet concat using dpdk mbuf chaining. After reaching
maximum segment chain length (256) the implementation falls back to packet
copy.

Signed-off-by: Matias Elo <matias.elo@nokia.com>
Suggested-by: Nubin Stanley <nubin.stanley@nokia.com>
---
V2:
- Rebase

 platform/linux-dpdk/include/odp_packet_internal.h |  5 +++
 platform/linux-dpdk/odp_packet.c                  | 37 ++++++++++++++++++-----
 2 files changed, 35 insertions(+), 7 deletions(-)

Comments

Bill Fischofer April 30, 2017, 7:49 p.m. | #1
On Fri, Apr 28, 2017 at 3:13 AM, Matias Elo <matias.elo@nokia.com> wrote:

> Implement zero-copy packet concat using dpdk mbuf chaining. After reaching
> maximum segment chain length (256) the implementation falls back to packet
> copy.
>
> Signed-off-by: Matias Elo <matias.elo@nokia.com>
> Suggested-by: Nubin Stanley <nubin.stanley@nokia.com>
>

Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org>


> ---
> V2:
> - Rebase
>
>  platform/linux-dpdk/include/odp_packet_internal.h |  5 +++
>  platform/linux-dpdk/odp_packet.c                  | 37
> ++++++++++++++++++-----
>  2 files changed, 35 insertions(+), 7 deletions(-)
>
> diff --git a/platform/linux-dpdk/include/odp_packet_internal.h
> b/platform/linux-dpdk/include/odp_packet_internal.h
> index 56a664a..3d0173f 100644
> --- a/platform/linux-dpdk/include/odp_packet_internal.h
> +++ b/platform/linux-dpdk/include/odp_packet_internal.h
> @@ -192,6 +192,11 @@ static inline odp_packet_hdr_t
> *odp_packet_hdr(odp_packet_t pkt)
>         return (odp_packet_hdr_t *)(uintptr_t)pkt;
>  }
>
> +static inline struct rte_mbuf *pkt_to_mbuf(odp_packet_hdr_t *pkt_hdr)
> +{
> +       return &pkt_hdr->buf_hdr.mb;
> +}
> +
>  static inline void copy_packet_parser_metadata(odp_packet_hdr_t *src_hdr,
>                                                odp_packet_hdr_t *dst_hdr)
>  {
> diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_
> packet.c
> index a092d60..1460b2a 100644
> --- a/platform/linux-dpdk/odp_packet.c
> +++ b/platform/linux-dpdk/odp_packet.c
> @@ -815,17 +815,40 @@ int odp_packet_align(odp_packet_t *pkt, uint32_t
> offset, uint32_t len,
>
>  int odp_packet_concat(odp_packet_t *dst, odp_packet_t src)
>  {
> -       uint32_t dst_len = odp_packet_len(*dst);
> -       uint32_t src_len = odp_packet_len(src);
> +       odp_packet_hdr_t *dst_hdr = odp_packet_hdr(*dst);
> +       odp_packet_hdr_t *src_hdr = odp_packet_hdr(src);
> +       struct rte_mbuf *mb_dst = pkt_to_mbuf(dst_hdr);
> +       struct rte_mbuf *mb_src = pkt_to_mbuf(src_hdr);
> +       odp_packet_t new_dst;
> +       odp_pool_t pool;
> +       uint32_t dst_len;
> +       uint32_t src_len;
>
> -       if (odp_packet_extend_tail(dst, src_len, NULL, NULL) >= 0) {
> -               (void)odp_packet_copy_from_pkt(*dst, dst_len,
> +       if (odp_likely(!rte_pktmbuf_chain(mb_dst, mb_src))) {
> +               dst_hdr->buf_hdr.totsize += src_hdr->buf_hdr.totsize;
> +               return 0;
> +       }
> +
> +       /* Fall back to using standard copy operations after maximum
> number of
> +        * segments has been reached. */
> +       dst_len = odp_packet_len(*dst);
> +       src_len = odp_packet_len(src);
> +       pool = odp_packet_pool(*dst);
> +
> +       new_dst = odp_packet_copy(*dst, pool);
> +       if (odp_unlikely(new_dst == ODP_PACKET_INVALID))
> +               return -1;
> +
> +       if (odp_packet_extend_tail(&new_dst, src_len, NULL, NULL) >= 0) {
> +               (void)odp_packet_copy_from_pkt(new_dst, dst_len,
>                                                src, 0, src_len);
> -               if (src != *dst)
> -                       odp_packet_free(src);
> -               return 0;
> +               odp_packet_free(*dst);
> +               odp_packet_free(src);
> +               *dst = new_dst;
> +               return 1;
>         }
>
> +       odp_packet_free(new_dst);
>         return -1;
>  }
>
> --
> 2.7.4
>
> _______________________________________________
> lng-odp-dpdk mailing list
> lng-odp-dpdk@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp-dpdk
>
Krishna Garapati May 5, 2017, 12:38 p.m. | #2
Merged

/Krishna

On 30 April 2017 at 21:49, Bill Fischofer <bill.fischofer@linaro.org> wrote:

> On Fri, Apr 28, 2017 at 3:13 AM, Matias Elo <matias.elo@nokia.com> wrote:
>
> > Implement zero-copy packet concat using dpdk mbuf chaining. After
> reaching
> > maximum segment chain length (256) the implementation falls back to
> packet
> > copy.
> >
> > Signed-off-by: Matias Elo <matias.elo@nokia.com>
> > Suggested-by: Nubin Stanley <nubin.stanley@nokia.com>
> >
>
> Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org>
>
>
> > ---
> > V2:
> > - Rebase
> >
> >  platform/linux-dpdk/include/odp_packet_internal.h |  5 +++
> >  platform/linux-dpdk/odp_packet.c                  | 37
> > ++++++++++++++++++-----
> >  2 files changed, 35 insertions(+), 7 deletions(-)
> >
> > diff --git a/platform/linux-dpdk/include/odp_packet_internal.h
> > b/platform/linux-dpdk/include/odp_packet_internal.h
> > index 56a664a..3d0173f 100644
> > --- a/platform/linux-dpdk/include/odp_packet_internal.h
> > +++ b/platform/linux-dpdk/include/odp_packet_internal.h
> > @@ -192,6 +192,11 @@ static inline odp_packet_hdr_t
> > *odp_packet_hdr(odp_packet_t pkt)
> >         return (odp_packet_hdr_t *)(uintptr_t)pkt;
> >  }
> >
> > +static inline struct rte_mbuf *pkt_to_mbuf(odp_packet_hdr_t *pkt_hdr)
> > +{
> > +       return &pkt_hdr->buf_hdr.mb;
> > +}
> > +
> >  static inline void copy_packet_parser_metadata(odp_packet_hdr_t
> *src_hdr,
> >                                                odp_packet_hdr_t *dst_hdr)
> >  {
> > diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_
> > packet.c
> > index a092d60..1460b2a 100644
> > --- a/platform/linux-dpdk/odp_packet.c
> > +++ b/platform/linux-dpdk/odp_packet.c
> > @@ -815,17 +815,40 @@ int odp_packet_align(odp_packet_t *pkt, uint32_t
> > offset, uint32_t len,
> >
> >  int odp_packet_concat(odp_packet_t *dst, odp_packet_t src)
> >  {
> > -       uint32_t dst_len = odp_packet_len(*dst);
> > -       uint32_t src_len = odp_packet_len(src);
> > +       odp_packet_hdr_t *dst_hdr = odp_packet_hdr(*dst);
> > +       odp_packet_hdr_t *src_hdr = odp_packet_hdr(src);
> > +       struct rte_mbuf *mb_dst = pkt_to_mbuf(dst_hdr);
> > +       struct rte_mbuf *mb_src = pkt_to_mbuf(src_hdr);
> > +       odp_packet_t new_dst;
> > +       odp_pool_t pool;
> > +       uint32_t dst_len;
> > +       uint32_t src_len;
> >
> > -       if (odp_packet_extend_tail(dst, src_len, NULL, NULL) >= 0) {
> > -               (void)odp_packet_copy_from_pkt(*dst, dst_len,
> > +       if (odp_likely(!rte_pktmbuf_chain(mb_dst, mb_src))) {
> > +               dst_hdr->buf_hdr.totsize += src_hdr->buf_hdr.totsize;
> > +               return 0;
> > +       }
> > +
> > +       /* Fall back to using standard copy operations after maximum
> > number of
> > +        * segments has been reached. */
> > +       dst_len = odp_packet_len(*dst);
> > +       src_len = odp_packet_len(src);
> > +       pool = odp_packet_pool(*dst);
> > +
> > +       new_dst = odp_packet_copy(*dst, pool);
> > +       if (odp_unlikely(new_dst == ODP_PACKET_INVALID))
> > +               return -1;
> > +
> > +       if (odp_packet_extend_tail(&new_dst, src_len, NULL, NULL) >= 0)
> {
> > +               (void)odp_packet_copy_from_pkt(new_dst, dst_len,
> >                                                src, 0, src_len);
> > -               if (src != *dst)
> > -                       odp_packet_free(src);
> > -               return 0;
> > +               odp_packet_free(*dst);
> > +               odp_packet_free(src);
> > +               *dst = new_dst;
> > +               return 1;
> >         }
> >
> > +       odp_packet_free(new_dst);
> >         return -1;
> >  }
> >
> > --
> > 2.7.4
> >
> > _______________________________________________
> > lng-odp-dpdk mailing list
> > lng-odp-dpdk@lists.linaro.org
> > https://lists.linaro.org/mailman/listinfo/lng-odp-dpdk
> >
> _______________________________________________
> lng-odp-dpdk mailing list
> lng-odp-dpdk@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp-dpdk
>

Patch

diff --git a/platform/linux-dpdk/include/odp_packet_internal.h b/platform/linux-dpdk/include/odp_packet_internal.h
index 56a664a..3d0173f 100644
--- a/platform/linux-dpdk/include/odp_packet_internal.h
+++ b/platform/linux-dpdk/include/odp_packet_internal.h
@@ -192,6 +192,11 @@  static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt)
 	return (odp_packet_hdr_t *)(uintptr_t)pkt;
 }
 
+static inline struct rte_mbuf *pkt_to_mbuf(odp_packet_hdr_t *pkt_hdr)
+{
+	return &pkt_hdr->buf_hdr.mb;
+}
+
 static inline void copy_packet_parser_metadata(odp_packet_hdr_t *src_hdr,
 					       odp_packet_hdr_t *dst_hdr)
 {
diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_packet.c
index a092d60..1460b2a 100644
--- a/platform/linux-dpdk/odp_packet.c
+++ b/platform/linux-dpdk/odp_packet.c
@@ -815,17 +815,40 @@  int odp_packet_align(odp_packet_t *pkt, uint32_t offset, uint32_t len,
 
 int odp_packet_concat(odp_packet_t *dst, odp_packet_t src)
 {
-	uint32_t dst_len = odp_packet_len(*dst);
-	uint32_t src_len = odp_packet_len(src);
+	odp_packet_hdr_t *dst_hdr = odp_packet_hdr(*dst);
+	odp_packet_hdr_t *src_hdr = odp_packet_hdr(src);
+	struct rte_mbuf *mb_dst = pkt_to_mbuf(dst_hdr);
+	struct rte_mbuf *mb_src = pkt_to_mbuf(src_hdr);
+	odp_packet_t new_dst;
+	odp_pool_t pool;
+	uint32_t dst_len;
+	uint32_t src_len;
 
-	if (odp_packet_extend_tail(dst, src_len, NULL, NULL) >= 0) {
-		(void)odp_packet_copy_from_pkt(*dst, dst_len,
+	if (odp_likely(!rte_pktmbuf_chain(mb_dst, mb_src))) {
+		dst_hdr->buf_hdr.totsize += src_hdr->buf_hdr.totsize;
+		return 0;
+	}
+
+	/* Fall back to using standard copy operations after maximum number of
+	 * segments has been reached. */
+	dst_len = odp_packet_len(*dst);
+	src_len = odp_packet_len(src);
+	pool = odp_packet_pool(*dst);
+
+	new_dst = odp_packet_copy(*dst, pool);
+	if (odp_unlikely(new_dst == ODP_PACKET_INVALID))
+		return -1;
+
+	if (odp_packet_extend_tail(&new_dst, src_len, NULL, NULL) >= 0) {
+		(void)odp_packet_copy_from_pkt(new_dst, dst_len,
 					       src, 0, src_len);
-		if (src != *dst)
-			odp_packet_free(src);
-		return 0;
+		odp_packet_free(*dst);
+		odp_packet_free(src);
+		*dst = new_dst;
+		return 1;
 	}
 
+	odp_packet_free(new_dst);
 	return -1;
 }