aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick/network_services/traffic_profile/rfc2544.py
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick/network_services/traffic_profile/rfc2544.py')
-rw-r--r--yardstick/network_services/traffic_profile/rfc2544.py164
1 files changed, 114 insertions, 50 deletions
diff --git a/yardstick/network_services/traffic_profile/rfc2544.py b/yardstick/network_services/traffic_profile/rfc2544.py
index c24e2f65a..aaa491b75 100644
--- a/yardstick/network_services/traffic_profile/rfc2544.py
+++ b/yardstick/network_services/traffic_profile/rfc2544.py
@@ -19,10 +19,11 @@ from trex_stl_lib import trex_stl_client
from trex_stl_lib import trex_stl_packet_builder_scapy
from trex_stl_lib import trex_stl_streams
+from yardstick.common import constants
from yardstick.network_services.traffic_profile import trex_traffic_profile
-LOGGING = logging.getLogger(__name__)
+LOG = logging.getLogger(__name__)
SRC_PORT = 'sport'
DST_PORT = 'dport'
@@ -52,7 +53,7 @@ class PortPgIDMap(object):
self._port_pg_id_map[port] = []
def get_pg_ids(self, port):
- return self._port_pg_id_map.get(port)
+ return self._port_pg_id_map.get(port, [])
def increase_pg_id(self, port=None):
port = self._last_port if not port else port
@@ -70,15 +71,17 @@ class PortPgIDMap(object):
class RFC2544Profile(trex_traffic_profile.TrexProfile):
"""TRex RFC2544 traffic profile"""
- TOLERANCE_LIMIT = 0.05
+ TOLERANCE_LIMIT = 0.01
+ STATUS_SUCCESS = "Success"
+ STATUS_FAIL = "Failure"
def __init__(self, traffic_generator):
super(RFC2544Profile, self).__init__(traffic_generator)
self.generator = None
+ self.iteration = 0
self.rate = self.config.frame_rate
self.max_rate = self.config.frame_rate
self.min_rate = 0
- self.drop_percent_max = 0
def register_generator(self, generator):
self.generator = generator
@@ -118,15 +121,17 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
ports.append(port_num)
port_pg_id.add_port(port_num)
profile = self._create_profile(profile_data,
- self.rate, port_pg_id)
+ self.rate, port_pg_id,
+ self.config.enable_latency)
self.generator.client.add_streams(profile, ports=[port_num])
self.generator.client.start(ports=ports,
duration=self.config.duration,
force=True)
+ self.iteration = self.generator.rfc2544_helper.iteration.value
return ports, port_pg_id
- def _create_profile(self, profile_data, rate, port_pg_id):
+ def _create_profile(self, profile_data, rate, port_pg_id, enable_latency):
"""Create a STL profile (list of streams) for a port"""
streams = []
for packet_name in profile_data:
@@ -134,11 +139,13 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
get('outer_l2', {}).get('framesize'))
imix_data = self._create_imix_data(imix)
self._create_vm(profile_data[packet_name])
- _streams = self._create_streams(imix_data, rate, port_pg_id)
+ _streams = self._create_streams(imix_data, rate, port_pg_id,
+ enable_latency)
streams.extend(_streams)
return trex_stl_streams.STLProfile(streams)
- def _create_imix_data(self, imix):
+ def _create_imix_data(self, imix,
+ weight_mode=constants.DISTRIBUTION_IN_BYTES):
"""Generate the IMIX distribution for a STL profile
The input information is the framesize dictionary in a test case
@@ -157,6 +164,20 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
E.g.:
imix_count = {64: 25, 128: 75}
+ The weight mode is described in [1]. There are two ways to describe the
+ weight of the packets:
+ - Distribution in packets: the weight defines the percentage of
+ packets sent per packet size. IXIA uses this definition.
+ - Distribution in bytes: the weight defines the percentage of bytes
+ sent per packet size.
+
+ Packet size # packets D. in packets Bytes D. in bytes
+ 40 7 58.33% 280 7%
+ 576 4 33.33% 2304 56%
+ 1500 1 8.33% 1500 37%
+
+ [1] https://en.wikipedia.org/wiki/Internet_Mix
+
:param imix: (dict) IMIX size and weight
"""
imix_count = {}
@@ -171,7 +192,15 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
imix_sum = 100
weight_normalize = float(imix_sum) / 100
- return {size: float(weight) / weight_normalize
+ imix_dip = {size: float(weight) / weight_normalize
+ for size, weight in imix_count.items()}
+
+ if weight_mode == constants.DISTRIBUTION_IN_PACKETS:
+ return imix_dip
+
+ byte_total = sum([int(size) * weight
+ for size, weight in imix_count.items()])
+ return {size: float(int(size) * weight * 100) / byte_total
for size, weight in imix_count.items()}
def _create_vm(self, packet_definition):
@@ -213,7 +242,7 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
return trex_stl_packet_builder_scapy.STLPktBuilder(
pkt=base_pkt / pad, vm=self.trex_vm)
- def _create_streams(self, imix_data, rate, port_pg_id):
+ def _create_streams(self, imix_data, rate, port_pg_id, enable_latency):
"""Create a list of streams per packet size
The STL TX mode speed of the generated streams will depend on the frame
@@ -237,28 +266,34 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
in imix_data.items() if float(weight) > 0):
packet = self._create_single_packet(size)
pg_id = port_pg_id.increase_pg_id()
- stl_flow = trex_stl_streams.STLFlowLatencyStats(pg_id=pg_id)
+ stl_flow = (trex_stl_streams.STLFlowLatencyStats(pg_id=pg_id) if
+ enable_latency else None)
mode = trex_stl_streams.STLTXCont(percentage=weight * rate / 100)
streams.append(trex_stl_client.STLStream(
packet=packet, flow_stats=stl_flow, mode=mode))
return streams
def get_drop_percentage(self, samples, tol_low, tol_high,
- correlated_traffic):
+ correlated_traffic, resolution): # pylint: disable=unused-argument
"""Calculate the drop percentage and run the traffic"""
- tx_rate_fps = 0
- rx_rate_fps = 0
- for sample in samples:
- tx_rate_fps += sum(
- port['tx_throughput_fps'] for port in sample.values())
- rx_rate_fps += sum(
- port['rx_throughput_fps'] for port in sample.values())
- tx_rate_fps = round(float(tx_rate_fps) / len(samples), 2)
- rx_rate_fps = round(float(rx_rate_fps) / len(samples), 2)
-
- # TODO(esm): RFC2544 doesn't tolerate packet loss, why do we?
- out_packets = sum(port['out_packets'] for port in samples[-1].values())
- in_packets = sum(port['in_packets'] for port in samples[-1].values())
+ completed = False
+ status = self.STATUS_FAIL
+ out_pkt_end = sum(port['out_packets'] for port in samples[-1].values())
+ in_pkt_end = sum(port['in_packets'] for port in samples[-1].values())
+ out_pkt_ini = sum(port['out_packets'] for port in samples[0].values())
+ in_pkt_ini = sum(port['in_packets'] for port in samples[0].values())
+ in_bytes_ini = sum(port['in_bytes'] for port in samples[0].values())
+ out_bytes_ini = sum(port['out_bytes'] for port in samples[0].values())
+ in_bytes_end = sum(port['in_bytes'] for port in samples[-1].values())
+ out_bytes_end = sum(port['out_bytes'] for port in samples[-1].values())
+ time_diff = (list(samples[-1].values())[0]['timestamp'] -
+ list(samples[0].values())[0]['timestamp']).total_seconds()
+ out_packets = out_pkt_end - out_pkt_ini
+ in_packets = in_pkt_end - in_pkt_ini
+ out_bytes = out_bytes_end - out_bytes_ini
+ in_bytes = in_bytes_end - in_bytes_ini
+ tx_rate_fps = float(out_packets) / time_diff
+ rx_rate_fps = float(in_packets) / time_diff
drop_percent = 100.0
# https://tools.ietf.org/html/rfc2544#section-26.3
@@ -266,33 +301,62 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
drop_percent = round(
(float(abs(out_packets - in_packets)) / out_packets) * 100, 5)
- tol_high = tol_high if tol_high > self.TOLERANCE_LIMIT else tol_high
- tol_low = tol_low if tol_low > self.TOLERANCE_LIMIT else tol_low
+ tol_high = max(tol_high, self.TOLERANCE_LIMIT)
+ tol_low = min(tol_low, self.TOLERANCE_LIMIT)
if drop_percent > tol_high:
self.max_rate = self.rate
elif drop_percent < tol_low:
self.min_rate = self.rate
- # else:
- # NOTE(ralonsoh): the test should finish here
- # pass
- last_rate = self.rate
- self.rate = round(float(self.max_rate + self.min_rate) / 2.0, 5)
-
- throughput = rx_rate_fps * 2 if correlated_traffic else rx_rate_fps
-
- if drop_percent > self.drop_percent_max:
- self.drop_percent_max = drop_percent
-
- latency = {port_num: value['latency']
- for port_num, value in samples[-1].items()}
+ else:
+ status = self.STATUS_SUCCESS
+ completed = True
- output = {
- 'TxThroughput': tx_rate_fps,
- 'RxThroughput': rx_rate_fps,
- 'CurrentDropPercentage': drop_percent,
- 'Throughput': throughput,
- 'DropPercentage': self.drop_percent_max,
- 'Rate': last_rate,
- 'Latency': latency
- }
- return output
+ last_rate = self.rate
+ self.rate = self._get_next_rate()
+ if abs(last_rate - self.rate) < resolution:
+ # stop test if the difference between the rate transmission
+ # in two iterations is smaller than the value of the resolution
+ completed = True
+ LOG.debug("rate=%s, next_rate=%s, resolution=%s, completed=%s",
+ last_rate, self.rate, resolution, completed)
+
+ ports = samples[-1].keys()
+ num_ports = len(ports)
+
+ output = {}
+ for port in ports:
+ output[port] = {}
+ first = samples[0][port]
+ last = samples[-1][port]
+ output[port]['InPackets'] = last['in_packets'] - first['in_packets']
+ output[port]['OutPackets'] = last['out_packets'] - first['out_packets']
+ output[port]['InBytes'] = last['in_bytes'] - first['in_bytes']
+ output[port]['OutBytes'] = last['out_bytes'] - first['out_bytes']
+ if self.config.enable_latency:
+ output[port]['LatencyAvg'] = float(sum(
+ [last['latency'][id]['average'] for id in
+ last['latency']]) * 1000) / len(last['latency'])
+ output[port]['LatencyMin'] = min(
+ [last['latency'][id]['total_min'] for id in
+ last['latency']]) * 1000
+ output[port]['LatencyMax'] = max(
+ [last['latency'][id]['total_max'] for id in
+ last['latency']]) * 1000
+
+ output['TxThroughput'] = tx_rate_fps
+ output['RxThroughput'] = rx_rate_fps
+ output['RxThroughputBps'] = round(float(in_bytes) / time_diff, 3)
+ output['TxThroughputBps'] = round(float(out_bytes) / time_diff, 3)
+ output['DropPercentage'] = drop_percent
+ output['Rate'] = last_rate
+ output['PktSize'] = self._get_framesize()
+ output['Iteration'] = self.iteration
+ output['Status'] = status
+
+ if self.config.enable_latency:
+ output['LatencyAvg'] = float(
+ sum([output[port]['LatencyAvg'] for port in ports])) / num_ports
+ output['LatencyMin'] = min([output[port]['LatencyMin'] for port in ports])
+ output['LatencyMax'] = max([output[port]['LatencyMax'] for port in ports])
+
+ return completed, output