When the source port has VLAN strip enabled, captured packets have
the VLAN tag in mbuf metadata (vlan_tci) but not in the packet data.
Similarly, TX captures with pending VLAN insert have the tag only
in metadata. The resulting pcap files contain untagged packets.

Convert RX_VLAN_STRIPPED metadata to TX_VLAN offload requests on
dequeued mbufs and call rte_eth_tx_prepare() before rte_eth_tx_burst()
so the pcap vdev inserts the tag into the packet data.

Signed-off-by: Stephen Hemminger <[email protected]>
---
 lib/pdump/rte_pdump.c | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/lib/pdump/rte_pdump.c b/lib/pdump/rte_pdump.c
index ac94efe7ff..6ffe72e284 100644
--- a/lib/pdump/rte_pdump.c
+++ b/lib/pdump/rte_pdump.c
@@ -9,6 +9,7 @@
 #include <rte_mbuf.h>
 #include <rte_ethdev.h>
 #include <rte_lcore.h>
+#include <rte_ether.h>
 #include <rte_log.h>
 #include <rte_memzone.h>
 #include <rte_errno.h>
@@ -135,6 +136,29 @@ pdump_cb_release(struct pdump_rxtx_cbs *cbs)
        rte_atomic_store_explicit(&cbs->use_count, count, 
rte_memory_order_release);
 }
 
+/*
+ * Reconstruct VLAN tag in packet data if it was offloaded to metadata.
+ *
+ * When VLAN strip is active on RX, or VLAN insert is pending on TX,
+ * the VLAN tag exists only in mbuf metadata (vlan_tci / ol_flags)
+ * and not in the packet data.  For packet capture we need the
+ * complete wire-format packet, so insert the tag back into the
+ * cloned mbuf.
+ */
+static inline void
+pdump_vlan_restore(struct rte_mbuf *m)
+{
+       if (m->ol_flags & (RTE_MBUF_F_RX_VLAN_STRIPPED | RTE_MBUF_F_TX_VLAN)) {
+               if (rte_vlan_insert(&m) != 0)
+                       return;
+               /*
+                * Clear offload flags so the pcap writer sees the packet
+                * as a plain tagged frame rather than acting on these again.
+                */
+               m->ol_flags &= ~(RTE_MBUF_F_RX_VLAN_STRIPPED | 
RTE_MBUF_F_TX_VLAN);
+       }
+}
+
 /* Create a clone of mbuf to be placed into ring. */
 static void
 pdump_copy_burst(uint16_t port_id, uint16_t queue_id,
@@ -182,8 +206,14 @@ pdump_copy_burst(uint16_t port_id, uint16_t queue_id,
 
                if (unlikely(p == NULL))
                        rte_atomic_fetch_add_explicit(&stats->nombuf, 1, 
rte_memory_order_relaxed);
-               else
+               else {
+                       /*
+                        * Restore any VLAN tag that was offloaded to metadata
+                        * so the captured packet has the complete wire format.
+                        */
+                       pdump_vlan_restore(p);
                        dup_bufs[d_pkts++] = p;
+               }
        }
 
        if (d_pkts == 0)
-- 
2.51.0

Reply via email to