Dear Petr,

Thank you for your quick and detailed reply.


Am 23.03.26 um 09:37 schrieb Petr Oros:

On 3/20/26 15:29, Paul Menzel wrote:

Am 20.03.26 um 14:53 schrieb Petr Oros:
The IAVF_RXD_LEGACY_L2TAG2_M mask was incorrectly defined as
GENMASK_ULL(63, 32), extracting 32 bits from qw2 instead of the
16-bit VLAN tag. In the legacy Rx descriptor layout, the 2nd L2TAG2
(VLAN tag) occupies bits 63:48 of qw2, not 63:32.

The oversized mask causes FIELD_GET to return a 32-bit value where the
actual VLAN tag sits in bits 31:16. When this value is passed to
iavf_receive_skb() as a u16 parameter, it gets truncated to the lower
16 bits (which contain the 1st L2TAG2, typically zero). As a result,
__vlan_hwaccel_put_tag() is never called and software VLAN interfaces
on VFs receive no traffic.

This affects VFs behind ice PF (VIRTCHNL VLAN v2) when the PF
advertises VLAN stripping into L2TAG2_2 and legacy descriptors are
used.

The flex descriptor path already uses the correct mask
(IAVF_RXD_FLEX_L2TAG2_2_M = GENMASK_ULL(63, 48)).

Do you have a reproducer to verify the fix?

Yes, i have

  1. Create 2 VFs on ice PF (echo 2 > sriov_numvfs)
  2. Disable spoofchk on both VFs
  3. Move each VF into a separate network namespace
  4. On each VF: create VLAN interface (e.g. vlan 198), assign IP, bring up
  5. Set rx-vlan-offload OFF on both VFs
  6. Ping between VLAN interfaces → expect PASS
      (VLAN tag stays in packet data, kernel matches in-band)
  7. Set rx-vlan-offload ON on both VFs
  8. Ping between VLAN interfaces → expect FAIL if bug present
      (HW strips VLAN tag into descriptor L2TAG2 field,
       wrong mask extracts bits 47:32 instead of 63:48,
       truncated to u16 → zero, __vlan_hwaccel_put_tag() never called,
       packet delivered to parent interface, not VLAN interface)

Fixes: 2dc8e7c36d80 ("iavf: refactor iavf_clean_rx_irq to support legacy and flex descriptors")

(That first entered Linux v6.15-rc1, and Linux 6.12 and 6.18 are LTS series.)

The reproducer works but requires legacy Rx descriptors to be in use.
On modern ice + iavf with full PTP support, flex descriptors are always
negotiated and the buggy legacy path is never reached.

Flex descriptors require all of the following:
   - CONFIG_PTP_1588_CLOCK enabled in kernel config
   - VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC granted by PF
   - PTP capabilities negotiated (VIRTCHNL_VF_CAP_PTP)
   - VIRTCHNL_1588_PTP_CAP_RX_TSTAMP supported
   - VIRTCHNL_RXDID_2_FLEX_SQ_NIC present in DDP profile

If any of these conditions is not met, iavf_select_rx_desc_format()
falls back to legacy descriptors (RXDID=1) and the wrong L2TAG2 mask is hit.

In our kernel we ended up in a state where the iavf Rx path refactor was
backported but the full PTP support chain was not. Without PTP,
iavf_ptp_cap_supported() returns false and flex descriptors
are never selected, exposing the bug.

Personally, I’d like to have this helpful information (reproducer and requisites) in the commit message, and it’d be great if you resend with the extended commit message.


Kind regards,

Paul


Signed-off-by: Petr Oros <[email protected]>
---
  drivers/net/ethernet/intel/iavf/iavf_type.h | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/iavf/iavf_type.h 
b/drivers/net/ethernet/intel/iavf/iavf_type.h
index 1d8cf29cb65ac5..5bb1de1cfd33b1 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_type.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_type.h
@@ -277,7 +277,7 @@ struct iavf_rx_desc {
  /* L2 Tag 2 Presence */
  #define IAVF_RXD_LEGACY_L2TAG2P_M        BIT(0)
  /* Stripped S-TAG VLAN from the receive packet */
-#define IAVF_RXD_LEGACY_L2TAG2_M        GENMASK_ULL(63, 32)
+#define IAVF_RXD_LEGACY_L2TAG2_M        GENMASK_ULL(63, 48)
  /* Stripped S-TAG VLAN from the receive packet */
  #define IAVF_RXD_FLEX_L2TAG2_2_M        GENMASK_ULL(63, 48)
  /* The packet is a UDP tunneled packet */

Nice find.

Reviewed-by: Paul Menzel <[email protected]>


Kind regards,

Paul



Reply via email to