I am trying to implement an obscure workaround to a specific problem tied to a switch misconfiguration I observe in a real case scenario.

Please just assume the following :

  • My system is plugged to a trunk link with a cisco switch ;
  • I can send tagged packets in a specific VLAN (not native vlan), it will be properly routed to the correct VLAN ;
  • I receive responses as untagged traffic, even though it is on a trunk and from not-native VLAN ;
  • I cannot modify the switch's configuration.

What I am trying to perform is a way to use a single network interface on Debian, where I can send and receive traffic correctly to insert my traffic in the desired VLAN, even though the packets must be tagged going out and will be caught back untagged.

To give an example, It is possible to ping a remote system with an ICMP echo request. Using my simple eth0 interface will have no effect, no ICMP echo reply will be seen back. However, if I tag my ICMP echo request in say VLAN 10, I will receive an untagged ICMP echo reply ! It works also with DHCP for example (the remote network do has a DHCP server). If I send a tagged DHCP discover packet, I will receive an untagged DHCP offer with the corresponding transaction ID.

I know this is not normal behavior and it can end up in having packets being wrongly routed or assumed to be in a VLAN falsely. It is due to switches being misconfigured (I think it has something to do with native vlan mismatch somewhere).

If I use a vlan subinterface (ip link add link type vlan ...), I will send tagged traffic but responses will never be routed back from the main interface to the sub interface because it expects traffic to be tagged back.

I then discovered vlan aware bridges, which look like a proper solution to my problem, though I dont succeed in doing this with the bridge vlan add commands (pvid, vid, untagged or not, do I need to use a vlan sub-interface anyway ?).

I only need to do this for a single VLAN at a time. It will not be possible to determine to which VLAN a packet is sent because of the tags missing. However, I can infer this VLAN tag based on IP address, STP and CDP traffic. I do not want to do anything automated, I dont want to guess the vlan, I just want to be able to force untagged traffic to be considered being in a chosen, arbitrary vlan, one at a time.

