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
18 from nfvbench.log import LOG
19 from . import traffic_utils
20 from hdrh.histogram import HdrHistogram
21 from functools import reduce
24 class Latency(object):
25 """A class to hold latency data."""
27 def __init__(self, latency_list=None):
28 """Create a latency instance.
30 latency_list: aggregate all latency values from list if not None
32 self.min_usec = sys.maxsize
38 for lat in latency_list:
40 self.min_usec = min(self.min_usec, lat.min_usec)
41 self.max_usec = max(self.max_usec, lat.max_usec)
42 self.avg_usec += lat.avg_usec
43 if lat.hdrh_available():
44 hdrh_list.append(HdrHistogram.decode(lat.hdrh))
46 # aggregate histograms if any
51 decoded_hdrh = reduce(add_hdrh, hdrh_list)
52 self.hdrh = HdrHistogram.encode(decoded_hdrh).decode('utf-8')
54 # round to nearest usec
55 self.avg_usec = int(round(float(self.avg_usec) / len(latency_list)))
58 """Return True if latency information is available."""
59 return self.min_usec != sys.maxsize
61 def hdrh_available(self):
62 """Return True if latency histogram information is available."""
63 return self.hdrh is not None
65 class TrafficGeneratorException(Exception):
66 """Exception for traffic generator."""
68 class AbstractTrafficGenerator(object):
70 def __init__(self, traffic_client):
71 self.traffic_client = traffic_client
72 self.generator_config = traffic_client.generator_config
73 self.config = traffic_client.config
76 def get_version(self):
77 # Must be implemented by sub classes
82 # Must be implemented by sub classes
86 def create_traffic(self, l2frame_size, rates, bidirectional, latency=True, e2e=False):
87 # Must be implemented by sub classes
90 def modify_rate(self, rate, reverse):
91 """Change the rate per port.
93 rate: new rate in % (0 to 100)
94 reverse: 0 for port 0, 1 for port 1
96 port_index = int(reverse)
97 port = self.port_handle[port_index]
98 self.rates[port_index] = traffic_utils.to_rate_str(rate)
99 LOG.info('Modified traffic stream for port %s, new rate=%s.', port, self.rates[port_index])
102 def get_stats(self, ifstats):
103 # Must be implemented by sub classes
107 def start_traffic(self):
108 # Must be implemented by sub classes
112 def stop_traffic(self):
113 # Must be implemented by sub classes
118 """Cleanup the traffic generator."""
121 def clear_streamblock(self):
122 """Clear all streams from the traffic generator."""
125 def resolve_arp(self):
126 """Resolve all configured remote IP addresses.
128 return: None if ARP failed to resolve for all IP addresses
129 else a dict of list of dest macs indexed by port#
130 the dest macs in the list are indexed by the chain id
135 """Return the local port MAC addresses.
137 return: a list of MAC addresses indexed by the port#
141 def get_port_speed_gbps(self):
142 """Return the local port speeds.
144 return: a list of speed in Gbps indexed by the port#
147 def get_theoretical_rates(self, avg_packet_size):
151 # actual interface speed? (may be a virtual override)
152 intf_speed = self.config.intf_speed_used
154 if hasattr(self.config, 'user_info') and self.config.user_info is not None:
155 if "extra_encapsulation_bytes" in self.config.user_info:
156 frame_size_full_encapsulation = avg_packet_size + self.config.user_info[
157 "extra_encapsulation_bytes"]
158 result['theoretical_tx_rate_pps'] = traffic_utils.bps_to_pps(
159 intf_speed, frame_size_full_encapsulation) * 2
160 result['theoretical_tx_rate_bps'] = traffic_utils.pps_to_bps(
161 result['theoretical_tx_rate_pps'], avg_packet_size)
163 result['theoretical_tx_rate_pps'] = traffic_utils.bps_to_pps(intf_speed,
165 result['theoretical_tx_rate_bps'] = traffic_utils.pps_to_bps(
166 result['theoretical_tx_rate_pps'], avg_packet_size)