NFVBENCH-56 Multi-chaining traffic starts may be too early for some runs
[nfvbench.git] / nfvbench / traffic_gen / dummy.py
1 # Copyright 2016 Cisco Systems, Inc.  All rights reserved.
2 #
3 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
4 #    not use this file except in compliance with the License. You may obtain
5 #    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, WITHOUT
11 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 #    License for the specific language governing permissions and limitations
13 #    under the License.
14
15 from traffic_base import AbstractTrafficGenerator
16 import traffic_utils as utils
17
18
19 class DummyTG(AbstractTrafficGenerator):
20     """Experimental dummy traffic generator.
21
22     This traffic generator will pretend to generate traffic and return fake data.
23     Useful for unit testing without actually generating any traffic.
24     """
25
26     def __init__(self, config):
27         AbstractTrafficGenerator.__init__(self, config)
28         self.port_handle = []
29         self.rates = []
30         self.l2_frame_size = 0
31         self.duration_sec = self.config.duration_sec
32         self.intf_speed = config.generator_config.intf_speed
33         self.set_response_curve()
34         self.packet_list = [{
35             "binary": "01234567890123456789"
36         }, {
37             "binary": "98765432109876543210"
38         }]
39
40     def get_version(self):
41         return "0.1"
42
43     def init(self):
44         pass
45
46     def get_tx_pps_dropped_pps(self, tx_rate):
47         '''Get actual tx packets based on requested tx rate
48
49         :param tx_rate: requested TX rate with unit ('40%', '1Mbps', '1000pps')
50
51         :return: the actual TX pps and the dropped pps corresponding to the requested TX rate
52         '''
53         dr, tx = self.__get_dr_actual_tx(tx_rate)
54         actual_tx_bps = utils.load_to_bps(tx, self.intf_speed)
55         avg_packet_size = utils.get_average_packet_size(self.l2_frame_size)
56         tx_packets = utils.bps_to_pps(actual_tx_bps, avg_packet_size)
57
58         dropped = tx_packets * dr / 100
59         # print '===get_tx_pkts_dropped_pkts req tex=', tx_rate, 'dr=', dr,
60         # 'actual tx rate=', tx, 'actual tx pkts=', tx_packets, 'dropped=', dropped
61         return int(tx_packets), int(dropped)
62
63     def set_response_curve(self, lr_dr=0, ndr=100, max_actual_tx=100, max_11_tx=100):
64         '''Set traffic gen response characteristics
65
66         Specifies the drop rate curve and the actual TX curve
67         :param float lr_dr: The actual drop rate at TX line rate (in %, 0..100)
68         :param float ndr: The true NDR  (0 packet drop) in % (0..100) of line rate"
69         :param float max_actual_tx: highest actual TX when requested TX is 100%
70         :param float max_11_tx: highest requested TX that results in same actual TX
71         '''
72         self.target_ndr = ndr
73         if ndr < 100:
74             self.dr_slope = float(lr_dr) / (100 - ndr)
75         else:
76             self.dr_slope = 0
77         self.max_11_tx = max_11_tx
78         self.max_actual_tx = max_actual_tx
79         if max_11_tx < 100:
80             self.tx_slope = float(max_actual_tx - max_11_tx) / (100 - max_11_tx)
81         else:
82             self.tx_slope = 0
83
84     def __get_dr_actual_tx(self, requested_tx_rate):
85         '''Get drop rate at given requested tx rate
86         :param float requested_tx_rate: requested tx rate in % (0..100)
87         :return: the drop rate and actual tx rate at that requested_tx_rate in % (0..100)
88         '''
89         if requested_tx_rate <= self.max_11_tx:
90             actual_tx = requested_tx_rate
91         else:
92             actual_tx = self.max_11_tx + (requested_tx_rate - self.max_11_tx) * self.tx_slope
93         if actual_tx <= self.target_ndr:
94             dr = 0.0
95         else:
96             dr = (actual_tx - self.target_ndr) * self.dr_slope
97         return dr, actual_tx
98
99     def connect(self):
100         ports = list(self.config.generator_config.ports)
101         self.port_handle = ports
102
103     def is_arp_successful(self):
104         return True
105
106     def config_interface(self):
107         pass
108
109     def create_traffic(self, l2frame_size, rates, bidirectional, latency=True):
110         self.rates = [utils.to_rate_str(rate) for rate in rates]
111         self.l2_frame_size = l2frame_size
112
113     def clear_streamblock(self):
114         pass
115
116     def get_stats(self):
117         '''Get stats from current run.
118
119         The binary search mainly looks at 2 results to make the decision:
120             actual tx packets
121             actual rx dropped packets
122         From the Requested TX rate - we get the Actual TX rate and the RX drop rate
123         From the Run duration and actual TX rate - we get the actual total tx packets
124         From the Actual tx packets and RX drop rate - we get the RX dropped packets
125         '''
126         result = {}
127         total_tx_pps = 0
128
129         # use dummy values for all other result field as the goal is to
130         # test the ndr/pdr convergence code
131         for idx, ph in enumerate(self.port_handle):
132             requested_tx_rate = utils.get_load_from_rate(self.rates[idx])
133             tx_pps, dropped_pps = self.get_tx_pps_dropped_pps(requested_tx_rate)
134
135             # total packets sent per direction - used by binary search
136             total_pkts = tx_pps * self.duration_sec
137             dropped_pkts = dropped_pps * self.duration_sec
138             _, tx_pkt_rate = self.__get_dr_actual_tx(requested_tx_rate)
139             result[ph] = {
140                 'tx': {
141                     'total_pkts': total_pkts,
142                     'total_pkt_bytes': 100000,
143                     'pkt_rate': tx_pkt_rate,
144                     'pkt_bit_rate': 1000000
145                 },
146                 'rx': {
147                     # total packets received
148                     'total_pkts': total_pkts - dropped_pkts,
149                     'total_pkt_bytes': 100000,
150                     'pkt_rate': 100,
151                     'pkt_bit_rate': 1000000,
152                     'dropped_pkts': dropped_pkts
153                 }
154             }
155             result[ph]['rx']['max_delay_usec'] = 10.0
156             result[ph]['rx']['min_delay_usec'] = 1.0
157             result[ph]['rx']['avg_delay_usec'] = 2.0
158             total_tx_pps += tx_pps
159         # actual total tx rate in pps
160         result['total_tx_rate'] = total_tx_pps
161         return result
162
163     def get_macs(self):
164         return ['00.00.00.00.00.01', '00.00.00.00.00.02']
165
166     def clear_stats(self):
167         pass
168
169     def start_traffic(self):
170         pass
171
172     def fetch_capture_packets(self):
173         pass
174
175     def stop_traffic(self):
176         pass
177
178     def start_capture(self):
179         pass
180
181     def stop_capture(self):
182         pass
183
184     def cleanup(self):
185         pass
186
187     def set_mode(self):
188         pass
189
190     def resolve_arp(self):
191         return True