Showing posts with label OVS. Show all posts
Showing posts with label OVS. Show all posts

Tuesday, September 29, 2020

DPDK Hands-On - Part VIII - Creating Virtual DPDK Ports on OpenVSwitch

Before we get into the procedure of adding virtual ports to the switch, it is important to understand the two types of DPDK virtual ports, and their differences.

In the earlier versions of DPDK+OVS, virtual interfaces were defined with a type called vhostuser. These interfaces would connect to OpenVSwitch. Meaning, from a socket perspective, that OpenVSwitch managed the socket. More technically, OVS binds to a socket in /var/run/openvswitch/<portname>  behaving as a server, while the VMs connect to this socket as a client.

There is a fundamental flaw in this design. A rather major one! Picture a situation where a dozen virtual machines launch with ports that are connected to the OVS, and the OVS is rebooted! All of those sockets are destroyed on the OVS, leaving all of the VMs "stranded".

To address this flaw, the socket model needed to be reversed. The virtual machine (i.e. qemu) needed to act as the server, and the switch needed to be the client! 

Hence, a new port type was created: vhostuserclient.

A more graphical and elaborative explanation of this can be found on this link:

https://software.intel.com/content/www/us/en/develop/articles/data-plane-development-kit-vhost-user-client-mode-with-open-vswitch.html 

Now because there are two sides to any socket connection, it makes sense that BOTH sides need to be configured properly with the proper port type for this communication to work.

This post deals with simply adding the right DPDK virtual port type (vhostuser or vhostuserclient) to the switch. But configuring the VM properly is also necessary, and will be covered in a follow-up post after this one is published.

I think the easiest way to show how these two port types are added, with some discussion.

VhostUser

To add a vhostuser port, the following command can be run:

# ovs-vsctl add-port br-tun dpdkvhost1 -- set Interface dpdkvhost1 type=dpdkvhostuser ofport_request=2

It is as simple as adding a port to a bridge, giving it a name, and using the appropriate type for a legacy virtual DPDK port (dpdkvhostuer). We also give it port number 2 (in our earlier post, we added a physical DPDK PCI NIC to port 1 so we will assume port 1 is used by that).

Notice, that there is no socket information included in this. OpenVSwitch will create a socket, by default, in /var/run/openvswitch/<portname> once the vhostuser port is added to the switch. 

NOTE: The OVS socket location can be overridden but for simplicity we will assume default location. Another issue is socket permissions. When the VM launches under a different userid such as qemu, the socket will need to be writable by qemu!

The virtual machine, with a vhostuser interface defined on it, will need to be instructed where to connect; what socket to connect to. So because the VM needs to know where to connect to, it actually makes the OVS configuration somewhat simpler in this model because OVS will create the socket where it is configured to do so, the default being in /var/run/openvswitch.

So after adding a port to the bridge, we can do a quick show on our bridge to ensure it created properly.

# ovs-vsctl show 

 Bridge br-tun
        fail_mode: standalone
        Port "dpdkvhost1"
            Interface "dpdkvhost1"
                type: dpdkvhostuser

        Port "dpdk0"
            Interface "dpdk0"
                type: dpdk
                options: {dpdk-devargs="0000:01:00.0"}
        Port br-tun
            Interface br-tun
                type: internal

With this configuration, we can do a test between a physical interface and a virtual interface, or the virtual interface can attempt to reach something outside of the host (i.e. a ping test to a default gateway and/or an internet address). With this configuration, a virtual machine could also attempt a DHCP request to obtain its IP address for the segment is on if a DHCP server indeed exists.

If we wanted to test between two virtual machines, another such interface would need to be added:

# ovs-vsctl add-port br-tun dpdkvhost2 -- set Interface dpdkvhost2 type=dpdkvhostuser ofport_request=3

And, this would result in the following configuration:

  Bridge br-tun
        fail_mode: standalone
        Port "dpdkvhost2"
            Interface "dpdkvhost2"
                type: dpdkvhostuser
        Port "dpdkvhost1"
            Interface "dpdkvhost1"
                type: dpdkvhostuser

        Port "dpdk0"
            Interface "dpdk0"
                type: dpdk
                options: {dpdk-devargs="0000:01:00.0"}
        Port br-tun
            Interface br-tun
                type: internal

