Hello, trying to ingest packets to a network monitoring tool using AF_Packet, I noticed that VLAN tags are stripped off even if VLAN offloading is disabled. As described in [1] the tags are stripped that early in the receive path that raw sockets do not receive the packets as seen on the wire. However, the man pages [2] state:
> SOCK_RAW packets are passed to and from the device driver without any > changes in the packet data. So at least the docs are wrong here. While the VLAN information is present in the tpacket_hdr, the packets themselves are manipulated by the kernel. In my case, for example, I need to pass on each packet (in form of a packet) and thus would have to reinsert the tag manually, which is definitely undesirable. As I am dealing with a monitoring application, the following patch that disables untagging VLANs in promisc mode fixes the issue for me: diff --git a/net/core/dev.c b/net/core/dev.c index 54f8c16..ec5b1c5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4104,8 +4104,9 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc) __this_cpu_inc(softnet_data.processed); - if (skb->protocol == cpu_to_be16(ETH_P_8021Q) || - skb->protocol == cpu_to_be16(ETH_P_8021AD)) { + if ((skb->protocol == cpu_to_be16(ETH_P_8021Q) || + skb->protocol == cpu_to_be16(ETH_P_8021AD)) && + skb->dev->promiscuity < 1) { skb = skb_vlan_untag(skb); if (unlikely(!skb)) goto out; -- I tested the patch with tcpdump and suricata. As they are designed to handle VLAN tags anyway, both work as expected. Still there are two caveats regarding this patch: First, there might be software out there that does not work as expected anymore. Second, the semantics of raw sockets are even more cluttered than before. I could imagine the following solutions: 1) Disable VLAN untagging done by the kernel or move it up the receive path - probably least practicable. 2) Parse VLAN info into the tpacket_hdr but keep the packet as is (at least in promisc mode) - still, seems clumsy and error-prone to me. 3) Introduce a new socket option to disable VLAN untagging for raw sockets - maybe overkill. I would be happy to receive some feedback! Best regards, Jan [1] https://www.spinics.net/lists/netdev/msg244668.html [2] http://man7.org/linux/man-pages/man7/ip.7.html