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
17 from nfvbench.utils import multiplier_map
19 imix_avg_l2_size = None
22 def convert_rates(l2frame_size, rate, intf_speed):
23 """Convert a given rate unit into the other rate units.
25 l2frame_size: size of the L2 frame in bytes or 'IMIX'
26 rate: a dict that has at least one of the following key:
27 'rate_pps', 'rate_bps', 'rate_percent'
28 with the corresponding input value
29 intf_speed: the line rate speed in bits per second
31 avg_packet_size = get_average_packet_size(l2frame_size)
32 if 'rate_pps' in rate:
34 initial_rate_type = 'rate_pps'
35 pps = rate['rate_pps']
36 bps = pps_to_bps(pps, avg_packet_size)
37 load = bps_to_load(bps, intf_speed)
38 elif 'rate_bps' in rate:
39 # input = bits per second
40 initial_rate_type = 'rate_bps'
41 bps = rate['rate_bps']
42 load = bps_to_load(bps, intf_speed)
43 pps = bps_to_pps(bps, avg_packet_size)
44 elif 'rate_percent' in rate:
45 # input = percentage of the line rate (between 0.0 and 100.0)
46 initial_rate_type = 'rate_percent'
47 load = rate['rate_percent']
48 bps = load_to_bps(load, intf_speed)
49 pps = bps_to_pps(bps, avg_packet_size)
51 raise Exception('Traffic config needs to have a rate type key')
54 'initial_rate_type': initial_rate_type,
61 def get_average_packet_size(l2frame_size):
62 if l2frame_size.upper() == 'IMIX':
63 return imix_avg_l2_size
64 return float(l2frame_size)
67 def load_to_bps(load_percentage, intf_speed):
68 return float(load_percentage) / 100.0 * intf_speed
71 def bps_to_load(bps, intf_speed):
72 return float(bps) / intf_speed * 100.0
75 def bps_to_pps(bps, avg_packet_size):
76 return float(bps) / (avg_packet_size + 20.0) / 8
79 def pps_to_bps(pps, avg_packet_size):
80 return float(pps) * (avg_packet_size + 20.0) * 8
83 def weighted_avg(weight, count):
86 return sum([x[0] * x[1] for x in zip(weight, count)]) / sum(weight)
89 def _get_bitmath_rate(rate_bps):
90 rate = rate_bps.replace('ps', '').strip()
91 bitmath_rate = bitmath.parse_string(rate)
92 if bitmath_rate.bits <= 0:
93 raise Exception('%s is out of valid range' % rate_bps)
96 def parse_rate_str(rate_str):
97 if rate_str.endswith('pps'):
98 rate_pps = rate_str[:-3]
100 raise Exception('%s is missing a numeric value' % rate_str)
102 multiplier = multiplier_map[rate_pps[-1].upper()]
103 rate_pps = rate_pps[:-1]
106 rate_pps = int(rate_pps.strip()) * multiplier
108 raise Exception('%s is out of valid range' % rate_str)
109 return {'rate_pps': str(rate_pps)}
110 elif rate_str.endswith('ps'):
111 rate = rate_str.replace('ps', '').strip()
112 bit_rate = bitmath.parse_string(rate).bits
114 raise Exception('%s is out of valid range' % rate_str)
115 return {'rate_bps': str(int(bit_rate))}
116 elif rate_str.endswith('%'):
117 rate_percent = float(rate_str.replace('%', '').strip())
118 if rate_percent <= 0 or rate_percent > 100.0:
119 raise Exception('%s is out of valid range (must be 1-100%%)' % rate_str)
120 return {'rate_percent': str(rate_percent)}
122 raise Exception('Unknown rate string format %s' % rate_str)
124 def get_load_from_rate(rate_str, avg_frame_size=64, line_rate='10Gbps'):
125 '''From any rate string (with unit) return the corresponding load (in % unit)
127 :param str rate_str: the rate to convert - must end with a unit (e.g. 1Mpps, 30%, 1Gbps)
128 :param int avg_frame_size: average frame size in bytes (needed only if pps is given)
129 :param str line_rate: line rate ending with bps unit (e.g. 1Mbps, 10Gbps) is the rate that
130 corresponds to 100% rate
131 :return float: the corresponding rate in % of line rate
133 rate_dict = parse_rate_str(rate_str)
134 if 'rate_percent' in rate_dict:
135 return float(rate_dict['rate_percent'])
136 lr_bps = _get_bitmath_rate(line_rate).bits
137 if 'rate_bps' in rate_dict:
138 bps = int(rate_dict['rate_bps'])
141 pps = rate_dict['rate_pps']
142 bps = pps_to_bps(pps, avg_frame_size)
143 return bps_to_load(bps, lr_bps)
145 def divide_rate(rate, divisor):
146 if 'rate_pps' in rate:
148 value = int(rate[key])
149 elif 'rate_bps' in rate:
151 value = int(rate[key])
154 value = float(rate[key])
157 rate[key] = str(value) if value else str(1)
161 def to_rate_str(rate):
162 if 'rate_pps' in rate:
163 pps = rate['rate_pps']
164 return '{}pps'.format(pps)
165 elif 'rate_bps' in rate:
166 bps = rate['rate_bps']
167 return '{}bps'.format(bps)
168 elif 'rate_percent' in rate:
169 load = rate['rate_percent']
170 return '{}%'.format(load)
172 # avert pylint warning
177 """Replaces every occurence of 'N/A' with float nan."""
178 for k, v in d.iteritems():
179 if isinstance(v, dict):
186 """Converts MAC address to integer representation."""
187 return int(mac.translate(None, ":.- "), 16)
191 """Converts integer representation of MAC address to hex string."""
192 mac = format(i, 'x').zfill(12)
193 blocks = [mac[x:x + 2] for x in xrange(0, len(mac), 2)]
194 return ':'.join(blocks)