Merge "sriov: Determine path to the bind-tool"
[vswitchperf.git] / vswitches / vpp_dpdk_vhost.py
index 6837553..c62e28d 100644 (file)
@@ -50,6 +50,7 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
         self._phy_ports = []
         self._virt_ports = []
         self._switches = {}
+        self._vpp_ctl = ['sudo', S.getValue('TOOLS')['vppctl']]
 
         # configure DPDK NICs
         tmp_args = copy.deepcopy(S.getValue('VSWITCH_VPP_ARGS'))
@@ -63,8 +64,28 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
         tmp_args['dpdk'].append('socket-mem ' +
                                 ','.join(S.getValue('DPDK_SOCKET_MEM')))
 
+        # create directory for vhostuser sockets if needed
+        if not os.path.exists(S.getValue('TOOLS')['ovs_var_tmp']):
+            tasks.run_task(['sudo', 'mkdir', '-p',
+                            S.getValue('TOOLS')['ovs_var_tmp']], self._logger)
+
+        # configure path to the plugins
+        tmp_args['plugin_path'] = S.getValue('TOOLS')['vpp_plugin_path']
+
+        # cli sock file must be used for VPP 17.10 and newer
+        if S.getValue('VSWITCH_VPP_CLI_SOCK'):
+            self._vpp_ctl += ['-s', S.getValue('VSWITCH_VPP_CLI_SOCK')]
+            tmp_args['unix'].append('cli-listen {}'.format(
+                S.getValue('VSWITCH_VPP_CLI_SOCK')))
+
+        mqs = int(S.getValue('VSWITCH_DPDK_MULTI_QUEUES'))
+        tmp_rxqs = ''
+        if mqs:
+            tmp_rxqs = " {{ num-rx-queues {} }}".format(mqs)
+
+        # configure physical ports
         for nic in S.getValue('NICS'):
-            tmp_args['dpdk'].append("dev {}".format(nic['pci']))
+            tmp_args['dpdk'].append("dev {}{}".format(nic['pci'], tmp_rxqs))
         self._vswitch_args = self._process_vpp_args(tmp_args)
 
     def _get_nic_info(self, key='Name'):
@@ -84,6 +105,8 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
         keyidx = keys.index(key)
         for iface in ifaces[1:]:
             tmpif = iface.split()
+            if not tmpif:
+                continue
             # get PCI address of given interface
             output = self.run_vppctl(['show', 'hardware', tmpif[1], 'detail'])
             match = re.search(r'pci address:\s*([\d:\.]+)', output[0])
@@ -106,7 +129,10 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
         cli_args = []
         for cfg_key in args:
             cli_args.append(cfg_key)
-            cli_args.append("{{ {} }}".format(' '.join(args[cfg_key])))
+            if isinstance(args[cfg_key], str):
+                cli_args.append(args[cfg_key])
+            else:
+                cli_args.append("{{ {} }}".format(' '.join(args[cfg_key])))
 
         self._logger.debug("VPP CLI args: %s", cli_args)
         return cli_args
@@ -145,16 +171,17 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
 
         Kills ``vpp``
         """
-        # try to get VPP pid
-        output = self.run_vppctl(['show', 'version', 'verbose'])
-        match = re.search(r'Current PID:\s*([0-9]+)', output[0])
-        if match:
-            vpp_pid = match.group(1)
-            tasks.terminate_task(vpp_pid, logger=self._logger)
+        if self.is_running():
+            # try to get VPP pid
+            output = self.run_vppctl(['show', 'version', 'verbose'])
+            match = re.search(r'Current PID:\s*([0-9]+)', output[0])
+            if match:
+                vpp_pid = match.group(1)
+                tasks.terminate_task(vpp_pid, logger=self._logger)
 
-        # in case, that pid was not detected or sudo envelope
-        # has not been terminated yet
-        tasks.Process.kill(self, signal, sleep)
+            # in case, that pid was not detected or sudo envelope
+            # has not been terminated yet
+            tasks.Process.kill(self, signal, sleep)
 
     def get_version(self):
         """See IVswitch for general description
@@ -212,9 +239,15 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
         """See IVswitch for general description
         """
         socket_name = S.getValue('TOOLS')['ovs_var_tmp'] + 'dpdkvhostuser' + str(len(self._virt_ports))
-        output = self.run_vppctl(['create', 'vhost-user', 'socket', socket_name, 'server'] +
+        if S.getValue('VSWITCH_VHOSTUSER_SERVER_MODE'):
+            mode = ['server']
+        else:
+            mode = []
+        output = self.run_vppctl(['create', 'vhost-user', 'socket', socket_name] + mode +
                                  S.getValue('VSWITCH_VPP_VHOSTUSER_ARGS'))
-        nic_name = output[0]
+        if output[0].find('returned') >= 0:
+            raise RuntimeError('VPP VhostUser interface cannot be created.')
+        nic_name = output[0].strip()
         self._virt_ports.append(nic_name)
         self.run_vppctl(['set', 'int', 'state', nic_name, 'up'])
         return (nic_name, None)
@@ -345,7 +378,7 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
 
         :return: None
         """
-        cmd = ['sudo', S.getValue('TOOLS')['vppctl']] + args
+        cmd = self._vpp_ctl + args
         return tasks.run_task(cmd, self._logger, 'Running vppctl...', check_error)
 
     #
@@ -377,6 +410,23 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
         return not (port_name in self._phy_ports or port_name in self._virt_ports)
 
     # pylint: disable=no-self-use
+    def validate_add_connection(self, dummy_result, dummy_switch_name, dummy_port1,
+                                dummy_port2, dummy_bidir=False):
+        """ Validate that connection was added
+        """
+        return True
+
+    def validate_del_connection(self, dummy_result, dummy_switch_name, dummy_port1,
+                                dummy_port2, dummy_bidir=False):
+        """ Validate that connection was deleted
+        """
+        return True
+
+    def validate_dump_connections(self, dummy_result, dummy_switch_name):
+        """ Validate dump connections call
+        """
+        return True
+
     def validate_run_vppctl(self, result, dummy_args, dummy_check_error=False):
         """validate execution of ``vppctl`` with supplied arguments.
         """