f373fd2ecbd687ad3aedde3f672d1bf2ed8c45fa
[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, context):
41         self.context = context
42         self.setup_done = False
43
44     def setup(self):
45         '''scenario setup'''
46         self.target_script = pkg_resources.resource_filename(
47             'yardstick.benchmark.scenarios.networking',
48             Pktgen.TARGET_SCRIPT)
49         user = self.context.get('user', 'ubuntu')
50         host = self.context.get('host', None)
51         target = self.context.get('target', None)
52         key_filename = self.context.get('key_filename', '~/.ssh/id_rsa')
53
54         LOG.info("user:%s, target:%s", user, target)
55         self.server = ssh.SSH(user, target, key_filename=key_filename)
56         self.server.wait(timeout=600)
57
58         LOG.info("user:%s, host:%s", user, host)
59         self.client = ssh.SSH(user, host, key_filename=key_filename)
60         self.client.wait(timeout=600)
61
62         # copy script to host
63         self.client.run("cat > ~/pktgen.sh",
64                         stdin=open(self.target_script, "rb"))
65
66         self.setup_done = True
67
68     def _iptables_setup(self):
69         """Setup iptables on server to monitor for received packets"""
70         cmd = "sudo iptables -F; " \
71               "sudo iptables -A INPUT -p udp --dport 1000:%s -j DROP" \
72               % (1000 + self.number_of_ports)
73         LOG.debug("Executing command: %s", cmd)
74         status, _, stderr = self.server.execute(cmd)
75         if status:
76             raise RuntimeError(stderr)
77
78     def _iptables_get_result(self):
79         """Get packet statistics from server"""
80         cmd = "sudo iptables -L INPUT -vnx |" \
81               "awk '/dpts:1000:%s/ {{printf \"%%s\", $1}}'" \
82               % (1000 + self.number_of_ports)
83         LOG.debug("Executing command: %s", cmd)
84         status, stdout, stderr = self.server.execute(cmd)
85         if status:
86             raise RuntimeError(stderr)
87         return int(stdout)
88
89     def run(self, args, result):
90         """execute the benchmark"""
91
92         if not self.setup_done:
93             self.setup()
94
95         ipaddr = args.get("ipaddr", '127.0.0.1')
96
97         options = args['options']
98         packetsize = options.get("packetsize", 60)
99         self.number_of_ports = options.get("number_of_ports", 10)
100         # if run by a duration runner
101         duration_time = self.context.get("duration", None)
102         # if run by an arithmetic runner
103         arithmetic_time = options.get("duration", None)
104
105         if duration_time:
106             duration = duration_time
107         elif arithmetic_time:
108             duration = arithmetic_time
109         else:
110             duration = 20
111
112         self._iptables_setup()
113
114         cmd = "sudo bash pktgen.sh %s %s %s %s" \
115             % (ipaddr, self.number_of_ports, packetsize, duration)
116         LOG.debug("Executing command: %s", cmd)
117         status, stdout, stderr = self.client.execute(cmd)
118
119         if status:
120             raise RuntimeError(stderr)
121
122         result.update(json.loads(stdout))
123
124         result['packets_received'] = self._iptables_get_result()
125
126         if "sla" in args:
127             sent = result['packets_sent']
128             received = result['packets_received']
129             ppm = 1000000 * (sent - received) / sent
130             sla_max_ppm = int(args["sla"]["max_ppm"])
131             assert ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d; " \
132                 % (ppm, sla_max_ppm)
133
134
135 def _test():
136     '''internal test function'''
137     key_filename = pkg_resources.resource_filename('yardstick.resources',
138                                                    'files/yardstick_key')
139     ctx = {'host': '172.16.0.137',
140            'target': '172.16.0.138',
141            'user': 'ubuntu',
142            'key_filename': key_filename
143            }
144
145     logger = logging.getLogger('yardstick')
146     logger.setLevel(logging.DEBUG)
147
148     p = Pktgen(ctx)
149
150     options = {'packetsize': 120}
151
152     args = {'options': options,
153             'ipaddr': '192.168.111.31'}
154     result = p.run(args)
155     print result
156
157 if __name__ == '__main__':
158     _test()