Merge "Bugfix: task_id parameter from API can not pass to yardstick core"
[yardstick.git] / yardstick / benchmark / scenarios / networking / pktgen.py
1 ##############################################################################
2 # Copyright (c) 2015 Ericsson AB 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 from __future__ import absolute_import
10 from __future__ import print_function
11
12 import logging
13
14 import pkg_resources
15 from oslo_serialization import jsonutils
16
17 import yardstick.ssh as ssh
18 from yardstick.benchmark.scenarios import base
19
20 LOG = logging.getLogger(__name__)
21
22
23 class Pktgen(base.Scenario):
24     """Execute pktgen between two hosts
25
26   Parameters
27     packetsize - packet size in bytes without the CRC
28         type:    int
29         unit:    bytes
30         default: 60
31     number_of_ports - number of UDP ports to test
32         type:    int
33         unit:    na
34         default: 10
35     duration - duration of the test
36         type:    int
37         unit:    seconds
38         default: 20
39     """
40     __scenario_type__ = "Pktgen"
41
42     TARGET_SCRIPT = 'pktgen_benchmark.bash'
43
44     def __init__(self, scenario_cfg, context_cfg):
45         self.scenario_cfg = scenario_cfg
46         self.context_cfg = context_cfg
47         self.setup_done = False
48
49     def setup(self):
50         """scenario setup"""
51         self.target_script = pkg_resources.resource_filename(
52             'yardstick.benchmark.scenarios.networking',
53             Pktgen.TARGET_SCRIPT)
54         host = self.context_cfg['host']
55         host_user = host.get('user', 'ubuntu')
56         host_ssh_port = host.get('ssh_port', ssh.DEFAULT_PORT)
57         host_ip = host.get('ip', None)
58         host_key_filename = host.get('key_filename', '~/.ssh/id_rsa')
59         target = self.context_cfg['target']
60         target_user = target.get('user', 'ubuntu')
61         target_ssh_port = target.get('ssh_port', ssh.DEFAULT_PORT)
62         target_ip = target.get('ip', None)
63         target_key_filename = target.get('key_filename', '~/.ssh/id_rsa')
64
65         LOG.info("user:%s, target:%s", target_user, target_ip)
66         self.server = ssh.SSH(target_user, target_ip,
67                               key_filename=target_key_filename,
68                               port=target_ssh_port)
69         self.server.wait(timeout=600)
70
71         LOG.info("user:%s, host:%s", host_user, host_ip)
72         self.client = ssh.SSH(host_user, host_ip,
73                               key_filename=host_key_filename,
74                               port=host_ssh_port)
75         self.client.wait(timeout=600)
76
77         # copy script to host
78         self.client._put_file_shell(self.target_script, '~/pktgen.sh')
79
80         self.setup_done = True
81
82     def _iptables_setup(self):
83         """Setup iptables on server to monitor for received packets"""
84         cmd = "sudo iptables -F; " \
85               "sudo iptables -A INPUT -p udp --dport 1000:%s -j DROP" \
86               % (1000 + self.number_of_ports)
87         LOG.debug("Executing command: %s", cmd)
88         status, _, stderr = self.server.execute(cmd)
89         if status:
90             raise RuntimeError(stderr)
91
92     def _iptables_get_result(self):
93         """Get packet statistics from server"""
94         cmd = "sudo iptables -L INPUT -vnx |" \
95               "awk '/dpts:1000:%s/ {{printf \"%%s\", $1}}'" \
96               % (1000 + self.number_of_ports)
97         LOG.debug("Executing command: %s", cmd)
98         status, stdout, stderr = self.server.execute(cmd)
99         if status:
100             raise RuntimeError(stderr)
101         return int(stdout)
102
103     def run(self, result):
104         """execute the benchmark"""
105
106         if not self.setup_done:
107             self.setup()
108
109         ipaddr = self.context_cfg["target"].get("ipaddr", '127.0.0.1')
110
111         options = self.scenario_cfg['options']
112         packetsize = options.get("packetsize", 60)
113         self.number_of_ports = options.get("number_of_ports", 10)
114         # if run by a duration runner
115         duration_time = self.scenario_cfg["runner"].get("duration", None) \
116             if "runner" in self.scenario_cfg else None
117         # if run by an arithmetic runner
118         arithmetic_time = options.get("duration", None)
119
120         if duration_time:
121             duration = duration_time
122         elif arithmetic_time:
123             duration = arithmetic_time
124         else:
125             duration = 20
126
127         self._iptables_setup()
128
129         cmd = "sudo bash pktgen.sh %s %s %s %s" \
130             % (ipaddr, self.number_of_ports, packetsize, duration)
131         LOG.debug("Executing command: %s", cmd)
132         status, stdout, stderr = self.client.execute(cmd)
133
134         if status:
135             raise RuntimeError(stderr)
136
137         result.update(jsonutils.loads(stdout))
138
139         result['packets_received'] = self._iptables_get_result()
140
141         if "sla" in self.scenario_cfg:
142             sent = result['packets_sent']
143             received = result['packets_received']
144             ppm = 1000000 * (sent - received) / sent
145             sla_max_ppm = int(self.scenario_cfg["sla"]["max_ppm"])
146             assert ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d; " \
147                 % (ppm, sla_max_ppm)
148
149
150 def _test():
151     """internal test function"""
152     key_filename = pkg_resources.resource_filename('yardstick.resources',
153                                                    'files/yardstick_key')
154     ctx = {
155         'host': {
156             'ip': '10.229.47.137',
157             'user': 'root',
158             'key_filename': key_filename
159         },
160         'target': {
161             'ip': '10.229.47.137',
162             'user': 'root',
163             'key_filename': key_filename,
164             'ipaddr': '10.229.47.137',
165         }
166     }
167
168     logger = logging.getLogger('yardstick')
169     logger.setLevel(logging.DEBUG)
170
171     options = {'packetsize': 120}
172     args = {'options': options}
173     result = {}
174
175     p = Pktgen(args, ctx)
176     p.run(result)
177     print(result)
178
179
180 if __name__ == '__main__':
181     _test()