From adbab34aab5513e57bb66415de9a67072ddddab6 Mon Sep 17 00:00:00 2001 From: Christophe Fontaine Date: Tue, 25 Nov 2025 15:36:29 +0100 Subject: [PATCH] infra: add gr_mbuf deepcopy For packet duplication or fragmentation, traces must be duplicated as the packet may go through different paths. Add: - a helper to copy traces - a helper to copy the mbuf, its payload, specific mbuf_data and traces. Suggested-by: David Marchand Signed-off-by: Christophe Fontaine Reviewed-by: Anthony Harivel Reviewed-by: Robin Jarry --- modules/infra/datapath/gr_mbuf.h | 17 ++++++++++++++++ modules/infra/datapath/trace.c | 32 +++++++++++++++++++++++++++++++ modules/ip/datapath/ip_fragment.c | 5 +++-- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/modules/infra/datapath/gr_mbuf.h b/modules/infra/datapath/gr_mbuf.h index 2770b09df..a596f73ad 100644 --- a/modules/infra/datapath/gr_mbuf.h +++ b/modules/infra/datapath/gr_mbuf.h @@ -64,5 +64,22 @@ static inline bool gr_mbuf_is_traced(struct rte_mbuf *m) { // Returns a pointer to a gr_trace_item.data buffer. void *gr_mbuf_trace_add(struct rte_mbuf *m, struct rte_node *node, size_t data_len); +// Copy all trace items from source mbuf to destination mbuf. +// +// This creates a deep copy of the entire trace chain, preserving timestamps, +// node IDs, and trace data. Used when cloning packets to maintain trace history. +void gr_mbuf_trace_copy(struct rte_mbuf *dst, struct rte_mbuf *src); + // Detach the trace items from an mbuf and store them in the trace buffer. void gr_mbuf_trace_finish(struct rte_mbuf *m); + +// Deep copy of an mbuf: duplicates mbuf, copies mbuf priv data and traces +static inline struct rte_mbuf *gr_mbuf_copy(struct rte_mbuf *m, size_t data_len, size_t priv_len) { + struct rte_mbuf *copy = rte_pktmbuf_copy(m, m->pool, 0, data_len); + if (copy) { + memcpy(mbuf_data(copy), mbuf_data(m), priv_len); + if (gr_mbuf_is_traced(m)) + gr_mbuf_trace_copy(copy, m); + } + return copy; +} diff --git a/modules/infra/datapath/trace.c b/modules/infra/datapath/trace.c index b02fde1f5..47871f9ba 100644 --- a/modules/infra/datapath/trace.c +++ b/modules/infra/datapath/trace.c @@ -618,6 +618,38 @@ void *gr_mbuf_trace_add(struct rte_mbuf *m, struct rte_node *node, size_t data_l return trace->data; } +void gr_mbuf_trace_copy(struct rte_mbuf *dst, struct rte_mbuf *src) { + struct gr_trace_head *src_traces = gr_mbuf_traces(src); + struct gr_trace_head *dst_traces = gr_mbuf_traces(dst); + struct gr_trace_item *src_trace, *dst_trace; + void *data; + + // Reset trace head + STAILQ_INIT(dst_traces); + + // Copy each trace item from source to destination + STAILQ_FOREACH (src_trace, src_traces, next) { + // Allocate new trace item for destination + while (rte_mempool_get(trace_pool, &data) < 0) { + void *oldest = NULL; + rte_ring_dequeue(traced_packets, &oldest); + free_trace(oldest); + } + + dst_trace = data; + + // Copy all trace item data + dst_trace->ts = src_trace->ts; + dst_trace->cpu_id = src_trace->cpu_id; + dst_trace->node_id = src_trace->node_id; + dst_trace->len = src_trace->len; + memcpy(dst_trace->data, src_trace->data, src_trace->len); + + // Add to destination trace chain + STAILQ_INSERT_TAIL(dst_traces, dst_trace, next); + } +} + void gr_mbuf_trace_finish(struct rte_mbuf *m) { struct gr_trace_head *traces = gr_mbuf_traces(m); struct gr_trace_item *trace = STAILQ_FIRST(traces); diff --git a/modules/ip/datapath/ip_fragment.c b/modules/ip/datapath/ip_fragment.c index 8e5ee1bee..627f21624 100644 --- a/modules/ip/datapath/ip_fragment.c +++ b/modules/ip/datapath/ip_fragment.c @@ -96,7 +96,9 @@ ip_fragment_process(struct rte_graph *graph, struct rte_node *node, void **objs, // Create and enqueue remaining fragments for (i = 1; i < num_frags; i++) { // Create new fragment, copying the original IPv4 header. - frag_mbuf = rte_pktmbuf_copy(mbuf, mbuf->pool, 0, ip_hdr_len); + frag_mbuf = gr_mbuf_copy( + mbuf, ip_hdr_len, sizeof(struct ip_output_mbuf_data) + ); if (unlikely(frag_mbuf == NULL)) { break; } @@ -122,7 +124,6 @@ ip_fragment_process(struct rte_graph *graph, struct rte_node *node, void **objs, frag_ip->hdr_checksum = 0; frag_ip->hdr_checksum = rte_ipv4_cksum(frag_ip); - *ip_output_mbuf_data(frag_mbuf) = *ip_output_mbuf_data(mbuf); frag_mbuf->packet_type = mbuf->packet_type; if (gr_mbuf_is_traced(mbuf)) { struct ip_fragment_trace_data *t;