With this configuration, TWO virtual machines would connect to their respective OVS switch sockets:

VM1 connects to OVS socket for vhostusr1 --> /var/run/openvswitch/vhostusr1

VM2 connects to OVS socket for vhostusr2 --> /var/run/openvswitch/vhostusr2

Thanks to the PCI port we added earlier these two VMs "reach outside" to request an IP Address, and ping each other on the same segment if they both have an IP address.

dpdkvhost1      dpdkvhost2                          

      =|==========|=

      OVS Bridge (br-tun)

      ======|======

                dpdk0

                    |

        Upstream Router         

VhostUserClient

This configuration looks similar to the vhostuser configuration, but with a subtle difference. In this case, the VM is the server in the client server socket model, so the OVS port, as a client, needs to know where the socket it in order to connect to it!

# ovs-vsctl add-port br-tun dpdkvhostclt1 -- set Interface dpdkvhostclt1 type=dpdkvhostuserclient "options:vhost-server-path=/var/lib/libvirt/qemu/vhost_sockets/dpdkvhostclt1" ofport_request=4

In this directive, the only thing that changes is the addition of the parameter telling OVS where the socket is to connect to, and of course the type of port needs to be set to dpdkvhostuserclient (instead of the vhostuser).

And, if we run out ovs-vsctl show command, we will see that the port looks similar to the vhostuser ports, except for two differences:

  • the type is now vhostuserclient, rather than vhostuser
  • the option parameter which instructs OVS (the socket client) where to connect to.

Bridge br-tun
        fail_mode: standalone
        Port "dpdkvhostclt1"
            Interface "dpdkvhostclt1"
                type: dpdkvhostuserclient
                options: {vhost-server-path="/var/lib/libvirt/qemu/vhost_sockets/dpdkvhostclt1"}

        Port "dpdkvhost2"
            Interface "dpdkvhost2"
                type: dpdkvhostuser
        Port "dpdkvhost1"
            Interface "dpdkvhost1"
                type: dpdkvhostuser
        Port "dpdk0"
            Interface "dpdk0"
                type: dpdk
                options: {dpdk-devargs="0000:01:00.0"}
        Port br-tun
            Interface br-tun
                type: internal

Setting up Flows

Just because we have added these port, does not necessarily mean they'll work after creation. The next step, is to enable flows (rules) for traffic forwarding between these ports.

Setting up switch flows is an in-depth topic in and of itself, and one we won't cover in this post. There are advanced OpenVSwitch tutorials on Flow Programming (OpenFlow).

The first thing you can generally do, if you don't have special flow requirements that you're aware of, is to set the traffic processing to "normal", as seen below for the br-tun bridge/switch.

# ovs-ofctl add-flow br-tun actions=normal 

This should give normal L2/L3 packet processing. But, if you can't ping or your network forwarding behavior isn't as desired, you may need to program more detailed or sophisticated flows.

For simplicity, I can show you a couple of examples of how one could attempt to enable some traffic to flow between ports:

allows you to ping from the bridges out to the host on their PCI interfaces... 

# ovs-ofctl add-flow br-tun in_port=LOCAL,actions=output:dpdk0

# ovs-ofctl add-flow br-prv in_port=LOCAL,actions=output:dpdk1

allows you to forward packets to the proper VM when they come into the host.

# ovs-ofctl add-flow br-tun ip_dst=192.168.30.202,actions=output:dpdkvhost1

# ovs-ofctl add-flow br-prv ip_dest=192.168.20.202,actions=output:dpdkvhost0

To debug the packet flows, you can dump them with the "dump-flows" command. There is a similarity between iptables rules (iptables -nvL) and openvswitch flows, and debugging is somewhat similar in that you can dump flows, and look for packet counts.

# ovs-ofctl dump-flows br-prv
 cookie=0xd2e1f3bff05fa3bf, duration=153844.320s, table=0, n_packets=0, n_bytes=0, priority=2,in_port="phy-br-prv" actions=drop
 cookie=0xd2e1f3bff05fa3bf, duration=153844.322s, table=0, n_packets=10224168, n_bytes=9510063469, priority=0 actions=NORMAL

In the example above, we have two flows on the bridge br-prv. And we do not see any packets being dropped. So, presumably, anything connected to this bridge should be able to communicate from a flow perspective.

