8038cad607e5a2fb28a96b71bff900baeaca662f
[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 LOG.setLevel(logging.DEBUG)
18
19
20 class Pktgen(base.Scenario):
21     """Executes a pktgen benchmark between two hosts"""
22     __scenario_type__ = "Pktgen"
23
24     TARGET_SCRIPT = 'pktgen_benchmark.bash'
25
26     def __init__(self, context):
27         self.context = context
28         self.setup_done = False
29
30     def setup(self):
31         '''scenario setup'''
32         self.target_script = pkg_resources.resource_filename(
33             'yardstick.benchmark.scenarios.networking',
34             Pktgen.TARGET_SCRIPT)
35         user = self.context.get('user', 'ubuntu')
36         host = self.context.get('host', None)
37         target = self.context.get('target', None)
38         key_filename = self.context.get('key_filename', '~/.ssh/id_rsa')
39
40         LOG.debug("user:%s, target:%s", user, target)
41         self.server = ssh.SSH(user, target, key_filename=key_filename)
42         self.server.wait(timeout=600)
43
44         LOG.debug("user:%s, host:%s", user, host)
45         self.client = ssh.SSH(user, host, key_filename=key_filename)
46         self.client.wait(timeout=600)
47
48         # copy script to host
49         self.client.run("cat > ~/pktgen.sh",
50                         stdin=open(self.target_script, "rb"))
51
52         self.setup_done = True
53
54     def _iptables_setup(self):
55         """Setup iptables on server to monitor for received packets"""
56         cmd = "sudo iptables -F; " \
57               "sudo iptables -A INPUT -p udp --dport 1000:%s -j DROP" \
58               % (1000 + self.number_of_ports)
59         LOG.debug("Executing command: %s", cmd)
60         status, _, stderr = self.server.execute(cmd)
61         if status:
62             raise RuntimeError(stderr)
63
64     def _iptables_get_result(self):
65         """Get packet statistics from server"""
66         cmd = "sudo iptables -L INPUT -vnx |" \
67               "awk '/dpts:1000:%s/ {{printf \"%%s\", $1}}'" \
68               % (1000 + self.number_of_ports)
69         LOG.debug("Executing command: %s", cmd)
70         status, stdout, stderr = self.server.execute(cmd)
71         if status:
72             raise RuntimeError(stderr)
73         return int(stdout)
74
75     def run(self, args):
76         """execute the benchmark"""
77
78         if not self.setup_done:
79             self.setup()
80
81         ipaddr = args.get("ipaddr", '127.0.0.1')
82
83         options = args['options']
84         packetsize = options.get("packetsize", 60)
85         self.number_of_ports = options.get("number_of_ports", 10)
86
87         self._iptables_setup()
88
89         cmd = "sudo bash pktgen.sh %s %s %s" \
90             % (ipaddr, self.number_of_ports, packetsize)
91         LOG.debug("Executing command: %s", cmd)
92         status, stdout, stderr = self.client.execute(cmd)
93
94         if status:
95             raise RuntimeError(stderr)
96
97         data = json.loads(stdout)
98
99         data['packets_received'] = self._iptables_get_result()
100
101         if "sla" in args:
102             sent = data['packets_sent']
103             received = data['packets_received']
104             ppm = 1000000 * (sent - received) / sent
105             sla_max_ppm = int(args["sla"]["max_ppm"])
106             assert ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d" \
107                 % (ppm, sla_max_ppm)
108
109         return data
110
111
112 def _test():
113     '''internal test function'''
114     key_filename = pkg_resources.resource_filename('yardstick.resources',
115                                                    'files/yardstick_key')
116     ctx = {'host': '172.16.0.137',
117            'target': '172.16.0.138',
118            'user': 'ubuntu',
119            'key_filename': key_filename
120            }
121
122     logger = logging.getLogger('yardstick')
123     logger.setLevel(logging.DEBUG)
124
125     p = Pktgen(ctx)
126
127     options = {'packetsize': 120}
128
129     args = {'options': options,
130             'ipaddr': '192.168.111.31'}
131     result = p.run(args)
132     print result
133
134 if __name__ == '__main__':
135     _test()