Add support for Python 3
[yardstick.git] / yardstick / vTC / apexlake / experimental_framework / benchmarks / instantiation_validation_benchmark.py
1 # Copyright (c) 2015 Intel Research and Development Ireland Ltd.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 from __future__ import absolute_import
16 import os
17 # import signal
18 import time
19
20 import subprocess
21 from experimental_framework.benchmarks import benchmark_base_class as base
22 from experimental_framework.constants import framework_parameters as fp
23 from experimental_framework.constants import conf_file_sections as cfs
24 from experimental_framework.packet_generators import dpdk_packet_generator \
25     as dpdk
26 import experimental_framework.common as common
27 from six.moves import range
28
29
30 THROUGHPUT = 'throughput'
31 VLAN_SENDER = 'vlan_sender'
32 VLAN_RECEIVER = 'vlan_receiver'
33 PACKETS_FILE_NAME = 'packets.res'
34 PACKET_CHECKER_PROGRAM_NAME = 'test_sniff'
35 MULTICAST_GROUP = '224.192.16.1'
36
37
38 class InstantiationValidationBenchmark(base.BenchmarkBaseClass):
39
40     def __init__(self, name, params):
41         base.BenchmarkBaseClass.__init__(self, name, params)
42         self.base_dir = os.path.join(
43             common.get_base_dir(), fp.EXPERIMENTAL_FRAMEWORK_DIR,
44             fp.DPDK_PKTGEN_DIR)
45         self.results_file = self.base_dir + PACKETS_FILE_NAME
46         self.lua_file = self.base_dir + 'constant_traffic.lua'
47         self.res_dir = ''
48         self.interface_name = ''
49
50         # Set the packet checker command
51         self.pkt_checker_command = os.path.join(
52             common.get_base_dir(),
53             'experimental_framework/libraries/',
54             'packet_checker/',
55             PACKET_CHECKER_PROGRAM_NAME + ' ')
56
57     def init(self):
58         """
59         Initialize the benchmark
60         :return: None
61         """
62         pass
63
64     def finalize(self):
65         """
66         Finalizes the benchmark
67         :return: None
68         """
69         pass
70
71     def get_features(self):
72         features = dict()
73         features['description'] = 'Instantiation Validation Benchmark'
74         features['parameters'] = [THROUGHPUT, VLAN_SENDER, VLAN_RECEIVER]
75         features['allowed_values'] = dict()
76         features['allowed_values'][THROUGHPUT] = [str(x) for x in range(100)]
77         features['allowed_values'][VLAN_SENDER] = [str(x) for x in
78                                                    range(-1, 4096)]
79         features['allowed_values'][VLAN_RECEIVER] = [str(x)
80                                                      for x in range(-1, 4096)]
81         features['default_values'] = dict()
82         features['default_values'][THROUGHPUT] = '1'
83         features['default_values'][VLAN_SENDER] = '-1'
84         features['default_values'][VLAN_RECEIVER] = '-1'
85         return features
86
87     def run(self):
88         # Setup packet generator
89         traffic_time = '10'
90         packet_size = '512'
91         traffic_rate_percentage = self.params[THROUGHPUT]
92
93         dpdk_pktgen_vars = common.get_dpdk_pktgen_vars()
94         # bus_address = dpdk_pktgen_vars[cfs.CFSP_DPDK_BUS_SLOT_NIC_2]
95         self.interface_name = dpdk_pktgen_vars[cfs.CFSP_DPDK_NAME_IF_2]
96         packetgen = dpdk.DpdkPacketGenerator()
97         self._configure_lua_file(traffic_rate_percentage, traffic_time)
98         packetgen.init_dpdk_pktgen(dpdk_interfaces=1,
99                                    pcap_file_0='packet_' + packet_size +
100                                                '.pcap',
101                                    pcap_file_1='igmp.pcap',
102                                    lua_script='constant_traffic.lua',
103                                    vlan_0=self.params[VLAN_SENDER],
104                                    vlan_1=self.params[VLAN_RECEIVER])
105
106         self._init_packet_checker()
107         # Send constant traffic at a specified rate
108         common.LOG.debug('Start the packet generator')
109         packetgen.send_traffic()
110         common.LOG.debug('Stop the packet generator')
111         time.sleep(5)
112         self._finalize_packet_checker()
113         self._reset_lua_file(traffic_rate_percentage, traffic_time)
114         return self._get_results()
115
116     def _configure_lua_file(self, traffic_rate_percentage, traffic_time):
117         """
118         Configure the packet gen to write the results into the right file
119         :return: None
120         """
121         common.replace_in_file(self.lua_file, 'local out_file = ""',
122                                'local out_file = "' +
123                                self.results_file + '"')
124         common.replace_in_file(self.lua_file, 'local traffic_rate = 0',
125                                'local traffic_rate = ' +
126                                traffic_rate_percentage)
127         common.replace_in_file(self.lua_file, 'local traffic_delay = 0',
128                                'local traffic_delay = ' + traffic_time)
129
130     def _reset_lua_file(self, traffic_rate_percentage, traffic_time):
131         """
132         Configure the packet gen to write the results into the right file
133         :param traffic_rate_percentage:
134         :param traffic_time:
135         :return: None
136         """
137
138         common.replace_in_file(self.lua_file, 'local out_file = "' +
139                                self.results_file + '"',
140                                'local out_file = ""')
141         common.replace_in_file(self.lua_file, 'local traffic_rate = ' +
142                                traffic_rate_percentage,
143                                'local traffic_rate = 0')
144         common.replace_in_file(self.lua_file, 'local traffic_delay = ' +
145                                traffic_time, 'local traffic_delay = 0')
146
147     def _get_results(self):
148         ret_val = dict()
149         packet_checker_res = 0
150         if self.res_dir:
151             packet_checker_res = \
152                 int(common.get_file_first_line(self.res_dir +
153                                                'packet_checker.res'))
154         pkt_gen_res = int(common.get_file_first_line(self.results_file))
155         if pkt_gen_res <= packet_checker_res or \
156            (float(pkt_gen_res - packet_checker_res) / pkt_gen_res) <= 0.1:
157             ret_val['failure'] = '0'
158         else:
159             ret_val['failure'] = '1'
160         return ret_val
161
162     def _init_packet_checker(self):
163         """
164         Sets up the multicast and starts the packet checker
165         :return:
166         """
167         # Kill any other process running from previous failed execution
168         self.res_dir = common.get_result_dir()
169         pids = self._get_pids()
170         for pid in pids:
171             # os.kill(pid, signal.SIGTERM)
172             command = 'sudo kill ' + str(pid)
173             common.run_command(command)
174
175         # initialization of the VLAN interface
176         command = "sudo ip link add link "
177         command += self.interface_name
178         command += " name "
179         command += self.interface_name + '.' + self.params[VLAN_RECEIVER]
180         command += " type vlan id " + self.params[VLAN_RECEIVER]
181         common.run_command(command)
182
183         # set up the new
184         command = 'sudo ifconfig ' + self.interface_name + '.' + \
185                   self.params[VLAN_RECEIVER]
186         # An IP address is required for the interface to receive a multicast
187         # flow. The specific address is not important
188         command += ' 10.254.254.254 up netmask 255.255.255.248'
189         common.run_command(command)
190
191         command = "sudo ifconfig "
192         command += self.interface_name + "." + self.params[VLAN_RECEIVER]
193         command += " promisc"
194         common.run_command(command)
195
196         # configure smcroute
197         command = "sudo echo 'mgroup from "
198         command += self.interface_name + '.' + self.params[VLAN_RECEIVER]
199         command += " group "
200         command += MULTICAST_GROUP
201         command += "' > /etc/smcroute.conf"
202         common.run_command(command)
203
204         # run smcroute on the interface
205         command = 'sudo smcroute -d'
206         common.run_command(command)
207         time.sleep(3)
208
209         # Start the packet checker
210         current_dir = os.path.dirname(os.path.realpath(__file__))
211         dir_list = self.pkt_checker_command.split('/')
212         directory = os.pathsep.join(dir_list[0:len(dir_list) - 1])
213         os.chdir(directory)
214         command = "make"
215         common.run_command(command)
216         os.chdir(current_dir)
217
218         command = "sudo chmod +x {}".format(self.pkt_checker_command)
219         common.run_command(command)
220
221         command = 'sudo ' + self.pkt_checker_command
222         command += self.interface_name + '.' + self.params[VLAN_RECEIVER]
223         command += ' 128'
224         command += ' &'
225         common.run_command(command)
226
227     def _finalize_packet_checker(self):
228         """
229         Obtains the PID of the packet checker and sends an alarm to
230         terminate it
231         :return: None
232         """
233         pids = self._get_pids()
234         for pid in pids:
235             # os.kill(pid, signal.SIGTERM)
236             command = 'sudo kill ' + str(pid)
237             common.run_command(command)
238
239         # stop smcroute on the interface
240         command = 'sudo smcroute -k'
241         common.run_command(command)
242
243         # finalization of the VLAN interface
244         command = "sudo ip link delete "
245         command += self.interface_name + '.' + self.params[VLAN_RECEIVER]
246         common.run_command(command)
247
248     def _get_pids(self):
249         """
250         Returns a list of integers containing the pid or the pids of the
251         processes currently running on the host
252         :return: type: list of int
253         """
254         output = subprocess.check_output(
255             'pgrep "{}"'.format(PACKET_CHECKER_PROGRAM_NAME))
256         if not output:
257             pids = []
258         else:
259             pids = [int(x) for x in output.splitlines()]
260         return pids