aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorMichal Kubeček <mkubecek@suse.cz>2014-11-13 01:54:50 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-13 14:48:56 -0500
commitfbe168ba91f7c327856f205699404284c2f09e36 (patch)
treecc69d067c84f90e105f098127fdd25330c5baf99 /net/core/dev.c
parentb6267d3e803b9adf73893f932f7c7f3a2167c908 (diff)
net: generic dev_disable_lro() stacked device handling
Large receive offloading is known to cause problems if received packets are passed to other host. Therefore the kernel disables it by calling dev_disable_lro() whenever a network device is enslaved in a bridge or forwarding is enabled for it (or globally). For virtual devices we need to disable LRO on the underlying physical device (which is actually receiving the packets). Current dev_disable_lro() code handles this propagation for a vlan (including 802.1ad nested vlan), macvlan or a vlan on top of a macvlan. It doesn't handle other stacked devices and their combinations, in particular propagation from a bond to its slaves which often causes problems in virtualization setups. As we now have generic data structures describing the upper-lower device relationship, dev_disable_lro() can be generalized to disable LRO also for all lower devices (if any) once it is disabled for the device itself. For bonding and teaming devices, it is necessary to disable LRO not only on current slaves at the moment when dev_disable_lro() is called but also on any slave (port) added later. v2: use lower device links for all devices (including vlan and macvlan) Signed-off-by: Michal Kubecek <mkubecek@suse.cz> Acked-by: Veaceslav Falico <vfalico@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c15
1 files changed, 5 insertions, 10 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index bb09b0364619..1ab168e0fdf7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1437,22 +1437,17 @@ EXPORT_SYMBOL(dev_close);
1437 */ 1437 */
1438void dev_disable_lro(struct net_device *dev) 1438void dev_disable_lro(struct net_device *dev)
1439{ 1439{
1440 /* 1440 struct net_device *lower_dev;
1441 * If we're trying to disable lro on a vlan device 1441 struct list_head *iter;
1442 * use the underlying physical device instead
1443 */
1444 if (is_vlan_dev(dev))
1445 dev = vlan_dev_real_dev(dev);
1446
1447 /* the same for macvlan devices */
1448 if (netif_is_macvlan(dev))
1449 dev = macvlan_dev_real_dev(dev);
1450 1442
1451 dev->wanted_features &= ~NETIF_F_LRO; 1443 dev->wanted_features &= ~NETIF_F_LRO;
1452 netdev_update_features(dev); 1444 netdev_update_features(dev);
1453 1445
1454 if (unlikely(dev->features & NETIF_F_LRO)) 1446 if (unlikely(dev->features & NETIF_F_LRO))
1455 netdev_WARN(dev, "failed to disable LRO!\n"); 1447 netdev_WARN(dev, "failed to disable LRO!\n");
1448
1449 netdev_for_each_lower_dev(dev, lower_dev, iter)
1450 dev_disable_lro(lower_dev);
1456} 1451}
1457EXPORT_SYMBOL(dev_disable_lro); 1452EXPORT_SYMBOL(dev_disable_lro);
1458 1453