On 2/27/26 9:29 AM, David Marchand via dev wrote: > Let's allow growing a dp_packet_batch. > This will help for software GSO as we can define a helper that > will segment all packets and return them in the input batch. > > To limit heap allocations, keep an embedded array of packets > in the batch structure, and switch to heap allocated packets > array when reaching the NETDEV_MAX_BURST previous limit. > > The refill API becomes simpler, as the only operation needed now is to > reset the count of packets when starting a refill loop. > > ipf and GSO software helper are left untouched (keeping the > behavior of accumulating up to NETDEV_MAX_BURST packets) and are updated > in next commits. > > At this point in time, no part of OVS should grow batches. Add a check > in OVS_VSWITCHD_STOP, with a macro to simplify testing later commits. > > Signed-off-by: David Marchand <[email protected]> > --- > lib/dp-packet-gso.c | 6 ++-- > lib/dp-packet.c | 24 ++++++++++++++++ > lib/dp-packet.h | 61 +++++++++++++++-------------------------- > lib/dpif-netdev.c | 6 ++-- > lib/ipf.c | 15 +++++----- > lib/netdev-dpdk.c | 4 +-- > lib/netdev.c | 6 ++-- > lib/odp-execute.c | 2 +- > tests/ofproto-macros.at | 10 +++++++ > tests/test-conntrack.c | 4 +-- > 10 files changed, 77 insertions(+), 61 deletions(-) > > diff --git a/lib/dp-packet-gso.c b/lib/dp-packet-gso.c > index bceb851fb9..83a07c8e31 100644 > --- a/lib/dp-packet-gso.c > +++ b/lib/dp-packet-gso.c > @@ -196,7 +196,7 @@ dp_packet_gso__(struct dp_packet *p, struct > dp_packet_batch **batches, > > /* Put back the first segment in the batch, it will be trimmed after > * all segments have been copied. */ > - if (dp_packet_batch_is_full(curr_batch)) { > + if (curr_batch->count == NETDEV_MAX_BURST) { > curr_batch++; > } > dp_packet_batch_add(curr_batch, p); > @@ -228,7 +228,7 @@ dp_packet_gso__(struct dp_packet *p, struct > dp_packet_batch **batches, > dp_packet_gso_update_segment(seg, i, n_segs, tso_segsz, udp_tnl, > gre_tnl); > > - if (dp_packet_batch_is_full(curr_batch)) { > + if (curr_batch->count == NETDEV_MAX_BURST) { > curr_batch++; > } > dp_packet_batch_add(curr_batch, seg); > @@ -241,7 +241,7 @@ last_seg: > dp_packet_gso_update_segment(seg, n_segs - 1, n_segs, tso_segsz, udp_tnl, > gre_tnl); > > - if (dp_packet_batch_is_full(curr_batch)) { > + if (curr_batch->count == NETDEV_MAX_BURST) { > curr_batch++; > } > dp_packet_batch_add(curr_batch, seg); > diff --git a/lib/dp-packet.c b/lib/dp-packet.c > index c04d608be6..e4b6878b6d 100644 > --- a/lib/dp-packet.c > +++ b/lib/dp-packet.c > @@ -18,6 +18,7 @@ > #include <stdlib.h> > #include <string.h> > > +#include "coverage.h" > #include "dp-packet.h" > #include "netdev-afxdp.h" > #include "netdev-dpdk.h" > @@ -25,6 +26,8 @@ > #include "openvswitch/dynamic-string.h" > #include "util.h" > > +COVERAGE_DEFINE(dp_packet_batch_grow); > + > static void > dp_packet_init__(struct dp_packet *b, size_t allocated, enum > dp_packet_source source) > { > @@ -646,3 +649,24 @@ dp_packet_ol_send_prepare(struct dp_packet *p, uint64_t > flags) > } > } > } > + > +void > +dp_packet_batch_grow(struct dp_packet_batch *batch, size_t count) > +{ > + struct dp_packet **old_packets; > + > + COVERAGE_INC(dp_packet_batch_grow); > + > + if (batch->packets == batch->embedded) { > + old_packets = NULL; > + } else { > + old_packets = batch->packets; > + } > + > + batch->packets = xrealloc(old_packets, > + (batch->size + count) * sizeof > *batch->packets); > + if (!old_packets) { > + memcpy(batch->packets, batch->embedded, sizeof batch->embedded); > + } > + batch->size += count; > +} > diff --git a/lib/dp-packet.h b/lib/dp-packet.h > index 2540534cc3..03d1eda6a6 100644 > --- a/lib/dp-packet.h > +++ b/lib/dp-packet.h > @@ -862,7 +862,9 @@ enum { NETDEV_MAX_BURST = 32 }; /* Maximum number packets > in a batch. */ > struct dp_packet_batch { > size_t count; > bool trunc; /* true if the batch needs truncate. */ > - struct dp_packet *packets[NETDEV_MAX_BURST]; > + struct dp_packet **packets; > + size_t size;
We may want to find a different word for this field, e.g. 'capacity', or rename the dp_packet_batch_size() into dp_packet_batch_count(). Otherwise, it is confusing. We would probably need a helper to get the capacity as well, so method renaming may become confusing when looking across diferent OVS versions. Best regards, Ilya Maximets. _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
