]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: usb: lan78xx: disable VLAN filter in promiscuous mode
authorEnrico Pozzobon <enrico.pozzobon@dissecto.com>
Wed, 1 Jul 2026 14:47:23 +0000 (16:47 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 7 Jul 2026 11:07:51 +0000 (13:07 +0200)
The hardware VLAN filter (RFE_CTL_VLAN_FILTER_) drops VLAN-tagged frames
whose VID has not been registered via lan78xx_vlan_rx_add_vid(). It is
left enabled in promiscuous mode, so packet capture (e.g. tcpdump or
Wireshark) does not see tagged frames for unregistered VIDs.

Clear the filter while the interface is promiscuous and restore it from
NETIF_F_HW_VLAN_CTAG_FILTER otherwise. Enforce the same condition in
lan78xx_set_features() so netdev_update_features() cannot re-enable the
filter while promiscuous.

Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver")
Signed-off-by: Enrico Pozzobon <enrico.pozzobon@dissecto.com>
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Link: https://patch.msgid.link/20260701-lan78xx-vlan-promisc-v3-1-232266d32743@dissecto.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/usb/lan78xx.c

index c4cebacabcb5343d3e8c93fc3d4ad310f9728db7..cb782d81d84f2ad2df2f732267058c29db3a5a00 100644 (file)
@@ -1499,6 +1499,17 @@ multicast_write_done:
        return;
 }
 
+static void lan78xx_update_vlan_filter(struct lan78xx_priv *pdata,
+                                      struct net_device *netdev,
+                                      netdev_features_t features)
+{
+       if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
+           !(netdev->flags & IFF_PROMISC))
+               pdata->rfe_ctl |= RFE_CTL_VLAN_FILTER_;
+       else
+               pdata->rfe_ctl &= ~RFE_CTL_VLAN_FILTER_;
+}
+
 static void lan78xx_set_multicast(struct net_device *netdev)
 {
        struct lan78xx_net *dev = netdev_priv(netdev);
@@ -1533,6 +1544,8 @@ static void lan78xx_set_multicast(struct net_device *netdev)
                }
        }
 
+       lan78xx_update_vlan_filter(pdata, dev->net, dev->net->features);
+
        if (netdev_mc_count(dev->net)) {
                struct netdev_hw_addr *ha;
                int i;
@@ -3074,10 +3087,7 @@ static int lan78xx_set_features(struct net_device *netdev,
        else
                pdata->rfe_ctl &= ~RFE_CTL_VLAN_STRIP_;
 
-       if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
-               pdata->rfe_ctl |= RFE_CTL_VLAN_FILTER_;
-       else
-               pdata->rfe_ctl &= ~RFE_CTL_VLAN_FILTER_;
+       lan78xx_update_vlan_filter(pdata, netdev, features);
 
        spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags);