| From foo@baz Wed Aug 26 03:58:58 PM CEST 2020 |
| From: Mahesh Bandewar <maheshb@google.com> |
| Date: Fri, 14 Aug 2020 22:53:24 -0700 |
| Subject: ipvlan: fix device features |
| |
| From: Mahesh Bandewar <maheshb@google.com> |
| |
| [ Upstream commit d0f5c7076e01fef6fcb86988d9508bf3ce258bd4 ] |
| |
| Processing NETDEV_FEAT_CHANGE causes IPvlan links to lose |
| NETIF_F_LLTX feature because of the incorrect handling of |
| features in ipvlan_fix_features(). |
| |
| --before-- |
| lpaa10:~# ethtool -k ipvl0 | grep tx-lockless |
| tx-lockless: on [fixed] |
| lpaa10:~# ethtool -K ipvl0 tso off |
| Cannot change tcp-segmentation-offload |
| Actual changes: |
| vlan-challenged: off [fixed] |
| tx-lockless: off [fixed] |
| lpaa10:~# ethtool -k ipvl0 | grep tx-lockless |
| tx-lockless: off [fixed] |
| lpaa10:~# |
| |
| --after-- |
| lpaa10:~# ethtool -k ipvl0 | grep tx-lockless |
| tx-lockless: on [fixed] |
| lpaa10:~# ethtool -K ipvl0 tso off |
| Cannot change tcp-segmentation-offload |
| Could not change any device features |
| lpaa10:~# ethtool -k ipvl0 | grep tx-lockless |
| tx-lockless: on [fixed] |
| lpaa10:~# |
| |
| Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") |
| Signed-off-by: Mahesh Bandewar <maheshb@google.com> |
| Cc: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/ipvlan/ipvlan_main.c | 25 +++++++++++++++++++++---- |
| 1 file changed, 21 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/net/ipvlan/ipvlan_main.c |
| +++ b/drivers/net/ipvlan/ipvlan_main.c |
| @@ -168,12 +168,21 @@ static void ipvlan_port_destroy(struct n |
| kfree_rcu(port, rcu); |
| } |
| |
| +#define IPVLAN_ALWAYS_ON_OFLOADS \ |
| + (NETIF_F_SG | NETIF_F_HW_CSUM | \ |
| + NETIF_F_GSO_ROBUST | NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL) |
| + |
| +#define IPVLAN_ALWAYS_ON \ |
| + (IPVLAN_ALWAYS_ON_OFLOADS | NETIF_F_LLTX | NETIF_F_VLAN_CHALLENGED) |
| + |
| #define IPVLAN_FEATURES \ |
| (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ |
| NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ |
| NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \ |
| NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER) |
| |
| + /* NETIF_F_GSO_ENCAP_ALL NETIF_F_GSO_SOFTWARE Newly added */ |
| + |
| #define IPVLAN_STATE_MASK \ |
| ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT)) |
| |
| @@ -186,7 +195,9 @@ static int ipvlan_init(struct net_device |
| dev->state = (dev->state & ~IPVLAN_STATE_MASK) | |
| (phy_dev->state & IPVLAN_STATE_MASK); |
| dev->features = phy_dev->features & IPVLAN_FEATURES; |
| - dev->features |= NETIF_F_LLTX; |
| + dev->features |= IPVLAN_ALWAYS_ON; |
| + dev->vlan_features = phy_dev->vlan_features & IPVLAN_FEATURES; |
| + dev->vlan_features |= IPVLAN_ALWAYS_ON_OFLOADS; |
| dev->gso_max_size = phy_dev->gso_max_size; |
| dev->gso_max_segs = phy_dev->gso_max_segs; |
| dev->hard_header_len = phy_dev->hard_header_len; |
| @@ -274,7 +285,14 @@ static netdev_features_t ipvlan_fix_feat |
| { |
| struct ipvl_dev *ipvlan = netdev_priv(dev); |
| |
| - return features & (ipvlan->sfeatures | ~IPVLAN_FEATURES); |
| + features |= NETIF_F_ALL_FOR_ALL; |
| + features &= (ipvlan->sfeatures | ~IPVLAN_FEATURES); |
| + features = netdev_increment_features(ipvlan->phy_dev->features, |
| + features, features); |
| + features |= IPVLAN_ALWAYS_ON; |
| + features &= (IPVLAN_FEATURES | IPVLAN_ALWAYS_ON); |
| + |
| + return features; |
| } |
| |
| static void ipvlan_change_rx_flags(struct net_device *dev, int change) |
| @@ -675,10 +693,9 @@ static int ipvlan_device_event(struct no |
| |
| case NETDEV_FEAT_CHANGE: |
| list_for_each_entry(ipvlan, &port->ipvlans, pnode) { |
| - ipvlan->dev->features = dev->features & IPVLAN_FEATURES; |
| ipvlan->dev->gso_max_size = dev->gso_max_size; |
| ipvlan->dev->gso_max_segs = dev->gso_max_segs; |
| - netdev_features_change(ipvlan->dev); |
| + netdev_update_features(ipvlan->dev); |
| } |
| break; |
| |