gso_features_check() decides whether an egress device can offload a GSO
skb as a single TSO frame by comparing the segment count and the frame
length against the device limits. The resegmentation path added by a
later patch caps the MSS segments per output skb and needs the same
features computed without those limits, so put the two tests in a helper
and gate them with one flag.
No functional changes.
Assisted-by: LLM
Signed-off-by: Wang Zhan <redacted>
---
v3:
- rename the helper to gso_within_dev_limits
- move the check_gso_limits flag and the wrapper split here from patch 4
v2: https://lore.kernel.org/20260918084651.3022878-2-wang.zhan@smartx.com/ (local)
v1: https://lore.kernel.org/20260917063854.2011613-2-wang.zhan@smartx.com/ (local)
---
net/core/dev.c | 29 +++++++++++++++++++----------
1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index ffa9b0c27788c..d66b667071837 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3834,17 +3834,19 @@ static bool skb_gso_has_extension_hdr(const struct sk_buff *skb)
skb_inner_network_header_len(skb) != sizeof(struct ipv6hdr)));
}
+static bool
+gso_within_dev_limits(const struct sk_buff *skb, const struct net_device *dev)
+{
+ return skb_shinfo(skb)->gso_segs <= READ_ONCE(dev->gso_max_segs) &&
+ skb->len < netif_get_gso_max_size(dev, vlan_get_protocol(skb));
+}
+
static netdev_features_t gso_features_check(const struct sk_buff *skb,
struct net_device *dev,
- netdev_features_t features)
+ netdev_features_t features,
+ bool check_limits)
{
- u16 gso_segs = skb_shinfo(skb)->gso_segs;
-
- if (gso_segs > READ_ONCE(dev->gso_max_segs))
- return features & ~NETIF_F_GSO_MASK;
-
- if (unlikely(skb->len >=
- netif_get_gso_max_size(dev, vlan_get_protocol(skb))))
+ if (check_limits && !gso_within_dev_limits(skb, dev))
return features & ~NETIF_F_GSO_MASK;
if (!skb_shinfo(skb)->gso_type) {@@ -3893,13 +3895,15 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb,
return features;
}
-netdev_features_t netif_skb_features(struct sk_buff *skb)
+static netdev_features_t
+__netif_skb_features(struct sk_buff *skb, bool check_gso_limits)
{
struct net_device *dev = skb->dev;
netdev_features_t features = dev->features;
if (skb_is_gso(skb))
- features = gso_features_check(skb, dev, features);
+ features = gso_features_check(skb, dev, features,
+ check_gso_limits);
/* If encapsulation offload request, verify we are testing
* hardware encapsulation features instead of standard@@ -3922,6 +3926,11 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
return harmonize_features(skb, features);
}
+
+netdev_features_t netif_skb_features(struct sk_buff *skb)
+{
+ return __netif_skb_features(skb, true);
+}
EXPORT_SYMBOL(netif_skb_features);
static int xmit_one(struct sk_buff *skb, struct net_device *dev,--
2.47.3