Skip to content

Commit 797f87f

Browse files
Florian Westphaldavem330
authored andcommitted
macvlan: fix netdev feature propagation from lower device
There are inconsistencies wrt. feature propagation/inheritance between macvlan and the underlying interface. When a feature is turned off on the real device before a macvlan is created on top, these will remain enabled on the macvlan device, whereas turning off the feature on the lower device after macvlan creation the kernel will propagate the changes to the macvlan. The second issue is that, when propagating changes from underlying device to the macvlan interface, macvlan can erronously lose its NETIF_F_LLTX flag, as features are anded with the underlying device. However, LLTX should be kept since it has no dependencies on physical hardware (LLTX is set on macvlan creation regardless of the lower device properties, see 8ffab51 (macvlan: lockless tx path). The LLTX flag is now forced regardless of user settings in absence of layer2 hw acceleration (a6cc0cf, net: Add layer 2 hardware acceleration operations for macvlan devices). Use netdev_increment_features to rebuild the feature set on capability changes on either the lower device or on the macvlan interface. As pointed out by Ben Hutchings, use netdev_update_features on NETDEV_FEAT_CHANGE event (it calls macvlan_fix_features/netdev_features_change if needed). Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 61e7f09 commit 797f87f

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

drivers/net/macvlan.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -690,8 +690,19 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
690690
netdev_features_t features)
691691
{
692692
struct macvlan_dev *vlan = netdev_priv(dev);
693+
netdev_features_t mask;
693694

694-
return features & (vlan->set_features | ~MACVLAN_FEATURES);
695+
features |= NETIF_F_ALL_FOR_ALL;
696+
features &= (vlan->set_features | ~MACVLAN_FEATURES);
697+
mask = features;
698+
699+
features = netdev_increment_features(vlan->lowerdev->features,
700+
features,
701+
mask);
702+
if (!vlan->fwd_priv)
703+
features |= NETIF_F_LLTX;
704+
705+
return features;
695706
}
696707

697708
static const struct ethtool_ops macvlan_ethtool_ops = {
@@ -1019,9 +1030,8 @@ static int macvlan_device_event(struct notifier_block *unused,
10191030
break;
10201031
case NETDEV_FEAT_CHANGE:
10211032
list_for_each_entry(vlan, &port->vlans, list) {
1022-
vlan->dev->features = dev->features & MACVLAN_FEATURES;
10231033
vlan->dev->gso_max_size = dev->gso_max_size;
1024-
netdev_features_change(vlan->dev);
1034+
netdev_update_features(vlan->dev);
10251035
}
10261036
break;
10271037
case NETDEV_UNREGISTER:

0 commit comments

Comments
 (0)