add option to connect to non-standard ssh port
[yardstick.git] / yardstick / benchmark / scenarios / networking / pktgen_dpdk.py
1 ##############################################################################
2 # Copyright (c) 2016 ZTE corporation and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9 import pkg_resources
10 import logging
11 import time
12
13 import yardstick.ssh as ssh
14 from yardstick.benchmark.scenarios import base
15
16 LOG = logging.getLogger(__name__)
17
18
19 class PktgenDPDKLatency(base.Scenario):
20     """Execute pktgen-dpdk on one vm and execute testpmd on the other vm
21
22   Parameters
23     packetsize - packet size in bytes without the CRC
24         type:    int
25         unit:    bytes
26         default: 64
27     """
28     __scenario_type__ = "PktgenDPDKLatency"
29
30     PKTGEN_DPDK_SCRIPT = 'pktgen_dpdk_latency_benchmark.bash'
31     TESTPMD_SCRIPT = 'testpmd_fwd.bash'
32
33     def __init__(self, scenario_cfg, context_cfg):
34         self.scenario_cfg = scenario_cfg
35         self.context_cfg = context_cfg
36         self.setup_done = False
37
38     def setup(self):
39         '''scenario setup'''
40         self.pktgen_dpdk_script = pkg_resources.resource_filename(
41             'yardstick.benchmark.scenarios.networking',
42             PktgenDPDKLatency.PKTGEN_DPDK_SCRIPT)
43         self.testpmd_script = pkg_resources.resource_filename(
44             'yardstick.benchmark.scenarios.networking',
45             PktgenDPDKLatency.TESTPMD_SCRIPT)
46         host = self.context_cfg['host']
47         host_user = host.get('user', 'ubuntu')
48         host_ssh_port = host.get('ssh_port', ssh.DEFAULT_PORT)
49         host_ip = host.get('ip', None)
50         host_key_filename = host.get('key_filename', '~/.ssh/id_rsa')
51         target = self.context_cfg['target']
52         target_user = target.get('user', 'ubuntu')
53         target_ssh_port = target.get('ssh_port', ssh.DEFAULT_PORT)
54         target_ip = target.get('ip', None)
55         target_key_filename = target.get('key_filename', '~/.ssh/id_rsa')
56         LOG.info("user:%s, target:%s", target_user, target_ip)
57         self.server = ssh.SSH(target_user, target_ip,
58                               key_filename=target_key_filename,
59                               port=target_ssh_port)
60         self.server.wait(timeout=600)
61
62         # copy script to host
63         self.server.run("cat > ~/testpmd_fwd.sh",
64                         stdin=open(self.testpmd_script, "rb"))
65
66         LOG.info("user:%s, host:%s", host_user, host_ip)
67         self.client = ssh.SSH(host_user, host_ip,
68                               key_filename=host_key_filename,
69                               port=host_ssh_port)
70         self.client.wait(timeout=600)
71
72         # copy script to host
73         self.client.run("cat > ~/pktgen_dpdk.sh",
74                         stdin=open(self.pktgen_dpdk_script, "rb"))
75
76         self.setup_done = True
77         self.testpmd_args = ''
78         self.pktgen_args = []
79
80     @staticmethod
81     def get_port_mac(sshclient, port):
82         cmd = "ifconfig |grep HWaddr |grep %s |awk '{print $5}' " % port
83         LOG.debug("Executing command: %s", cmd)
84         status, stdout, stderr = sshclient.execute(cmd)
85
86         if status:
87             raise RuntimeError(stderr)
88         else:
89             return stdout.rstrip()
90
91     @staticmethod
92     def get_port_ip(sshclient, port):
93         cmd = "ifconfig %s |grep 'inet addr' |awk '{print $2}' \
94             |cut -d ':' -f2 " % port
95         LOG.debug("Executing command: %s", cmd)
96         status, stdout, stderr = sshclient.execute(cmd)
97
98         if status:
99             raise RuntimeError(stderr)
100         else:
101             return stdout.rstrip()
102
103     def run(self, result):
104         """execute the benchmark"""
105
106         if not self.setup_done:
107             self.setup()
108
109         if not self.testpmd_args:
110             self.testpmd_args = self.get_port_mac(self.client, 'eth2')
111
112         if not self.pktgen_args:
113             server_rev_mac = self.get_port_mac(self.server, 'eth1')
114             server_send_mac = self.get_port_mac(self.server, 'eth2')
115             client_src_ip = self.get_port_ip(self.client, 'eth1')
116             client_dst_ip = self.get_port_ip(self.client, 'eth2')
117
118             self.pktgen_args = [client_src_ip, client_dst_ip,
119                                 server_rev_mac, server_send_mac]
120
121         options = self.scenario_cfg['options']
122         packetsize = options.get("packetsize", 64)
123         rate = options.get("rate", 100)
124
125         cmd = "screen sudo -E bash ~/testpmd_fwd.sh %s " % (self.testpmd_args)
126         LOG.debug("Executing command: %s", cmd)
127         self.server.send_command(cmd)
128
129         time.sleep(1)
130
131         cmd = "screen sudo -E bash ~/pktgen_dpdk.sh %s %s %s %s %s %s" % \
132             (self.pktgen_args[0], self.pktgen_args[1], self.pktgen_args[2],
133              self.pktgen_args[3], rate, packetsize)
134         LOG.debug("Executing command: %s", cmd)
135         self.client.send_command(cmd)
136
137         # wait for finishing test
138         time.sleep(1)
139
140         cmd = "cat ~/result.log -vT \
141                |awk '{match($0,/\[8;40H +[0-9]+/)} \
142                {print substr($0,RSTART,RLENGTH)}' \
143                |grep -v ^$ |awk '{if ($2 != 0) print $2}'"
144         client_status, client_stdout, client_stderr = self.client.execute(cmd)
145
146         if client_status:
147             raise RuntimeError(client_stderr)
148
149         avg_latency = 0
150         if client_stdout:
151             latency_list = client_stdout.split('\n')[0:-2]
152             LOG.info("10 samples of latency: %s", latency_list)
153             latency_sum = 0
154             for i in latency_list:
155                 latency_sum += int(i)
156             avg_latency = latency_sum/len(latency_list)
157
158         result.update({"avg_latency": avg_latency})
159
160         if avg_latency and "sla" in self.scenario_cfg:
161             sla_max_latency = int(self.scenario_cfg["sla"]["max_latency"])
162             LOG.info("avg_latency : %d ", avg_latency)
163             LOG.info("sla_max_latency: %d", sla_max_latency)
164             debug_info = "avg_latency %d > sla_max_latency %d" \
165                 % (avg_latency, sla_max_latency)
166             assert avg_latency <= sla_max_latency, debug_info