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

Reply via email to