Thank you !

  • As there's no data given I'll assume the worst. What can be done if the same packet, thus with same IP source address and same IP destination address (eg because it's routed multiple times from elsewhere and thus appears in multiple VLANs) crosses twice the system from the same misconfigured switch, normally once in VLAN 10 and again in VLAN 20 but here twice untagged? How can the system figure out (whatever the mean) if it should be in VLAN 10 or VLAN 20? Answer: it can't. That means additional properties in the topology must be known to avoid this to ever happen.
    – A.B
    Commented Feb 17 at 9:54
  • You must give additional information on the setup so that above never happens (eg: because no such routing ever happens). So if you want an answer, there has to be one or multiple examples describing what is expected and what is not to be expected and can be ignored. Examples with actual IP addresses (they can be faked, but eg using or, not 10.x.y.z or, their CIDR, the relation between IP address and VLAN or the lack of such relation (which might make the problem unsolvable) etc.
    – A.B
    Commented Feb 17 at 9:55
  • An example of all this is the following : If I create a VLAN subinterface in VLAN 10, I can then perform a dhcp discover (with dhclient command for instance). The DHCP Discover packet is sent tagged in VLAN 10 with destination address My eth0 interface will then see an untagged DHCP Offer packet coming back with the same DHCP transaction ID as my first DHCP discover packet. This untagged packet is then not forwarded to the subvlan interface because it is not tagged and the system cannot infere that I want to assume that it is vlan 10.
    – Almandin
    Commented Feb 19 at 7:35
  • To answer another previous comment here, I understand this is not a normal behavior at all and might lead to routing errors and unexpected behaviors. I just need to assume that any untagged packet is a chosen VLAN, even if it is untrue. It definitely looks like a native vlan mismatch somewhere near in the network I am in.
    – Almandin
    Commented Feb 19 at 7:47
  • The bug could as well be on the DHCP server (I know this topic is often found on Internet) than on the switch. Anyway... So you just have to "remap" a single VLAN, not an arbitrary number of VLANs? Can you edit your question and add the information provided in comments inside it? And specify if you have to do this only for a single VLAN (eg: VLAN 10) and not for multiple VLANs? If it's still for multiple VLANs, then there is still not enough information.
    – A.B
    Commented Feb 19 at 9:59

1 Answer 1


Introduction/Initial setup

This answer doesn't attempt to integrate in network configuration tools the commands used below. The following tools, at least, are expected to be usable for this purpose without requiring extra commands:

A VLAN-aware bridge interface can fix a single VLAN misconfigured like this, by using a Port VLAN ID (PVID). It will be used only as a layer to cancel the external misconfiguration, even if using a single bridge port.

As no initial configuration was provided to build upon, I use an example with VLAN 10 and IP address used within this VLAN, with interface eth0. Consider the initial configuration to be like this:

ip link set dev eth0 up
ip link add link eth0 name eth0.10 up type vlan id 10
ip addr add dev eth0.10 # or use DHCP
ip route add default via dev eth0.10

Because of OP's current case, this wouldn't work because the network stack (eg: ARP reply received on eth0 and ignored when expected on eth0.10) or other components (DHCP client using a RAW socket receiving replies on an interface it's not listening on) will ignore return traffic because (due to outside bug) it's not the same interface (untagged eth0, isntead of tagged eth0 <=> untagged eth0.10).

Using a VLAN-aware bridge instead

What can be done is replace the use of a VLAN interface by a VLAN-aware bridge with a single bridge port (eth0). VLAN tagging and Port VLAN ID can now be dynamically configured on the bridge instead of creating/deleting VLAN interfaces. Adequate configuration will cancel the remote misconfiguration.

  • Clean previous state (warning: connectivity loss)

    ip link del dev eth0.10
  • Create VLAN-aware bridge

    ip link add name br0 type bridge vlan_filtering 1 vlan_default_pvid 0

    Above vlan_filtering 1 creates the bridge VLAN-aware and vlan_default_pvid 0 makes it use no VLAN by default, so there will be no need to first delete unused VLANs anywhere. VLANs will have to be added explicitly for actual bridge communication to start.

  • Optional: (mainly for MAC-based DHCP server configuration keeping the same address) copy eth0's MAC address to br0

    ... because this address won't be inherited in any recent systemd environment. With the help of the jq command one can copy eth0's MAC address to br0. This should be done before setting eth0 as bridge port.

    ip link set dev br0 address "$(ip -json link show dev eth0 | jq -r '.[].address')"
  • Set eth0 as bridge port and set the bridge up:

    ip link set dev eth0 master br0
    ip link set br0 up
  • Configure the bridge interface itself, the only part of the bridge linked to the routing stack, as untagged and PVID 10: the routing stack doesn't handle VLANs frames, only IP (and ARP) frames, so make sure no tagged frames are emitted or expected.

    The obsolete brctl command can't handle VLAN-aware bridges. This requires the bridge vlan ... command already provided by the iproute2 suite. When it's about the bridge interface itself rather than a bridge port the additional keyword self is needed.

    bridge vlan add vid 10 dev br0 pvid untagged self
  • Add the bridge port eth0 as (tagged) VLAN 10 but also as PVID: it will thus emit tagged frames, and will accept both tagged frames (only VLAN 10) and also consider untagged frames as VLAN 10 frames: will work with the switch misconfigured or not.

    bridge vlan add vid 10 dev eth0 pvid

    Alternatively, have the bridge first accept all tagged VLANs first and alter configuration just for VLAN 10. This is useless in the current configuration but would be useful if (an) other bridge port(s) is/are added to bridge traffic elsewhere. That would be:

    bridge vlan add vid 2-4094 dev eth0
    bridge vlan add vid 10 dev eth0 pvid

    which would get:

    # bridge -compressvlans vlan show
    port              vlan-id  
    eth0              2-9
                      10 PVID
    br0               10 PVID Egress Untagged

This will now work around the misconfiguration and allow normal use of br0 as the main interface, for example by configuring back a static address on it like this is expected to allow communication:

ip addr add dev br0
ip route add default via

or by running a DHCP client on br0 to configure it.

To change the VLAN to tune in, for example from VLAN 10 to VLAN 11:

  • Reconfigure bridge interface br0

    bridge vlan del vid 10 dev br0 self
    bridge vlan add vid 11 dev br0 pvid untagged self
  • Reconfigure bridge port eth0

    bridge vlan del vid 10 dev eth0
    bridge vlan add vid 11 dev eth0 pvid

    If instead all VLANs have to be received, since there is only one PVID per port, switch it to VLAN 11 instead without deleting VLAN 10:

    bridge vlan add vid 11 dev eth0 pvid


  • This answer was tested by simulating the misconfigured switch using... a Linux VLAN-aware bridge with the system's side bridge port on VLAN 10 but also untagged.
  • As there's now a new bridge around, expect issues if the module br_netfilter is loaded: running Docker on this system might require additional workarounds.
  • 1
    Thank you, your answer is awesome, it works perfectly and answers exactly to my problem.
    – Almandin
    Commented Feb 20 at 7:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .