bugfix: Trafficgen Ixia does not work
[vswitchperf.git] / vswitches / ovs_dpdk_vhost.py
1 # Copyright 2015-2016 Intel Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #   http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """VSPERF VSwitch implementation using DPDK and vhost ports
16 """
17
18 import logging
19 import subprocess
20 import os
21
22 from src.ovs import OFBridge
23 from src.dpdk import dpdk
24 from conf import settings
25 from conf import get_test_param
26 from vswitches.ovs import IVSwitchOvs
27
28 class OvsDpdkVhost(IVSwitchOvs):
29     """ Open vSwitch with DPDK support
30
31     Generic OVS wrapper functionality in src.ovs is maximally used. This
32     class wraps DPDK system configuration along with DPDK specific OVS
33     parameters
34
35     The method docstrings document only considerations specific to this
36     implementation. For generic information of the nature of the methods,
37     see the interface.
38     """
39
40     def __init__(self):
41         super(OvsDpdkVhost, self).__init__()
42         self._logger = logging.getLogger(__name__)
43
44         vswitchd_args = []
45
46         # legacy DPDK configuration through --dpdk option of vswitchd
47         if self.old_dpdk_config():
48             vswitchd_args = ['--dpdk'] + settings.getValue('VSWITCHD_DPDK_ARGS')
49             if self._vswitchd_args:
50                 self._vswitchd_args = vswitchd_args + ['--'] + self._vswitchd_args
51             else:
52                 self._vswitchd_args = vswitchd_args
53
54     def configure(self):
55         """ Configure vswitchd DPDK options through ovsdb if needed
56         """
57         dpdk_config = settings.getValue('VSWITCHD_DPDK_CONFIG')
58         if dpdk_config and not self.old_dpdk_config():
59             # enforce calls to ovs-vsctl with --no-wait
60             tmp_br = OFBridge(timeout=-1)
61             for option in dpdk_config:
62                 tmp_br.set_db_attribute('Open_vSwitch', '.',
63                                         'other_config:' + option, dpdk_config[option])
64
65     def start(self):
66         """See IVswitch for general description
67
68         Activates DPDK kernel modules, ovsdb and vswitchd.
69         """
70         dpdk.init()
71         super(OvsDpdkVhost, self).start()
72         # old style OVS <= 2.5.0 multi-queue enable
73         vswitch_dpdk_multi_queues = \
74             int(get_test_param('vswitch_dpdk_multi_queues', 0))
75         if vswitch_dpdk_multi_queues:
76             settings.setValue('VSWITCH_DPDK_MULTI_QUEUES', \
77                 vswitch_dpdk_multi_queues)
78         if settings.getValue('OVS_OLD_STYLE_MQ') and \
79                 int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')):
80             tmp_br = OFBridge(timeout=-1)
81             tmp_br.set_db_attribute(
82                 'Open_vSwitch', '.', 'other_config:' +
83                 'n-dpdk-rxqs', settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))
84
85     def stop(self):
86         """See IVswitch for general description
87
88         Kills ovsdb and vswitchd and removes DPDK kernel modules.
89         """
90
91         super(OvsDpdkVhost, self).stop()
92         dpdk.cleanup()
93
94     def add_switch(self, switch_name, params=None):
95         """See IVswitch for general description
96         """
97         switch_params = ['--', 'set', 'bridge', switch_name, 'datapath_type=netdev']
98         if params:
99             switch_params = switch_params + params
100
101         super(OvsDpdkVhost, self).add_switch(switch_name, switch_params)
102         if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
103             # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
104             # for CPU core affinitization
105             self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.',
106                                                         'other_config:pmd-cpu-mask',
107                                                         settings.getValue('VSWITCH_PMD_CPU_MASK'))
108
109     def add_phy_port(self, switch_name):
110         """See IVswitch for general description
111
112         Creates a port of type dpdk.
113         The new port is named dpdk<n> where n is an integer starting from 0.
114         """
115         bridge = self._bridges[switch_name]
116         dpdk_count = self._get_port_count('type=dpdk')
117         port_name = 'dpdk' + str(dpdk_count)
118         params = ['--', 'set', 'Interface', port_name, 'type=dpdk']
119         # multi-queue enable
120
121         if int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \
122                 not settings.getValue('OVS_OLD_STYLE_MQ'):
123                 params += ['options:n_rxq={}'.format(
124                     settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))]
125         of_port = bridge.add_port(port_name, params)
126         return (port_name, of_port)
127
128     def add_vport(self, switch_name):
129         """See IVswitch for general description
130
131         Creates a port of type dpdkvhost
132         The new port is named dpdkvhost<n> where n is an integer starting
133         from 0
134         """
135         bridge = self._bridges[switch_name]
136         vhost_count = self._get_port_count('type=dpdkvhostuser')
137         port_name = 'dpdkvhostuser' + str(vhost_count)
138         params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser']
139         # multi queue enable
140         if int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \
141                 not settings.getValue('OVS_OLD_STYLE_MQ'):
142             params += ['options:n_rxq={}'.format(
143                 settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))]
144         of_port = bridge.add_port(port_name, params)
145
146         return (port_name, of_port)
147
148     @staticmethod
149     def old_dpdk_config():
150         """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
151
152         :returns: True if legacy --dpdk option is supported, otherwise it returns False
153         """
154
155         ovs_vswitchd_bin = settings.getValue('TOOLS')['ovs-vswitchd']
156         try:
157             subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
158             return True
159         except subprocess.CalledProcessError:
160             return False