Skip to content

Commit fbe168b

Browse files
mkubecekdavem330
authored andcommitted
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>
1 parent b6267d3 commit fbe168b

File tree

3 files changed

+11
-10
lines changed

3 files changed

+11
-10
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
15261526
}
15271527
#endif
15281528

1529+
if (!(bond_dev->features & NETIF_F_LRO))
1530+
dev_disable_lro(slave_dev);
1531+
15291532
res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
15301533
new_slave);
15311534
if (res) {

drivers/net/team/team.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev)
11791179
goto err_enable_netpoll;
11801180
}
11811181

1182+
if (!(dev->features & NETIF_F_LRO))
1183+
dev_disable_lro(port_dev);
1184+
11821185
err = netdev_rx_handler_register(port_dev, team_handle_frame,
11831186
port);
11841187
if (err) {

net/core/dev.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,22 +1437,17 @@ EXPORT_SYMBOL(dev_close);
14371437
*/
14381438
void dev_disable_lro(struct net_device *dev)
14391439
{
1440-
/*
1441-
* If we're trying to disable lro on a vlan device
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);
1440+
struct net_device *lower_dev;
1441+
struct list_head *iter;
14501442

14511443
dev->wanted_features &= ~NETIF_F_LRO;
14521444
netdev_update_features(dev);
14531445

14541446
if (unlikely(dev->features & NETIF_F_LRO))
14551447
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);
14561451
}
14571452
EXPORT_SYMBOL(dev_disable_lro);
14581453

0 commit comments

Comments
 (0)