1 # Copyright (c) 2015 Intel Research and Development Ireland Ltd.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
16 import base_packet_generator
17 import experimental_framework.common as common
19 from experimental_framework.constants import conf_file_sections as conf_file
20 from experimental_framework.constants import framework_parameters as fp
23 class DpdkPacketGenerator(base_packet_generator.BasePacketGenerator):
26 base_packet_generator.BasePacketGenerator.__init__(self)
29 self.program_name = ''
30 self.command_options = list()
31 self.dpdk_interfaces = -1
33 def send_traffic(self):
35 Calls the packet generator and starts to send traffic
38 current_dir = os.path.dirname(os.path.realpath(__file__))
39 DpdkPacketGenerator._chdir(self.directory)
40 dpdk_vars = common.get_dpdk_pktgen_vars()
41 self._init_physical_nics(self.dpdk_interfaces, dpdk_vars)
42 common.run_command(self.command)
43 self._finalize_physical_nics(self.dpdk_interfaces, dpdk_vars)
44 DpdkPacketGenerator._chdir(current_dir)
46 def init_dpdk_pktgen(self,
48 lua_script='generic_test.lua',
54 Initializes internal parameters and configuration of the module.
55 Needs to be called before the send_traffic
56 :param dpdk_interfaces: Number of interfaces to be used (type: int)
57 :param lua_script: Full path of the Lua script to be used (type: str)
58 :param pcap_file_0: Full path of the Pcap file to be used for port 0
60 :param pcap_file_1: Full path of the Pcap file to be used for port 1
62 :param vlan_0: VLAN tag to be used for port 0 (type: str)
63 :param vlan_1: VLAN tag to be used for port 1 (type: str)
67 if pcap_file_0 and not vlan_0:
68 message = 'In order to use NIC_0, the parameter vlan_0 is required'
69 raise ValueError(message)
70 if dpdk_interfaces > 1 and pcap_file_1 and not vlan_1:
71 message = 'in order to use NIC_1, the parameter vlan_1 is required'
72 raise ValueError(message)
74 self.dpdk_interfaces = dpdk_interfaces
75 vars = common.get_dpdk_pktgen_vars()
77 lua_directory = common.get_base_dir()
78 lua_directory += fp.EXPERIMENTAL_FRAMEWORK_DIR
79 lua_directory += fp.DPDK_PKTGEN_DIR
81 pcap_directory = common.get_base_dir()
82 pcap_directory += fp.EXPERIMENTAL_FRAMEWORK_DIR
83 pcap_directory += fp.PCAP_DIR
85 DpdkPacketGenerator._init_input_validation(pcap_file_0,
92 self.directory = vars[conf_file.CFSP_DPDK_PKTGEN_DIRECTORY]
93 self.program_name = vars[conf_file.CFSP_DPDK_PROGRAM_NAME]
95 core_nics = DpdkPacketGenerator.\
96 _get_core_nics(dpdk_interfaces, vars[conf_file.CFSP_DPDK_COREMASK])
97 self.command_options = ['-c ' + vars[conf_file.CFSP_DPDK_COREMASK],
98 '-n ' + vars[conf_file.
99 CFSP_DPDK_MEMORY_CHANNEL],
104 '-m "' + core_nics + '"',
105 '-f ' + lua_directory + lua_script,
106 '-s 0:' + pcap_directory + pcap_file_0]
109 self.command_options.append('-s 1:' + pcap_directory + pcap_file_1)
111 # Avoid to show the output of the packet generator
112 self.command_options.append('> /dev/null')
113 # Prepare the command to be invoked
114 self.command = 'sudo ' + self.directory + self.program_name
115 for opt in self.command_options:
116 self.command += (' ' + opt)
117 if pcap_file_0 and vlan_0:
118 DpdkPacketGenerator._change_vlan(pcap_directory, pcap_file_0,
120 if pcap_file_1 and vlan_1:
121 DpdkPacketGenerator._change_vlan(pcap_directory, pcap_file_1,
125 def _get_core_nics(dpdk_interfaces, coremask):
127 Retruns the core_nics string to be used in the dpdk pktgen command
128 :param dpdk_interfaces: number of interfaces to be used in the pktgen
130 :param coremask: hexadecimal value representing the cores assigned to
131 the pktgen (type: str)
132 :return: Returns the core nics param for pktgen (type: str)
134 if dpdk_interfaces == 1:
135 return DpdkPacketGenerator._cores_configuration(coremask, 1, 2, 0)
136 elif dpdk_interfaces == 2:
137 return DpdkPacketGenerator._cores_configuration(coremask, 1, 2, 2)
138 raise ValueError("This framework only supports two ports to generate "
142 def _change_vlan(pcap_directory, pcap_file, vlan):
143 common.LOG.info("Changing VLAN Tag on Packet: " + pcap_file +
144 ". New VLAN Tag is " + vlan)
145 command = "chmod +x {}{}".format(pcap_directory, 'vlan_tag.sh')
146 common.run_command(command)
147 command = pcap_directory + 'vlan_tag.sh '
148 command += pcap_directory + pcap_file + ' ' + vlan
149 common.run_command(command)
152 def _init_input_validation(pcap_file_0, pcap_file_1, lua_script,
153 pcap_directory, lua_directory, variables):
155 Validates the input parameters values and raises an exception if
156 there is any non valid param
157 :param pcap_file_0: file name of the pcap file for NIC 0
158 (it does not includes the path) (type: str)
159 :param pcap_file_1: file name of the pcap file for NIC 1
160 (it does not includes the path) (type: str)
161 :param lua_script: file name of the lua script to be used
162 (it does not includes the path) (type: str)
163 :param pcap_directory: directory where the pcap files are located
165 :param lua_directory: directory where the lua scripts are located
167 :param variables: variables for the packet gen from configuration file
171 if not pcap_directory:
172 raise ValueError("pcap_directory not provided correctly")
174 raise ValueError("pcap_file_0 not provided correctly")
176 raise ValueError("pcap_file_1 not provided correctly")
178 raise ValueError("lua_script not provided correctly")
179 if not os.path.isfile(pcap_directory + pcap_file_0):
180 raise ValueError("The file " + pcap_file_0 + " does not exist")
181 if not os.path.isfile(pcap_directory + pcap_file_1):
182 raise ValueError("The file " + pcap_file_1 + " does not exist")
183 if not os.path.isfile(lua_directory + lua_script):
184 raise ValueError("The file " + lua_script + " does not exist")
185 for var in [conf_file.CFSP_DPDK_PKTGEN_DIRECTORY,
186 conf_file.CFSP_DPDK_PROGRAM_NAME,
187 conf_file.CFSP_DPDK_COREMASK,
188 conf_file.CFSP_DPDK_MEMORY_CHANNEL]:
189 if var not in variables.keys() or (var in variables.keys() and
190 variables[var] is ''):
191 raise ValueError("The variable " + var + " does not exist")
194 def _chdir(directory):
196 Changes the current directory
197 :param directory: directory where to move (type: str)
202 def _init_physical_nics(self, dpdk_interfaces, dpdk_vars):
204 Initializes the physical interfaces
205 :param dpdk_interfaces: Number of interfaces to be used (type: int)
206 :param dpdk_vars: variables from config file related to DPDK pktgen
210 if not dpdk_interfaces == 1 and not dpdk_interfaces == 2:
211 raise ValueError('The number of NICs can be 1 or 2')
213 # bus_address_1 = dpdk_vars[conf_file.CFSP_DPDK_BUS_SLOT_NIC_1]
214 interface_1 = dpdk_vars[conf_file.CFSP_DPDK_NAME_IF_1]
215 common.run_command('sudo ifconfig ' + interface_1 + ' down')
216 common.run_command('sudo ' +
217 dpdk_vars[conf_file.CFSP_DPDK_DPDK_DIRECTORY] +
218 'tools/dpdk_nic_bind.py --unbind ' +
219 dpdk_vars[conf_file.CFSP_DPDK_BUS_SLOT_NIC_1])
220 common.run_command('sudo ' +
221 dpdk_vars[conf_file.CFSP_DPDK_DPDK_DIRECTORY] +
222 'tools/dpdk_nic_bind.py --bind=igb_uio ' +
223 dpdk_vars[conf_file.CFSP_DPDK_BUS_SLOT_NIC_1])
224 if dpdk_interfaces == 2:
226 # bus_address_2 = dpdk_vars[conf_file.CFSP_DPDK_BUS_SLOT_NIC_2]
227 interface_2 = dpdk_vars[conf_file.CFSP_DPDK_NAME_IF_2]
228 common.run_command('sudo ifconfig ' + interface_2 + ' down')
229 common.run_command('sudo ' +
230 dpdk_vars[conf_file.CFSP_DPDK_DPDK_DIRECTORY] +
231 'tools/dpdk_nic_bind.py --unbind ' +
232 dpdk_vars[conf_file.CFSP_DPDK_BUS_SLOT_NIC_2])
233 common.run_command('sudo ' +
234 dpdk_vars[conf_file.CFSP_DPDK_DPDK_DIRECTORY] +
235 'tools/dpdk_nic_bind.py --bind=igb_uio ' +
236 dpdk_vars[conf_file.CFSP_DPDK_BUS_SLOT_NIC_2])
238 def _finalize_physical_nics(self, dpdk_interfaces, dpdk_vars):
240 Finalizes the physical interfaces
241 :param dpdk_interfaces: Number of interfaces to be used (type: int)
242 :param dpdk_vars: variables from config file related to DPDK pktgen
246 if not dpdk_interfaces == 1 and not dpdk_interfaces == 2:
247 raise ValueError('No interfaces have been indicated for packet '
248 'generation usage. Please specify one or two '
251 common.run_command('sudo ' +
252 dpdk_vars[conf_file.CFSP_DPDK_DPDK_DIRECTORY] +
253 'tools/dpdk_nic_bind.py --unbind ' +
254 dpdk_vars[conf_file.CFSP_DPDK_BUS_SLOT_NIC_1])
256 common.run_command('sudo ' +
257 dpdk_vars[conf_file.CFSP_DPDK_DPDK_DIRECTORY] +
258 'tools/dpdk_nic_bind.py --bind=ixgbe ' +
259 dpdk_vars[conf_file.CFSP_DPDK_BUS_SLOT_NIC_1])
260 common.run_command('sudo ifconfig ' +
261 dpdk_vars[conf_file.CFSP_DPDK_NAME_IF_1] +
263 if dpdk_interfaces == 2:
265 common.run_command('sudo ' +
266 dpdk_vars[conf_file.CFSP_DPDK_DPDK_DIRECTORY] +
267 'tools/dpdk_nic_bind.py --unbind ' +
268 dpdk_vars[conf_file.CFSP_DPDK_BUS_SLOT_NIC_2])
270 common.run_command('sudo ' +
271 dpdk_vars[conf_file.CFSP_DPDK_DPDK_DIRECTORY] +
272 'tools/dpdk_nic_bind.py --bind=ixgbe ' +
273 dpdk_vars[conf_file.CFSP_DPDK_BUS_SLOT_NIC_2])
274 common.run_command('sudo ifconfig ' +
275 dpdk_vars[conf_file.CFSP_DPDK_NAME_IF_2] +
279 def _cores_configuration(coremask, pktgen_cores=1, nic_1_cores=2,
282 Calculation of the core_nics parameter which is necessary for the
283 packet generator to run
285 :param coremask: Hexadecimal value indicating the cores to be assigned
286 to the whole dpdk pktgen software (included the
287 ones to receive and send packets from NICs)
289 :param pktgen_cores: number of cores to be assigned to main thread of
291 :param nic_1_cores: number of cores to be assigned to the first NIC
292 :param nic_2_nics: number of cores to be assigned to the second NIC
293 :return: returns the core_nics parameter (type: str)
295 required_cores = pktgen_cores + nic_1_cores + nic_2_cores
296 bin_coremask = bin(int(coremask, 16))[2:]
297 index = len(bin_coremask)
301 if bin_coremask[index] == '1':
304 if len(cores) < required_cores:
305 raise ValueError('The provided coremask does not provide'
306 ' enough cores for the DPDK packet generator')
307 # ret_pktgen_cores = []
313 ret_nic_2_cores.append(cores[current_core])
316 ret_nic_2_cores.append(cores[current_core])
320 ret_nic_1_cores.append(cores[current_core])
323 ret_nic_1_cores.append(cores[current_core])
326 # for n in range(0, pktgen_cores):
327 # ret_pktgen_cores.append(cores[n])
328 # for n in range(0, nic_1_cores):
329 # ret_nic_1_cores.append(cores[pktgen_cores + n])
330 # for n in range(0, nic_2_cores):
331 # ret_nic_2_cores.append(cores[pktgen_cores + nic_1_cores + n])
336 corenics += str(ret_nic_1_cores[0]) + '.0'
338 corenics += '[' + str(ret_nic_1_cores[0])
339 corenics += ':' + str(ret_nic_1_cores[1])
344 corenics += str(ret_nic_2_cores[0]) + '.1'
346 corenics += '[' + str(ret_nic_2_cores[0])
347 corenics += ':' + str(ret_nic_2_cores[1])