VLAN tutorial

Next we are going to introduce VLANs.

ETA: ~30 mins.


  • Install Faucet - Package installation steps 1 & 2

  • Install Open vSwitch - Connect your first datapath steps 1 & 2

  • Useful Bash Functions - Copy and paste the following definitions into your bash terminal, or to make them persistent between sessions add them to the bottom of your .bashrc and run ‘source .bashrc’.

    # Run command inside network namespace
    as_ns () {
        sudo ip netns exec ${NETNS} $@
    # Create network namespace
    create_ns () {
        sudo ip netns add ${NETNS}
        sudo ip link add dev veth-${NAME} type veth peer name veth0 netns ${NETNS}
        sudo ip link set dev veth-${NAME} up
        as_ns ${NAME} ip link set dev lo up
        [ -n "${IP}" ] && as_ns ${NAME} ip addr add dev veth0 ${IP}
        as_ns ${NAME} ip link set dev veth0 up
    # Clean up namespaces, bridges and processes created during faucet tutorial
    cleanup () {
        for NETNS in $(sudo ip netns list | grep "faucet-" | awk '{print $1}'); do
            [ -n "${NETNS}" ] || continue
            if [ -f "/run/dhclient-${NAME}.pid" ]; then
                # Stop dhclient
                sudo pkill -F "/run/dhclient-${NAME}.pid"
            if [ -f "/run/iperf3-${NAME}.pid" ]; then
                # Stop iperf3
                sudo pkill -F "/run/iperf3-${NAME}.pid"
            if [ -f "/run/bird-${NAME}.pid" ]; then
                # Stop bird
                sudo pkill -F "/run/bird-${NAME}.pid"
            # Remove netns and veth pair
            sudo ip link delete veth-${NAME}
            sudo ip netns delete ${NETNS}
        for isl in $(ip -o link show | awk -F': ' '{print $2}' | grep -oE "^l-br[0-9](_[0-9]*)?-br[0-9](_[0-9]*)?"); do
            # Delete inter-switch links
            sudo ip link delete dev $isl 2>/dev/null || true
        for DNSMASQ in /run/dnsmasq-vlan*.pid; do
            [ -e "${DNSMASQ}" ] || continue
            # Stop dnsmasq
            sudo pkill -F "${DNSMASQ}"
        # Remove faucet dataplane connection
        sudo ip link delete veth-faucet 2>/dev/null || true
        # Remove openvswitch bridges
        sudo ovs-vsctl --if-exists del-br br0
        sudo ovs-vsctl --if-exists del-br br1
        sudo ovs-vsctl --if-exists del-br br2
        sudo ovs-vsctl --if-exists del-br br3
    # Add tagged VLAN interface to network namespace
    add_tagged_interface () {
         as_ns ${NAME} ip link add link veth0 name veth0.${VLAN} type vlan id ${VLAN}
         [ -n "${IP}" ] && as_ns ${NAME} ip addr add dev veth0.${VLAN} ${IP}
         as_ns ${NAME} ip link set dev veth0.${VLAN} up
         as_ns ${NAME} ip addr flush dev veth0


In this tutorial we will look at how to do the following tasks using Faucet:

  • Use VLANs to segment traffic.

  • Create VLAN Trunks.

  • Apply an ACL to an entire VLAN.


We cover Routing between VLANs in a later tutorial.

A port can be in several VLAN modes:

  1. Native - where packets come into the switch with no 802.1Q tag.

  2. Tagged - where packets come into the switch with a 802.1Q tag.

  3. Mixed - where both native and tagged packets appear on the same port.

If a packet comes in with a tag for a VLAN that the port is not configured for it will be dropped.

Configuring VLANs

To demonstrate these tasks we will use a demo network where a single switch br0 connects to 9 hosts.

Ports 1, 2, 5, 6 will be native (untagged) ports. While ports 3, 4, 7, 8, and 9 will be tagged ports.

Here is the structure of the demo setup.

VLAN Network Diagram


Keep this diagram nearby to simplify following the rest of the tutorial.

Network setup

Let’s start. Keep host1, host2 on the native VLAN 100 (office VLAN) as in the first and second tutorials.


To create the hosts and switch again run

create_ns host1
create_ns host2
sudo ovs-vsctl add-br br0 \
-- set bridge br0 other-config:datapath-id=0000000000000001 \
-- set bridge br0 other-config:disable-in-band=true \
-- set bridge br0 fail_mode=secure \
-- add-port br0 veth-host1 -- set interface veth-host1 ofport_request=1 \
-- add-port br0 veth-host2 -- set interface veth-host2 ofport_request=2 \
-- set-controller br0 tcp: tcp:

Then add the following hosts with the corresponding VLAN:

  • Assign host3 and host4 a VLAN interface (vid:100) as they are on a tagged port.

create_ns host3
create_ns host4
add_tagged_interface host3 100
add_tagged_interface host4 100
  • Assign host5 and host6 an IP address from the VLAN 200 range.

create_ns host5
create_ns host6
  • Assign host7 and host8 a VLAN interface (vid:300) as they are on a tagged port.

create_ns host7
create_ns host8
add_tagged_interface host7 300
add_tagged_interface host8 300
  • Add host9 to all VLANs (100, 200, 300) to work as a NFV host.

create_ns host9
add_tagged_interface host9 100
add_tagged_interface host9 200
add_tagged_interface host9 300

Then connect all the hosts to the switch (br0)

sudo ovs-vsctl add-port br0 veth-host3 -- set interface veth-host3 ofport_request=3 \
-- add-port br0 veth-host4 -- set interface veth-host4 ofport_request=4 \
-- add-port br0 veth-host5 -- set interface veth-host5 ofport_request=5 \
-- add-port br0 veth-host6 -- set interface veth-host6 ofport_request=6 \
-- add-port br0 veth-host7 -- set interface veth-host7 ofport_request=7 \
-- add-port br0 veth-host8 -- set interface veth-host8 ofport_request=8 \
-- add-port br0 veth-host9 -- set interface veth-host9 ofport_request=9

Now we have everything to start working with faucet through its configuration file. Each time we will only need to change the configuration file and restart faucet (or send it HUP signal to reload the configuration file).

Basic VLAN settings

Change /etc/faucet/faucet.yaml to reflect our setting.

        vid: 100
        vid: 200
        vid: 300
        dp_id: 0x1
        hardware: "Open vSwitch"
                name: "host1"
                description: "host2 network namespace"
                native_vlan: vlan100
                name: "host2"
                description: "host2 network namespace"
                native_vlan: vlan100
                name: "host3"
                tagged_vlans: [vlan100]
                name: "host4"
                tagged_vlans: [vlan100]
                name: "host5"
                native_vlan: vlan200
                name: "host6"
                native_vlan: vlan200
                name: "host7"
                tagged_vlans: [vlan300]
                name: "host8"
                tagged_vlans: [vlan300]
                name: "host9"
                tagged_vlans: [vlan100,vlan200,vlan300]

Send SIGHUP signal to reload the configuration file, and check how its log the new configuration in /var/log/faucet/faucet.log

sudo systemctl reload faucet
cat /var/log/faucet/faucet.log

Let’s do the following simple tests:

  1. Ping between hosts in the same VLAN (all should work)

as_ns host1 ping
as_ns host3 ping
as_ns host5 ping
as_ns host7 ping
  1. Ping between hosts in the same VLAN where the one host is native and the other is tagged should work also. In particular between host1 (native VLAN 100) to host3 (tagged VLAN 100).

as_ns host1 ping
  1. Ping between hosts in different VLANs should fail. To test that let’s add the IP address to host5 (native VLAN 200) and try to ping it from host1 (native VLAN 100).

as_ns host5 ip address add dev veth0
as_ns host1 ping
  1. Now we can test the trunk link to host9 from different VLANs (all should work)

as_ns host1 ping
as_ns host3 ping
as_ns host5 ping
as_ns host7 ping


Let’s apply an ACL on a particular VLAN (e.g. VLAN 300). We will block any ICMP packets on VLAN 300. First create an ACL to block the ping. Open /etc/faucet/faucet.yaml and add the ‘acls’ section.

        - rule:
            dl_type: 0x800      # IPv4
            ip_proto: 1         # ICMP
                allow: False
        - rule:
            dl_type: 0x86dd     # IPv6
            ip_proto: 58        # ICMPv6
                allow: False

Then apply this ACL on VLAN 300.

        vid: 100
        vid: 200
        vid: 300
        acls_in: [block-ping] # Apply ACL only on vlan300

Just before we reload the configuration file. Let’s verify that pinging is working between hosts in VLAN 300.

as_ns host7 ping

Now let’s apply the configuration, send SIGHUP signal to reload the configuration file.

sudo systemctl reload faucet

Now if you try to ping from host7 and host8, it will not work as it is specified by their VLAN ACL.

as_ns host7 ping