After setting these kinds of flows, ping tests and traffic verification tests will need to be done. 

I refer to this as "port plumbing" and these rules indeed can get very advanced, sophisticated and complex - potentially. 

If you are launching a VM on Linux, via KVM (a script usually), or using Virsh Manager (which drives off of an xml file that describes the VM), you will need to set these "port plumbing" rules up manually, and you would probably start with the basic normal processing unless you want to do something sophisticated.

If you are using OpenStack, however, OpenStack does a lot of things automatically, and the things it does is influenced by your underlying OpenStack configuration (files). For example, if you are launching a DPDK VM on an OpenStack that is using OpenVSwitch, each compute node that will be running a neutron-openvswitch-agent service. This service,  is actually a Ryu OpenFlow Controller, and when you start this service, it plumbs ports on behalf of OpenStack Neutron on the basis of your Neutron configuration. So you may look at your flows with just OpenVSwitch running and see a smaller subset of flows than you would, if the neutron-openvswitch-agent were running! I may get into some of this in a subsequent post, if time allows.

Friday, June 12, 2020

DPDK Hands-On - Part V - Custom Compiling DPDK and OpenVSwitch

So in our last blog, I pointed out that you could "just use yum" to install your DPDK and your OpenVSwitch packages.

There are several problems with this. Let me go through them.

OpenVSwitch is not compiled for DPDK by default

First, and most importantly, when you use yum to install OpenVSwitch, you do NOT get an OpenVSwitch that has been compiled with DPDK support. And this is a very time-consuming and painful lesson to learn.

I just assumed, at first, that the reason nothing seemed to be working was that maybe DPDK wasn't enabled. No. It in fact has to have a special compile flag --with-dpdk in order to support DPDK.

Versions Matter - for BOTH DPDK and OpenVSwitch

At this OpenVSwitch link, http://docs.openvswitch.org/en/latest/faq/releases/ there are two very very important tables you need to examine and consider when choosing your DPDK and OpenVSwitch.
  • Kernel version - DPDK version compatibility
  • DPDK version - OpenVSwitch compatibility
There are also some specific feature tables as well, so that you don't use the wrong version for a specific feature you want.

So given that yum makes it easy to install a particular version of DPDK and OpenVSwitch, the versions are pinned to those in their repository, and the OVS is not compiled for DPDK. Neither version may line up with the kernel you happen to be running.

For example, I am still on a 3.x kernel on this system. Not a 4.x kernel. I wound up choosing:
  1. DPDK 17.11.10
  2. OVS 2.10.2
Note: I learned how important these versions are, because I have older Intel e1000e NICs on this little Dell Precision T1700 box. Apparently these NICs were all the rage early on in the development cycles for DPDK and OpenVSwitch. But after a while, these NICs are no longer tested, and in fact may no longer work as new drivers are introduced. So in my case, I was advised to go backwards on DPDK and OVS to ensure that I could find a driver that worked and was tested on the e1000e (more on that in a later post).

Uninstalling OpenVSwitch will break your OpenStack!!!
Before compiling a new from-scratch version of DPDK and OpenVSwitch, you need to remove the DPDK and OpenVSwitch that yum had installed from the default repositories (CentOS 7 in my case). When I did a "yum remove" on DPDK, that went smoothly enough, but when I ran "yum remove openvswitch", there are a plethora of packages that have dependencies on this, and yum removed those as well. All of my Neutron OpenVSwitch packages, for example, were removed. So I saved off the names of these packages, so that I could install them later after I custom compiled my DPDK and OpenVSwitch.

Compiling DPDK
I read the documentation on how to download and compile DPDK and OpenVSwitch. How hard could it be, right? make, make configure, make install. bang bang bang. 

And, within a couple of hours, I had compiled DPDK and OpenVSwitch (for DPDK). I was able to bind a NIC using the vfio driver, initialize OpenVSwitch for DPDK, and add ports to a bridge.
 
NOTE: Later, I will learn that the drivers did not work properly and revert to igb_uio drivers.

Then I realized, that there was no way to start up OpenVSwitch like a typical service. And, as mentioned, my OpenStack was not there anymore because of the fact that I ran a yum remove on openvswitch.

And THAT, is why you want to install packages instead of just compiling stuff.

