From 0fb65d2afadad1f092788f5a4f251b09851b3ae7 Mon Sep 17 00:00:00 2001
From: Christian Trautman <ctrautma@redhat.com>
Date: Fri, 22 Jul 2016 15:54:18 -0400
Subject: Vanilla_Multi_Queue: Add vanilla ovs multi-queue functionality

Adds multi-queue for vanilla OVS using virtio-net.

TunTap ports will use multi_queue parameter when ports are
created/deleted if guest nic queues are enabled and
vswitch is ovs vanilla. Virtio net will now add guest nic
queues to qemu command line if appropriate.

Reworked multi-queue documentation to reflect these changes.

Adds vhost net thread affinitization which is recommended
when performing vanilla ovs multi-queue.

Guests will require ethtool if using l2fwd or linux bridge
as the loopback application when vanilla ovs multi-queue
is enabled.

Modified dpdk setting in vswitch conf to be better worded
for separation from vanilla ovs multi-queue.

Updated release and installation doc for new vloop image
that includes required ethtool utility.

JIRA: VSPERF-373

Change-Id: Idb550515190b1a93390308c11f54da368f962512
Signed-off-by: Christian Trautman <ctrautma@redhat.com>
---
 vnfs/qemu/qemu.py            | 48 ++++++++++++++++++++++++++++++++++++++++++++
 vnfs/qemu/qemu_virtio_net.py | 26 +++++++++++++++++-------
 2 files changed, 67 insertions(+), 7 deletions(-)

(limited to 'vnfs')

diff --git a/vnfs/qemu/qemu.py b/vnfs/qemu/qemu.py
index e91eaa29..dd9ad818 100644
--- a/vnfs/qemu/qemu.py
+++ b/vnfs/qemu/qemu.py
@@ -129,6 +129,10 @@ class IVnfQemu(IVnf):
         if S.getValue('VNF_AFFINITIZATION_ON'):
             self._affinitize()
 
+        if S.getValue('VSWITCH_VHOST_NET_AFFINITIZATION') and S.getValue(
+                'VNF') == 'QemuVirtioNet':
+            self._affinitize_vhost_net()
+
         if self._timeout:
             self._config_guest_loopback()
 
@@ -236,6 +240,34 @@ class IVnfQemu(IVnf):
                 self._logger.error('Failed to affinitize guest core #%d. Could'
                                    ' not parse tid.', cpu)
 
