Boot integration of the Openvswitch in Ubuntu

The installation of the Openvswitch on Ubuntu brings an automatic integration into the boot sequence. When Ubuntu is booted, the Openvswitch is also started. Any bridge or port, which has been defined in previous sessions, is restored.
BUT: No L3 interfaces are set up, junk interfaces, which have been defined in previous sessions, are restored.

The ideal start sequence of the Openvswitch delivers:

  • an empty Openvswitch database during the startup of Ubuntu –> clean the Openvswitch database (patch necessary)
  • define all bridges, interfaces, port,… using /etc/network/interfaces –> this is supported
  • brings also up all defined L3 interfaces on Openvswitch internal interfaces –> patch necessary

With Ubuntu 16.04 systemd is used to start the system. Older systems using upstart have now a fixed upstart script (see below) – but the systemd scripts do not allow out of the box an automatic setup of OVS interfaces. How to fix it? See below… 🙂 Lets hope, that Canonical provides a patch for 16.04 before 18.04 shows up…

With Ubuntu 16.10 boot integration works out of the box.

Define bridges, ports, interfaces using /etc/network/interfaces

All configurations items, which are necessary to set up the Openvswitch, can be defined in /etc/network/interfaces .

Define a bridge

All ports and interfaces on the Openvswitch must be attached to a bridge. Defining a bridge (which is a virtual switch) requires the following configuration items:

#
# create an Openvswitch bridge
# on the commandline: ovs-vsctl add-br vmbr-int
#
auto vmbr-int
allow-ovs vmbr-int
iface vmbr-int inet manual
  ovs_type OVSBridge

The configurations lines are

  • auto is necessary to allow an automatic start (Ubuntu 16.04 using systemd)
  • allow-ovs is the marker for an Openvswitch bridge. The bridge name follows, here vmbr-int
  • iface is the well known /etc/network/interfaces identifier to start an interface configuration
  • ovs_type defines the interface type for ovs. OVSBridge identifies an Openvswitch bridge

The lines above are an equivalent of the command ovs-vsctl add-br vmbr-int

Define a L2 port (untagged)

The next step is to attach a port (not seen by Linux) to the bridge above.

#
# create an untagged ovs port in vlan 444
# (config not yet complete)
#
allow-vmbr-int l2port
iface l2port inet manual
  ovs_bridge vmbr-int
  ovs_type OVSPort
  ovs_options tag=444

The configuration lines are

  • allow-[name of the bridge to attach the port] defines the name of the bridge, to which the port should be attached to. In our example this is vmbr-int. The name of the port follows (here l2port)
  • iface is the well known /etc/network/interfaces identifier to start an interface configuration — set the config to manual
  • ovs-bridge holds the name of the bridge to which the port should be attached to. In our example this is vmbr-int.
  • ovs_type defines the interface type for ovs. OVSPort identifies an Openvswitch port not seen by the Linux Operating system
  • ovs_options defines additional options for the port – here define an untagged port, which is member of Vlan 444. If this option is not set, a port may use all vlan tags on the interfaces, because all ports transport vlan tags by default.

The bad thing is, that the bridge (vmbr-int) must be defined twice. But this is not the whole truth. This definition is required a third time. The complete definition for the bridge and port is now:

#
# create an Openvswitch bridge
#
auto vmbr-int
allow-ovs vmbr-int
iface vmbr-int inet manual
  ovs_type OVSBridge
  ovs_ports l2port
#
# create an untagged ovs port in vlan 444
#
allow-vmbr-int l2port
iface l2port inet manual
  ovs_bridge vmbr-int
  ovs_type OVSPort
  ovs_options tag=444

This is the summary definition. It contains one additional line in the bridge definition iface

  • ovs_ports holds the list of all ports which should be attached to the bridge

The port which is added to the bridge in the example above can also be an existing physical nic. The example below shows the config to add a physical interface to a bridge:

auto br-phys
allow-ovs br-phys
iface br-phys inet manual
  ovs_type OVSBridge
  ovs_ports eno1

allow-br-phys eno1
iface eno1 inet manual
  ovs_bridge br-phys
  ovs_type OVSPort

Define a L3 interface

The definition of a L3 interface requires the following configuration lines

#
# create an untagged ovs port in vlan 444
#
allow-vmbr-int l3port
iface l3port inet static
  ovs_bridge vmbr-int
  ovs_type OVSIntPort
  ovs_options tag=444
  address 192.168.1.254
  netmask 255.255.255.0

