ice: Implement FCS/CRC and VLAN stripping co-existence policy
authorAnatolii Gerasymenko <anatolii.gerasymenko@intel.com>
Wed, 27 Jul 2022 07:24:06 +0000 (09:24 +0200)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Thu, 18 Aug 2022 15:08:23 +0000 (08:08 -0700)
Make sure that only the valid combinations of FCS/CRC stripping and
VLAN stripping offloads are allowed.

You cannot have FCS/CRC stripping disabled while VLAN stripping is
enabled - this breaks the correctness of the FCS/CRC.

If administrator tries to enable VLAN stripping when FCS/CRC stripping is
disabled, the request should be rejected.

If administrator tries to disable FCS/CRC stripping when VLAN stripping
is enabled, the request should be rejected if VLANs are configured. If
there is no VLAN configured, then both FCS/CRC and VLAN stripping should
be disabled.

Testing Hints:
The default settings after driver load are:
- VLAN C-Tag offloads are enabled
- VLAN S-Tag offloads are disabled
- FCS/CRC stripping is enabled

Restore the default settings before each test with the command:
ethtool -K eth0 rx-fcs off rxvlan on txvlan on rx-vlan-stag-hw-parse off
tx-vlan-stag-hw-insert off

Test 1:
Disable FCS/CRC and VLAN stripping:
ethtool -K eth0 rx-fcs on rxvlan off
Try to enable VLAN stripping:
ethtool -K eth0 rxvlan on

Expected: VLAN stripping request is rejected

Test 2:
Try to disable FCS/CRC stripping:
ethtool -K eth0 rx-fcs on

Expected: VLAN stripping is also disabled, as there are no VLAN
configured

Test 3:
Add a VLAN:
ip link add link eth0 eth0.42 type vlan id 42
ip link set eth0 up
Try to disable FCS/CRC stripping:
ethtool -K eth0 rx-fcs on

Expected: FCS/CRC stripping request is rejected

Signed-off-by: Anatolii Gerasymenko <anatolii.gerasymenko@intel.com>
Tested-by: Gurucharan <gurucharanx.g@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/ice/ice_main.c

index a827045198cc0546c1aec3d7c8994023917d62ac..8dfecdc74a18d456e4590569cb72de4b9219ccbd 100644 (file)
@@ -5722,6 +5722,9 @@ ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
                                         NETIF_F_HW_VLAN_STAG_RX | \
                                         NETIF_F_HW_VLAN_STAG_TX)
 
+#define NETIF_VLAN_STRIPPING_FEATURES  (NETIF_F_HW_VLAN_CTAG_RX | \
+                                        NETIF_F_HW_VLAN_STAG_RX)
+
 #define NETIF_VLAN_FILTERING_FEATURES  (NETIF_F_HW_VLAN_CTAG_FILTER | \
                                         NETIF_F_HW_VLAN_STAG_FILTER)
 
@@ -5808,6 +5811,14 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
                              NETIF_F_HW_VLAN_STAG_TX);
        }
 
+       if (!(netdev->features & NETIF_F_RXFCS) &&
+           (features & NETIF_F_RXFCS) &&
+           (features & NETIF_VLAN_STRIPPING_FEATURES) &&
+           !ice_vsi_has_non_zero_vlans(np->vsi)) {
+               netdev_warn(netdev, "Disabling VLAN stripping as FCS/CRC stripping is also disabled and there is no VLAN configured\n");
+               features &= ~NETIF_VLAN_STRIPPING_FEATURES;
+       }
+
        return features;
 }
 
@@ -5901,6 +5912,13 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
        current_vlan_features = netdev->features & NETIF_VLAN_OFFLOAD_FEATURES;
        requested_vlan_features = features & NETIF_VLAN_OFFLOAD_FEATURES;
        if (current_vlan_features ^ requested_vlan_features) {
+               if ((features & NETIF_F_RXFCS) &&
+                   (features & NETIF_VLAN_STRIPPING_FEATURES)) {
+                       dev_err(ice_pf_to_dev(vsi->back),
+                               "To enable VLAN stripping, you must first enable FCS/CRC stripping\n");
+                       return -EIO;
+               }
+
                err = ice_set_vlan_offload_features(vsi, features);
                if (err)
                        return err;
@@ -5986,6 +6004,13 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
         * flag the packet data will have the 4 byte CRC appended
         */
        if (changed & NETIF_F_RXFCS) {
+               if ((features & NETIF_F_RXFCS) &&
+                   (features & NETIF_VLAN_STRIPPING_FEATURES)) {
+                       dev_err(ice_pf_to_dev(vsi->back),
+                               "To disable FCS/CRC stripping, you must first disable VLAN stripping\n");
+                       return -EIO;
+               }
+
                ice_vsi_cfg_crc_strip(vsi, !!(features & NETIF_F_RXFCS));
                ret = ice_down_up(vsi);
                if (ret)