Wang Zhan wrote:
> The re-segmentation added by the next patch splits an oversized TCP GSO skb
> into several GSO skbs which fit the device limits.  That needs the GSO
> engine to group several MSS segments into one output skb, so let callers
> set the number of MSS segments each output skb may carry and pass it
> through the existing __skb_gso_segment() entry point.  Ordinary callers
> pass zero for no limit.
> 
> Without max_segs, skb_segment() groups several MSS into one output skb only
> for a device which advertises NETIF_F_GSO_PARTIAL or for a skb with a
> frag_list which can be split into uniform pieces, and falls back to one
> segment per skb otherwise.  A caller which sets max_segs asks for the
> grouping regardless, so the block which makes that decision is skipped.
> Callers which pass zero keep it, and the re-segmentation path only runs for
> an unencapsulated TCP skb without a frag_list.
> 
> The output stays a GSO skb: gso_size is the original MSS and gso_segs is
> the number of MSS it holds, so a downstream device can still perform
> ordinary TSO.  Store max_segs in the existing skb_gso_cb scratch context,
> alongside the call-local data_offset and mac_offset fields, so that the
> segmentation methods keep their signature.  A zero max_segs value means
> that no limit is active; it is not a persistent skb flag.
> 
> Assisted-by: LLM

Reviewed-by: Willem de Bruijn <[email protected]>

If respinning, consider asking the LLM to rewrite commit messages to be
more concise.

> @@ -4839,7 +4840,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
>       csum = !!can_checksum_protocol(features, proto);
>  
>       if (sg && csum && !gso_by_frags)  {
> -             if (!(features & NETIF_F_GSO_PARTIAL)) {
> +             if (!max_segs && !(features & NETIF_F_GSO_PARTIAL)) {
>                       struct sk_buff *iter;
>                       unsigned int frag_len;
>  
> @@ -4874,7 +4875,10 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
>                * now.
>                */
>               DEBUG_NET_WARN_ON_ONCE(len / mss > GSO_MAX_SEGS);
> -             partial_segs = min(len / mss, GSO_MAX_SEGS);
> +             if (max_segs)
> +                     partial_segs = min(len / mss, max_segs);
> +             else
> +                     partial_segs = min(len / mss, GSO_MAX_SEGS);
>               if (partial_segs > 1)
>                       mss *= partial_segs;
>               else

Not new with this series, nor high priority, so only if respinning:

Consider adding

@@ -5121,7 +5121,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
                }
 
                if (tail->len - doffset <= gso_size)
-                       skb_shinfo(tail)->gso_size = 0;
+                       skb_gso_reset(tail);
                else if (tail != segs)

Because packets looped into the Rx path will sometimes have their
gso_segs used without first checking gso_size /  skb_is_gso. For instance
in ip_rcv_core __IP_ADD_STATS.

Additionally for patch 5/5, consider one testcase that resegments, but for
which the last skb is not a GSO skb.

> diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
> index 21870341432552..e793aead68372d 100644
> --- a/net/openvswitch/datapath.c
> +++ b/net/openvswitch/datapath.c
> @@ -375,7 +375,7 @@ static int queue_gso_packets(struct datapath *dp, struct 
> sk_buff *skb,
>       int err;
>  
>       BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_GSO_CB_OFFSET);
> -     segs = __skb_gso_segment(skb, NETIF_F_SG, false);
> +     segs = __skb_gso_segment(skb, NETIF_F_SG, false, 0);
>       if (IS_ERR(segs))
>               return PTR_ERR(segs);
>       if (segs == NULL)
> -- 
> 2.47.3
> 


_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to