The differences compared to the L2 port are

  • iface — set the mode to static — because an IP address is configured on this interface
  • ovs_type — an L3 port must be defined as an internal port — must be set to OVSIntPort
  • address and netmask are the well known parameters for IPV4 an address/netmask combination

Do not forget to add the port to the bridge definition of vmbr-int.

Define a L2 port (tagged/trunking)

The definition of a L2 port, which is tagged looks like:

#
# create an tagged ovs port
#
allow-vmbr-int l2taggedport
iface l2taggedport inet manual
  ovs_bridge vmbr-int
  ovs_type OVSPort
  ovs_options trunks=2101,2102,2110,2120,2999,3000

A trunking port does not require an additional definition. In the example above, we want to limit the vlans on the port. This requires a trunk definition using the ovs_options line.

Define a fake bridge

It is also possible to add the definition of an ovs fake bridge

#
# a fake bridge without an ip address
# ovs-vsctl add-br fakebr vmbr-int 2102
#
allow-vmbr-int fakebr
iface fakebr inet manual
  ovs_bridge vmbr-int
  ovs_type OVSBridge
  ovs_options vmbr-int 2102

A fake bridge definition requires a special option

  • ovs_options must be set to vmbr-int 2102

On the commandline the command would be: ovs-vsctl add-br fakebr vmbr-int 2102 . The ovs_options are the two last options being necessary on the commandline.

Define a tagged LACP bond port

It is also possible to define a tagged bond port using LACP as the bonding protocol

#
# add a tagged bond port using LACP
#
allow-vmbr-int bondpub
iface bondpub inet manual
  ovs_bridge vmbr-int 
  ovs_type OVSBond
  ovs_bonds eth4 eth5
  ovs_options other_config:lacp-port-id=103 bond_fake_iface=true bond_mode=balance-slb lacp=active other_config:lacp-time=fast bond_updelay=2000 bond_downdelay=400 trunks=2101,2102,2110,2120,2999,3000

The options are

  • ovs_type must be set to OVSBond
  • ovs_bonds has the list of the interfaces to be added to the bond — here eth4 and eth5
  • ovs_options holds all the extra options for the bond and the trunk. These are the same options, which have to be used on the command line

Interface helper script

ifup and ifdown are using a helper script, which is part of the openvswitch-switch package. This script openvswitch is located in /etc/network/if-pre-up.d/ . This script executes all commands.

This script is missing only the support to change the mtu of Openvswitch bridges, ports and interfaces.

Boot support (Ubuntu 20.04)

Boot support in Ubuntu 20.04 should work out of the box – should. But in Ubuntu 20.04 and some version before, there is a race condition which makes the ovs interface setup not predictable.

A small change helps here.

The systemd file for the ovsdb server in /lib/systemd/system/ovsdb-server.service should be changed.

[Unit]
Description=Open vSwitch Database Unit
After=syslog.target network-pre.target dpdk.service local-fs.target
Before=network.target networking.service
PartOf=openvswitch-switch.service
DefaultDependencies=no

< more data below>

The dependencies must be adjusted in order to avoid ovs components start before the local file systems are mounted.
Add „local-fs.target“ to the „After“ list.

Boot support (Ubuntu 16.04 – when using systemd)

Canonical did it again – deliver an OS which does not support the autostart of OVS interfaces.. The upstart scripts have been fixed to allow the autostart of OVS interfaces, but now systemd is used – and the automatic start of OVS interfaces is broken again.

A fix is available, see Launchpad Bug. The systemd start file for OVS needs to be changed to add dependencies. OVS must be started before setting up the network interfaces.

[Unit]
Description=Open vSwitch Internal Unit
PartOf=openvswitch-switch.service

#https://bugs.launchpad.net/ubuntu/+source/openvswitch/+bug/1448254

# Without this all sorts of looping dependencies occur doh!
DefaultDependencies=no

#precedants pulled from isup@ service requirements
After=apparmor.service local-fs.target systemd-tmpfiles-setup.service

#subsequent to this service we need the network to start
Wants=network-pre.target openvswitch-switch.service
Before=network-pre.target openvswitch-switch.service

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/etc/default/openvswitch-switch
ExecStart=/usr/share/openvswitch/scripts/ovs-ctl start \
          --system-id=random $OVS_CTL_OPTS
ExecStop=/usr/share/openvswitch/scripts/ovs-ctl stop

Replace /lib/systemd/system/openvswitch-nonetwork.service with the file content above, and you’re done.

