diff options
Diffstat (limited to 'nfvbench/traffic_gen/traffic_utils.py')
-rw-r--r-- | nfvbench/traffic_gen/traffic_utils.py | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/nfvbench/traffic_gen/traffic_utils.py b/nfvbench/traffic_gen/traffic_utils.py new file mode 100644 index 0000000..e5dc463 --- /dev/null +++ b/nfvbench/traffic_gen/traffic_utils.py @@ -0,0 +1,160 @@ +# Copyright 2016 Cisco Systems, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +import bitmath +from traffic_base import AbstractTrafficGenerator + + +def convert_rates(l2frame_size, rate, intf_speed): + avg_packet_size = get_average_packet_size(l2frame_size) + if 'rate_pps' in rate: + 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: + 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: + initial_rate_type = 'rate_percent' + load = rate['rate_percent'] + bps = load_to_bps(load, intf_speed) + pps = bps_to_pps(bps, avg_packet_size) + else: + raise Exception('Traffic config needs to have a rate type key') + + return { + 'initial_rate_type': initial_rate_type, + 'rate_pps': pps, + 'rate_percent': load, + 'rate_bps': bps + } + + +def get_average_packet_size(l2frame_size): + if l2frame_size.upper() == 'IMIX': + return AbstractTrafficGenerator.imix_avg_l2_size + else: + return float(l2frame_size) + + +def load_to_bps(load_percentage, intf_speed): + return float(load_percentage) / 100.0 * intf_speed + + +def bps_to_load(bps, intf_speed): + return float(bps) / intf_speed * 100.0 + + +def bps_to_pps(bps, avg_packet_size): + return float(bps) / (avg_packet_size + 20.0) / 8 + + +def pps_to_bps(pps, avg_packet_size): + return float(pps) * (avg_packet_size + 20.0) * 8 + + +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 +} + +def parse_rate_str(rate_str): + if rate_str.endswith('pps'): + rate_pps = rate_str[:-3] + if not rate_pps: + raise Exception('%s is missing a numeric value' % rate_str) + try: + multiplier = multiplier_map[rate_pps[-1].upper()] + rate_pps = rate_pps[:-1] + except KeyError: + multiplier = 1 + rate_pps = int(rate_pps.strip()) * multiplier + if rate_pps <= 0: + raise Exception('%s is out of valid range' % rate_str) + return {'rate_pps': str(rate_pps)} + elif rate_str.endswith('ps'): + rate = rate_str.replace('ps', '').strip() + bit_rate = bitmath.parse_string(rate).bits + if bit_rate <= 0: + raise Exception('%s is out of valid range' % rate_str) + return {'rate_bps': str(int(bit_rate))} + elif rate_str.endswith('%'): + rate_percent = float(rate_str.replace('%', '').strip()) + if rate_percent <= 0 or rate_percent > 100.0: + raise Exception('%s is out of valid range (must be 1-100%%)' % rate_str) + return {'rate_percent': str(rate_percent)} + else: + raise Exception('Unknown rate string format %s' % rate_str) + + +def divide_rate(rate, divisor): + if 'rate_pps' in rate: + key = 'rate_pps' + value = int(rate[key]) + elif 'rate_bps' in rate: + key = 'rate_bps' + value = int(rate[key]) + else: + key = 'rate_percent' + value = float(rate[key]) + value /= divisor + rate = dict(rate) + rate[key] = str(value) if value else str(1) + return rate + + +def to_rate_str(rate): + if 'rate_pps' in rate: + pps = rate['rate_pps'] + return '{}pps'.format(pps) + elif 'rate_bps' in rate: + bps = rate['rate_bps'] + return '{}bps'.format(bps) + elif 'rate_percent' in rate: + load = rate['rate_percent'] + return '{}%'.format(load) + else: + assert False + + +def nan_replace(d): + """Replaces every occurence of 'N/A' with float nan.""" + for k, v in d.iteritems(): + if isinstance(v, dict): + nan_replace(v) + elif v == 'N/A': + d[k] = float('nan') + + +def mac_to_int(mac): + """Converts MAC address to integer representation.""" + return int(mac.translate(None, ":.- "), 16) + + +def int_to_mac(i): + """Converts integer representation of MAC address to hex string.""" + mac = format(i, 'x').zfill(12) + blocks = [mac[x:x + 2] for x in xrange(0, len(mac), 2)] + return ':'.join(blocks) |