OpenvSwitch. Basic usage


Open vSwitch (OVS) is an open source OpenFlow implementation mainly used in virtualized environments. OpenvSwitch has a lot of features and it can be confusing when starting out, so the idea is to write several post with information related to the the use of OpenvSwitch, virtual network interfaces and related items, which can be used as a reference in the future

To start working with OVS only a linux box is needed (debian of course! :) ) and OVS is installed just with the openvswitch-switch package:

apt install openvswitch-switch

It’s also possible to install the package openvswitch-switch-dpdk for DPDK enabled OVS used in specific situations where high performance network throughput is needed, but it implies the use of network interfaces supported by dpdk.

Basic OVS CLI

There are different OVS related command line interfaces, the main ones are the following:

ovs-appctl
ovs-ofctl
ovs-dpctl
ovs-vsctl

For example, to create a new OVS bridge, just type (autocomplete is enabled when used by root user):

ovs-vsctl br-add br1

ovs-vsctl show 
572ef28b-6429-4a71-aad8-f634d8274930
    Bridge br1
        Port br1
            Interface br1
                type: internal
    ovs_version: "2.15.0"

8: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 4e:e6:18:c3:77:20 brd ff:ff:ff:ff:ff:ff
9: br1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 4e:76:98:43:ff:44 brd ff:ff:ff:ff:ff:ff

The ovs bridge is down, the following steps are taken to bring it up, assign an IP address and set iptables rule to allow NAT access to the Internet:

ip l set br1 up

ip a add 192.168.100.1/24 dev br1

iptables -t nat -A POSTROUTING -s 192.168.100.0/24 ! -d 192.168.100.0/24 \
-j MASQUERADE

ip a show dev br1
9: br1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether 4e:76:98:43:ff:44 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 scope global br1
       valid_lft forever preferred_lft forever
    inet6 fe80::4c76:98ff:fe43:ff44/64 scope link 
       valid_lft forever preferred_lft forever

br1 shows an administrative state UP (because we have brought it up), the operational state LOWER_UP means that the link is detected at the «physical layer» (Driver signals L1 up according to netdevice man page) and the state will remain UNKNOWN becase iproute2 can’t obtain ovs states.

LXC test environment

Once OVS is installed on the host machine, several virtual instances can be created to connect to OVS bridges and to interact to each other. In this case we’re going to use LXC (linux containers), but any other virtualization technology can be used.

The default bridge used can be changed to br1 on /etc/lxc/default.conf, and the container can be easily created:

lxc-create -n test1 -t debian

Once the container is created, the corresponding config file (/var/lib/lxc/test1/config) can be modified (in this case, we’re going to add static IP address for the container and the gateway because there’s no DHCP server connected to the OVS bridge, adding the following lines):

lxc.net.0.ipv4.address = 192.168.100.2/24
lxc.net.0.ipv4.gateway = 192.168.100.1

Note: Config file can be checked with lxc-checkconfig

Once the container is started, a veth interface is created and added as a port to br1:

lxc-start -n test1

ovs-vsctl show
572ef28b-6429-4a71-aad8-f634d8274930
    Bridge br1
        Port vethrVi2DI
            Interface vethrVi2DI
        Port br1
            Interface br1
                type: internal
    ovs_version: "2.15.0"

ip l show dev vethrVi2DI
14: vethrVi2DI@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master ovs-system state UP mode DEFAULT group default qlen 1000
    link/ether fe:0d:8f:5c:88:f2 brd ff:ff:ff:ff:ff:ff link-netnsid 0

The same name is used for a ovs interface and a ovs port. The difference is that a port can contain several interfaces in a link aggregation (bond), but in this case only one interface is used for each port.

lxc-attach can be initially used to access to the container, and the network configuration and external connectivity can be tested:

ip a s dev eth0
2: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:b1:20:18 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.100.2/24 brd 192.168.100.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::216:3eff:feb1:2018/64 scope link 
       valid_lft forever preferred_lft forever

We’re using a veth interface that is a virtual Ethernet interface with interconnected pairs, in this case one pair (vethrVi2DI) is in the host and the other (eth0) is in the container, but the link between them is shown with the «@» sign:

So it’s easy to know what interface in the host is connected to each container.

