@@ -486,7 +486,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(!netif_carrier_ok(dev) ||
(frags > 1 && !xennet_can_sg(dev)) ||
- netif_needs_gso(dev, skb))) {
+ netif_needs_gso(skb, netif_skb_features(dev, skb)))) {
spin_unlock_irq(&np->tx_lock);
goto drop;
}
@@ -907,6 +907,8 @@ struct net_device
/* for setting kernel sock attribute on TCP connection setup */
#define GSO_MAX_SIZE 65536
unsigned int gso_max_size;
+#define GSO_MAX_SEGS 65535
+ u16 gso_max_segs;
#ifdef CONFIG_DCB
/* Data Center Bridging netlink ops */
@@ -1933,10 +1935,10 @@ static inline int skb_gso_ok(struct sk_buff *skb, int features)
(!skb_has_frags(skb) || (features & NETIF_F_FRAGLIST));
}
-static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
+static inline int netif_needs_gso(struct sk_buff *skb, int features)
{
return skb_is_gso(skb) &&
- (!skb_gso_ok(skb, dev->features) ||
+ (!skb_gso_ok(skb, features) ||
unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
}
@@ -1516,6 +1516,17 @@ static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
return false;
}
+int netif_skb_features(struct net_device *dev, struct sk_buff *skb)
+{
+ int features = dev->features;
+
+ if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
+ features &= ~NETIF_F_GSO_MASK;
+
+ return features;
+}
+EXPORT_SYMBOL(netif_skb_features);
+
/*
* Invalidate hardware checksum when packet is to be mangled, and
* complete checksum manually on outgoing path.
@@ -1682,13 +1693,12 @@ static void dev_gso_skb_destructor(struct sk_buff *skb)
* This function segments the given skb and stores the list of segments
* in skb->next.
*/
-static int dev_gso_segment(struct sk_buff *skb)
+static int dev_gso_segment(struct sk_buff *skb, int features)
{
struct net_device *dev = skb->dev;
struct sk_buff *segs;
- int features = dev->features & ~(illegal_highdma(dev, skb) ?
- NETIF_F_SG : 0);
+ features &= ~(illegal_highdma(dev, skb) ? NETIF_F_SG : 0);
segs = skb_gso_segment(skb, features);
/* Verifying header integrity only. */
@@ -1712,11 +1722,15 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
int rc;
if (likely(!skb->next)) {
+ int features;
+
if (!list_empty(&ptype_all))
dev_queue_xmit_nit(skb, dev);
- if (netif_needs_gso(dev, skb)) {
- if (unlikely(dev_gso_segment(skb)))
+ features = netif_skb_features(dev, skb);
+
+ if (netif_needs_gso(skb, features)) {
+ if (unlikely(dev_gso_segment(skb, features)))
goto out_kfree_skb;
if (skb->next)
goto gso;
@@ -1887,7 +1901,7 @@ int dev_queue_xmit(struct sk_buff *skb)
int rc = -ENOMEM;
/* GSO will handle the following emulations directly. */
- if (netif_needs_gso(dev, skb))
+ if (netif_needs_gso(skb, netif_skb_features(dev, skb)))
goto gso;
if (skb_has_frags(skb) &&
@@ -5195,6 +5209,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
dev->real_num_tx_queues = queue_count;
dev->gso_max_size = GSO_MAX_SIZE;
+ dev->gso_max_segs = GSO_MAX_SEGS;
netdev_init_queues(dev);