aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick/network_services
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick/network_services')
-rw-r--r--yardstick/network_services/helpers/dpdkbindnic_helper.py1
-rw-r--r--yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py54
-rw-r--r--yardstick/network_services/traffic_profile/__init__.py1
-rw-r--r--yardstick/network_services/traffic_profile/ixia_rfc2544.py99
-rw-r--r--yardstick/network_services/traffic_profile/rfc2544.py91
-rw-r--r--yardstick/network_services/traffic_profile/trex_traffic_profile.py22
-rw-r--r--yardstick/network_services/traffic_profile/vpp_rfc2544.py321
-rw-r--r--yardstick/network_services/vnf_generic/vnf/acl_vnf.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/base.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/epc_vnf.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/prox_helpers.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/prox_irq.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/prox_vnf.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/router_vnf.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/sample_vnf.py42
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_ixload.py7
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_landslide.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_ping.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_pktgen.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_prox.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py124
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py59
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_trex.py4
-rw-r--r--yardstick/network_services/vnf_generic/vnf/udp_replay.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/vfw_vnf.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/vpe_vnf.py2
28 files changed, 666 insertions, 191 deletions
diff --git a/yardstick/network_services/helpers/dpdkbindnic_helper.py b/yardstick/network_services/helpers/dpdkbindnic_helper.py
index 1c74355ef..0fc63f88d 100644
--- a/yardstick/network_services/helpers/dpdkbindnic_helper.py
+++ b/yardstick/network_services/helpers/dpdkbindnic_helper.py
@@ -284,6 +284,7 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
res = self.ssh_helper.execute(*args, **kwargs)
if res[0] != 0:
template = '{} command failed with rc={}'
+ LOG.critical("DPDK_DEVBIND Failure %s", res[1])
raise DpdkBindHelperException(template.format(self.dpdk_devbind, res[0]))
return res
diff --git a/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
index e0b7aa000..89a855480 100644
--- a/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
+++ b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2018 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -94,12 +94,8 @@ class IxNextgen(object): # pragma: no cover
"port_name": 'Port Name',
"Frames_Tx": 'Frames Tx.',
"Valid_Frames_Rx": 'Valid Frames Rx.',
- "Frames_Tx_Rate": 'Frames Tx. Rate',
- "Valid_Frames_Rx_Rate": 'Valid Frames Rx. Rate',
- "Tx_Rate_Kbps": 'Tx. Rate (Kbps)',
- "Rx_Rate_Kbps": 'Rx. Rate (Kbps)',
- "Tx_Rate_Mbps": 'Tx. Rate (Mbps)',
- "Rx_Rate_Mbps": 'Rx. Rate (Mbps)',
+ "Bytes_Tx": 'Bytes Tx.',
+ "Bytes_Rx": 'Bytes Rx.'
}
LATENCY_NAME_MAP = {
@@ -405,7 +401,25 @@ class IxNextgen(object): # pragma: no cover
'/traffic/protocolTemplate:"{}"'.format(protocol_name))
self.ixnet.execute('append', previous_element, protocol)
- def _setup_config_elements(self, add_default_proto=True):
+ def is_qinq(self, flow_data):
+ for traffic_type in flow_data:
+ if flow_data[traffic_type]['outer_l2'].get('QinQ'):
+ return True
+ return False
+
+ def _flows_settings(self, cfg):
+ flows_data = []
+ res = [key for key in cfg.keys() if key.split('_')[0] in ['uplink', 'downlink']]
+ for i in range(len(res)):
+ uplink = 'uplink_{}'.format(i)
+ downlink = 'downlink_{}'.format(i)
+ if uplink in res:
+ flows_data.append(cfg[uplink])
+ if downlink in res:
+ flows_data.append(cfg[downlink])
+ return flows_data
+
+ def _setup_config_elements(self, traffic_profile, add_default_proto=True):
"""Setup the config elements
The traffic item is configured to allow individual configurations per
@@ -421,7 +435,9 @@ class IxNextgen(object): # pragma: no cover
'trafficItem')[0]
log.info('Split the frame rate distribution per config element')
config_elements = self.ixnet.getList(traffic_item_id, 'configElement')
- for config_element in config_elements:
+ flows = self._flows_settings(traffic_profile.params)
+ # TODO: check length of both lists, it should be equal!!!
+ for config_element, flow_data in zip(config_elements, flows):
self.ixnet.setAttribute(config_element + '/frameRateDistribution',
'-portDistribution', 'splitRateEvenly')
self.ixnet.setAttribute(config_element + '/frameRateDistribution',
@@ -432,8 +448,13 @@ class IxNextgen(object): # pragma: no cover
PROTO_UDP, config_element + '/stack:"ethernet-1"')
self._append_procotol_to_stack(
PROTO_IPV4, config_element + '/stack:"ethernet-1"')
+ if self.is_qinq(flow_data):
+ self._append_procotol_to_stack(
+ PROTO_VLAN, config_element + '/stack:"ethernet-1"')
+ self._append_procotol_to_stack(
+ PROTO_VLAN, config_element + '/stack:"ethernet-1"')
- def create_traffic_model(self, uplink_ports, downlink_ports):
+ def create_traffic_model(self, uplink_ports, downlink_ports, traffic_profile):
"""Create a traffic item and the needed flow groups
Each flow group inside the traffic item (only one is present)
@@ -448,9 +469,10 @@ class IxNextgen(object): # pragma: no cover
uplink_endpoints = [port + '/protocols' for port in uplink_ports]
downlink_endpoints = [port + '/protocols' for port in downlink_ports]
self._create_flow_groups(uplink_endpoints, downlink_endpoints)
- self._setup_config_elements()
+ self._setup_config_elements(traffic_profile=traffic_profile)
- def create_ipv4_traffic_model(self, uplink_endpoints, downlink_endpoints):
+ def create_ipv4_traffic_model(self, uplink_endpoints, downlink_endpoints,
+ traffic_profile):
"""Create a traffic item and the needed flow groups
Each flow group inside the traffic item (only one is present)
@@ -463,7 +485,8 @@ class IxNextgen(object): # pragma: no cover
"""
self._create_traffic_item('ipv4')
self._create_flow_groups(uplink_endpoints, downlink_endpoints)
- self._setup_config_elements(False)
+ self._setup_config_elements(traffic_profile=traffic_profile,
+ add_default_proto=False)
def _update_frame_mac(self, ethernet_descriptor, field, mac_address):
"""Set the MAC address in a config element stack Ethernet field
@@ -530,11 +553,6 @@ class IxNextgen(object): # pragma: no cover
'-fieldValue', ETHER_TYPE_802_1ad,
'-valueType', SINGLE_VALUE)
- self._append_procotol_to_stack(
- PROTO_VLAN, config_element + '/stack:"ethernet-1"')
- self._append_procotol_to_stack(
- PROTO_VLAN, config_element + '/stack:"ethernet-1"')
-
self._update_vlan_tag(fg_id, s_vlan, S_VLAN)
self._update_vlan_tag(fg_id, c_vlan, C_VLAN)
diff --git a/yardstick/network_services/traffic_profile/__init__.py b/yardstick/network_services/traffic_profile/__init__.py
index 72a61b6b4..c5d8eff0b 100644
--- a/yardstick/network_services/traffic_profile/__init__.py
+++ b/yardstick/network_services/traffic_profile/__init__.py
@@ -30,6 +30,7 @@ def register_modules():
'yardstick.network_services.traffic_profile.rfc2544',
'yardstick.network_services.traffic_profile.pktgen',
'yardstick.network_services.traffic_profile.landslide_profile',
+ 'yardstick.network_services.traffic_profile.vpp_rfc2544',
]
for module in modules:
diff --git a/yardstick/network_services/traffic_profile/ixia_rfc2544.py b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
index 89bb3ef7a..ca45b500d 100644
--- a/yardstick/network_services/traffic_profile/ixia_rfc2544.py
+++ b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
UPLINK = 'uplink'
DOWNLINK = 'downlink'
DROP_PERCENT_ROUND = 6
- RATE_ROUND = 5
STATUS_SUCCESS = "Success"
STATUS_FAIL = "Failure"
@@ -36,6 +35,7 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
super(IXIARFC2544Profile, self).__init__(yaml_data)
self.rate = self.config.frame_rate
self.rate_unit = self.config.rate_unit
+ self.iteration = 0
self.full_profile = {}
def _get_ip_and_mask(self, ip_range):
@@ -171,10 +171,6 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
self.ports = [port for port in port_generator()]
- def _get_next_rate(self):
- rate = round(float(self.max_rate + self.min_rate)/2.0, self.RATE_ROUND)
- return rate
-
def execute_traffic(self, traffic_generator, ixia_obj=None, mac=None):
mac = {} if mac is None else mac
first_run = self.first_run
@@ -186,6 +182,7 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
else:
self.rate = self._get_next_rate()
+ self.iteration = traffic_generator.rfc_helper.iteration.value
traffic = self._get_ixia_traffic_profile(self.full_profile, mac)
self._ixia_traffic_generate(traffic, ixia_obj, traffic_generator)
return first_run
@@ -198,11 +195,19 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
num_ifaces = len(samples)
duration = self.config.duration
in_packets_sum = sum(
- [samples[iface]['in_packets'] for iface in samples])
+ [samples[iface]['InPackets'] for iface in samples])
out_packets_sum = sum(
- [samples[iface]['out_packets'] for iface in samples])
+ [samples[iface]['OutPackets'] for iface in samples])
+ in_bytes_sum = sum(
+ [samples[iface]['InBytes'] for iface in samples])
+ out_bytes_sum = sum(
+ [samples[iface]['OutBytes'] for iface in samples])
rx_throughput = round(float(in_packets_sum) / duration, 3)
tx_throughput = round(float(out_packets_sum) / duration, 3)
+ # Rx throughput in Bps
+ rx_throughput_bps = round(float(in_bytes_sum) / duration, 3)
+ # Tx throughput in Bps
+ tx_throughput_bps = round(float(out_bytes_sum) / duration, 3)
packet_drop = abs(out_packets_sum - in_packets_sum)
try:
@@ -225,6 +230,7 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
else:
completed = True
+ last_rate = self.rate
next_rate = self._get_next_rate()
if abs(next_rate - self.rate) < resolution:
LOG.debug("rate=%s, next_rate=%s, resolution=%s", self.rate,
@@ -237,15 +243,10 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
"completed=%s", tolerance, precision, drop_percent,
completed)
- latency_ns_avg = float(
- sum([samples[iface]['Store-Forward_Avg_latency_ns']
- for iface in samples])) / num_ifaces
- latency_ns_min = float(
- sum([samples[iface]['Store-Forward_Min_latency_ns']
- for iface in samples])) / num_ifaces
- latency_ns_max = float(
- sum([samples[iface]['Store-Forward_Max_latency_ns']
- for iface in samples])) / num_ifaces
+ latency_ns_avg = float(sum(
+ [samples[iface]['LatencyAvg'] for iface in samples])) / num_ifaces
+ latency_ns_min = min([samples[iface]['LatencyMin'] for iface in samples])
+ latency_ns_max = max([samples[iface]['LatencyMax'] for iface in samples])
samples['Status'] = self.STATUS_FAIL
if round(drop_percent, precision) <= tolerance:
@@ -253,10 +254,15 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
samples['TxThroughput'] = tx_throughput
samples['RxThroughput'] = rx_throughput
+ samples['TxThroughputBps'] = tx_throughput_bps
+ samples['RxThroughputBps'] = rx_throughput_bps
samples['DropPercentage'] = drop_percent
- samples['latency_ns_avg'] = latency_ns_avg
- samples['latency_ns_min'] = latency_ns_min
- samples['latency_ns_max'] = latency_ns_max
+ samples['LatencyAvg'] = latency_ns_avg
+ samples['LatencyMin'] = latency_ns_min
+ samples['LatencyMax'] = latency_ns_max
+ samples['Rate'] = last_rate
+ samples['PktSize'] = self._get_framesize()
+ samples['Iteration'] = self.iteration
return completed, samples
@@ -304,10 +310,10 @@ class IXIARFC2544PppoeScenarioProfile(IXIARFC2544Profile):
drop_percent = 100
for prio_id in stats:
prio_flow = stats[prio_id]
- sum_packet_drop = abs(prio_flow['out_packets'] - prio_flow['in_packets'])
+ sum_packet_drop = abs(prio_flow['OutPackets'] - prio_flow['InPackets'])
try:
drop_percent = round(
- (sum_packet_drop / float(prio_flow['out_packets'])) * 100,
+ (sum_packet_drop / float(prio_flow['OutPackets'])) * 100,
self.DROP_PERCENT_ROUND)
except ZeroDivisionError:
LOG.info('No traffic is flowing')
@@ -316,10 +322,10 @@ class IXIARFC2544PppoeScenarioProfile(IXIARFC2544Profile):
def _get_summary_pppoe_subs_counters(self, samples):
result = {}
- keys = ['sessions_up',
- 'sessions_down',
- 'sessions_not_started',
- 'sessions_total']
+ keys = ['SessionsUp',
+ 'SessionsDown',
+ 'SessionsNotStarted',
+ 'SessionsTotal']
for key in keys:
result[key] = \
sum([samples[port][key] for port in samples
@@ -332,15 +338,24 @@ class IXIARFC2544PppoeScenarioProfile(IXIARFC2544Profile):
sum_drop_percent = 100
num_ifaces = len(samples)
duration = self.config.duration
+ last_rate = self.rate
priority_stats = samples.pop('priority_stats')
priority_stats = self._get_prio_flows_drop_percentage(priority_stats)
summary_subs_stats = self._get_summary_pppoe_subs_counters(samples)
in_packets_sum = sum(
- [samples[iface]['in_packets'] for iface in samples])
+ [samples[iface]['InPackets'] for iface in samples])
out_packets_sum = sum(
- [samples[iface]['out_packets'] for iface in samples])
+ [samples[iface]['OutPackets'] for iface in samples])
+ in_bytes_sum = sum(
+ [samples[iface]['InBytes'] for iface in samples])
+ out_bytes_sum = sum(
+ [samples[iface]['OutBytes'] for iface in samples])
rx_throughput = round(float(in_packets_sum) / duration, 3)
tx_throughput = round(float(out_packets_sum) / duration, 3)
+ # Rx throughput in Bps
+ rx_throughput_bps = round(float(in_bytes_sum) / duration, 3)
+ # Tx throughput in Bps
+ tx_throughput_bps = round(float(out_bytes_sum) / duration, 3)
sum_packet_drop = abs(out_packets_sum - in_packets_sum)
try:
@@ -350,29 +365,29 @@ class IXIARFC2544PppoeScenarioProfile(IXIARFC2544Profile):
except ZeroDivisionError:
LOG.info('No traffic is flowing')
- latency_ns_avg = float(
- sum([samples[iface]['Store-Forward_Avg_latency_ns']
- for iface in samples])) / num_ifaces
- latency_ns_min = float(
- sum([samples[iface]['Store-Forward_Min_latency_ns']
- for iface in samples])) / num_ifaces
- latency_ns_max = float(
- sum([samples[iface]['Store-Forward_Max_latency_ns']
- for iface in samples])) / num_ifaces
+ latency_ns_avg = float(sum(
+ [samples[iface]['LatencyAvg'] for iface in samples])) / num_ifaces
+ latency_ns_min = min([samples[iface]['LatencyMin'] for iface in samples])
+ latency_ns_max = max([samples[iface]['LatencyMax'] for iface in samples])
samples['TxThroughput'] = tx_throughput
samples['RxThroughput'] = rx_throughput
+ samples['TxThroughputBps'] = tx_throughput_bps
+ samples['RxThroughputBps'] = rx_throughput_bps
samples['DropPercentage'] = sum_drop_percent
- samples['latency_ns_avg'] = latency_ns_avg
- samples['latency_ns_min'] = latency_ns_min
- samples['latency_ns_max'] = latency_ns_max
- samples['priority'] = priority_stats
+ samples['LatencyAvg'] = latency_ns_avg
+ samples['LatencyMin'] = latency_ns_min
+ samples['LatencyMax'] = latency_ns_max
+ samples['Priority'] = priority_stats
+ samples['Rate'] = last_rate
+ samples['PktSize'] = self._get_framesize()
+ samples['Iteration'] = self.iteration
samples.update(summary_subs_stats)
if tc_rfc2544_opts:
priority = tc_rfc2544_opts.get('priority')
if priority:
- drop_percent = samples['priority'][priority]['DropPercentage']
+ drop_percent = samples['Priority'][priority]['DropPercentage']
else:
drop_percent = sum_drop_percent
else:
diff --git a/yardstick/network_services/traffic_profile/rfc2544.py b/yardstick/network_services/traffic_profile/rfc2544.py
index e33c437c9..aaa491b75 100644
--- a/yardstick/network_services/traffic_profile/rfc2544.py
+++ b/yardstick/network_services/traffic_profile/rfc2544.py
@@ -23,7 +23,7 @@ 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'
@@ -72,14 +72,16 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
"""TRex RFC2544 traffic profile"""
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
@@ -126,6 +128,7 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
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, enable_latency):
@@ -142,7 +145,7 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
return trex_stl_streams.STLProfile(streams)
def _create_imix_data(self, imix,
- weight_mode=constants.DISTRIBUTION_IN_PACKETS):
+ 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
@@ -192,13 +195,13 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
imix_dip = {size: float(weight) / weight_normalize
for size, weight in imix_count.items()}
- if weight_mode == constants.DISTRIBUTION_IN_BYTES:
+ if weight_mode == constants.DISTRIBUTION_IN_PACKETS:
return imix_dip
byte_total = sum([int(size) * weight
- for size, weight in imix_dip.items()])
- return {size: (int(size) * weight * 100) / byte_total
- for size, weight in imix_dip.items()}
+ 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):
"""Create the STL Raw instructions"""
@@ -271,17 +274,24 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
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"""
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
@@ -298,26 +308,55 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
elif drop_percent < tol_low:
self.min_rate = self.rate
else:
+ status = self.STATUS_SUCCESS
completed = True
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()}
+ 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])
- 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 completed, output
diff --git a/yardstick/network_services/traffic_profile/trex_traffic_profile.py b/yardstick/network_services/traffic_profile/trex_traffic_profile.py
index ed0355fa5..cf538d488 100644
--- a/yardstick/network_services/traffic_profile/trex_traffic_profile.py
+++ b/yardstick/network_services/traffic_profile/trex_traffic_profile.py
@@ -52,6 +52,7 @@ class TrexProfile(base.TrafficProfile):
IPv6: ('ip6_packet', Pkt.IPv6),
UDP: ('udp_packet', Pkt.UDP),
}
+ RATE_ROUND = 5
def _general_single_action_partial(self, protocol):
def f(field):
@@ -186,6 +187,8 @@ class TrexProfile(base.TrafficProfile):
self.qinq = False
self.vm_flow_vars = []
self.packets = []
+ self.max_rate = 0
+ self.min_rate = 0
self._map_proto_actions = {
# the tuple is (single value function, range value function, if the values should be
@@ -337,6 +340,25 @@ class TrexProfile(base.TrafficProfile):
if 'dstport' in outer_l4:
self._set_proto_addr(UDP, DST_PORT, outer_l4['dstport'], outer_l4['count'])
+ def _get_next_rate(self):
+ rate = round(float(self.max_rate + self.min_rate)/2.0, self.RATE_ROUND)
+ return rate
+
+ def _get_framesize(self):
+ framesizes = []
+ for traffickey, value in self.params.items():
+ if not traffickey.startswith((self.UPLINK, self.DOWNLINK)):
+ continue
+ for _, data in value.items():
+ framesize = data['outer_l2']['framesize']
+ for size in (s for s, w in framesize.items() if int(w) != 0):
+ framesizes.append(size)
+ if len(set(framesizes)) == 0:
+ return ''
+ elif len(set(framesizes)) == 1:
+ return framesizes[0]
+ return 'IMIX'
+
@classmethod
def _count_ip(cls, start_ip, end_ip):
start = ipaddress.ip_address(six.u(start_ip))
diff --git a/yardstick/network_services/traffic_profile/vpp_rfc2544.py b/yardstick/network_services/traffic_profile/vpp_rfc2544.py
new file mode 100644
index 000000000..0f8185f90
--- /dev/null
+++ b/yardstick/network_services/traffic_profile/vpp_rfc2544.py
@@ -0,0 +1,321 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# 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 datetime
+import logging
+from random import choice
+from string import ascii_letters
+
+from ipaddress import ip_address
+from trex_stl_lib import api as Pkt
+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.rfc2544 import RFC2544Profile, \
+ PortPgIDMap
+from yardstick.network_services.traffic_profile.trex_traffic_profile import IP, \
+ DST
+
+LOGGING = logging.getLogger(__name__)
+
+
+class VppRFC2544Profile(RFC2544Profile):
+
+ def __init__(self, traffic_generator):
+ super(VppRFC2544Profile, self).__init__(traffic_generator)
+
+ self.duration = self.config.duration
+ self.precision = self.config.test_precision
+ self.lower_bound = self.config.lower_bound
+ self.upper_bound = self.config.upper_bound
+ self.step_interval = self.config.step_interval
+ self.enable_latency = self.config.enable_latency
+
+ self.pkt_size = None
+ self.flow = None
+
+ self.tolerance_low = 0
+ self.tolerance_high = 0
+
+ self.queue = None
+ self.port_pg_id = None
+
+ self.current_lower = self.lower_bound
+ self.current_upper = self.upper_bound
+
+ self.ports = []
+ self.profiles = {}
+
+ @property
+ def delta(self):
+ return self.current_upper - self.current_lower
+
+ @property
+ def mid_point(self):
+ return (self.current_lower + self.current_upper) / 2
+
+ @staticmethod
+ def calculate_frame_size(imix):
+ if not imix:
+ return 64, 100
+
+ imix_count = {size.upper().replace('B', ''): int(weight)
+ for size, weight in imix.items()}
+ imix_sum = sum(imix_count.values())
+ if imix_sum <= 0:
+ return 64, 100
+ packets_total = sum([int(size) * weight
+ for size, weight in imix_count.items()])
+ return packets_total / imix_sum, imix_sum
+
+ @staticmethod
+ def _gen_payload(length):
+ payload = ""
+ for _ in range(length):
+ payload += choice(ascii_letters)
+
+ return payload
+
+ def bounds_iterator(self, logger=None):
+ self.current_lower = self.lower_bound
+ self.current_upper = self.upper_bound
+
+ test_value = self.current_upper
+ while abs(self.delta) >= self.precision:
+ if logger:
+ logger.debug("New interval [%s, %s), precision: %d",
+ self.current_lower,
+ self.current_upper, self.step_interval)
+ logger.info("Testing with value %s", test_value)
+
+ yield test_value
+ test_value = self.mid_point
+
+ def register_generator(self, generator):
+ super(VppRFC2544Profile, self).register_generator(generator)
+ self.init_traffic_params(generator)
+
+ def init_queue(self, queue):
+ self.queue = queue
+ self.queue.cancel_join_thread()
+
+ def init_traffic_params(self, generator):
+ if generator.rfc2544_helper.latency:
+ self.enable_latency = True
+ self.tolerance_low = generator.rfc2544_helper.tolerance_low
+ self.tolerance_high = generator.rfc2544_helper.tolerance_high
+ self.max_rate = generator.scenario_helper.all_options.get('vpp_config',
+ {}).get(
+ 'max_rate', self.rate)
+
+ def create_profile(self, profile_data, current_port):
+ streams = []
+ for packet_name in profile_data:
+ imix = (profile_data[packet_name].
+ get('outer_l2', {}).get('framesize'))
+ self.pkt_size, imix_sum = self.calculate_frame_size(imix)
+ self._create_vm(profile_data[packet_name])
+ if self.max_rate > 100:
+ imix_data = self._create_imix_data(imix,
+ constants.DISTRIBUTION_IN_PACKETS)
+ else:
+ imix_data = self._create_imix_data(imix)
+ _streams = self._create_single_stream(current_port, imix_data,
+ imix_sum)
+ streams.extend(_streams)
+ return trex_stl_streams.STLProfile(streams)
+
+ def _set_outer_l3v4_fields(self, outer_l3v4):
+ """ setup outer l3v4 fields from traffic profile """
+ ip_params = {}
+ if 'proto' in outer_l3v4:
+ ip_params['proto'] = outer_l3v4['proto']
+ self._set_proto_fields(IP, **ip_params)
+
+ self.flow = int(outer_l3v4['count'])
+ src_start_ip, _ = outer_l3v4['srcip4'].split('-')
+ dst_start_ip, _ = outer_l3v4['dstip4'].split('-')
+
+ self.ip_packet = Pkt.IP(src=src_start_ip,
+ dst=dst_start_ip,
+ proto=outer_l3v4['proto'])
+ if self.flow > 1:
+ dst_start_int = int(ip_address(str(dst_start_ip)))
+ dst_end_ip_new = ip_address(dst_start_int + self.flow - 1)
+ # self._set_proto_addr(IP, SRC, outer_l3v4['srcip4'], outer_l3v4['count'])
+ self._set_proto_addr(IP, DST,
+ "{start_ip}-{end_ip}".format(
+ start_ip=dst_start_ip,
+ end_ip=str(dst_end_ip_new)),
+ self.flow)
+
+ def _create_single_packet(self, size=64):
+ ether_packet = self.ether_packet
+ ip_packet = self.ip6_packet if self.ip6_packet else self.ip_packet
+ base_pkt = ether_packet / ip_packet
+ payload_len = max(0, size - len(base_pkt) - 4)
+ packet = trex_stl_packet_builder_scapy.STLPktBuilder(
+ pkt=base_pkt / self._gen_payload(payload_len),
+ vm=self.trex_vm)
+ packet_lat = trex_stl_packet_builder_scapy.STLPktBuilder(
+ pkt=base_pkt / self._gen_payload(payload_len))
+
+ return packet, packet_lat
+
+ def _create_single_stream(self, current_port, imix_data, imix_sum,
+ isg=0.0):
+ streams = []
+ for size, weight in ((int(size), float(weight)) for (size, weight)
+ in imix_data.items() if float(weight) > 0):
+ if current_port == 1:
+ isg += 10.0
+ if self.max_rate > 100:
+ mode = trex_stl_streams.STLTXCont(
+ pps=int(weight * imix_sum / 100))
+ mode_lat = mode
+ else:
+ mode = trex_stl_streams.STLTXCont(
+ percentage=weight * self.max_rate / 100)
+ mode_lat = trex_stl_streams.STLTXCont(pps=9000)
+
+ packet, packet_lat = self._create_single_packet(size)
+ streams.append(
+ trex_stl_client.STLStream(isg=isg, packet=packet, mode=mode))
+ if self.enable_latency:
+ pg_id = self.port_pg_id.increase_pg_id(current_port)
+ stl_flow = trex_stl_streams.STLFlowLatencyStats(pg_id=pg_id)
+ stream_lat = trex_stl_client.STLStream(isg=isg,
+ packet=packet_lat,
+ mode=mode_lat,
+ flow_stats=stl_flow)
+ streams.append(stream_lat)
+ return streams
+
+ def execute_traffic(self, traffic_generator=None):
+ if traffic_generator is not None and self.generator is None:
+ self.generator = traffic_generator
+
+ self.ports = []
+ self.profiles = {}
+ self.port_pg_id = PortPgIDMap()
+ for vld_id, intfs in sorted(self.generator.networks.items()):
+ profile_data = self.params.get(vld_id)
+ if not profile_data:
+ continue
+ if (vld_id.startswith(self.DOWNLINK) and
+ self.generator.rfc2544_helper.correlated_traffic):
+ continue
+ for intf in intfs:
+ current_port = int(self.generator.port_num(intf))
+ self.port_pg_id.add_port(current_port)
+ profile = self.create_profile(profile_data, current_port)
+ self.generator.client.add_streams(profile,
+ ports=[current_port])
+
+ self.ports.append(current_port)
+ self.profiles[current_port] = profile
+
+ timeout = self.generator.scenario_helper.scenario_cfg["runner"][
+ "duration"]
+ test_data = {
+ "test_duration": timeout,
+ "test_precision": self.precision,
+ "tolerated_loss": self.tolerance_high,
+ "duration": self.duration,
+ "packet_size": self.pkt_size,
+ "flow": self.flow
+ }
+
+ if self.max_rate > 100:
+ self.binary_search_with_optimized(self.generator, self.duration,
+ timeout, test_data)
+ else:
+ self.binary_search(self.generator, self.duration,
+ self.tolerance_high, test_data)
+
+ def binary_search_with_optimized(self, traffic_generator, duration,
+ timeout, test_data):
+ # TODO Support FD.io Multiple Loss Ratio search (MLRsearch)
+ pass
+
+ def binary_search(self, traffic_generator, duration, tolerance_value,
+ test_data):
+ theor_max_thruput = 0
+ result_samples = {}
+
+ for test_value in self.bounds_iterator(LOGGING):
+ stats = traffic_generator.send_traffic_on_tg(self.ports,
+ self.port_pg_id,
+ duration,
+ str(
+ test_value / self.max_rate / 2),
+ latency=self.enable_latency)
+ traffic_generator.client.reset(ports=self.ports)
+ traffic_generator.client.clear_stats(ports=self.ports)
+ traffic_generator.client.remove_all_streams(ports=self.ports)
+ for port, profile in self.profiles.items():
+ traffic_generator.client.add_streams(profile, ports=[port])
+
+ loss_ratio = (float(traffic_generator.loss) / float(
+ traffic_generator.sent)) * 100
+
+ samples = traffic_generator.generate_samples(stats, self.ports,
+ self.port_pg_id,
+ self.enable_latency)
+ samples.update(test_data)
+ LOGGING.info("Collect TG KPIs %s %s %s", datetime.datetime.now(),
+ test_value, samples)
+ self.queue.put(samples)
+
+ if float(loss_ratio) > float(tolerance_value):
+ LOGGING.debug("Failure... Decreasing upper bound")
+ self.current_upper = test_value
+ else:
+ LOGGING.debug("Success! Increasing lower bound")
+ self.current_lower = test_value
+
+ rate_total = float(traffic_generator.sent) / float(duration)
+ bandwidth_total = float(rate_total) * (
+ float(self.pkt_size) + 20) * 8 / (10 ** 9)
+
+ success_samples = {'Result_' + key: value for key, value in
+ samples.items()}
+ success_samples["Result_{}".format('PDR')] = {
+ "rate_total_pps": float(rate_total),
+ "bandwidth_total_Gbps": float(bandwidth_total),
+ "packet_loss_ratio": float(loss_ratio),
+ "packets_lost": int(traffic_generator.loss),
+ }
+ self.queue.put(success_samples)
+
+ # Store Actual throughput for result samples
+ for intf in traffic_generator.vnfd_helper.interfaces:
+ name = intf["name"]
+ result_samples[name] = {
+ "Result_Actual_throughput": float(
+ success_samples["Result_{}".format(name)][
+ "rx_throughput_bps"]),
+ }
+
+ for intf in traffic_generator.vnfd_helper.interfaces:
+ name = intf["name"]
+ if theor_max_thruput < samples[name]["tx_throughput_bps"]:
+ theor_max_thruput = samples[name]['tx_throughput_bps']
+ self.queue.put({'theor_max_throughput': theor_max_thruput})
+
+ result_samples["Result_theor_max_throughput"] = theor_max_thruput
+ self.queue.put(result_samples)
+ return result_samples
diff --git a/yardstick/network_services/vnf_generic/vnf/acl_vnf.py b/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
index 46380e216..69d29bf76 100644
--- a/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/acl_vnf.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py b/yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py
index 5856eb6e0..d1d9667db 100644
--- a/yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Intel Corporation
+# Copyright (c) 2018-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/base.py b/yardstick/network_services/vnf_generic/vnf/base.py
index 1f49b22d5..8064ae927 100644
--- a/yardstick/network_services/vnf_generic/vnf/base.py
+++ b/yardstick/network_services/vnf_generic/vnf/base.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py b/yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py
index 62e15094a..ee4a581b1 100644
--- a/yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/epc_vnf.py b/yardstick/network_services/vnf_generic/vnf/epc_vnf.py
index 1b06c59c1..8112963e9 100644
--- a/yardstick/network_services/vnf_generic/vnf/epc_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/epc_vnf.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Intel Corporation
+# Copyright (c) 2018-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/prox_helpers.py b/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
index aeb41858f..a3d0c19cd 100644
--- a/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
+++ b/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Intel Corporation
+# Copyright (c) 2018-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/prox_irq.py b/yardstick/network_services/vnf_generic/vnf/prox_irq.py
index 4cc8923cb..614066e46 100644
--- a/yardstick/network_services/vnf_generic/vnf/prox_irq.py
+++ b/yardstick/network_services/vnf_generic/vnf/prox_irq.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Intel Corporation
+# Copyright (c) 2018-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/prox_vnf.py b/yardstick/network_services/vnf_generic/vnf/prox_vnf.py
index 0d1360dd0..c9abc757e 100644
--- a/yardstick/network_services/vnf_generic/vnf/prox_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/prox_vnf.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Intel Corporation
+# Copyright (c) 2018-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/router_vnf.py b/yardstick/network_services/vnf_generic/vnf/router_vnf.py
index 90b7b215e..f1486bdb4 100644
--- a/yardstick/network_services/vnf_generic/vnf/router_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/router_vnf.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
index aec085057..a369a3ae6 100644
--- a/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/sample_vnf.py
@@ -14,7 +14,7 @@
import logging
import decimal
-from multiprocessing import Queue, Value, Process
+from multiprocessing import Queue, Value, Process, JoinableQueue
import os
import posixpath
import re
@@ -231,6 +231,9 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
exit_status = self.dpdk_bind_helper.check_dpdk_driver()
if exit_status == 0:
return
+ else:
+ LOG.critical("DPDK Driver not installed")
+ return
def _setup_resources(self):
# what is this magic? how do we know which socket is for which port?
@@ -716,8 +719,8 @@ class SampleVNF(GenericVNF):
scenarios:
- type: NSPerf
nodes:
- tg__0: trafficgen_1.yardstick
- vnf__0: vnf.yardstick
+ tg__0: trafficgen_0.yardstick
+ vnf__0: vnf_0.yardstick
options:
collectd:
<options> # COLLECTD priority 3
@@ -948,6 +951,39 @@ class SampleVNFTrafficGen(GenericTrafficGen):
self.traffic_finished = False
self._tg_process = None
self._traffic_process = None
+ self._tasks_queue = JoinableQueue()
+ self._result_queue = Queue()
+
+ def _test_runner(self, traffic_profile, tasks, results):
+ self.resource_helper.run_test(traffic_profile, tasks, results)
+
+ def _init_traffic_process(self, traffic_profile):
+ name = '{}-{}-{}-{}'.format(self.name, self.APP_NAME,
+ traffic_profile.__class__.__name__,
+ os.getpid())
+ self._traffic_process = Process(name=name, target=self._test_runner,
+ args=(
+ traffic_profile, self._tasks_queue,
+ self._result_queue))
+
+ self._traffic_process.start()
+ while self.resource_helper.client_started.value == 0:
+ time.sleep(1)
+ if not self._traffic_process.is_alive():
+ break
+
+ def run_traffic_once(self, traffic_profile):
+ if self.resource_helper.client_started.value == 0:
+ self._init_traffic_process(traffic_profile)
+
+ # continue test - run next iteration
+ LOG.info("Run next iteration ...")
+ self._tasks_queue.put('RUN_TRAFFIC')
+
+ def wait_on_traffic(self):
+ self._tasks_queue.join()
+ result = self._result_queue.get()
+ return result
def _start_server(self):
# we can't share ssh paramiko objects to force new connection
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_ixload.py b/yardstick/network_services/vnf_generic/vnf/tg_ixload.py
index 97b36d708..38b00a4b2 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_ixload.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_ixload.py
@@ -142,7 +142,12 @@ class IxLoadTrafficGen(sample_vnf.SampleVNFTrafficGen):
"external-interface"] if
intf["virtual-interface"]["vld_id"] == name)
- links[name]["ip"]["gateway"] = gateway
+ try:
+ links[name]["ip"]["gateway"] = gateway
+ except KeyError:
+ LOG.error("Invalid traffic profile: No IP section defined for %s", name)
+ raise
+
except StopIteration:
LOG.debug("Cant find gateway for link %s", name)
links[name]["ip"]["gateway"] = "0.0.0.0"
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_landslide.py b/yardstick/network_services/vnf_generic/vnf/tg_landslide.py
index fb8c24752..285374a92 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_landslide.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_landslide.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Intel Corporation
+# Copyright (c) 2018-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_ping.py b/yardstick/network_services/vnf_generic/vnf/tg_ping.py
index a989543f5..5c8819119 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_ping.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_ping.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_pktgen.py b/yardstick/network_services/vnf_generic/vnf/tg_pktgen.py
index e73cebc40..5da2178af 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_pktgen.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_pktgen.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Intel Corporation
+# Copyright (c) 2018-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_prox.py b/yardstick/network_services/vnf_generic/vnf/tg_prox.py
index 61ff2e036..65b7bac10 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_prox.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_prox.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2017 Intel Corporation
+# Copyright (c) 2017-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
index f8eec4f4c..80812876d 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
@@ -16,13 +16,8 @@ import ipaddress
import logging
import six
import collections
-import os
-import time
from six import moves
-
-from multiprocessing import Queue, Process, JoinableQueue
-
from yardstick.common import utils
from yardstick.common import exceptions
from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
@@ -59,13 +54,13 @@ class IxiaBasicScenario(object):
def stop_protocols(self):
pass
- def create_traffic_model(self, traffic_profile=None):
- # pylint: disable=unused-argument
+ def create_traffic_model(self, traffic_profile):
vports = self.client.get_vports()
self._uplink_vports = vports[::2]
self._downlink_vports = vports[1::2]
self.client.create_traffic_model(self._uplink_vports,
- self._downlink_vports)
+ self._downlink_vports,
+ traffic_profile)
def _get_stats(self):
return self.client.get_statistics()
@@ -85,17 +80,17 @@ class IxiaBasicScenario(object):
min_latency = stats['Store-Forward_Min_latency_ns'][port_num]
max_latency = stats['Store-Forward_Max_latency_ns'][port_num]
samples[port_name] = {
- 'rx_throughput_kps': float(stats['Rx_Rate_Kbps'][port_num]),
- 'tx_throughput_kps': float(stats['Tx_Rate_Kbps'][port_num]),
- 'rx_throughput_mbps': float(stats['Rx_Rate_Mbps'][port_num]),
- 'tx_throughput_mbps': float(stats['Tx_Rate_Mbps'][port_num]),
- 'in_packets': int(stats['Valid_Frames_Rx'][port_num]),
- 'out_packets': int(stats['Frames_Tx'][port_num]),
+ 'RxThroughputBps': float(stats['Bytes_Rx'][port_num]) / duration,
+ 'TxThroughputBps': float(stats['Bytes_Tx'][port_num]) / duration,
+ 'InPackets': int(stats['Valid_Frames_Rx'][port_num]),
+ 'OutPackets': int(stats['Frames_Tx'][port_num]),
+ 'InBytes': int(stats['Bytes_Rx'][port_num]),
+ 'OutBytes': int(stats['Bytes_Tx'][port_num]),
'RxThroughput': float(stats['Valid_Frames_Rx'][port_num]) / duration,
'TxThroughput': float(stats['Frames_Tx'][port_num]) / duration,
- 'Store-Forward_Avg_latency_ns': utils.safe_cast(avg_latency, int, 0),
- 'Store-Forward_Min_latency_ns': utils.safe_cast(min_latency, int, 0),
- 'Store-Forward_Max_latency_ns': utils.safe_cast(max_latency, int, 0)
+ 'LatencyAvg': utils.safe_cast(avg_latency, int, 0),
+ 'LatencyMin': utils.safe_cast(min_latency, int, 0),
+ 'LatencyMax': utils.safe_cast(max_latency, int, 0)
}
except IndexError:
pass
@@ -170,8 +165,7 @@ class IxiaL3Scenario(IxiaBasicScenario):
self._add_interfaces()
self._add_static_ips()
- def create_traffic_model(self, traffic_profile=None):
- # pylint: disable=unused-argument
+ def create_traffic_model(self, traffic_profile):
vports = self.client.get_vports()
self._uplink_vports = vports[::2]
self._downlink_vports = vports[1::2]
@@ -182,7 +176,8 @@ class IxiaL3Scenario(IxiaBasicScenario):
for port in self._downlink_vports]
self.client.create_ipv4_traffic_model(uplink_endpoints,
- downlink_endpoints)
+ downlink_endpoints,
+ traffic_profile)
class IxiaPppoeClientScenario(object):
@@ -221,7 +216,8 @@ class IxiaPppoeClientScenario(object):
uplink_endpoints = self._access_topologies
downlink_endpoints = self._core_topologies
self.client.create_ipv4_traffic_model(uplink_endpoints,
- downlink_endpoints)
+ downlink_endpoints,
+ traffic_profile)
def run_protocols(self):
LOG.info('PPPoE Scenario - Start Protocols')
@@ -524,22 +520,22 @@ class IxiaPppoeClientScenario(object):
avg_latency_ns = sum(
[int(flow['Store-Forward_Avg_latency_ns']) for flow in samples
if flow['IP_Priority'] == priority]) / prio_flows_num
- min_latency_ns = sum(
+ min_latency_ns = min(
[int(flow['Store-Forward_Min_latency_ns']) for flow in samples
- if flow['IP_Priority'] == priority]) / prio_flows_num
- max_latency_ns = sum(
+ if flow['IP_Priority'] == priority])
+ max_latency_ns = max(
[int(flow['Store-Forward_Max_latency_ns']) for flow in samples
- if flow['IP_Priority'] == priority]) / prio_flows_num
+ if flow['IP_Priority'] == priority])
tx_throughput = float(tx_frames) / duration
rx_throughput = float(rx_frames) / duration
results[priority] = {
- 'in_packets': rx_frames,
- 'out_packets': tx_frames,
+ 'InPackets': rx_frames,
+ 'OutPackets': tx_frames,
'RxThroughput': round(rx_throughput, 3),
'TxThroughput': round(tx_throughput, 3),
- 'avg_latency_ns': utils.safe_cast(avg_latency_ns, int, 0),
- 'min_latency_ns': utils.safe_cast(min_latency_ns, int, 0),
- 'max_latency_ns': utils.safe_cast(max_latency_ns, int, 0)
+ 'LatencyAvg': utils.safe_cast(avg_latency_ns, int, 0),
+ 'LatencyMin': utils.safe_cast(min_latency_ns, int, 0),
+ 'LatencyMax': utils.safe_cast(max_latency_ns, int, 0)
}
return results
@@ -600,34 +596,34 @@ class IxiaPppoeClientScenario(object):
flows_stats, flow, 'Store-Forward_Avg_latency_ns'))
for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num])
min_latency = \
- sum([float(self.get_flow_id_data(
+ min([float(self.get_flow_id_data(
flows_stats, flow, 'Store-Forward_Min_latency_ns'))
- for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num])
+ for flow in port_flow_map[port_num]])
max_latency = \
- sum([float(self.get_flow_id_data(
+ max([float(self.get_flow_id_data(
flows_stats, flow, 'Store-Forward_Max_latency_ns'))
- for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num])
+ for flow in port_flow_map[port_num]])
samples[port_name] = {
- 'rx_throughput_kps': float(ports_stats[port_num]['Rx_Rate_Kbps']),
- 'tx_throughput_kps': float(ports_stats[port_num]['Tx_Rate_Kbps']),
- 'rx_throughput_mbps': float(ports_stats[port_num]['Rx_Rate_Mbps']),
- 'tx_throughput_mbps': float(ports_stats[port_num]['Tx_Rate_Mbps']),
- 'in_packets': int(ports_stats[port_num]['Valid_Frames_Rx']),
- 'out_packets': int(ports_stats[port_num]['Frames_Tx']),
+ 'RxThroughputBps': float(ports_stats[port_num]['Bytes_Rx']) / duration,
+ 'TxThroughputBps': float(ports_stats[port_num]['Bytes_Tx']) / duration,
+ 'InPackets': int(ports_stats[port_num]['Valid_Frames_Rx']),
+ 'OutPackets': int(ports_stats[port_num]['Frames_Tx']),
+ 'InBytes': int(ports_stats[port_num]['Bytes_Rx']),
+ 'OutBytes': int(ports_stats[port_num]['Bytes_Tx']),
'RxThroughput': float(ports_stats[port_num]['Valid_Frames_Rx']) / duration,
'TxThroughput': float(ports_stats[port_num]['Frames_Tx']) / duration,
- 'Store-Forward_Avg_latency_ns': utils.safe_cast(avg_latency, int, 0),
- 'Store-Forward_Min_latency_ns': utils.safe_cast(min_latency, int, 0),
- 'Store-Forward_Max_latency_ns': utils.safe_cast(max_latency, int, 0)
+ 'LatencyAvg': utils.safe_cast(avg_latency, int, 0),
+ 'LatencyMin': utils.safe_cast(min_latency, int, 0),
+ 'LatencyMax': utils.safe_cast(max_latency, int, 0)
}
if port_subs_stats:
samples[port_name].update(
- {'sessions_up': int(port_subs_stats[0]['Sessions_Up']),
- 'sessions_down': int(port_subs_stats[0]['Sessions_Down']),
- 'sessions_not_started': int(port_subs_stats[0]['Sessions_Not_Started']),
- 'sessions_total': int(port_subs_stats[0]['Sessions_Total'])}
+ {'SessionsUp': int(port_subs_stats[0]['Sessions_Up']),
+ 'SessionsDown': int(port_subs_stats[0]['Sessions_Down']),
+ 'SessionsNotStarted': int(port_subs_stats[0]['Sessions_Not_Started']),
+ 'SessionsTotal': int(port_subs_stats[0]['Sessions_Total'])}
)
except IndexError:
@@ -843,9 +839,6 @@ class IxiaTrafficGen(SampleVNFTrafficGen):
self._ixia_traffic_gen = None
self.ixia_file_name = ''
self.vnf_port_pairs = []
- self._traffic_process = None
- self._tasks_queue = JoinableQueue()
- self._result_queue = Queue()
def _check_status(self):
pass
@@ -853,34 +846,3 @@ class IxiaTrafficGen(SampleVNFTrafficGen):
def terminate(self):
self.resource_helper.stop_collect()
super(IxiaTrafficGen, self).terminate()
-
- def _test_runner(self, traffic_profile, tasks, results):
- self.resource_helper.run_test(traffic_profile, tasks, results)
-
- def _init_traffic_process(self, traffic_profile):
- name = '{}-{}-{}-{}'.format(self.name, self.APP_NAME,
- traffic_profile.__class__.__name__,
- os.getpid())
- self._traffic_process = Process(name=name, target=self._test_runner,
- args=(
- traffic_profile, self._tasks_queue,
- self._result_queue))
-
- self._traffic_process.start()
- while self.resource_helper.client_started.value == 0:
- time.sleep(1)
- if not self._traffic_process.is_alive():
- break
-
- def run_traffic_once(self, traffic_profile):
- if self.resource_helper.client_started.value == 0:
- self._init_traffic_process(traffic_profile)
-
- # continue test - run next iteration
- LOG.info("Run next iteration ...")
- self._tasks_queue.put('RUN_TRAFFIC')
-
- def wait_on_traffic(self):
- self._tasks_queue.join()
- result = self._result_queue.get()
- return result
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
index 7c2079101..a9c0222ac 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,12 +15,14 @@
import logging
import time
+from six import moves
from yardstick.common import utils
from yardstick.network_services.vnf_generic.vnf import sample_vnf
from yardstick.network_services.vnf_generic.vnf import tg_trex
+from trex_stl_lib.trex_stl_exceptions import STLError
-LOGGING = logging.getLogger(__name__)
+LOG = logging.getLogger(__name__)
class TrexRfcResourceHelper(tg_trex.TrexResourceHelper):
@@ -48,7 +50,8 @@ class TrexRfcResourceHelper(tg_trex.TrexResourceHelper):
completed, output = traffic_profile.get_drop_percentage(
samples, self.rfc2544_helper.tolerance_low,
self.rfc2544_helper.tolerance_high,
- self.rfc2544_helper.correlated_traffic)
+ self.rfc2544_helper.correlated_traffic,
+ self.rfc2544_helper.resolution)
self._queue.put(output)
return completed
@@ -58,6 +61,56 @@ class TrexRfcResourceHelper(tg_trex.TrexResourceHelper):
def clear_client_stats(self, ports):
self.client.clear_stats(ports=ports)
+ def run_test(self, traffic_profile, tasks_queue, results_queue, *args): # pragma: no cover
+ LOG.debug("Trex resource_helper run_test")
+ if self._terminated.value:
+ return
+ # if we don't do this we can hang waiting for the queue to drain
+ # have to do this in the subprocess
+ self._queue.cancel_join_thread()
+ try:
+ self._build_ports()
+ self.client = self._connect()
+ self.client.reset(ports=self.all_ports)
+ self.client.remove_all_streams(self.all_ports) # remove all streams
+ traffic_profile.register_generator(self)
+
+ completed = False
+ self.rfc2544_helper.iteration.value = 0
+ self.client_started.value = 1
+ while completed is False and not self._terminated.value:
+ LOG.debug("Wait for task ...")
+ try:
+ task = tasks_queue.get(True, 5)
+ except moves.queue.Empty:
+ LOG.debug("Wait for task timeout, continue waiting...")
+ continue
+ else:
+ if task != 'RUN_TRAFFIC':
+ continue
+ self.rfc2544_helper.iteration.value += 1
+ LOG.info("Got %s task, start iteration %d", task,
+ self.rfc2544_helper.iteration.value)
+ completed = self._run_traffic_once(traffic_profile)
+ if completed:
+ LOG.debug("%s::run_test - test completed",
+ self.__class__.__name__)
+ results_queue.put('COMPLETE')
+ else:
+ results_queue.put('CONTINUE')
+ tasks_queue.task_done()
+
+ self.client.stop(self.all_ports)
+ self.client.disconnect()
+ self._terminated.value = 0
+ except STLError:
+ if self._terminated.value:
+ LOG.debug("traffic generator is stopped")
+ return # return if trex/tg server is stopped.
+ raise
+
+ self.client_started.value = 0
+ LOG.debug("%s::run_test done", self.__class__.__name__)
class TrexTrafficGenRFC(tg_trex.TrexTrafficGen):
"""
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_trex.py b/yardstick/network_services/vnf_generic/vnf/tg_trex.py
index 43ee82629..0cb66a714 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_trex.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_trex.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -179,6 +179,8 @@ class TrexResourceHelper(ClientResourceHelper):
'tx_throughput_bps': float(port_stats.get('tx_bps', 0.0)),
'in_packets': int(port_stats.get('ipackets', 0)),
'out_packets': int(port_stats.get('opackets', 0)),
+ 'in_bytes': int(port_stats.get('ibytes', 0)),
+ 'out_bytes': int(port_stats.get('obytes', 0)),
'timestamp': timestamp
}
diff --git a/yardstick/network_services/vnf_generic/vnf/udp_replay.py b/yardstick/network_services/vnf_generic/vnf/udp_replay.py
index fa92744d8..3f9994486 100644
--- a/yardstick/network_services/vnf_generic/vnf/udp_replay.py
+++ b/yardstick/network_services/vnf_generic/vnf/udp_replay.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py b/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
index 572243194..743f2d4bb 100644
--- a/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py b/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
index 08fcb5e14..322ecd016 100644
--- a/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
+++ b/yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.