58c0e6c86e5a1c6dac5ef0036f1d8a05771054dd
[bottlenecks.git] / vstf / vstf / agent / perf / pktgen.py
1 #!/usr/bin/python
2 # -*- coding: utf8 -*-
3 # author:
4 # date: 2015-09-15
5 # see license for license details
6 import subprocess
7 import time
8 import logging
9 import vstf.agent.perf.utils as utils
10 import vstf.common.decorator as deco
11 from vstf.common.utils import my_popen
12
13 LOG = logging.getLogger(__name__)
14
15
16 class Pktgen(object):
17     def __init__(self):
18         utils.modprobe_pktgen()
19         self._send_processes = []
20
21     def _psetpg(self, dev):
22         self._dev = dev
23
24     def _vsetpg(self, key, value=''):
25         with open(self._dev, 'w') as f:
26             txt = "%(key)s %(value)s\n" % {'key': key, 'value': value}
27             f.write(txt)
28             LOG.info("write(%s) to %s", txt.strip(), self._dev)
29
30     def _start(self):
31         cmd = 'echo start > /proc/net/pktgen/pgctrl'
32         process = my_popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
33         LOG.info('running pid:%s', process.pid)
34         time.sleep(0.5)
35         ret = process.poll()
36         if ret is None:
37             ret = 0
38             self._send_processes.append(process)
39             error_str = "start pktgen send success"
40         else:
41             error_str = "start pktgen send failed, stdout:%s,stderr:%s" % (process.stdout.read(), process.stderr.read())
42             LOG.info(error_str)
43         return ret, error_str
44
45     def _rem_device_all(self):
46         cpu_num = utils.get_cpu_num()
47         for thread in range(0, cpu_num - 1):
48             self._psetpg("/proc/net/pktgen/kpktgend_%s" % thread)
49             self._vsetpg('rem_device_all')
50         return True
51
52     @deco.check("protocol", choices=['udp_bw'], defaults='udp_bw')
53     @deco.check("namespace", defaults=None)
54     @deco.check("dst")
55     @deco.check("src")
56     @deco.check("size", defaults=64)
57     @deco.check("threads", defaults=utils.get_default_threads())
58     @deco.check("clone_skb", defaults=1)
59     @deco.check("count", defaults=0)
60     @deco.check("ratep", defaults=0)
61     def send_start(self, **kwargs):
62         # ensure that all sends is exit
63         self.send_stop()
64
65         interface_num = len(kwargs['src'])
66         interfaces = []
67         for i in range(interface_num):
68             device = kwargs['src'][i]['iface']
69             interfaces.append(device)
70             utils.iface_up(device)
71
72         self._rem_device_all()
73
74         threads = kwargs['threads']
75         for i in range(interface_num):
76             dev_min = i * threads
77             dev_max = (i + 1) * threads
78             device = interfaces[i]
79             for dev_id in range(dev_min, dev_max):
80                 queue_id = dev_id % threads
81                 self._psetpg("/proc/net/pktgen/kpktgend_%s" % dev_id)
82                 self._vsetpg('add_device', "%s@%s" % (device, queue_id))
83                 self._psetpg("/proc/net/pktgen/%s@%s" % (device, queue_id))
84                 self._vsetpg('pkt_size', kwargs['size'])
85                 self._vsetpg('clone_skb', kwargs['clone_skb'])
86                 self._vsetpg('dst_mac', kwargs['dst'][i]['mac'])
87                 self._vsetpg('src_mac', kwargs['src'][i]['mac'])
88                 self._vsetpg('count', kwargs['count'])
89                 if kwargs['ratep']:
90                     self._vsetpg('ratep', kwargs['ratep'])
91         return self._start()
92
93     def send_stop(self, **kwargs):
94         results = []
95         ret = 0
96         for process in self._send_processes:
97             process.kill()
98             process.wait()
99             LOG.info("process.kill(pktgen:%s)", process.pid)
100             results.append((ret, process.stdout.read()))
101         self._send_processes = []
102         return results
103
104     def receive_start(self, **kwargs):
105         ret = 0
106         error_str = "%s pktgen neednt receive start" % (self.__class__)
107         LOG.debug(error_str)
108         return ret, error_str
109
110     def receive_stop(self, **kwargs):
111         ret = 0
112         error_str = "pktgen neednt receive stop"
113         LOG.debug(error_str)
114         return ret, error_str
115
116     def clean(self):
117         self.send_stop()
118         return True
119
120     def force_clean(self):
121         LOG.info("%s %s start", self.__class__, self.force_clean.__name__)
122         return self.clean()
123
124
125 def unit_test():
126     perf = Pktgen()
127     print perf.receive_start()
128     send = {
129         "src": [
130             {"iface": 'eth4', "mac": "90:e2:ba:20:1f:d8"}
131         ],
132         "dst": [
133             {"mac": '90:e2:ba:20:1f:d9'}
134         ],
135         "size": 64,
136         "threads": 1,
137         'ratep': 0
138     }
139     print perf.send_start(**send)
140     time.sleep(30)
141     print perf.send_stop()
142     print perf.receive_stop()
143
144
145 if __name__ == "__main__":
146     from vstf.common.log import setup_logging
147
148     setup_logging(level=logging.DEBUG, log_file="/var/log/vstf/vstf-pktgen.log", clevel=logging.DEBUG)
149     unit_test()