Wang Zhan wrote:
> The bounded resegmentation 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 bound the number of MSS segments each output skb carries and pass
> the bound through the existing __skb_gso_segment() entry point. Ordinary
> callers use zero for no limit.
> 
> skb_segment() only groups several MSS into one output skb when the device
> advertises NETIF_F_GSO_PARTIAL, or when the skb has a frag_list which can
> be split into uniform pieces, and falls back to one segment per skb
> otherwise. A caller which passes a bound asks for that grouping
> regardless, so the frag_list check is skipped when max_segs is set. Every
> other caller keeps it, and the bounded path is only used for skbs which do
> not carry 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 the bound 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 bound is active; it is not a persistent skb flag. Clear the value
> when each output skb copies the input header so the temporary limit is not
> propagated to the next GSO call.
> 
> Assisted-by: LLM
> Signed-off-by: Wang Zhan <[email protected]>
 
> @@ -117,6 +119,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
>  
>       SKB_GSO_CB(skb)->mac_offset = skb_headroom(skb);
>       SKB_GSO_CB(skb)->encap_level = 0;
> +     SKB_GSO_CB(skb)->max_segs = min_t(unsigned int, max_segs, U16_MAX);

Can this use GSO_MAX_SEGS rather than U16_MAX.
>  
>       skb_reset_mac_header(skb);
>       skb_reset_mac_len(skb);
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index dbbe10277d51d..9c0d140236bc6 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -4793,6 +4793,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
>       struct sk_buff *segs = NULL;
>       struct sk_buff *tail = NULL;
>       struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list;
> +     unsigned int max_segs = SKB_GSO_CB(head_skb)->max_segs;
>       unsigned int mss = skb_shinfo(head_skb)->gso_size;
>       bool gso_by_frags = mss == GSO_BY_FRAGS;
>       unsigned int doffset = head_skb->data - skb_mac_header(head_skb);
> @@ -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
> @@ -4975,6 +4979,12 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
>  
>               __copy_skb_header(nskb, head_skb);
>  
> +             /*
> +              * max_segs is a per-call limit, so output skbs must not
> +              * inherit it from the input skb.
> +              */
> +             SKB_GSO_CB(nskb)->max_segs = 0;
> +

cb has to be treated as uninitialized between layers. All callers of
__skb_gso_segment should (re)initialize this field. Is it necessary to
clear it here. Note that we do not do that for any other cb fields.
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to