I’m not @mkx, but here’s my understanding. If it isn’t correct, someone can correct me.
From the Linux point of view, this is what makes an interface “vlan-aware”, and the name is the interface representing the vlan, and the vlan interface will be IEEE 802.1Q tagged (tagged when leaving/egressing, untagged when entering/ingressing) the “linux” interface.
But when using an /interface vlan with a bridge interface in vlan-filtering mode, it isn’t that simple. What it represents is the CPU routing engine’s “connection” to the specified vlan on the bridge(switch). Whether that vlan is tagged or untagged on the bridge-port depends on both the /interface bridge port and /interface bridge vlan settings. The /interface bridge vlan command is quite overloaded. I have included an annotated extract with my current interpretation.
My understanding is that you name the vlan connection to the switch. You don’t have direct physical access to either side of the interface, it’s the CPU end of the “internal” trunk link going to the switch. It’s the same vlan whether it is tagged or untagged when it egresses or ingresses any bridge-port associated with the vlan. My limited understanding is that the linux kernel expects what it receives to be in Ethernet II (DIX) format, i.e. it expects the 2 octet field following the src mac address in the frame to have the ethertype associated with the data, e.g. 0x0800 for ip, not the ethertype 0x8100 that is the Tag protocol identifier (TPID).
Here is my current interpretation:
Here’s an extract from my config in this post with my comments in red below the MikroTik commands they refer to.
mar/13/2022 03:34:32 by RouterOS 7.2rc4
model = RB760iGS
/interface bridge add admin-mac=DC:2C:6E:CA:FE:F2 auto-mac=no comment=defconf name=BR-SW vlan-filtering=yes
the above creates the vlan-aware bridge and names it BR-SW. PVID 1 is implicit, I assume that is also true for the internal trunk link between the CPU and switch, i.e vlan 1 traverses the CPU-switch internal trunk “untagged”
/interface ethernet set [ find default-name=ether2 ] name=ether2-BR-SW-Base-U1
this names the ether2 port ether2-BR-SW-Base-U1 because I intend this port to be an access port for the base bridge interface (which has default PVID 1)
/interface ethernet set [ find default-name=ether3 ] name=ether3-BR-SW-U241
this names the ether3 port ether3-BR-SW-U241 because I intend this port to be an access port for vlan 241
/interface ethernet set [ find default-name=ether4 ] name=ether4-BR-SW_U10_T241
this names the ether4 port ether4-BR-SW_U10_T241 because I intend this to be a “hybrid” port with native (untagged) vlan 10, and tagged vlan 241
/interface vlan add interface=BR-SW name=vlan10 vlan-id=10
This creates a new vlan “shim” interface for the the CPU’s “connection” to vlan 10 on the BR-SW bridge over the “internal” trunk link between the CPU and switch (bridge), and the bridge (switch) facing side will be IEEE 802.1Q tagged with vlan 10
/interface vlan add interface=BR-SW name=vlan241 vlan-id=241
This creates a new vlan “shim” interface for the the CPU’s “connection” to vlan 241 on the BR-SW bridge over the “internal” trunk link between the CPU and switch (bridge), and the bridge (switch) facing side will be IEEE 802.1Q tagged with vlan 241
/interface bridge port add bridge=BR-SW comment=defconf interface=ether2-BR-SW-Base-U1
This sets the ingress rules for bridge-port ether2-BR-SW-Base-U1 connected to the base BR-SW (implicitly PVID 1); at least this is my current understanding. Perhaps it should filter frame types to admit-only-untagged-and-priority-tagged, I didn’t change this, it was part of the default config.
/interface bridge port add bridge=BR-SW comment=defconf frame-types=admit-only-untagged-and-priority-tagged interface=ether3-BR-SW-U241 pvid=241
This sets the “ingress” rules for bridge-port ether3-BR-SW-U241; it only accepts untagged ethernet frames, and classifies them as members of vlan 241 in the bridge
/interface bridge port add bridge=BR-SW comment=defconf interface=ether4-BR-SW_U10_T241 pvid=10
This sets the “ingress” rules for bridge-port ether4-BR-SW_U10_T241; it accepts all ethernet frames, and classifies untagged frames as members of vlan 10 in the bridge
/interface bridge vlan add bridge=BR-SW tagged=BR-SW,ether4-BR-SW_U10_T241 untagged=ether3-BR-SW-U241 vlan-ids=241
This sets the egress tagging status for all ports that are members of vlan 241. the tagged=BR-SW sets the CPU facing internal trunk port link on the bridge side to tagged, so it will match the tagged vlan interface connection from the CPU side of the internal trunk link created by the /interface vlan add interface=BR-SW name=vlan241 vlan-id=241 command above. The tagged=ether4-BR-SW_U10_T241 part is setting the egress rule for vlan 241 when it leaves ether4-BR-SW_U10_T241. The untagged=ether3-BR-SW-U241 tells it to send vlan 241 traffic untagged from ether3-BR-SW-U241. vlan-ids=241 tells it what vlans are involved. Recommendation, put only one vlan-id here*.
/interface bridge vlan add bridge=BR-SW tagged=BR-SW untagged=ether4-BR-SW_U10_T241 vlan-ids=10
This sets the egress tagging status for all ports that are members of vlan 10. The tagged=BR-SW sets the CPU facing internal trunk port link on the bridge side to tagged, so it will match the tagged vlan interface connection from the CPU side of the internal trunk link created by the /interface vlan add interface=BR-SW name=vlan10 vlan-id=10 command above. The untagged=ether4-BR-SW_U10_T241 tells it to send vlan 10 traffic untagged from ether4-BR-SW_U10_T241. vlan-ids=10 tells it what vlans are involved. Recommendation, put only one vlan-id here*.
- It isn’t a hard requirement, but if you don’t know why you should not put more than one, just use one vlan-id in the vlan-ids list in /interfaces bridge vlan add bridge command. Most configs won’t have so many vlans that it will be much extra work adding them, and it can eliminate hard to debug problems. For more details about why see the help article VLAN filtering with simplified bridge VLAN table
Here’s a Linux Journal article VLAN Support in Linux that covers what the vlan package “shim” does to allow the linux kernel to deal with a canonical format, but send tagged data on the port/wire that the parent base interface is using for untagged data.
An electrical analogy would be a “voltage level shifter”. Older microcontrollers (e.g. AVR/Arduino) used 5VDC as logic level 1 and 0VDC as logic level 0. The current “standard” is 3.3V logic, and connecting a sensor that is designed for 5V with a 3.3V microcontroller requires something to change the voltage from 3.3V on the microcontroller side to 5V on the sensor side, and visa-versa. (similar to a transformer in an AC circuit). So in this analogy, you could think of 5V as tagged, and 3.3V as untagged, but the signal (e.g. TX) is still the same (this signal is like the vlan, it’s the same data, just in different format) But analogy’s can only go so far…