Merge "ixia: VLAN support without l3/l4 headers"
[vswitchperf.git] / core / traffic_controller.py
1 # Copyright 2015-2016 Intel Corporation.
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 """Base class for traffic controllers
16 """
17
18 import logging
19 import os
20 import time
21
22 from core.results.results_constants import ResultsConstants
23 from conf import settings
24
25 class TrafficController(object):
26     """Base class which defines a common functionality for all traffic
27        controller classes.
28
29     Used to setup and control a traffic generator for a particular deployment
30     scenario.
31     """
32     def __init__(self, traffic_gen_class):
33         """Initialization common for all types of traffic controllers
34
35         :param traffic_gen_class: The traffic generator class to be used.
36         """
37         self._type = None
38         self._logger = logging.getLogger(__name__)
39         self._logger.debug("__init__")
40         self._traffic_gen_class = traffic_gen_class()
41         self._traffic_started = False
42         self._traffic_started_call_count = 0
43         self._duration = int(settings.getValue('TRAFFICGEN_DURATION'))
44         self._lossrate = float(settings.getValue('TRAFFICGEN_LOSSRATE'))
45         self._packet_sizes = settings.getValue('TRAFFICGEN_PKT_SIZES')
46
47         self._mode = settings.getValue('mode').lower()
48         self._results = []
49
50     def __enter__(self):
51         """Call initialisation function.
52         """
53         self._traffic_gen_class.connect()
54
55     def __exit__(self, type_, value, traceback):
56         """Stop traffic, clean up.
57         """
58         if self._traffic_started:
59             self.stop_traffic()
60
61     def _append_results(self, result_dict, packet_size):
62         """Adds common values to traffic generator results.
63
64         :param result_dict: Dictionary containing results from trafficgen
65         :param packet_size: Packet size value.
66
67         :returns: dictionary of results with additional entries.
68         """
69
70         ret_value = result_dict
71
72         ret_value[ResultsConstants.TYPE] = self._type
73         ret_value[ResultsConstants.PACKET_SIZE] = str(packet_size)
74
75         return ret_value
76
77     def traffic_required(self):
78         """Checks selected '--mode' of traffic generator and performs
79            its specific handling.
80
81         :returns: True - in case that traffic generator should be executed
82                   False - if traffic generation is not required
83         """
84         if self._mode == 'trafficgen-off':
85             time.sleep(2)
86             self._logger.debug("All is set. Please run traffic generator manually.")
87             input(os.linesep + "Press Enter to terminate vswitchperf..." +
88                   os.linesep + os.linesep)
89             return False
90         elif self._mode == 'trafficgen-pause':
91             time.sleep(2)
92             while True:
93                 choice = input(os.linesep + 'Transmission paused, should'
94                                ' transmission be resumed? [y/n]' + os.linesep).lower()
95                 if choice in ('yes', 'y', 'ye'):
96                     return True
97                 elif choice in ('no', 'n'):
98                     self._logger.info("Traffic transmission will be skipped.")
99                     return False
100                 else:
101                     print("Please respond with 'yes', 'y', 'no' or 'n' ", end='')
102         return True
103
104     def send_traffic(self, dummy_traffic):
105         """Triggers traffic to be sent from the traffic generator.
106
107         This is a blocking function.
108
109         :param traffic: A dictionary describing the traffic to send.
110         """
111         raise NotImplementedError(
112             "The TrafficController does not implement",
113             "the \"send_traffic\" function.")
114
115     def send_traffic_async(self, dummy_traffic, dummy_function):
116         """Triggers traffic to be sent  asynchronously.
117
118         This is not a blocking function.
119
120         :param traffic: A dictionary describing the traffic to send.
121         :param function: A dictionary describing the function to call between
122              send and wait in the form:
123              function = {
124                  'function' : package.module.function,
125                  'args' : args
126              }
127              If this function requires more than one argument, all should be
128              should be passed using the args list and appropriately handled.
129          """
130         raise NotImplementedError(
131             "The TrafficController does not implement",
132             "the \"send_traffic_async\" function.")
133
134     def stop_traffic(self):
135         """Kills traffic being sent from the traffic generator.
136         """
137         self._logger.debug("stop_traffic()")
138
139     def print_results(self):
140         """IResult interface implementation.
141         """
142         counter = 0
143         for item in self._results:
144             logging.info("Record: " + str(counter))
145             counter += 1
146             for(key, value) in list(item.items()):
147                 logging.info("         Key: " + str(key) +
148                              ", Value: " + str(value))
149
150     def get_results(self):
151         """IResult interface implementation.
152         """
153         return self._results
154
155     def validate_send_traffic(self, dummy_result, dummy_traffic):
156         """Verify that send traffic has succeeded
157         """
158         if len(self._results):
159             if 'b2b_frames' in self._results[-1]:
160                 return float(self._results[-1]['b2b_frames']) > 0
161             elif 'throughput_rx_fps' in self._results[-1]:
162                 return float(self._results[-1]['throughput_rx_fps']) > 0
163             else:
164                 return True
165         else:
166             return False