One option to delete all existing bridges should be set in the config file /etc/default/openvswitch-switch to start with an empty openvswitch config.

OVS_CTL_OPTS='--delete-bridges'

Boot support (Ubuntu 14.04 and later – when using upstart)

Ubuntu 14.04 has a better boot support for the openvswitch, but it is still not perfect. The interface up/down stuff is still missing.

One option to delete all existing bridges should be set in the config file /etc/defaults/openvswitch-switch

OVS_CTL_OPTS='--delete-bridges'

The upstart script must be patched twice to start and stop ovs components and the associated interfaces.

  "$@" || exit $?
  ########## PATCH START ##############
  # start the bridges
  bridges=`ifquery --allow ovs -l` 
  [ -n "${bridges}" ] && ifup --allow=ovs ${bridges}
  logger -t ovs-start pre-start end
  ########## PATCH END ################
end script

You must insert all lines between „exit $?“ and „end script“ to bring up the Openvswitch interfaces.

The shutdown sequence requires the following patch:

post-stop script
  ########### PATCH START ################
  logger -t ovs-stop post-stop
  bridges=`ifquery --allow ovs -l` 
  [ -n "${bridges}" ] && ifdown --allow=ovs ${bridges}
  ######### PATCH END ##############
  . /usr/share/openvswitch/scripts/ovs-lib
  test -e /etc/default/openvswitch-switch && . /etc/default/openvswitch-switch

There is still a dependency. The openvswitch start script assumes, that the loopback interface is brought up as the last interface.

Boot support (pre Ubuntu 14.04)

The boot support for the Openvswitch is implemented very different. It depends on the Openvswitch version, the Ubuntu version and the package repository. Up to now there is NO support to bring up the interfaces automatically. In any case, a patch is required.

All Ubuntu distributions are using Openvswitch packages(by November 2013), which do not have an openvswitch upstart script. One way to bring up interfaces here is using a few lines in /etc/rc.local or patching /etc/init.d/openvswitch-switch .

The necessary lines for /etc/rc.local would be:

#
# list the bridges
#
bridges=`awk '{ if ($1 == "allow-ovs") { print $2; } }' "${INTERFACES}"`
#
# and bring them up
#
[ -n "${bridges}" ] && ifup --allow=ovs ${bridges}

You may add the necessary lines to /etc/init.d/openvswitch-switch , but the interfaces may come up too late, because the non upstart script starts too late.

If you are using the openvswitch package from the Havana Ubuntu Cloud Archive [deb http://ubuntu-cloud.archive.canonical.com/ubuntu precise-updates/havana main] you have an openvswitch-switch upstart script. This must be patched to bring up all ovs network components.

  "$@" || exit $?
  ########## PATCH START ##############
  # get the bridges defined 
  INTERFACES="/etc/network/interfaces"
  [ -e "${INTERFACES}" ] || return
  bridges=$(ovs-vsctl list-br)
  # delete the bridges defined in interfaces which survived a crash or reboot
  if [ -n "${bridges}" ]
  then
    for b in ${bridges}
    do
      ovs-vsctl --timeout=2 -- --if-exists del-br $b
    done
  fi
  # and start the bridges
  bridges=`awk '{ if ($1 == "allow-ovs") { print $2; } }' "${INTERFACES}"`
  [ -n "${bridges}" ] && ifup --allow=ovs ${bridges}
  logger -t ovs-start pre-start end
  ########## PATCH END ################
end script

You must insert all lines between „exit $?“ and „end script“ to bring up the Openvswitch interface.

The shutdown sequence requires the following patch:

post-stop script
  ########### PATCH START ################
  logger -t ovs-stop post-stop
  INTERFACES="/etc/network/interfaces"
  [ -e "${INTERFACES}" ] || return
  bridges=`awk '{ if ($1 == "allow-ovs") { print $2; } }' "${INTERFACES}"`
  [ -n "${bridges}" ] && ifdown --allow=ovs ${bridges}
  ######### PATCH END ##############
  . /usr/share/openvswitch/scripts/ovs-lib
  test -e /etc/default/openvswitch-switch && . /etc/default/openvswitch-switch

There is still a dependency. „ifup -a“ in networking.conf brings up the loopback interface as the last interface. This is the trigger to emit the event „loopback interface is up“ which triggers then openvswitch-switch upstart script. This might be too late. Hopefully there will be a fully integrated solution for Ubuntu in future release (after 13.10)

Updated: 17/01/2021 — 12:02