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