1 # Copyright (c) 2018 Huawei Technologies Co.,Ltd and others.
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.
14 """ VsperfDPDK specific scenario definition """
16 from __future__ import absolute_import
22 from oslo_serialization import jsonutils
24 import yardstick.ssh as ssh
25 import yardstick.common.utils as utils
26 from yardstick.benchmark.scenarios import base
28 LOG = logging.getLogger(__name__)
31 class MoongenTestPMD(base.Scenario):
32 """Execute vsperf with defined parameters
35 frame_size - a frame size for which test should be executed;
36 Multiple frame sizes can be tested by modification of sequence runner
37 section inside TC YAML definition.
40 multistream - the number of simulated streams
43 testpmd_queue - specifies how many queues you will use the VM
44 only useful when forward_type is true.
47 trafficgen_port1 - specifies device name of 1st interface connected to
51 trafficgen_port2 - specifies device name of 2nd interface connected to
55 moongen_host_user - specifies moongen host ssh user name
58 moongen_host_passwd - specifies moongen host ssh user password
61 moongen_host_ip - specifies moongen host ssh ip address
64 moongen_dir - specifies where is the moongen installtion dir
67 moongen_runBidirec - specifies moongen will run in one traffic
71 Package_Loss - specifies the package_Loss number in moongen server.
74 SearchRuntime - specifies the SearchRuntime and validation time
78 moongen_port1_mac - moongen server port1 mac address.
81 moongen_port2_mac - moongen server port2 mac address.
84 forward_type - VM forward type is l2fwd or testpmd.
88 __scenario_type__ = "MoongenTestPMD"
90 TESTPMD_SCRIPT = 'moongen_testpmd.bash'
91 VSPERF_CONFIG = '/tmp/opnfv-vsperf-cfg.lua'
93 def __init__(self, scenario_cfg, context_cfg):
94 self.scenario_cfg = scenario_cfg
95 self.context_cfg = context_cfg
96 self.forward_setup_done = False
97 self.options = scenario_cfg.get('options', {})
98 self.moongen_host_user = \
99 self.options.get('moongen_host_user', "root")
100 self.moongen_host_passwd = \
101 self.options.get('moongen_host_passwd', "r00t")
103 self.options.get('moongen_dir', '~/moongen.py')
104 self.testpmd_queue = \
105 self.options.get('testpmd_queue', 1)
106 self.moongen_host_ip = \
107 self.options.get('moongen_host_ip', "127.0.0.1")
108 self.moongen_port1_mac = \
109 self.options.get('moongen_port1_mac', None)
110 self.moongen_port2_mac = \
111 self.options.get('moongen_port2_mac', None)
113 self.options.get('trafficgen_port1', "enp2s0f0")
115 self.options.get('trafficgen_port2', "enp2s0f1")
116 self.forward_type = \
117 self.options.get('forward_type', 'testpmd')
118 self.tgen_port1_mac = None
119 self.tgen_port2_mac = None
123 host = self.context_cfg['host']
125 task_id = self.scenario_cfg['task_id']
126 context_number = task_id.split('-')[0]
127 self.tg_port1_nw = 'demo' + \
128 "-" + context_number + "-" + \
129 self.options.get('trafficgen_port1_nw', 'test2')
130 self.tg_port2_nw = 'demo' + \
131 "-" + context_number + "-" + \
132 self.options.get('trafficgen_port2_nw', 'test3')
134 # copy vsperf conf to VM
135 self.client = ssh.SSH.from_node(host, defaults={"user": "ubuntu"})
136 # traffic generation could last long
137 self.client.wait(timeout=1800)
139 self.server = ssh.SSH(
140 self.moongen_host_user,
141 self.moongen_host_ip,
142 password=self.moongen_host_passwd
144 # traffic generation could last long
145 self.server.wait(timeout=1800)
147 self.setup_done = True
149 def forward_setup(self):
150 """forward tool setup"""
152 # setup forward loopback in VM
153 self.testpmd_script = pkg_resources.resource_filename(
154 'yardstick.benchmark.scenarios.networking',
157 self.client._put_file_shell(self.testpmd_script,
158 '~/testpmd_vsperf.sh')
160 # disable Address Space Layout Randomization (ASLR)
161 cmd = "echo 0 | sudo tee /proc/sys/kernel/randomize_va_space"
162 self.client.send_command(cmd)
164 if not self._is_forward_setup():
165 self.tgen_port1_ip = \
166 utils.get_port_ip(self.client, self.tg_port1)
167 self.tgen_port1_mac = \
168 utils.get_port_mac(self.client, self.tg_port1)
169 self.client.run("tee ~/.testpmd.ipaddr.port1 > /dev/null",
170 stdin=self.tgen_port1_ip)
171 self.client.run("tee ~/.testpmd.macaddr.port1 > /dev/null",
172 stdin=self.tgen_port1_mac)
173 self.tgen_port2_ip = \
174 utils.get_port_ip(self.client, self.tg_port2)
175 self.tgen_port2_mac = \
176 utils.get_port_mac(self.client, self.tg_port2)
177 self.client.run("tee ~/.testpmd.ipaddr.port2 > /dev/null",
178 stdin=self.tgen_port2_ip)
179 self.client.run("tee ~/.testpmd.macaddr.port2 > /dev/null",
180 stdin=self.tgen_port2_mac)
182 cmd = "cat ~/.testpmd.macaddr.port1"
183 status, stdout, stderr = self.client.execute(cmd)
185 raise RuntimeError(stderr)
186 self.tgen_port1_mac = stdout
187 cmd = "cat ~/.testpmd.ipaddr.port1"
188 status, stdout, stderr = self.client.execute(cmd)
190 raise RuntimeError(stderr)
191 self.tgen_port1_ip = stdout
192 cmd = "cat ~/.testpmd.macaddr.port2"
193 status, stdout, stderr = self.client.execute(cmd)
195 raise RuntimeError(stderr)
196 self.tgen_port2_mac = stdout
197 cmd = "cat ~/.testpmd.ipaddr.port2"
198 status, stdout, stderr = self.client.execute(cmd)
200 raise RuntimeError(stderr)
201 self.tgen_port2_ip = stdout
203 LOG.info("forward type is %s", self.forward_type)
204 if self.forward_type == 'testpmd':
205 cmd = "sudo ip link set %s down" % (self.tg_port1)
206 LOG.debug("Executing command: %s", cmd)
207 self.client.execute(cmd)
208 cmd = "sudo ip link set %s down" % (self.tg_port2)
209 LOG.debug("Executing command: %s", cmd)
210 self.client.execute(cmd)
211 cmd = "screen -d -m sudo -E bash ~/testpmd_vsperf.sh %s %s %d" % \
212 (self.moongen_port1_mac, self.moongen_port2_mac,
214 LOG.debug("Executing command: %s", cmd)
215 status, stdout, stderr = self.client.execute(cmd)
217 raise RuntimeError(stderr)
219 elif self.forward_type == 'l2fwd':
220 cmd = ('sed -i "s/static char *net1 = \\\"eth1\\\";'
221 '/static char *net1 = \\\"%s %s %s\\\";/g" /home/l2fwd/l2fwd.c'
222 % (self.tg_port1, self.tgen_port1_ip, self.moongen_port1_mac))
223 LOG.debug("Executing command: %s", cmd)
224 status, stdout, stderr = self.client.execute(cmd)
226 cmd = ('sed -i "s/static char *net2 = \\\"eth2\\\";'
227 '/static char *net2 = \\\"%s %s %s\\\";/g" /home/l2fwd/l2fwd.c'
228 % (self.tg_port2, self.tgen_port2_ip, self.moongen_port2_mac))
229 LOG.debug("Executing command: %s", cmd)
230 status, stdout, stderr = self.client.execute(cmd)
232 cmd = ('cd /home/l2fwd/;make;./gen_debian_package.sh;'
233 'sudo dpkg -i *.deb;'
234 'sudo modprobe l2fwd')
235 LOG.debug("Executing command: %s", cmd)
236 status, stdout, stderr = self.client.execute(cmd)
240 self.forward_setup_done = True
242 def _is_forward_setup(self):
243 """Is forward already setup in the host?"""
244 if self.forward_type is 'testpmd':
246 cmd = "ip a | grep %s 2>/dev/null" % (self.tg_port1)
247 LOG.debug("Executing command: %s", cmd)
248 _, stdout, _ = self.client.execute(cmd)
252 elif self.forward_type is 'l2fwd':
253 cmd = ('sudo lsmod |grep l2fwd')
254 LOG.debug("Executing command: %s", cmd)
255 _, stdout, _ = self.client.execute(cmd)
261 def generate_config_file(self, frame_size, multistream,
262 runBidirec, tg_port1_vlan, tg_port2_vlan,
263 SearchRuntime, Package_Loss):
266 testType = 'throughput',
270 srcMacs = {\'%s\', \'%s\'},
271 dstMacs = {\'%s\', \'%s\'},
274 validationRunTime = %d,
275 acceptableLossPct = %d,
278 """ % (multistream, runBidirec, frame_size, self.moongen_port1_mac,
279 self.moongen_port2_mac, self.tgen_port1_mac, self.tgen_port2_mac,
280 tg_port1_vlan, tg_port2_vlan, SearchRuntime, SearchRuntime, Package_Loss)
281 with open(self.VSPERF_CONFIG, "wt") as out_file:
282 out_file.write(out_text)
283 self.CONFIG_FILE = True
285 def result_to_data(self, result):
286 search_pattern = re.compile(
287 r'\[REPORT\]\s+total\:\s+'
288 r'Tx\s+frames\:\s+(\d+)\s+'
289 r'Rx\s+Frames\:\s+(\d+)\s+'
290 r'frame\s+loss\:\s+(\d+)\,'
291 r'\s+(\d+\.\d+|\d+)%\s+'
292 r'Tx\s+Mpps\:\s+(\d+.\d+|\d+)\s+'
293 r'Rx\s+Mpps\:\s+(\d+\.\d+|\d+)',
295 results_match = search_pattern.search(result)
297 rx_mpps = float(results_match.group(6))
298 tx_mpps = float(results_match.group(5))
302 test_result = {"rx_mpps": rx_mpps, "tx_mpps": tx_mpps}
306 def run(self, result):
307 """ execute the vsperf benchmark and return test results
308 within result dictionary
311 if not self.setup_done:
315 multistream = self.options.get("multistream", 1)
317 if not self.forward_setup_done:
320 if 'frame_size' in self.options:
321 frame_size = self.options.get("frame_size", 64)
322 Package_Loss = self.options.get("Package_Loss", 0)
323 runBidirec = self.options.get("moongen_runBidirec",
325 SearchRuntime = self.options.get("SearchRuntime", 10)
327 cmd = "openstack network show %s --format json -c " \
328 "provider:segmentation_id" % (self.tg_port1_nw)
329 LOG.debug("Executing command: %s", cmd)
330 output = subprocess.check_output(cmd, shell=True)
332 tg_port1_vlan = jsonutils.loads(output).get("provider:segmentation_id", 1)
336 cmd = "openstack network show %s --format json -c " \
337 "provider:segmentation_id" % (self.tg_port2_nw)
338 LOG.debug("Executing command: %s", cmd)
339 output = subprocess.check_output(cmd, shell=True)
341 tg_port2_vlan = jsonutils.loads(output).get("provider:segmentation_id", 2)
345 self.generate_config_file(frame_size, multistream,
346 runBidirec, tg_port1_vlan,
347 tg_port2_vlan, SearchRuntime, Package_Loss)
349 self.server.execute("rm -f -- %s/opnfv-vsperf-cfg.lua" %
351 self.server._put_file_shell(self.VSPERF_CONFIG,
352 "%s/opnfv-vsperf-cfg.lua"
353 % (self.moongen_dir))
356 cmd = ("cd %s;./MoonGen/build/MoonGen ./trafficgen.lua"
357 % (self.moongen_dir))
358 status, stdout, stderr = self.server.execute(cmd)
360 raise RuntimeError(stderr)
362 moongen_result = self.result_to_data(stdout)
363 LOG.info(moongen_result)
364 result.update(moongen_result)
366 if "sla" in self.scenario_cfg:
367 throughput_rx_mpps = int(
368 self.scenario_cfg["sla"]["throughput_rx_mpps"])
371 throughput_rx_mpps <= moongen_result["tx_mpps"],
372 "sla_throughput_rx_mpps %f > throughput_rx_mpps(%f); "
373 % (throughput_rx_mpps, moongen_result["tx_mpps"]))
376 """cleanup after the test execution"""
378 # execute external setup script
379 self.setup_done = False