When we install packages on Linux, we take for granted the rather esoteric and complicated process of compiling, linking, and copying resultant files into a package that can be installed on any POSIX-compliant Linux system. 
 
To make an rpm, the tool called rpmbuilder is required. rpmbuilder parses something called a "spec file" and uses that as the map for creating an rpm.

As I was googling around how to build a spec file for these two hand-compiled packages, I stumbled onto the fact that most "responsible" packages, include a spec file already in them. So that you can just run the rpmbuild command on them.

One issue I had was that I had no experience running rpmbuild. I didn't know what options to use. I got some tutelage from a developer on the OpenVSwitch Users Group, so let me cover that here.

For DPDK:
rpmbuild -bb --with shared  pkg/dpdk.spec

For OpenVSwitch:
rpmbuild --with-dpdk --without-check --with autoenable -bb openvswitch-fedora.spec

I did not know that you could pass compile flags into rpmbuild. At first, I had hacked up the Makefiles until I learned this. 

Unfortunately, DPDK did not compile, initially. And neither did OpenVSwitch. The reason for both of these, is that the spec file was not being maintained properly, and had to be tweaked and patched. DPDK is big on documentation, it being a development kit, and it does all kinds of doc-related stuff, and some of that wasn't working. I just needed the drivers, not the documentation. I wasn't writing packet sniffers.

DPDK:
  • removed inkscape and doxygen dependencies
  • removed texlive-collection-latexextra dependency 
  • removed %package doc and %description doc
  • removed the line make O=%{target} doc 
  • removed %files doc and %doc %{doctor}/dpdk
OpenVSwitch
  • Changed the BuildRequires for dpdk
    • dpdk-devel changed to dpdk-stable-devel
  • Commented out some man pages that were causing issues
    • ovs-test.8*
    • ovs-vlan-test.8*
    • ovsdb.5*
    • ovsdb.7*
    • ovs-db-server.7*
Finally, after all this tweaking of the spec files, we got a couple of successful rpms, and could install those with: 
# yum localinstall <rpm file>

Monday, May 11, 2020

DPDK Hands-On - Part IV - Setting Up the DPDK Package


This post is where the fun really started.

I failed to mention, probably, in any of my earlier posts, that I was using CentOS7 as my operating system. Why? Because I am more familiar with the Red Hat Linux than I am with Ubuntu. Going forward, it will be difficult to ride multiple horses with Linux, because RHEL and Ubuntu (especially in 18.04) are deviating quite a bit on System Administration and Tools.

So - when you go to the dpdk.org website, all of the instructions are written in such a way that they assume that you will download and compile the packages. This sounded scary to me. I mean, not really, because I have compiled packages in the past, but I know that when you compile packages from scratch, you typically don't get conveniences like SystemD unit files to set up the service for easy start/stop/restart.  We are in 2020 now. Why can't I just use yum and install the damned package?

As it turns out, on CentOS7, there are yum repositories for DPDK. And, when you run "yum install dpdk", you can get a package that is labeled 18.11.2 as the release. After installing this package, I quickly figured out that there are no scripts, tools or utilities. So, having some general experience with CentOS 7 and its package convention, I looked for the complement packages "devel and tools", and indeed, located those and installed them with "yum install dpdk-tools" and "yum install dpdk-devel".

NOTE: I only really needed the dpdk-tools, as I was not doing any dataplane kit development at this point.

But, things were going smooth so far. Knowing that VFIO is the new driver, I decided to go ahead and load the kernel module for VFIO.

Now, as I was looking over a couple of guys' scripts for doing this (both of them were using DPDK documentation as a basis), I saw that one fellow was installing two packages. Since we were dealing with PCI (more on this later), and Kernel Modules, it made sense to install these:
  1. pci_utils
  2. kernel-devel
After all, these are just tools and utilities and there should be no risk in installing these on your system.

Next, in his script, I saw him changing permissions on a file in /dev - and this really had me concerned. Why would someone be doing this? Is this a bug that he is fixing? 

Turns out, these are instructions on the dpdk.org website, which I found later after looking at his script.


#chmod a+x /dev/vfio
#chmod 0666 /dev/vfio/*

So basically, what this guy was doing, was pretty much following the standard "cookbook" for binding VFIO drivers. The VFIO drivers, as mentioned in Part II, are poll mode drivers that are installed on your system when you install DPDK.