14: vethrVi2DI@if2 <-> 2: eth0@if14

Note: The interface number, the OVS port and the veth name is going to change on the host every time the container is restarted

We can get information about different tables on the OVS database (Open_vSwitch, Bridge, Port, Datapath, Flow_Table, Port, Interface, …):

ovs-vsctl list Open_vSwitch
_uuid               : 572ef28b-6429-4a71-aad8-f634d8274930
bridges             : [4398764d-ef3e-44ff-a303-55bb02bd0662]
cur_cfg             : 8
datapath_types      : [netdev, system]
datapaths           : {}
db_version          : "8.2.0"
dpdk_initialized    : false
dpdk_version        : none
external_ids        : {hostname=mut, rundir="/var/run/openvswitch", system-id="5c827fe2-b53d-4eb9-9f4c-541043e61294"}
iface_types         : [bareudp, erspan, geneve, gre, gtpu, internal, ip6erspan, ip6gre, lisp, patch, stt, system, tap, vxlan]
manager_options     : []
next_cfg            : 8
other_config        : {}
ovs_version         : "2.15.0"
ssl                 : []
statistics          : {}
system_type         : debian
system_version      : "11"

ovs-vsctl list Bridge
_uuid               : 4398764d-ef3e-44ff-a303-55bb02bd0662
auto_attach         : []
controller          : []
datapath_id         : "00004e769843ff44"
datapath_type       : ""
...

ovs-vsctl list Port
_uuid               : bce0532e-9a1f-486f-8098-4a1c180c207b
bond_active_slave   : []
bond_downdelay      : 0
bond_fake_iface     : false
...

_uuid               : a2004f73-ee71-466a-a364-82ff0c5af87f
bond_active_slave   : []
bond_downdelay      : 0
bond_fake_iface     : false
...

ovs-vsctl list Interface
_uuid               : 88f9d3d0-9357-49bd-9811-d363304f2153
admin_state         : up
bfd                 : {}
...
mac_in_use          : "4e:76:98:43:ff:44"
mtu                 : 1500
mtu_request         : []
name                : br1
ofport              : 65534
ofport_request      : []
options             : {}
other_config        : {}
statistics          : {collisions=0, rx_bytes=278193, rx_crc_err=0, rx_dropped=0, rx_errors=0, rx_frame_err=0, rx_missed_errors=0, rx_over_err=0, rx_packets=4120, tx_bytes=12172817, tx_dropped=0, tx_errors=0, tx_packets=9745}
status              : {driver_name=openvswitch}
type                : internal

_uuid               : 1830b2f7-d50b-48a3-a033-2dbda929c3f2
admin_state         : up
bfd                 : {}
...
link_speed          : 10000000000
link_state          : up
lldp                : {}
mac                 : []
mac_in_use          : "fe:0d:8f:5c:88:f2"
mtu                 : 1500
mtu_request         : []
name                : vethrVi2DI
ofport              : 4
ofport_request      : []
options             : {}
other_config        : {}
statistics          : {collisions=0, rx_bytes=333025, rx_crc_err=0, rx_dropped=0, rx_errors=0, rx_frame_err=0, rx_missed_errors=0, rx_over_err=0, rx_packets=4104, tx_bytes=12074340, tx_dropped=0, tx_errors=0, tx_packets=9291}
status              : {driver_name=veth, driver_version="1.0", firmware_version=""}
type                : ""
Other basic commands to get information:
ovs-ofctl show br1
OFPT_FEATURES_REPLY (xid=0x2): dpid:00004e769843ff44
n_tables:254, n_buffers:0
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
 4(vethrVi2DI): addr:fe:0d:8f:5c:88:f2
     config:     0
     state:      0
     current:    10GB-FD COPPER
     speed: 10000 Mbps now, 0 Mbps max
 LOCAL(br1): addr:4e:76:98:43:ff:44
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0

ovs-dpctl show
system@ovs-system:
  lookups: hit:42 missed:48 lost:0
  flows: 0
  masks: hit:52 total:0 hit/pkt:0.58
  port 0: ovs-system (internal)
  port 1: br1 (internal)
  port 4: vethrVi2DI

References

OpenvSwitch. Basic usage

Deja un comentario