diff options
Diffstat (limited to 'yardstick/network_services')
7 files changed, 122 insertions, 106 deletions
diff --git a/yardstick/network_services/traffic_profile/base.py b/yardstick/network_services/traffic_profile/base.py index a8f950b7b..4fbceea9b 100644 --- a/yardstick/network_services/traffic_profile/base.py +++ b/yardstick/network_services/traffic_profile/base.py @@ -44,6 +44,7 @@ class TrafficProfileConfig(object): self.lower_bound = tprofile.get('lower_bound') self.upper_bound = tprofile.get('upper_bound') self.step_interval = tprofile.get('step_interval') + self.enable_latency = tprofile.get('enable_latency', False) def _parse_rate(self, rate): """Parse traffic profile rate diff --git a/yardstick/network_services/traffic_profile/ixia_rfc2544.py b/yardstick/network_services/traffic_profile/ixia_rfc2544.py index ccaf3ded3..461604fb8 100644 --- a/yardstick/network_services/traffic_profile/ixia_rfc2544.py +++ b/yardstick/network_services/traffic_profile/ixia_rfc2544.py @@ -168,12 +168,8 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile): [samples[iface]['in_packets'] for iface in samples]) out_packets_sum = sum( [samples[iface]['out_packets'] for iface in samples]) - rx_throughput = sum( - [samples[iface]['RxThroughput'] for iface in samples]) - rx_throughput = round(float(rx_throughput), 2) - tx_throughput = sum( - [samples[iface]['TxThroughput'] for iface in samples]) - tx_throughput = round(float(tx_throughput), 2) + rx_throughput = round(float(in_packets_sum) / duration, 3) + tx_throughput = round(float(out_packets_sum) / duration, 3) packet_drop = abs(out_packets_sum - in_packets_sum) try: @@ -183,10 +179,6 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile): except ZeroDivisionError: LOG.info('No traffic is flowing') - samples['TxThroughput'] = tx_throughput - samples['RxThroughput'] = rx_throughput - samples['DropPercentage'] = drop_percent - if first_run: completed = True if drop_percent <= tolerance else False if (first_run and @@ -200,4 +192,21 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile): else: completed = True + 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 + + samples['TxThroughput'] = tx_throughput + samples['RxThroughput'] = rx_throughput + 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 + return completed, samples diff --git a/yardstick/network_services/traffic_profile/prox_binsearch.py b/yardstick/network_services/traffic_profile/prox_binsearch.py index 506a880e0..16a0411ec 100644 --- a/yardstick/network_services/traffic_profile/prox_binsearch.py +++ b/yardstick/network_services/traffic_profile/prox_binsearch.py @@ -25,6 +25,14 @@ from yardstick.common import constants as overall_constants LOG = logging.getLogger(__name__) +STATUS_SUCCESS = "Success" +STATUS_FAIL = "Failure" +STATUS_RESULT = "Result" +STEP_CONFIRM = "Confirm retry" +STEP_INCREASE_LOWER = "Increase lower" +STEP_DECREASE_LOWER = "Decrease lower" +STEP_DECREASE_UPPER = "Decrease upper" + class ProxBinSearchProfile(ProxProfile): """ @@ -85,18 +93,16 @@ class ProxBinSearchProfile(ProxProfile): # success, the binary search will complete on an integer multiple # of the precision, rather than on a fraction of it. - theor_max_thruput = actual_max_thruput = 0 + theor_max_thruput = 0 result_samples = {} - # Store one time only value in influxdb - single_samples = { + test_data = { "test_duration": traffic_gen.scenario_helper.scenario_cfg["runner"]["duration"], "test_precision": self.params["traffic_profile"]["test_precision"], "tolerated_loss": self.params["traffic_profile"]["tolerated_loss"], "duration": duration } - self.queue.put(single_samples) self.prev_time = time.time() # throughput and packet loss from the most recent successful test @@ -110,85 +116,88 @@ class ProxBinSearchProfile(ProxProfile): neg_retry = 0 total_retry = 0 - LOG.info("Checking MAX %s MIN %s TEST %s", - self.current_upper, self.lower_bound, test_value) + LOG.info("Checking MAX %s MIN %s TEST %s", self.current_upper, + self.lower_bound, test_value) + while (pos_retry <= ok_retry) and (neg_retry <= ok_retry): total_retry = total_retry + 1 + result, port_samples = self._profile_helper.run_test(pkt_size, duration, test_value, self.tolerated_loss, line_speed) - if (total_retry > (ok_retry * 3)) and (ok_retry is not 0): - LOG.info("Failure.!! .. RETRY EXCEEDED ... decrease lower bound") + if (total_retry > (ok_retry * 3)) and (ok_retry is not 0): + status = STATUS_FAIL + next_step = STEP_DECREASE_LOWER successful_pkt_loss = result.pkt_loss - samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples) - self.current_upper = test_value neg_retry = total_retry elif result.success: if (pos_retry < ok_retry) and (ok_retry is not 0): - neg_retry = 0 - LOG.info("Success! ... confirm retry") - + status = STATUS_SUCCESS + next_step = STEP_CONFIRM successful_pkt_loss = result.pkt_loss - samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples) - + neg_retry = 0 else: - LOG.info("Success! Increasing lower bound") + status = STATUS_SUCCESS + next_step = STEP_INCREASE_LOWER self.current_lower = test_value - successful_pkt_loss = result.pkt_loss - samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples) - - # store results with success tag in influxdb - success_samples = \ - {'Success_' + key: value for key, value in samples.items()} - - success_samples["Success_rx_total"] = int(result.rx_total) - success_samples["Success_tx_total"] = int(result.tx_total) - success_samples["Success_can_be_lost"] = int(result.can_be_lost) - success_samples["Success_drop_total"] = int(result.drop_total) - success_samples["Success_RxThroughput"] = samples["RxThroughput"] - success_samples["Success_RxThroughput_gbps"] = \ - (samples["RxThroughput"] / 1000) * ((pkt_size + 20)* 8) - LOG.info(">>>##>>Collect SUCCESS TG KPIs %s %s", - datetime.datetime.now(), success_samples) - self.queue.put(success_samples, True, overall_constants.QUEUE_PUT_TIMEOUT) - - # Store Actual throughput for result samples - actual_max_thruput = success_samples["Success_RxThroughput"] pos_retry = pos_retry + 1 else: if (neg_retry < ok_retry) and (ok_retry is not 0): - + status = STATUS_FAIL + next_step = STEP_CONFIRM pos_retry = 0 - LOG.info("failure! ... confirm retry") else: - LOG.info("Failure... Decreasing upper bound") + status = STATUS_FAIL + next_step = STEP_DECREASE_UPPER self.current_upper = test_value neg_retry = neg_retry + 1 - samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples) + + LOG.info( + "Status = '%s' Next_Step = '%s'", status, next_step) + + samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples) if theor_max_thruput < samples["TxThroughput"]: theor_max_thruput = samples['TxThroughput'] - self.queue.put({'theor_max_throughput': theor_max_thruput}) - - LOG.info(">>>##>>Collect TG KPIs %s %s", datetime.datetime.now(), samples) + samples['theor_max_throughput'] = theor_max_thruput + + samples["rx_total"] = int(result.rx_total) + samples["tx_total"] = int(result.tx_total) + samples["can_be_lost"] = int(result.can_be_lost) + samples["drop_total"] = int(result.drop_total) + samples["RxThroughput_gbps"] = \ + (samples["RxThroughput"] / 1000) * ((pkt_size + 20) * 8) + samples['Status'] = status + samples['Next_Step'] = next_step samples["MAX_Rate"] = self.current_upper samples["MIN_Rate"] = self.current_lower samples["Test_Rate"] = test_value samples["Step_Id"] = step_id samples["Confirmation_Retry"] = total_retry + + samples.update(test_data) + + if status == STATUS_SUCCESS and next_step == STEP_INCREASE_LOWER: + # Store success samples for result samples + result_samples = samples + + LOG.info(">>>##>>Collect TG KPIs %s %s", datetime.datetime.now(), samples) + self.queue.put(samples, True, overall_constants.QUEUE_PUT_TIMEOUT) - LOG.info(">>>##>> Result Reached PktSize %s Theor_Max_Thruput %s Actual_throughput %s", - pkt_size, theor_max_thruput, actual_max_thruput) - result_samples["Result_pktSize"] = pkt_size - result_samples["Result_theor_max_throughput"] = theor_max_thruput - result_samples["Result_Actual_throughput"] = actual_max_thruput + LOG.info( + ">>>##>> Result Reached PktSize %s Theor_Max_Thruput %s Actual_throughput %s", + pkt_size, theor_max_thruput, result_samples.get("RxThroughput", 0)) + result_samples["Status"] = STATUS_RESULT + result_samples["Next_Step"] = "" + result_samples["Actual_throughput"] = result_samples.get("RxThroughput", 0) + result_samples["theor_max_throughput"] = theor_max_thruput self.queue.put(result_samples) diff --git a/yardstick/network_services/traffic_profile/rfc2544.py b/yardstick/network_services/traffic_profile/rfc2544.py index b54fc575f..987029373 100644 --- a/yardstick/network_services/traffic_profile/rfc2544.py +++ b/yardstick/network_services/traffic_profile/rfc2544.py @@ -118,7 +118,8 @@ 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, @@ -126,7 +127,7 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile): force=True) 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,7 +135,8 @@ 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) @@ -213,7 +215,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,7 +239,8 @@ 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)) @@ -247,19 +250,16 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile): correlated_traffic): """Calculate the drop percentage and run the traffic""" completed = False - 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()) + 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()) + 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 + 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 diff --git a/yardstick/network_services/vnf_generic/vnf/tg_prox.py b/yardstick/network_services/vnf_generic/vnf/tg_prox.py index 854319a21..d12c42ec8 100644 --- a/yardstick/network_services/vnf_generic/vnf/tg_prox.py +++ b/yardstick/network_services/vnf_generic/vnf/tg_prox.py @@ -12,9 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import absolute_import - import logging +import copy from yardstick.network_services.utils import get_nsb_option from yardstick.network_services.vnf_generic.vnf.prox_vnf import ProxApproxVnf @@ -32,7 +31,9 @@ class ProxTrafficGen(SampleVNFTrafficGen): def __init__(self, name, vnfd, task_id, setup_env_helper_type=None, resource_helper_type=None): - # don't call superclass, use custom wrapper of ProxApproxVnf + vnfd_cpy = copy.deepcopy(vnfd) + super(ProxTrafficGen, self).__init__(name, vnfd_cpy, task_id) + self._vnf_wrapper = ProxApproxVnf( name, vnfd, task_id, setup_env_helper_type, resource_helper_type) self.bin_path = get_nsb_option('bin_path', '') 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 4d3bc2ce5..94ab06980 100644 --- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py +++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py @@ -60,7 +60,7 @@ class IxiaResourceHelper(ClientResourceHelper): def stop_collect(self): self._terminated.value = 1 - def generate_samples(self, ports, key=None): + def generate_samples(self, ports, duration): stats = self.get_stats() samples = {} @@ -70,27 +70,23 @@ class IxiaResourceHelper(ClientResourceHelper): try: # reverse lookup port name from port_num so the stats dict is descriptive intf = self.vnfd_helper.find_interface_by_port(port_num) - port_name = intf["name"] + port_name = intf['name'] + avg_latency = stats['Store-Forward_Avg_latency_ns'][port_num] + 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]), - # NOTE(ralonsoh): we need to make the traffic injection - # time variable. - "RxThroughput": int(stats["Valid_Frames_Rx"][port_num]) / 30, - "TxThroughput": int(stats["Frames_Tx"][port_num]) / 30, + '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]), + '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) } - if key: - avg_latency = stats["Store-Forward_Avg_latency_ns"][port_num] - min_latency = stats["Store-Forward_Min_latency_ns"][port_num] - max_latency = stats["Store-Forward_Max_latency_ns"][port_num] - samples[port_name][key] = \ - {"Store-Forward_Avg_latency_ns": avg_latency, - "Store-Forward_Min_latency_ns": min_latency, - "Store-Forward_Max_latency_ns": max_latency} except IndexError: pass @@ -129,13 +125,11 @@ class IxiaResourceHelper(ClientResourceHelper): self, self.client, mac) self.client_started.value = 1 # pylint: disable=unnecessary-lambda - utils.wait_until_true(lambda: self.client.is_traffic_stopped()) - samples = self.generate_samples(traffic_profile.ports) + utils.wait_until_true(lambda: self.client.is_traffic_stopped(), + timeout=traffic_profile.config.duration * 2) + samples = self.generate_samples(traffic_profile.ports, + traffic_profile.config.duration) - # NOTE(ralonsoh): the traffic injection duration is fixed to 30 - # seconds. This parameter is configurable and must be retrieved - # from the traffic_profile.full_profile information. - # Every flow must have the same duration. completed, samples = traffic_profile.get_drop_percentage( samples, min_tol, max_tol, first_run=first_run) self._queue.put(samples) diff --git a/yardstick/network_services/vnf_generic/vnf/tg_trex.py b/yardstick/network_services/vnf_generic/vnf/tg_trex.py index 58b73488b..4296da84c 100644 --- a/yardstick/network_services/vnf_generic/vnf/tg_trex.py +++ b/yardstick/network_services/vnf_generic/vnf/tg_trex.py @@ -11,8 +11,8 @@ # 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. -""" Trex acts as traffic generation and vnf definitions based on IETS Spec """ +import datetime import logging import os @@ -167,6 +167,7 @@ class TrexResourceHelper(ClientResourceHelper): def _get_samples(self, ports, port_pg_id=None): stats = self.get_stats(ports) + timestamp = datetime.datetime.now() samples = {} for pname in (intf['name'] for intf in self.vnfd_helper.interfaces): port_num = self.vnfd_helper.port_num(pname) @@ -178,6 +179,7 @@ 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)), + 'timestamp': timestamp } pg_id_list = port_pg_id.get_pg_ids(port_num) |