import bitmath
-from traffic_base import AbstractTrafficGenerator
+from nfvbench.utils import multiplier_map
+
+# IMIX frame size including the 4-byte FCS field
+IMIX_L2_SIZES = [64, 594, 1518]
+IMIX_RATIOS = [7, 4, 1]
+# weighted average l2 frame size includng the 4-byte FCS
+IMIX_AVG_L2_FRAME_SIZE = sum(
+ [1.0 * imix[0] * imix[1] for imix in zip(IMIX_L2_SIZES, IMIX_RATIOS)]) / sum(IMIX_RATIOS)
def convert_rates(l2frame_size, rate, intf_speed):
+ """Convert a given rate unit into the other rate units.
+
+ l2frame_size: size of the L2 frame in bytes (includes 32-bit FCS) or 'IMIX'
+ rate: a dict that has at least one of the following key:
+ 'rate_pps', 'rate_bps', 'rate_percent'
+ with the corresponding input value
+ intf_speed: the line rate speed in bits per second
+ """
avg_packet_size = get_average_packet_size(l2frame_size)
if 'rate_pps' in rate:
+ # input = packets/sec
initial_rate_type = 'rate_pps'
pps = rate['rate_pps']
bps = pps_to_bps(pps, avg_packet_size)
load = bps_to_load(bps, intf_speed)
elif 'rate_bps' in rate:
+ # input = bits per second
initial_rate_type = 'rate_bps'
bps = rate['rate_bps']
load = bps_to_load(bps, intf_speed)
pps = bps_to_pps(bps, avg_packet_size)
elif 'rate_percent' in rate:
+ # input = percentage of the line rate (between 0.0 and 100.0)
initial_rate_type = 'rate_percent'
load = rate['rate_percent']
bps = load_to_bps(load, intf_speed)
def get_average_packet_size(l2frame_size):
+ """Retrieve the average L2 frame size
+
+ l2frame_size: an L2 frame size in bytes (including FCS) or 'IMIX'
+ return: average l2 frame size inlcuding the 32-bit FCS
+ """
if l2frame_size.upper() == 'IMIX':
- return AbstractTrafficGenerator.imix_avg_l2_size
- else:
- return float(l2frame_size)
+ return IMIX_AVG_L2_FRAME_SIZE
+ return float(l2frame_size)
def load_to_bps(load_percentage, intf_speed):
def weighted_avg(weight, count):
if sum(weight):
- return sum(map(lambda x: x[0] * x[1], zip(weight, count))) / sum(weight)
- else:
- return float('nan')
-multiplier_map = {
- 'K': 1000,
- 'M': 1000000,
- 'G': 1000000000
-}
+ return sum([x[0] * x[1] for x in zip(weight, count)]) / sum(weight)
+ return float('nan')
+
+def _get_bitmath_rate(rate_bps):
+ rate = rate_bps.replace('ps', '').strip()
+ bitmath_rate = bitmath.parse_string(rate)
+ if bitmath_rate.bits <= 0:
+ raise Exception('%s is out of valid range' % rate_bps)
+ return bitmath_rate
def parse_rate_str(rate_str):
if rate_str.endswith('pps'):
else:
raise Exception('Unknown rate string format %s' % rate_str)
+def get_load_from_rate(rate_str, avg_frame_size=64, line_rate='10Gbps'):
+ '''From any rate string (with unit) return the corresponding load (in % unit)
+
+ :param str rate_str: the rate to convert - must end with a unit (e.g. 1Mpps, 30%, 1Gbps)
+ :param int avg_frame_size: average frame size in bytes (needed only if pps is given)
+ :param str line_rate: line rate ending with bps unit (e.g. 1Mbps, 10Gbps) is the rate that
+ corresponds to 100% rate
+ :return float: the corresponding rate in % of line rate
+ '''
+ rate_dict = parse_rate_str(rate_str)
+ if 'rate_percent' in rate_dict:
+ return float(rate_dict['rate_percent'])
+ lr_bps = _get_bitmath_rate(line_rate).bits
+ if 'rate_bps' in rate_dict:
+ bps = int(rate_dict['rate_bps'])
+ else:
+ # must be rate_pps
+ pps = rate_dict['rate_pps']
+ bps = pps_to_bps(pps, avg_frame_size)
+ return bps_to_load(bps, lr_bps)
def divide_rate(rate, divisor):
if 'rate_pps' in rate:
elif 'rate_percent' in rate:
load = rate['rate_percent']
return '{}%'.format(load)
- else:
- assert False
+ assert False
+ # avert pylint warning
+ return None
def nan_replace(d):