When doing packet clone, if packet source is from DPDK driver,
multi-segment must be considered, and copy the segment's
data one by one.

Signed-off-by: Michael Qiu <qiud...@chinac.com>
Signed-off-by: Jijiang Liu <liujiji...@chinac.com>
---
 lib/dp-packet.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/lib/dp-packet.c b/lib/dp-packet.c
index 619f651..3ca1fde 100644
--- a/lib/dp-packet.c
+++ b/lib/dp-packet.c
@@ -164,9 +164,28 @@ dp_packet_clone_with_headroom(const struct dp_packet 
*buffer, size_t headroom)
 {
     struct dp_packet *new_buffer;
 
-    new_buffer = dp_packet_clone_data_with_headroom(dp_packet_data(buffer),
-                                                 dp_packet_size(buffer),
-                                                 headroom);
+    uint32_t size = dp_packet_size(buffer);
+
+    /* copy multi-seg data */
+    #ifdef DPDK_NETDEV
+    if (buffer->source == DPBUF_DPDK && buffer->mbuf.nb_segs > 1) {
+        struct rte_mbuf *tmbuf = &(buffer->mbuf);
+        new_buffer = dp_packet_new_with_headroom(size, headroom);
+        void *dst = dp_packet_put_uninit(new_buffer, size);
+        uint32_t off_set = 0;
+
+        while (tmbuf) {
+            rte_memcpy((char *)dst + off_set,
+                       rte_pktmbuf_mtod(tmbuf, void *), tmbuf->data_len);
+            off_set += tmbuf->data_len;
+            tmbuf = tmbuf->next;
+        }
+    }
+    else
+    #endif
+        new_buffer = dp_packet_clone_data_with_headroom(dp_packet_data(buffer),
+                                                        size, headroom);
+
     new_buffer->l2_pad_size = buffer->l2_pad_size;
     new_buffer->l2_5_ofs = buffer->l2_5_ofs;
     new_buffer->l3_ofs = buffer->l3_ofs;
-- 
1.8.3.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to