+    def _affinitize_vhost_net(self):
+        """
+        Affinitize the vhost net threads for Vanilla OVS and guest nic queues.
+
+        :return: None
+        """
+        self._logger.info('Affinitizing VHOST Net threads.')
+        args1 = ['ps', 'ax']
+        process1 = subprocess.Popen(args1, stdout=subprocess.PIPE,
+                                    shell=False)
+        out = process1.communicate()[0]
+        processes = list()
+        for line in out.decode(locale.getdefaultlocale()[1]).split('\n'):
+            if re.search('\[vhost-(\d+)', line):
+                processes.append(re.match('\s*(\d+)', line).group(1))
+        self._logger.info('Found %s vhost net threads...', len(processes))
+
+        cpumap = S.getValue('VSWITCH_VHOST_CPU_MAP')
+        mapcount = 0
+        for proc in processes:
+            self._affinitize_pid(cpumap[mapcount], proc)
+            mapcount += 1
+            if mapcount + 1 > len(cpumap):
+                # Not enough cpus were given in the mapping to cover all the
+                # threads on a 1 to 1 ratio with cpus so reset the list counter
+                #  to 0.
+                mapcount = 0
+
     def _config_guest_loopback(self):
         """
         Configure VM to run VNF, e.g. port forwarding application based on the configuration
@@ -380,6 +412,8 @@ class IVnfQemu(IVnf):
         """
         Configure VM to perform L2 forwarding between NICs by l2fwd module
         """
+        if int(S.getValue('GUEST_NIC_QUEUES')):
+            self._set_multi_queue_nic()
         self._configure_copy_sources('l2fwd')
         self._configure_disable_firewall()
 
@@ -397,6 +431,8 @@ class IVnfQemu(IVnf):
         """
         Configure VM to perform L2 forwarding between NICs by linux bridge
         """
+        if int(S.getValue('GUEST_NIC_QUEUES')):
+            self._set_multi_queue_nic()
         self._configure_disable_firewall()
 
         self.execute('ip addr add ' +
@@ -441,3 +477,15 @@ class IVnfQemu(IVnf):
         self.execute('sysctl -w net.ipv4.conf.all.rp_filter=0')
         self.execute('sysctl -w net.ipv4.conf.' + self._net1 + '.rp_filter=0')
         self.execute('sysctl -w net.ipv4.conf.' + self._net2 + '.rp_filter=0')
+
+    def _set_multi_queue_nic(self):
+        """
+        Enable multi-queue in guest kernel with ethool.
+        :return: None
+        """
+        self.execute_and_wait('ethtool -L {} combined {}'.format(
+            self._net1, S.getValue('GUEST_NIC_QUEUES')))
+        self.execute_and_wait('ethtool -l {}'.format(self._net1))
+        self.execute_and_wait('ethtool -L {} combined {}'.format(
+            self._net2, S.getValue('GUEST_NIC_QUEUES')))
+        self.execute_and_wait('ethtool -l {}'.format(self._net2))
diff --git a/vnfs/qemu/qemu_virtio_net.py b/vnfs/qemu/qemu_virtio_net.py
index e5e895f2..afb519c3 100644
--- a/vnfs/qemu/qemu_virtio_net.py
+++ b/vnfs/qemu/qemu_virtio_net.py
@@ -41,22 +41,34 @@ class QemuVirtioNet(IVnfQemu):
         if1 = str(i)
         if2 = str(i + 1)
 
+        # multi-queue values
+        if int(S.getValue('GUEST_NIC_QUEUES')):
+            queue_str = ',queues={}'.format(S.getValue('GUEST_NIC_QUEUES'))
+            mq_vector_str = ',mq=on,vectors={}'.format(
+                int(S.getValue('GUEST_NIC_QUEUES')) * 2 + 2)
+        else:
+            queue_str, mq_vector_str = '', ''
+
         self._cmd += ['-netdev',
-                      'type=tap,id=' + self._net1 +
+                      'tap,id=' + self._net1 + queue_str +
                       ',script=no,downscript=no,' +
                       'ifname=tap' + if1 + ',vhost=on',
                       '-device',
                       'virtio-net-pci,mac=' +
                       S.getValue('GUEST_NET1_MAC')[self._number] +
-                      ',netdev=' + self._net1 + ',csum=off,gso=off,' +
-                      'guest_tso4=off,guest_tso6=off,guest_ecn=off',
+                      ',netdev=' + self._net1 +
+                      ',csum=off,gso=off,' +
+                      'guest_tso4=off,guest_tso6=off,guest_ecn=off' +
+                      mq_vector_str,
                       '-netdev',
-                      'type=tap,id=' + self._net2 +
+                      'tap,id=' + self._net2 + queue_str +
                       ',script=no,downscript=no,' +
                       'ifname=tap' + if2 + ',vhost=on',
                       '-device',
                       'virtio-net-pci,mac=' +
                       S.getValue('GUEST_NET2_MAC')[self._number] +
-                      ',netdev=' + self._net2 + ',csum=off,gso=off,' +
-                      'guest_tso4=off,guest_tso6=off,guest_ecn=off',
-                     ]
+                      ',netdev=' + self._net2 +
+                      ',csum=off,gso=off,' +
+                      'guest_tso4=off,guest_tso6=off,guest_ecn=off' +
+                      mq_vector_str,
+        ]
-- 
cgit