The link for binding NICs can be found at: https://dpdk-guide.gitlab.io/dpdk-guide/setup/binding.html

This documentation gives you two methods for binding your NICs.
  1. driverctl - which was a utility I had not heard of and had to install (e.g. yum install driverctl)
  2. a DPDK utility script, written in Python, called dpdk-devbind.py
The script I was following as a reference was using #1, driverctl, and I figured I would use that instead of the utility script.

NOTE: Later, I decided to start using the utility script and found it to be wonderful

But first - before you bind your NIC, you need to load a kernel module.

I am familiar with kernel modules, so to load the module, you can use modprobe (or insmod, but modprobe is preferred). Again, this is via the DPDK website above on binding NICs.

If all goes well loading the vfio_pci kernel module, this module will in fact load 2 more kernel modules, and what I wound up with when I did "lsmod | grep vfio" was this:

# lsmod | grep vfio
vfio_pci               41412  2
vfio_iommu_type1       22440  1
vfio                   32657  6 vfio_iommu_type1,vfio_pci
irqbypass              13503  8 kvm,vfio_pci

So - there is that irqbypass - to disable interrupt processing. And, there is an IOMMU module that gets loaded, probably the result of having IOMMU enabled on the kernel command line!

It looks like the DPDK is loaded nicely. Now, it is time to load the drivers.

Let's talk about that in a Part V.

Wednesday, January 1, 2020

SDN- NFV Certified from Metro Ethernet Forum

It has been a while since I have blogged any updates, so I'll knock out a few!

First, I just completed the course and certification from Metro Ethernet Forum for SDN-NFV.

This was a 3 day course, and it was surprisingly hands-on as it focused heavily on OpenFlow and OpenDaylight. I was always wanting to learn more about these, so I found this quite rewarding.

One interesting stumbling block in the labs was the fact that there is a -O option that needs to be used to specify the proper version of OpenFlow. 

The course seemed to focus on the use case and context of using OpenFlow (and OpenDaylight) to configure switches - but not "everything else" out there in the field of networking that could be configured with something like OpenFlow.

For example, it was my understanding that the primary beneficiary of something like OpenFlow (and OpenDaylight) was in the Wireless (802.11x) domain, where people had scores, hundreds or even thousands of access points that had to be configured or upgraded, and it was extremely difficult to this by hand.

But, the course focused on switches - OpenVSwitch switches to be precise. And that was probably because the OpenVSwitch keeps things simple enough for the course and instructor.

Problem is, in my shop, everyone is using Juniper switches, and Juniper does not play ball with OpenFlow and OpenVSwitch. So I'm not sure how much this can or will be put to use in our specific environment. I do, however, use OpenVSwitch in my own personal OpenVSwitch-based OpenStack environment, and since OpenVSwitch works well with DPDK and VPP, this knowledge can come in handy as I need to start doing more sophisticated things with packet flows.

Nontheless, I found the course interesting and valuable. And the exam also centered around the ETSI-MANO Reference Architecture. I had familiar with this architecture, but like all exams like this, I missed questions because of time, or overthinking things, or picking the wrong of two correct answers (not the best answer), et al. But, I passed the exam, and I guess that's what matters most.

Tuesday, December 3, 2019

Virtualized Networking Acceleration Technologies - Part II


In Part I of this series of posts, I recapped my research on these virtualized networking technologies, with the aim to build an understanding of:

  • what they are
  • the history and evolution between them
What I did not cover, was a couple of further questions:
  1. When to Use Them
  2. Can you Combine Them?
This link is a fantastic link that discusses item number one. Now, I can't tell how "right" or "accurate" he is, and I typically look down in comments for rebuttals and refutes (I didn't see any and most commenters seemed relatively uninformed on this topic).

He concludes that in East-West (inter-data center) traffic, DPDK wins, and in North-South traffic, SR-IOV wins.
https://www.telcocloudbridge.com/blog/dpdk-vs-sr-iov-for-nfv-why-a-wrong-decision-can-impact-performance/

SLAs using Zabbix in a VMware Environment

 Zabbix 7 introduced some better support for SLAs. It also had better support for VMware. VMware, of course now owned by BroadSoft, has prio...