1 # Copyright 2016 Cisco Systems, Inc. All rights reserved.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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
15 from nfvbench.log import LOG
16 from traffic_base import AbstractTrafficGenerator
17 import traffic_utils as utils
20 class DummyTG(AbstractTrafficGenerator):
21 """Experimental dummy traffic generator.
23 This traffic generator will pretend to generate traffic and return fake data.
24 Useful for unit testing without actually generating any traffic.
27 def __init__(self, traffic_client):
28 AbstractTrafficGenerator.__init__(self, traffic_client)
31 self.l2_frame_size = 0
32 self.duration_sec = traffic_client.config.duration_sec
33 self.intf_speed = traffic_client.generator_config.intf_speed
34 self.set_response_curve()
35 self.packet_list = None
37 def get_version(self):
40 def get_tx_pps_dropped_pps(self, tx_rate):
41 """Get actual tx packets based on requested tx rate.
43 :param tx_rate: requested TX rate with unit ('40%', '1Mbps', '1000pps')
45 :return: the actual TX pps and the dropped pps corresponding to the requested TX rate
47 dr, tx = self.__get_dr_actual_tx(tx_rate)
48 actual_tx_bps = utils.load_to_bps(tx, self.intf_speed)
49 avg_packet_size = utils.get_average_packet_size(self.l2_frame_size)
50 tx_packets = utils.bps_to_pps(actual_tx_bps, avg_packet_size)
52 dropped = tx_packets * dr / 100
53 # print '===get_tx_pkts_dropped_pkts req tex=', tx_rate, 'dr=', dr,
54 # 'actual tx rate=', tx, 'actual tx pkts=', tx_packets, 'dropped=', dropped
55 return int(tx_packets), int(dropped)
57 def set_response_curve(self, lr_dr=0, ndr=100, max_actual_tx=100, max_11_tx=100):
58 """Set traffic gen response characteristics.
60 Specifies the drop rate curve and the actual TX curve
61 :param float lr_dr: The actual drop rate at TX line rate (in %, 0..100)
62 :param float ndr: The true NDR (0 packet drop) in % (0..100) of line rate"
63 :param float max_actual_tx: highest actual TX when requested TX is 100%
64 :param float max_11_tx: highest requested TX that results in same actual TX
68 self.dr_slope = float(lr_dr) / (100 - ndr)
71 self.max_11_tx = max_11_tx
72 self.max_actual_tx = max_actual_tx
74 self.tx_slope = float(max_actual_tx - max_11_tx) / (100 - max_11_tx)
78 def __get_dr_actual_tx(self, requested_tx_rate):
79 """Get drop rate at given requested tx rate.
81 :param float requested_tx_rate: requested tx rate in % (0..100)
82 :return: the drop rate and actual tx rate at that requested_tx_rate in % (0..100)
84 if requested_tx_rate <= self.max_11_tx:
85 actual_tx = requested_tx_rate
87 actual_tx = self.max_11_tx + (requested_tx_rate - self.max_11_tx) * self.tx_slope
88 if actual_tx <= self.target_ndr:
91 dr = (actual_tx - self.target_ndr) * self.dr_slope
95 ports = list(self.traffic_client.generator_config.ports)
96 self.port_handle = ports
98 def create_traffic(self, l2frame_size, rates, bidirectional, latency=True):
99 self.rates = [utils.to_rate_str(rate) for rate in rates]
100 self.l2_frame_size = l2frame_size
102 def clear_streamblock(self):
106 """Get stats from current run.
108 The binary search mainly looks at 2 results to make the decision:
110 actual rx dropped packets
111 From the Requested TX rate - we get the Actual TX rate and the RX drop rate
112 From the Run duration and actual TX rate - we get the actual total tx packets
113 From the Actual tx packets and RX drop rate - we get the RX dropped packets
118 # use dummy values for all other result field as the goal is to
119 # test the ndr/pdr convergence code
120 for idx, ph in enumerate(self.port_handle):
121 requested_tx_rate = utils.get_load_from_rate(self.rates[idx])
122 tx_pps, dropped_pps = self.get_tx_pps_dropped_pps(requested_tx_rate)
124 # total packets sent per direction - used by binary search
125 total_pkts = tx_pps * self.duration_sec
126 dropped_pkts = dropped_pps * self.duration_sec
127 _, tx_pkt_rate = self.__get_dr_actual_tx(requested_tx_rate)
130 'total_pkts': total_pkts,
131 'total_pkt_bytes': 100000,
132 'pkt_rate': tx_pkt_rate,
133 'pkt_bit_rate': 1000000
136 # total packets received
137 'total_pkts': total_pkts - dropped_pkts,
138 'total_pkt_bytes': 100000,
140 'pkt_bit_rate': 1000000,
141 'dropped_pkts': dropped_pkts
144 result[ph]['rx']['max_delay_usec'] = 10.0
145 result[ph]['rx']['min_delay_usec'] = 1.0
146 result[ph]['rx']['avg_delay_usec'] = 2.0
147 total_tx_pps += tx_pps
148 # actual total tx rate in pps
149 result['total_tx_rate'] = total_tx_pps
152 def get_stream_stats(self, tg_stats, if_stats, latencies, chain_idx):
153 for port in range(2):
154 if_stats[port].tx = 1000
155 if_stats[port].rx = 1000
156 latencies[port].min_usec = 10
157 latencies[port].max_usec = 100
158 latencies[port].avg_usec = 50
161 return ['00:00:00:00:00:01', '00:00:00:00:00:02']
163 def get_port_speed_gbps(self):
164 """Return the local port speeds.
166 return: a list of speed in Gbps indexed by the port#
170 def clear_stats(self):
173 def start_traffic(self):
176 def fetch_capture_packets(self):
177 def _get_packet_capture(mac):
178 # convert text to binary
179 src_mac = mac.replace(':', '').decode('hex')
180 return {'binary': 'SSSSSS' + src_mac}
182 # for packet capture, generate 2*scc random packets
183 # normally we should generate packets coming from the right dest macs
184 self.packet_list = []
185 for dest_macs in self.traffic_client.generator_config.get_dest_macs():
186 for mac in dest_macs:
187 self.packet_list.append(_get_packet_capture(mac))
189 def stop_traffic(self):
192 def start_capture(self):
195 def stop_capture(self):
204 def resolve_arp(self):
205 """Resolve ARP sucessfully."""
206 def get_macs(port, scc):
207 return ['00:00:00:00:%02x:%02x' % (port, chain) for chain in range(scc)]
208 scc = self.traffic_client.generator_config.service_chain_count
209 res = [get_macs(port, scc) for port in range(2)]
210 LOG.info('Dummy TG ARP: %s', str(res))