This part covers:
- Main Components (ovsdb-server, ovs-vswitchd, ovs kernel module)
- Utilities (ovs-vsctl, ovs-ofctl, ovs-appctl, etc)
- Modes (normal & flow)
Part 1 is here.
Open vSwitch Components
The following diagram shows Open vSwitch main components and in which space (kernel, user or remote server) each component is located
Let’s describe each one of them in more detail.
One of the core components. It is a Daemon which controls all Open vSwitch switches on the system.
When started for the first time, it gets its initial configuration from the ovsdb-server, using the OVSDB management protocol.
It communicates with the kernel module using the netlink protocol. For communication with the system, it uses netdev abstract interface.
It is also responsible for implementing switch features such as mirroring, bonding and VLANs.
A lightweight database that holds switch level configuration. Thanks to ovsdb-server, the switch configuration changes are persistent and should survive a system reboot. It Communicates with ovs-vswitchd using the OVSDB management protocol.
OpenvSwitch Kernel Module
Handles the switching and tunneling.
When a packet arrives, it checks if there is an existing entry for it (meaning if it’s an familiar flow) if not, the packet sent to the userspace, where it processed by ovs-vswitchd.
It’s designed to be fast and simple and knows nothing of OpenFlow. OpenFlow communication is done exclusively with ovs-vswitchd.
It implements “datapaths”. Datapath is a collection of physical or virtual ports. You can think of it as a bridge, but in the kernel and not in userspace. Each datapath can have one or more ports, which called “vports”. Datapaths are controlled with the ‘ovs-dpctl’ command (we’ll cover it in the ‘utilities’ section).
Although it’s not part of Open vSwitch components, it’s important to know what it is for since, you might have it in your environment.
All the flows kept in ovs-vswitchd will be lost in case of a restart or a crash. So to keep important flows persistent, an OpenFlow controller is usually used.
It’s common to find it installed on a remote server (that’s why it placed in different “space” in the drawing) although it can be installed on the same server.
Open vSwitch Utilities
Querying and updating the configuration of ovs-vswitchd.
Let’s see a few examples (most of them we already used in the previous post)
> ovs-vsctl add-br 'my_bridge' # Adds a new bridge named 'my_bridge' > ovs-vsctl add-port my_bridge new_port # Adds a new port named 'new_port' in 'my_bridge'
> ovs-vsctl show # Prints summary of of all the bridges, ports and interfaces 79ec4909-0d98-489b-a81b-a667cf26ad3d Bridge my_bridge Port "eth0" Interface "eth0" Port my_bridge Interface my_bridge type: internal ovs_version: "2.5.0"
> ovs-vsctl del-br my_bridge # Delete the bridge 'my_bridge' > sudo ovs-vsctl list-ifaces my_bridge # List the interfaces of 'my_bridge' eth0 new_port
Querying and controlling OpenFlow switches and controllers.
A few examples (more details on OpenFlow and ovs-ofctl can be found in the OpenFlow post):
> ovs-ofctl show <bridge_name> # Prints information on the bridge, its ports and flow table OFPT_FEATURES_REPLY (xid=0x2): dpid:0000ce8b5ba7a84f n_tables:254, n_buffers:256 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 1(eth0): addr:52:54:00:9f:63:08 config: 0 state: 0 speed: 0 Mbps now, 0 Mbps max LOCAL(my_bridge): addr:ce:8b:5b:a7:a8:4f config: 0 state: 0 speed: 0 Mbps now, 0 Mbps max OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0
> ovs-ofctl dump-flows my_bridge # Prints all the flows in 'my_bridge' flow table NXST_FLOW reply (xid=0x4): cookie=0x0, duration=176807.518s, table=0, n_packets=110496, n_bytes=5904834, idle_age=0, hard_age=65534, priority=0 actions=NORMAL
> ovs-ofctl add-flow my_Bridge action=normal # Add a new flow
Configuring the switch kernel module. Allows to to modify, create and delete data-paths.
> ovs-dpctl add-dp my_dp # Add a new data path > ovs-dpctl add-if my_dp eth0 # Adds existing interface to the specified data path
> ovs-dpctl show # Prints summary of the data paths and theirs ports system@ovs-system: lookups: hit:116813 missed:8250 lost:0 flows: 4 masks: hit:145936 total:3 hit/pkt:1.17 port 0: ovs-system (internal) port 1: my_bridge (internal) port 2: eth0
Sends commands to running Open vSwitch daemon.
One of its common uses is ‘ovs-appctl fsb/show <bridge_name>’. It basically prints the MAC address table.
> sudo ovs-appctl fdb/show my_bridge port VLAN MAC Age LOCAL 0 ce:8b:5b:a7:a8:4f 0 1 0 52:54:00:7b:f9:ea 0
Creating and managing the public-key infrastructure for OpenFlow switches.
> ovs-pki init # Creates an initial PKI structure > ovs-pki req+sign ctl controller # Creates controller private key and a certificate
A simple OpenFlow controller that may be useful for testing (don’t use it for production).
> vs-testcontroller ptcp: # Creates an test controller that waits for incoming connections
Open vSwitch Modes
Open vSwitch bridge can operate in either normal mode or flow mode when forwarding packets.
In normal mode, it acts as a layer 2 learning switch:
- When a frame first received it compares the frame’s source MAC address to the one in the table.
- If the source is unknown (= it’s not in the MAC address table) then it adds the source MAC address to the table with the port number the packet was received on
- It compares the destination MAC (where this packet should reach at the end) to the one in the MAC address table
- If there is an entry, the switch forwards the frame out through the associated port
- If there is no entry, it floods the packet out from all its ports, except the port where the frame was received
To view the MAC address table, you can use ‘ovs-appctl fdb/show’
> ovs-appctl fdb/show <bridge_name> port VLAN MAC Age LOCAL 0 ce:8b:5b:a7:a8:4f 0 1 0 52:54:00:7b:f9:ea 0
In flow mode, things are a little bit more complex. The switch makes forwarding decisions based on OpenFlow table entries.
A switch might have one or more flow tables. A flow table can be created manually by adding flows with ‘ovs-ofctl add-flow’ command or it can be set by an OpenFlow controller (as seen in the components drawing).
I won’t go into much detail on OpenFlow, there is a dedicated post for that, but let’s describe the workflow of a packet reaching a switch which operates in flow mode:
- When a packet first arrives the switch, it processed first by the lowest number flow table (usually table 0). Each table consists of flows or more accurately, flow entries.
- Each flow entry contains several fields/components. The packet is then matched to the ‘match fields’.
- ‘match fields’ are basically packet headers, the ingress port and optional additional fields such as the metadata. Match fields can be for example a destination IP address, VLAN id, UDP source port, ICMP code, etc.
- In case the packet matches several flow entries, the entry with the highest priority (anther field in flow entry) will be chosen.
- Once a match made, the action part (which also specified in the entry) defines what to do next. The action can be: forward to a specific port, drop, process through the specified group – those are called “required actions” (since the switch is required to support them). There are also optional actions such as: change TTL, change header fields, push tag.
- If the packet didn’t match any ‘field match’, this situation called ‘table-miss’ and unless there is a controller where the packet information can be sent to, the packet is dropped or redirected to another table.