[ovs-dev] [RFC v6 06/11] dp-packet: Handle multi-seg mbufs in put*() funcs.

Tiago Lam tiago.lam at intel.com
Wed May 16 17:32:38 UTC 2018


The dp_packet_put*() function - dp_packet_put_uninit(), dp_packet_put()
and dp_packet_put_zeros() - are, in their current implementation,
operating on the data buffer of a dp_packet as if it were contiguous,
which in the case of multi-segment mbufs means they operate on the first
mbuf in the chain. However, in the case of dp_packet_put_uninit(), for
example, it is the data length of the last mbuf in the mbuf chain that
should be adjusted. These functions have thus been modified to support
multi-segment mbufs.

Additionally, most of the core logic in dp_pcket_put_uninit() was moved
to a new helper function, dp_packet_put_uninit()_, to abstract the
implementation details from the API, since in the case of multi-seg
mbufs a new struct is returned that holds the mbuf and offset that
constitute the tail. For the single mbuf case a pointer to the byte that
constitute the tail still returned.

Co-authored-by: Mark Kavanagh <mark.b.kavanagh at intel.com>

Signed-off-by: Mark Kavanagh <mark.b.kavanagh at intel.com>
Signed-off-by: Tiago Lam <tiago.lam at intel.com>
---
 lib/dp-packet.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 lib/dp-packet.h |  7 +++++
 2 files changed, 92 insertions(+), 13 deletions(-)

diff --git a/lib/dp-packet.c b/lib/dp-packet.c
index 782e7c2..eefde37 100644
--- a/lib/dp-packet.c
+++ b/lib/dp-packet.c
@@ -312,27 +312,67 @@ dp_packet_shift(struct dp_packet *b, int delta)
     }
 }
 
-/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
- * copying its data if necessary.  Returns a pointer to the first byte of the
- * new data, which is left uninitialized. */
-void *
-dp_packet_put_uninit(struct dp_packet *b, size_t size)
+static void *
+dp_packet_put_uninit_(struct dp_packet *b, size_t size)
 {
     void *p;
     dp_packet_prealloc_tailroom(b, size);
+#ifdef DPDK_NETDEV
+    p = dp_packet_mbuf_tail(b);
+    /* In the case of multi-segment mbufs, the data length of the last mbuf
+     * should be adjusted by 'size' bytes. The packet length of the entire
+     * mbuf chain (stored in the first mbuf of said chain) is adjusted in
+     * the normal execution path below.
+     */
+
+    struct rte_mbuf *tmbuf = (struct rte_mbuf *) p;
+    struct mbuf_tail *mbuf_tail = xmalloc(sizeof(*mbuf_tail));
+    size_t pkt_len = size;
+
+    mbuf_tail->mbuf = tmbuf;
+    mbuf_tail->ofs = tmbuf->data_len;
+
+    /* Adjust size of intermediate mbufs from current tail to end */
+    while (tmbuf && pkt_len > 0) {
+        tmbuf->data_len = MIN(pkt_len, (rte_pktmbuf_mtod(tmbuf, char *) +
+            tmbuf->buf_len) - rte_pktmbuf_mtod(tmbuf, char *));
+        pkt_len -= tmbuf->data_len;
+
+        tmbuf = tmbuf->next;
+    }
+
+    p = (void *) mbuf_tail;
+#else
     p = dp_packet_tail(b);
+#endif
     dp_packet_set_size(b, dp_packet_size(b) + size);
+
     return p;
 }
 
-/* Appends 'size' zeroed bytes to the tail end of 'b'.  Data in 'b' is
- * reallocated and copied if necessary.  Returns a pointer to the first byte of
- * the data's location in the dp_packet. */
+static void *
+dp_packet_tail_to_addr(struct dp_packet *b OVS_UNUSED, void *p) {
+#ifdef DPDK_NETDEV
+    struct mbuf_tail *mbuf_tail = (struct mbuf_tail *) p;
+    p = (void *) rte_pktmbuf_mtod_offset(mbuf_tail->mbuf, void *,
+                                         mbuf_tail->ofs);
+#endif
+
+    return p;
+}
+
+/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
+ * copying its data if necessary.  Returns a pointer to the first byte of the
+ * new data, which is left uninitialized. */
 void *
-dp_packet_put_zeros(struct dp_packet *b, size_t size)
+dp_packet_put_uninit(struct dp_packet *b, size_t size)
 {
-    void *dst = dp_packet_put_uninit(b, size);
-    memset(dst, 0, size);
+    void *tail = dp_packet_put_uninit_(b, size);
+
+    void *dst = dp_packet_tail_to_addr(b, tail);
+
+    free(tail);
+
     return dst;
 }
 
@@ -342,8 +382,40 @@ dp_packet_put_zeros(struct dp_packet *b, size_t size)
 void *
 dp_packet_put(struct dp_packet *b, const void *p, size_t size)
 {
-    void *dst = dp_packet_put_uninit(b, size);
-    memcpy(dst, p, size);
+    void *tail = dp_packet_put_uninit_(b, size);
+#ifdef DPDK_NETDEV
+    struct mbuf_tail *mbuf_tail = (struct mbuf_tail *) tail;
+
+    dp_packet_mbuf_write(mbuf_tail->mbuf, mbuf_tail->ofs, size, p);
+#else
+    memcpy(tail, p, size);
+#endif
+
+    void *dst = dp_packet_tail_to_addr(b, tail);
+
+    free(tail);
+
+    return dst;
+}
+
+/* Appends 'size' zeroed bytes to the tail end of 'b'.  Data in 'b' is
+ * reallocated and copied if necessary.  Returns a pointer to the first byte of
+ * the data's location in the dp_packet. */
+void *
+dp_packet_put_zeros(struct dp_packet *b, size_t size)
+{
+    void *dst;
+#ifdef DPDK_NETDEV
+    char zeros[size];
+    memset(zeros, 0, size);
+
+    dst = dp_packet_put(b, zeros, size);
+
+    return dst;
+#endif
+    dst = dp_packet_put_uninit(b, size);
+    memset(dst, 0, size);
+
     return dst;
 }
 
diff --git a/lib/dp-packet.h b/lib/dp-packet.h
index 35ee6df..fcfa2d6 100644
--- a/lib/dp-packet.h
+++ b/lib/dp-packet.h
@@ -80,6 +80,13 @@ struct dp_packet {
     };
 };
 
+#ifdef DPDK_NETDEV
+struct mbuf_tail {
+    struct rte_mbuf *mbuf;
+    uint16_t ofs;
+};
+#endif
+
 static inline void *dp_packet_data(const struct dp_packet *);
 static inline void dp_packet_set_data(struct dp_packet *, void *);
 static inline void *dp_packet_base(const struct dp_packet *);
-- 
2.7.4



More information about the dev mailing list