Let’s continue with the blog posts related to OpenvSwitch:
In the following, we will show how to use the traditional VLAN 802.1q within OpenvSwitch and why this approach is an option for integrating OpenvSwitch with other network switches using 802.1q but it’s not necessary when using overlay networks (VXLAN or Geneve) because VNI can be used as an alternative method to tag VLANs.
Initial setup
The starting point is the setup used for OpenvSwitch. Geneve tunnel, but adding an additional guest on each host. 802.1q VLAN tags are added to OpenvSwitch ports to restrict communication between the ports in the same VLAN regardless of which switch they are on because VLAN tags are sent through the Geneve tunnel.

Before tagging ports
Before tagging the ports, all the guests are able to connect each other:
root@guest1:~# for i in `seq 3 5`; do ping -c1 192.168.100.$i; done
PING 192.168.100.3 (192.168.100.3) 56(84) bytes of data.
64 bytes from 192.168.100.3: icmp_seq=1 ttl=64 time=0.769 ms
--- 192.168.100.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.769/0.769/0.769/0.000 ms
PING 192.168.100.4 (192.168.100.4) 56(84) bytes of data.
64 bytes from 192.168.100.4: icmp_seq=1 ttl=64 time=0.214 ms
--- 192.168.100.4 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.214/0.214/0.214/0.000 ms
PING 192.168.100.5 (192.168.100.5) 56(84) bytes of data.
64 bytes from 192.168.100.5: icmp_seq=1 ttl=64 time=0.667 ms
--- 192.168.100.5 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.667/0.667/0.667/0.000 ms
OpenvSwitch output:
oot@host-1:~# ovs-vsctl show
20766dac-38e1-4ba8-9a99-6c5ae79983e9
Bridge br-int
Port veth9xK5JX
Interface veth9xK5JX
Port geneve0
Interface geneve0
type: geneve
options: {remote_ip="192.168.125.104"}
Port br-int
Interface br-int
type: internal
Port vethKjTcpM
Interface vethKjTcpM
ovs_version: "2.15.0"
root@host-2:~# ovs-vsctl show
5fb73e94-9839-48d2-a68e-fb000c525f86
Bridge br-int
Port veth5R37tt
Interface veth5R37tt
Port br-int
Interface br-int
type: internal
Port vethel8L7w
Interface vethel8L7w
Port geneve0
Interface geneve0
type: geneve
options: {remote_ip="192.168.125.2"}
ovs_version: "2.15.0"
What’s the veth peer?
Random names have been used for the virtual interfaces (veth) on the hosts and because they’re veth pairs, each interface peer has a different MAC address, so how can we identify the corresponding veth pair for an interface?
Linux network interfaces are numbered, for Host1, veth pairs are numbered as 11 and 12:
root@host-1:~# ip l sh |grep veth
11: veth9xK5JX@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 8900 qdisc noqueue master ovs-system state UP mode DEFAULT group default qlen 1000
12: vethKjTcpM@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 8900 qdisc noqueue master ovs-system state UP mode DEFAULT group default qlen 1000
And they both are associated to the second interface on the guests (@if2). The same information can be retrieved from the guests:
root@guest1:~# ip l |grep ^2
2: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 8900 qdisc noqueue state UP mode DEFAULT group default qlen 1000
root@guest3:~# ip l |grep ^2
2: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 8900 qdisc noqueue state UP mode DEFAULT group default qlen 1000
So, in this case the pairs for Host1 are:
- veth9xK5JX <-> eth0 (guest1)
- vethKjTcpM <-> eth0 (guest3)
For Host2:
- veth5R37tt <-> eth0 (guest4)
- vethel8L7w <-> eth0 (guest2)
Tagging ports
root@host-1:~# ovs-vsctl set port veth9xK5JX tag=20
root@host-1:~# ovs-vsctl set port vethKjTcpM tag=10
root@host-2:~# ovs-vsctl set port veth5R37tt tag=10
root@host-2:~# ovs-vsctl set port vethel8L7w tag=20
Tags are show in the normal output:
root@host-1:~# ovs-vsctl show
20766dac-38e1-4ba8-9a99-6c5ae79983e9
Bridge br-int
Port veth9xK5JX
tag: 20
Interface veth9xK5JX
Port geneve0
Interface geneve0
type: geneve
options: {remote_ip="192.168.125.104"}
Port br-int
Interface br-int
type: internal
Port vethKjTcpM
tag: 10
Interface vethKjTcpM
ovs_version: "2.15.0"
root@host-2:~# ovs-vsctl show
5fb73e94-9839-48d2-a68e-fb000c525f86
Bridge br-int
Port veth5R37tt
tag: 10
Interface veth5R37tt
Port br-int
Interface br-int
type: internal
Port vethel8L7w
tag: 20
Interface vethel8L7w
Port geneve0
Interface geneve0
type: geneve
options: {remote_ip="192.168.125.2"}
ovs_version: "2.15.0"
Analyzing traffic
The previous test can be repeated and now we can see that only the traffic between the guests on the same VLAN is allowed:
root@guest1:~# for i in `seq 3 5`; do ping -c1 192.168.100.$i; done
PING 192.168.100.3 (192.168.100.3) 56(84) bytes of data.
64 bytes from 192.168.100.3: icmp_seq=1 ttl=64 time=0.888 ms
--- 192.168.100.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.888/0.888/0.888/0.000 ms
PING 192.168.100.4 (192.168.100.4) 56(84) bytes of data.
--- 192.168.100.4 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
PING 192.168.100.5 (192.168.100.5) 56(84) bytes of data.
--- 192.168.100.5 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
A traffic capture with wireshark shows the 802.1q header with the VLAN identifier (VID) used:

Conclusion
We have seen how to configure 802.1q in OpenvSwitch and it is a very good option mainly when it is necessary to integrate OpenvSwitch with 802.1q VLANs of another existing device (physical or not).
However, OpenvSwitch is very much related to the configuration of networks in large virtualized environments, such as those used in cloud computing, in that case, this solution is not the most suitable because of the limited size of VID as only 12 bits can be used to define it and therefore there can be a maximum of 2^12=4096 VLANs, which is an insufficient number for large cloud computing infrastructure.
For those cases we can use the VNI included in the Geneve header (or equivalently in VXLAN) and restrict traffic using Openflow rules, but we will see that in another post.