# under the License.
"""Interface to the traffic generator clients including NDR/PDR binary search."""
-
from math import gcd
import socket
import struct
from attrdict import AttrDict
import bitmath
+from hdrh.histogram import HdrHistogram
from netaddr import IPNetwork
# pylint: disable=import-error
from trex.stl.api import Ether
else:
self.ip_block = IpBlock(self.ip, step, self.ip_size)
- if generator_config.gen_config.udp_port_step == 'random':
- step = 1
- else:
- step = generator_config.gen_config.udp_port_step
- self.udp_ports = UdpPorts(src_min, src_max, dst_min, dst_max, step)
+ self.udp_ports = UdpPorts(src_min, src_max, dst_min, dst_max,
+ generator_config.gen_config.udp_port_step)
self.gw_ip_block = IpBlock(generator_config.gateway_ips[port],
generator_config.gateway_ip_addrs_step,
self.chain_count)
value = int((ip_size / step)) + 1
return value
except ZeroDivisionError:
- raise ZeroDivisionError("step can't be zero !")
+ raise ZeroDivisionError("step can't be zero !") from ZeroDivisionError
def set_mac(self, mac):
"""Set the local MAC for this port device."""
self.cores = config.cores
else:
self.cores = gen_config.get('cores', 1)
+ # let's report the value actually used in the end
+ config.cores_used = self.cores
self.mbuf_factor = config.mbuf_factor
self.mbuf_64 = config.mbuf_64
self.hdrh = not config.disable_hdrh
- if gen_config.intf_speed:
- # interface speed is overriden from config
- self.intf_speed = bitmath.parse_string(gen_config.intf_speed.replace('ps', '')).bits
+ if config.intf_speed:
+ # interface speed is overriden from the command line
+ self.intf_speed = config.intf_speed
+ elif gen_config.intf_speed:
+ # interface speed is overriden from the generator config
+ self.intf_speed = gen_config.intf_speed
else:
+ self.intf_speed = "auto"
+ if self.intf_speed == "auto" or self.intf_speed == "0":
# interface speed is discovered/provided by the traffic generator
self.intf_speed = 0
+ else:
+ self.intf_speed = bitmath.parse_string(self.intf_speed.replace('ps', '')).bits
self.name = gen_config.name
self.zmq_pub_port = gen_config.get('zmq_pub_port', 4500)
self.zmq_rpc_port = gen_config.get('zmq_rpc_port', 4501)
# interface speed is overriden from config
if self.intf_speed != tg_if_speed:
# Warn the user if the speed in the config is different
- LOG.warning('Interface speed provided is different from actual speed (%d Gbps)',
- intf_speeds[0])
+ LOG.warning(
+ 'Interface speed provided (%g Gbps) is different from actual speed (%d Gbps)',
+ self.intf_speed / 1000000000.0, intf_speeds[0])
else:
# interface speed not provisioned by config
self.intf_speed = tg_if_speed
# also update the speed in the tg config
self.generator_config.intf_speed = tg_if_speed
+ # let's report detected and actually used interface speed
+ self.config.intf_speed_detected = tg_if_speed
+ self.config.intf_speed_used = self.intf_speed
# Save the traffic generator local MAC
for mac, device in zip(self.gen.get_macs(), self.generator_config.devices):
if self.config.no_latency_streams:
LOG.info("Latency streams are disabled")
+ # in service mode, we must disable flow stats (e2e=True)
self.gen.create_traffic(frame_size, self.run_config['rates'], bidirectional,
- latency=not self.config.no_latency_streams)
+ latency=not self.config.no_latency_streams,
+ e2e=self.runner.service_mode)
def _modify_load(self, load):
self.current_total_rate = {'rate_percent': str(load)}
def get_stats(self):
"""Collect final stats for previous run."""
- stats = self.gen.get_stats()
- retDict = {'total_tx_rate': stats['total_tx_rate']}
+ stats = self.gen.get_stats(self.ifstats)
+ retDict = {'total_tx_rate': stats['total_tx_rate'],
+ 'offered_tx_rate_bps': stats['offered_tx_rate_bps'],
+ 'theoretical_tx_rate_bps': stats['theoretical_tx_rate_bps'],
+ 'theoretical_tx_rate_pps': stats['theoretical_tx_rate_pps']}
tx_keys = ['total_pkts', 'total_pkt_bytes', 'pkt_rate', 'pkt_bit_rate']
rx_keys = tx_keys + ['dropped_pkts']
for key in ['pkt_bit_rate', 'pkt_rate']:
for dirc in ['tx', 'rx']:
retDict['overall'][dirc][key] /= 2.0
+ retDict['overall']['hdrh'] = stats.get('hdrh', None)
+ if retDict['overall']['hdrh']:
+ decoded_histogram = HdrHistogram.decode(retDict['overall']['hdrh'])
+ # override min max and avg from hdrh
+ retDict['overall']['rx']['min_delay_usec'] = decoded_histogram.get_min_value()
+ retDict['overall']['rx']['max_delay_usec'] = decoded_histogram.get_max_value()
+ retDict['overall']['rx']['avg_delay_usec'] = decoded_histogram.get_mean_value()
+ retDict['overall']['rx']['lat_percentile'] = {}
+ for percentile in self.config.lat_percentiles:
+ retDict['overall']['rx']['lat_percentile'][percentile] = \
+ decoded_histogram.get_value_at_percentile(percentile)
+
else:
retDict['overall'] = retDict[ports[0]]
retDict['overall']['drop_rate_percent'] = self.__get_dropped_rate(retDict['overall'])
'min_delay_usec': interface['rx']['min_delay_usec'],
}
+ if key == 'overall':
+ stats[key]['hdrh'] = interface.get('hdrh', None)
+ if stats[key]['hdrh']:
+ decoded_histogram = HdrHistogram.decode(stats[key]['hdrh'])
+ # override min max and avg from hdrh
+ stats[key]['min_delay_usec'] = decoded_histogram.get_min_value()
+ stats[key]['max_delay_usec'] = decoded_histogram.get_max_value()
+ stats[key]['avg_delay_usec'] = decoded_histogram.get_mean_value()
+ stats[key]['lat_percentile'] = {}
+ for percentile in self.config.lat_percentiles:
+ stats[key]['lat_percentile'][percentile] = decoded_histogram.\
+ get_value_at_percentile(percentile)
+
+
return stats
def __targets_found(self, rate, targets, results):
for chain_idx in range(self.config.service_chain_count)]
# note that we need to make a copy of the ifs list so that any modification in the
# list from pps will not change the list saved in self.ifstats
- self.pps_list = [PacketPathStats(list(ifs)) for ifs in self.ifstats]
+ self.pps_list = [PacketPathStats(self.config, list(ifs)) for ifs in self.ifstats]
# insert the corresponding pps in the passed list
pps_list.extend(self.pps_list)
]
"""
if diff:
- stats = self.gen.get_stats()
+ stats = self.gen.get_stats(self.ifstats)
for chain_idx, ifs in enumerate(self.ifstats):
# each ifs has exactly 2 InterfaceStats and 2 Latency instances
# corresponding to the