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]> > > --- > v2: > - wrap the tap.c declaration and skb_gso_cb comment to 80 columns > v1: https://lore.kernel.org/[email protected]/ > --- > drivers/net/tap.c | 3 ++- > include/net/gso.h | 6 ++++-- > include/net/udp.h | 2 +- > net/core/gso.c | 5 ++++- > net/core/skbuff.c | 14 ++++++++++++-- > net/ipv4/tcp_offload.c | 3 ++- > net/openvswitch/datapath.c | 2 +- > 7 files changed, 26 insertions(+), 9 deletions(-) > > diff --git a/drivers/net/tap.c b/drivers/net/tap.c > index ff67d99deb39e..bc111495ebbce 100644 > --- a/drivers/net/tap.c > +++ b/drivers/net/tap.c > @@ -278,9 +278,10 @@ rx_handler_result_t tap_handle_frame(struct sk_buff > **pskb) > if (q->flags & IFF_VNET_HDR) > features |= tap->tap_features; > if (netif_needs_gso(skb, features)) { > - struct sk_buff *segs = __skb_gso_segment(skb, features, false); > + struct sk_buff *segs; > struct sk_buff *next; > > + segs = __skb_gso_segment(skb, features, false, 0);
irrelevant? > 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; could this be computed inside skb_segment, rather than having to be passed through SKB_GSO_CB. I haven't checked, but it would simplify. > 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); _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
