Merge "testpmd_pvp: Adds pkt_fwd to allow pvp topology testing"
[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
21 from src.ovs import OFBridge
22 from src.dpdk import dpdk
23 from conf import settings
24 from vswitches.ovs import IVSwitchOvs
25
26 class OvsDpdkVhost(IVSwitchOvs):
27     """ Open vSwitch with DPDK support
28
29     Generic OVS wrapper functionality in src.ovs is maximally used. This
30     class wraps DPDK system configuration along with DPDK specific OVS
31     parameters
32
33     The method docstrings document only considerations specific to this
34     implementation. For generic information of the nature of the methods,
35     see the interface.
36     """
37
38     def __init__(self):
39         super(OvsDpdkVhost, self).__init__()
40         self._logger = logging.getLogger(__name__)
41
42         vswitchd_args = []
43
44         # legacy DPDK configuration through --dpdk option of vswitchd
45         if self.old_dpdk_config():
46             vswitchd_args = ['--dpdk'] + settings.getValue('VSWITCHD_DPDK_ARGS')
47             if self._vswitchd_args:
48                 self._vswitchd_args = vswitchd_args + ['--'] + self._vswitchd_args
49             else:
50                 self._vswitchd_args = vswitchd_args
51
52     def configure(self):
53         """ Configure vswitchd DPDK options through ovsdb if needed
54         """
55         dpdk_config = settings.getValue('VSWITCHD_DPDK_CONFIG')
56         if dpdk_config and not self.old_dpdk_config():
57             # enforce calls to ovs-vsctl with --no-wait
58             tmp_br = OFBridge(timeout=-1)
59             for option in dpdk_config:
60                 tmp_br.set_db_attribute('Open_vSwitch', '.',
61                                         'other_config:' + option, dpdk_config[option])
62
63     def start(self):
64         """See IVswitch for general description
65
66         Activates DPDK kernel modules, ovsdb and vswitchd.
67         """
68         dpdk.init()
69         super(OvsDpdkVhost, self).start()
70         # old style OVS <= 2.5.0 multi-queue enable
71         if settings.getValue('OVS_OLD_STYLE_MQ') and \
72                 int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')):
73             tmp_br = OFBridge(timeout=-1)
74             tmp_br.set_db_attribute(
75                 'Open_vSwitch', '.', 'other_config:' +
76                 'n-dpdk-rxqs', settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))
77
78     def stop(self):
79         """See IVswitch for general description
80
81         Kills ovsdb and vswitchd and removes DPDK kernel modules.
82         """
83
84         super(OvsDpdkVhost, self).stop()
85         dpdk.cleanup()
86
87     def add_switch(self, switch_name, params=None):
88         """See IVswitch for general description
89         """
90         switch_params = ['--', 'set', 'bridge', switch_name, 'datapath_type=netdev']
91         if params:
92             switch_params = switch_params + params
93
94         super(OvsDpdkVhost, self).add_switch(switch_name, switch_params)
95         if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
96             # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
97             # for CPU core affinitization
98             self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.',
99                                                         'other_config:pmd-cpu-mask',
100                                                         settings.getValue('VSWITCH_PMD_CPU_MASK'))
101
102     def add_phy_port(self, switch_name):
103         """See IVswitch for general description
104
105         Creates a port of type dpdk.
106         The new port is named dpdk<n> where n is an integer starting from 0.
107         """
108         bridge = self._bridges[switch_name]
109         dpdk_count = self._get_port_count('type=dpdk')
110         port_name = 'dpdk' + str(dpdk_count)
111         # PCI info. Please note there must be no blank space, eg must be
112         # like 'options:dpdk-devargs=0000:06:00.0'
113         _NICS = settings.getValue('NICS')
114         nic_pci = 'options:dpdk-devargs=' + _NICS[dpdk_count]['pci']
115         params = ['--', 'set', 'Interface', port_name, 'type=dpdk', nic_pci]
116         # multi-queue enable
117
118         if int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \
119                 not settings.getValue('OVS_OLD_STYLE_MQ'):
120             params += ['options:n_rxq={}'.format(
121                 settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))]
122         of_port = bridge.add_port(port_name, params)
123         return (port_name, of_port)
124
125     def add_vport(self, switch_name):
126         """See IVswitch for general description
127
128         Creates a port of type dpdkvhost
129         The new port is named dpdkvhost<n> where n is an integer starting
130         from 0
131         """
132         bridge = self._bridges[switch_name]
133         vhost_count = self._get_port_count('type=dpdkvhostuser')
134         port_name = 'dpdkvhostuser' + str(vhost_count)
135         params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser']
136         # multi queue enable
137         if int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \
138                 not settings.getValue('OVS_OLD_STYLE_MQ'):
139             params += ['options:n_rxq={}'.format(
140                 settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))]
141         of_port = bridge.add_port(port_name, params)
142
143         return (port_name, of_port)
144
145     @staticmethod
146     def old_dpdk_config():
147         """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
148
149         :returns: True if legacy --dpdk option is supported, otherwise it returns False
150         """
151
152         ovs_vswitchd_bin = settings.getValue('TOOLS')['ovs-vswitchd']
153         try:
154             subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
155             return True
156         except subprocess.CalledProcessError:
157             return False