diff options
12 files changed, 1116 insertions, 251 deletions
diff --git a/samples/vnf_samples/nsut/bng/tc_bng_pppoe_rfc2544_ixia_8ports_1port_congested_IMIX.yaml b/samples/vnf_samples/nsut/bng/tc_bng_pppoe_rfc2544_ixia_8ports_1port_congested_IMIX.yaml index 2c2010a11..441886224 100644 --- a/samples/vnf_samples/nsut/bng/tc_bng_pppoe_rfc2544_ixia_8ports_1port_congested_IMIX.yaml +++ b/samples/vnf_samples/nsut/bng/tc_bng_pppoe_rfc2544_ixia_8ports_1port_congested_IMIX.yaml @@ -15,6 +15,9 @@ --- {% set sessions_per_port = sessions_per_port or 4000 %} {% set sessions_per_svlan = sessions_per_svlan or 1000 %} +{% set duration = duration or 60 %} +{% set tolerance_low = tolerance_low or 0.0001 %} +{% set tolerance_high = tolerance_high or 0.0001 %} schema: yardstick:task:0.1 description: > vBNG RFC2544 test case with QoS base line with link congestion. @@ -31,10 +34,11 @@ scenarios: tg__0: tg_0.yardstick vnf__0: vnf_0.yardstick options: + duration: {{ duration }} pppoe_client: # access network sessions_per_port: {{ sessions_per_port }} sessions_per_svlan: {{ sessions_per_svlan }} - pap_user: 'wfnos' + pap_user: 'pppoe_user' pap_password: '' ip: [{'tg__0': 'xe0'}, {'tg__0': 'xe2'}, {'tg__0': 'xe4'}, {'tg__0': 'xe6'}] s_vlan: 100 # s-vlan applies per device group @@ -52,17 +56,27 @@ scenarios: framesize: uplink: {70B: 33, 940B: 33, 1470B: 34} downlink: {68B: 3, 932B: 1, 1470B: 96} + priority: + # 0 - (000) Routine + # 1 - (001) Priority + # 2 - (010) Immediate + # 3 - (011) Flash + # 4 - (100) Flash Override + # 5 - (101) CRITIC/ECP + # 6 - (110) Internetwork Control + # 7 - (111) Network Control + tos: {precedence: [0, 4, 7]} flow: src_ip: [{'tg__0': 'xe0'}, {'tg__0': 'xe2'}, {'tg__0': 'xe4'}, {'tg__0': 'xe6'}] dst_ip: [{'tg__0': 'xe1'}, {'tg__0': 'xe3'}, {'tg__0': 'xe5'}, {'tg__0': 'xe7'}] count: 1 traffic_type: 4 rfc2544: - allowed_drop_rate: 0.0001 - 0.0001 + allowed_drop_rate: "{{ tolerance_low }} - {{ tolerance_high }}" runner: type: Iteration - iterations: 10 - interval: 75 + iterations: 1 + interval: {{ duration + 15 }} context: type: Node name: yardstick diff --git a/samples/vnf_samples/nsut/bng/tc_bng_pppoe_rfc2544_ixia_IMIX_scale_up.yaml b/samples/vnf_samples/nsut/bng/tc_bng_pppoe_rfc2544_ixia_IMIX_scale_up.yaml index f0696ab24..afd60cc69 100644 --- a/samples/vnf_samples/nsut/bng/tc_bng_pppoe_rfc2544_ixia_IMIX_scale_up.yaml +++ b/samples/vnf_samples/nsut/bng/tc_bng_pppoe_rfc2544_ixia_IMIX_scale_up.yaml @@ -15,8 +15,10 @@ --- {% set sessions_per_port = sessions_per_port or 4000 %} {% set sessions_per_svlan = sessions_per_svlan or 1000 %} +{% set duration = duration or 60 %} {% set vports = vports or 2 %} -{% set svlans_per_port = sessions_per_port / sessions_per_svlan %} +{% set tolerance_low = tolerance_low or 0.0001 %} +{% set tolerance_high = tolerance_high or 0.0001 %} schema: yardstick:task:0.1 description: > vBNG RFC2544 test case with QoS base line without link congestion. @@ -28,16 +30,16 @@ scenarios: topology: "../agnostic/agnostic_vnf_topology_ixia_{{ vports }}ports.yaml" ixia_config: IxiaPppoeClient extra_args: - svlans_per_port: {{ svlans_per_port|int }} access_vports_num: {{ vports|int / 2 }} nodes: tg__0: tg_0.yardstick vnf__0: vnf_0.yardstick options: + duration: {{ duration }} pppoe_client: # access network sessions_per_port: {{ sessions_per_port }} sessions_per_svlan: {{ sessions_per_svlan }} - pap_user: 'wfnos' + pap_user: 'pppoe_user' pap_password: '' ip: {% for vnf_num in range(0, vports|int, 2) %} @@ -64,6 +66,16 @@ scenarios: framesize: uplink: {70B: 33, 940B: 33, 1470B: 34} downlink: {68B: 3, 932B: 1, 1470B: 96} + priority: + # 0 - (000) Routine + # 1 - (001) Priority + # 2 - (010) Immediate + # 3 - (011) Flash + # 4 - (100) Flash Override + # 5 - (101) CRITIC/ECP + # 6 - (110) Internetwork Control + # 7 - (111) Network Control + tos: {precedence: [0, 4, 7]} flow: src_ip: {% for vnf_num in range(0, vports|int, 2) %} @@ -76,11 +88,11 @@ scenarios: count: 1 traffic_type: 4 rfc2544: - allowed_drop_rate: 0.0001 - 0.0001 + allowed_drop_rate: "{{ tolerance_low }} - {{ tolerance_high }}" runner: type: Iteration iterations: 10 - interval: 75 + interval: {{ duration + 15 }} context: type: Node name: yardstick diff --git a/samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vbng_1port_congested-8.yaml b/samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vbng_1port_congested-8.yaml index a3170048a..77bc55751 100644 --- a/samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vbng_1port_congested-8.yaml +++ b/samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vbng_1port_congested-8.yaml @@ -25,9 +25,10 @@ traffic_profile: duration: {{ duration }} enable_latency: True -uplink_0: +uplink_0: # traffic flow from xe0 to xe1 ipv4: id: 1 + frame_rate: 25% port: xe0 outer_l2: framesize: &uplink_framesize @@ -49,12 +50,17 @@ uplink_0: 1518B: "{{get(imix, 'imix.uplink.1518B', '0') }}" outer_l3v4: - priority: + priority: &uplink_precedence + {% if priority %} + {{ priority }} + {% else %} tos: - precedence: &uplink_precedence [0, 4, 7] -downlink_0: + precedence: [0, 4, 7] + {% endif %} +downlink_0: # traffic flow from xe1 to xe0 ipv4: id: 2 + frame_rate: 50% port: xe1 outer_l2: framesize: &downlink_framesize @@ -76,337 +82,311 @@ downlink_0: 1518B: "{{get(imix, 'imix.downlink.1518B', '0') }}" outer_l3v4: - priority: + priority: &downlink_precedence + {% if priority %} + {{ priority }} + {% else %} tos: - precedence: &downlink_precedence [0, 4, 7] -uplink_1: + precedence: [0, 4, 7] + {% endif %} +uplink_1: # traffic flow from xe0 to xe1 ipv4: id: 3 + frame_rate: 25% port: xe0 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_1: + priority: *uplink_precedence +downlink_1: # traffic flow from xe1 to xe0 ipv4: id: 4 + frame_rate: 50% port: xe1 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_2: + priority: *downlink_precedence +uplink_2: # traffic flow from xe0 to xe3 ipv4: id: 5 + frame_rate: 25% port: xe0 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_2: + priority: *uplink_precedence +downlink_2: # traffic flow from xe3 to xe0 ipv4: id: 6 + frame_rate: 50% port: xe3 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_3: + priority: *downlink_precedence +uplink_3: # traffic flow from xe0 to xe3 ipv4: id: 7 + frame_rate: 25% port: xe0 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_3: + priority: *uplink_precedence +downlink_3: # traffic flow from xe3 to xe0 ipv4: id: 8 + frame_rate: 50% port: xe3 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_4: + priority: *downlink_precedence +uplink_4: # traffic flow from xe2 to xe5 ipv4: id: 9 + frame_rate: 25% port: xe2 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_4: + priority: *uplink_precedence +downlink_4: # traffic flow from xe5 to xe2 ipv4: id: 10 + frame_rate: 7% port: xe5 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_5: + priority: *downlink_precedence +uplink_5: # traffic flow from xe2 to xe5 ipv4: id: 11 + frame_rate: 25% port: xe2 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_5: + priority: *uplink_precedence +downlink_5: # traffic flow from xe5 to xe2 ipv4: id: 12 + frame_rate: 7% port: xe5 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_6: + priority: *downlink_precedence +uplink_6: # traffic flow from xe2 to xe5 ipv4: id: 13 + frame_rate: 25% port: xe2 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_6: + priority: *uplink_precedence +downlink_6: # traffic flow from xe5 to xe2 ipv4: id: 14 + frame_rate: 7% port: xe5 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_7: + priority: *downlink_precedence +uplink_7: # traffic flow from xe2 to xe5 ipv4: id: 15 + frame_rate: 25% port: xe2 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_7: + priority: *uplink_precedence +downlink_7: # traffic flow from xe5 to xe2 ipv4: id: 16 + frame_rate: 7% port: xe5 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_8: + priority: *downlink_precedence +uplink_8: # traffic flow from xe4 to xe5 ipv4: id: 17 + frame_rate: 25% port: xe4 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_8: + priority: *uplink_precedence +downlink_8: # traffic flow from xe5 to xe4 ipv4: id: 18 + frame_rate: 7% port: xe5 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_9: + priority: *downlink_precedence +uplink_9: # traffic flow from xe4 to xe5 ipv4: id: 19 + frame_rate: 25% port: xe4 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_9: + priority: *uplink_precedence +downlink_9: # traffic flow from xe5 to xe4 ipv4: id: 20 + frame_rate: 7% port: xe5 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_10: + priority: *downlink_precedence +uplink_10: # traffic flow from xe4 to xe7 ipv4: id: 21 + frame_rate: 25% port: xe4 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_10: + priority: *uplink_precedence +downlink_10: # traffic flow from xe7 to xe4 ipv4: id: 22 + frame_rate: 7% port: xe7 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_11: + priority: *downlink_precedence +uplink_11: # traffic flow from xe4 to xe7 ipv4: id: 23 + frame_rate: 25% port: xe4 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_11: + priority: *uplink_precedence +downlink_11: # traffic flow from xe7 to xe4 ipv4: id: 24 + frame_rate: 7% port: xe7 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence + priority: *downlink_precedence -uplink_12: +uplink_12: # traffic flow from xe6 to xe7 ipv4: id: 25 + frame_rate: 25% port: xe6 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_12: + priority: *uplink_precedence +downlink_12: # traffic flow from xe7 to xe6 ipv4: id: 26 + frame_rate: 7% port: xe7 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_13: + priority: *downlink_precedence +uplink_13: # traffic flow from xe6 to xe7 ipv4: id: 27 + frame_rate: 25% port: xe6 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_13: + priority: *uplink_precedence +downlink_13: # traffic flow from xe7 to xe6 ipv4: id: 28 + frame_rate: 7% port: xe7 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_14: + priority: *downlink_precedence +uplink_14: # traffic flow from xe6 to xe7 ipv4: id: 29 + frame_rate: 25% port: xe6 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_14: + priority: *uplink_precedence +downlink_14: # traffic flow from xe7 to xe6 ipv4: id: 30 + frame_rate: 7% port: xe7 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence -uplink_15: + priority: *downlink_precedence +uplink_15: # traffic flow from xe6 to xe7 ipv4: id: 31 + frame_rate: 25% port: xe6 outer_l2: framesize: *uplink_framesize outer_l3v4: - priority: - tos: - precedence: *uplink_precedence -downlink_15: + priority: *uplink_precedence +downlink_15: # traffic flow from xe7 to xe6 ipv4: id: 32 + frame_rate: 7% port: xe7 outer_l2: framesize: *downlink_framesize outer_l3v4: - priority: - tos: - precedence: *downlink_precedence + priority: *downlink_precedence diff --git a/samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vbng_scale_up.yaml b/samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vbng_scale_up.yaml index 4f427b76a..91658a586 100644 --- a/samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vbng_scale_up.yaml +++ b/samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vbng_scale_up.yaml @@ -13,7 +13,6 @@ # limitations under the License. --- -{% set svlan_per_port = get(extra_args, 'svlans_per_port') %} {% set ports = get(extra_args, 'access_vports_num')|int %} schema: "nsb:traffic_profile:0.1" @@ -23,11 +22,11 @@ name: rfc2544 description: Traffic profile to run RFC2544 latency traffic_profile: traffic_type : IXIARFC2544PppoeScenarioProfile # defines traffic behavior - constant or look for highest possible throughput - frame_rate : 12.5% # pc of linerate + frame_rate : 100% # pc of linerate duration: {{ duration }} enable_latency: True -{% for i in range(svlan_per_port|int * ports|int) %} +{% for i in range(ports|int) %} uplink_{{ i }}: ipv4: id: {{ (i * 2) + 1 }} @@ -51,9 +50,13 @@ uplink_{{ i }}: 1518B: "{{get(imix, 'imix.uplink.1518B', '0') }}" outer_l3v4: - priority: - tos: - precedence: [0, 4, 7] + priority: + {% if priority %} + {{ priority }} + {% else %} + tos: + precedence: [0, 4, 7] + {% endif %} downlink_{{ i }}: ipv4: id: {{ (i * 2) + 2 }} @@ -77,7 +80,11 @@ downlink_{{ i }}: 1518B: "{{get(imix, 'imix.downlink.1518B', '0') }}" outer_l3v4: - priority: - tos: - precedence: [0, 4, 7] + priority: + {% if priority %} + {{ priority }} + {% else %} + tos: + precedence: [0, 4, 7] + {% endif %} {% endfor %} diff --git a/yardstick/benchmark/scenarios/networking/vnf_generic.py b/yardstick/benchmark/scenarios/networking/vnf_generic.py index 3fd1845a0..dd5f4726f 100644 --- a/yardstick/benchmark/scenarios/networking/vnf_generic.py +++ b/yardstick/benchmark/scenarios/networking/vnf_generic.py @@ -164,6 +164,13 @@ class NetworkServiceBase(scenario_base.Scenario): imix = {} return imix + def _get_ip_priority(self): + try: + priority = self.scenario_cfg['options']['priority'] + except KeyError: + priority = {} + return priority + def _get_traffic_profile(self): profile = self.scenario_cfg["traffic_profile"] path = self.scenario_cfg["task_path"] @@ -201,6 +208,7 @@ class NetworkServiceBase(scenario_base.Scenario): tprofile_data = { 'flow': self._get_traffic_flow(), 'imix': self._get_traffic_imix(), + 'priority': self._get_ip_priority(), tprofile_base.TrafficProfile.UPLINK: {}, tprofile_base.TrafficProfile.DOWNLINK: {}, 'extra_args': extra_args, 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 cc627ef78..e0b7aa000 100644 --- a/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py +++ b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py @@ -14,6 +14,8 @@ import ipaddress import logging +import re +import collections import IxNetwork @@ -62,6 +64,13 @@ SUPPORTED_TOS_FIELDS = [ 'reliability' ] +IP_PRIORITY_PATTERN = r'[^\w+]*.+(Raw priority|' \ + 'Precedence|' \ + 'Default PHB|' \ + 'Class selector PHB|' \ + 'Assured forwarding selector PHB|' \ + 'Expedited forwarding PHB)' + class Vlan(object): def __init__(self, @@ -99,6 +108,18 @@ class IxNextgen(object): # pragma: no cover "Store-Forward_Max_latency_ns": 'Store-Forward Max Latency (ns)', } + FLOWS_STATS_NAME_MAP = { + "Tx_Port": 'Tx Port', + "VLAN-ID": 'VLAN:VLAN-ID', + "IP_Priority": re.compile(IP_PRIORITY_PATTERN), + "Flow_Group": 'Flow Group', + "Tx_Frames": 'Tx Frames', + "Rx_Frames": 'Rx Frames', + "Store-Forward_Avg_latency_ns": 'Store-Forward Avg Latency (ns)', + "Store-Forward_Min_latency_ns": 'Store-Forward Min Latency (ns)', + "Store-Forward_Max_latency_ns": 'Store-Forward Max Latency (ns)' + } + PPPOX_CLIENT_PER_PORT_NAME_MAP = { 'subs_port': 'Port', 'Sessions_Up': 'Sessions Up', @@ -111,6 +132,18 @@ class IxNextgen(object): # pragma: no cover FLOW_STATISTICS = '::ixNet::OBJ-/statistics/view:"Flow Statistics"' PPPOX_CLIENT_PER_PORT = '::ixNet::OBJ-/statistics/view:"PPPoX Client Per Port"' + PPPOE_SCENARIO_STATS = { + 'port_statistics': PORT_STATISTICS, + 'flow_statistic': FLOW_STATISTICS, + 'pppox_client_per_port': PPPOX_CLIENT_PER_PORT + } + + PPPOE_SCENARIO_STATS_MAP = { + 'port_statistics': PORT_STATS_NAME_MAP, + 'flow_statistic': FLOWS_STATS_NAME_MAP, + 'pppox_client_per_port': PPPOX_CLIENT_PER_PORT_NAME_MAP + } + @staticmethod def get_config(tg_cfg): card = [] @@ -731,6 +764,19 @@ class IxNextgen(object): # pragma: no cover 'getColumnValues', view_obj, data_ixia) for data_yardstick, data_ixia in name_map.items()} + def _get_view_page_stats(self, view_obj): + """Get full view page stats + + :param view_obj: view object, e.g. + '::ixNet::OBJ-/statistics/view:"Port Statistics"' + :return: (list) List of dicts. Each dict represents view page row + """ + view = view_obj + '/page' + column_headers = self.ixnet.getAttribute(view, '-columnCaptions') + view_rows = self.ixnet.getAttribute(view, '-rowValues') + view_page = [dict(zip(column_headers, row[0])) for row in view_rows] + return view_page + def _set_egress_flow_tracking(self, encapsulation, offset): """Set egress flow tracking options @@ -753,7 +799,7 @@ class IxNextgen(object): # pragma: no cover self.ixnet.setAttribute(enc_obj, '-offset', offset) self.ixnet.commit() - def _set_flow_tracking(self, track_by): + def set_flow_tracking(self, track_by): """Set flow tracking options :param track_by: list of tracking fields @@ -780,24 +826,39 @@ class IxNextgen(object): # pragma: no cover return stats def get_pppoe_scenario_statistics(self): - """Retrieve port, flow and PPPoE subscribers statistics - - "Port Statistics" parameters are stored in self.PORT_STATS_NAME_MAP. - "Flow Statistics" parameters are stored in self.LATENCY_NAME_MAP. - "PPPoX Client Per Port" parameters are stored in - self.PPPOE_CLIENT_PER_PORT_NAME_MAP - - :return: dictionary with the statistics; the keys of this dictionary - are PORT_STATS_NAME_MAP, LATENCY_NAME_MAP and - PPPOE_CLIENT_PER_PORT_NAME_MAP keys. - """ - stats = self._build_stats_map(self.PORT_STATISTICS, - self.PORT_STATS_NAME_MAP) - stats.update(self._build_stats_map(self.FLOW_STATISTICS, - self.LATENCY_NAME_MAP)) - stats.update(self._build_stats_map(self.PPPOX_CLIENT_PER_PORT, - self.PPPOX_CLIENT_PER_PORT_NAME_MAP)) - return stats + """Retrieve port, flow and PPPoE subscribers statistics""" + stats = collections.defaultdict(list) + result = collections.defaultdict(list) + for stat, view in self.PPPOE_SCENARIO_STATS.items(): + # Get view total pages number + total_pages = self.ixnet.getAttribute( + view + '/page', '-totalPages') + # Collect stats from all view pages + for page in range(1, int(total_pages) + 1): + current_page = int(self.ixnet.getAttribute( + view + '/page', '-currentPage')) + if page != int(current_page): + self.ixnet.setAttribute(view + '/page', '-currentPage', + str(page)) + self.ixnet.commit() + page_data = self._get_view_page_stats(view) + stats[stat].extend(page_data) + # Filter collected views stats + for stat in stats: + for view_row in stats[stat]: + filtered_row = {} + for key, value in self.PPPOE_SCENARIO_STATS_MAP[stat].items(): + if isinstance(value, str): + filtered_row.update({key: view_row[value]}) + # Handle keys which values are represented by regex + else: + for k in view_row.keys(): + if value.match(k): + value = value.match(k).group() + filtered_row.update({key: view_row[value]}) + break + result[stat].append(filtered_row) + return result def start_protocols(self): self.ixnet.execute('startAllProtocols') diff --git a/yardstick/network_services/traffic_profile/ixia_rfc2544.py b/yardstick/network_services/traffic_profile/ixia_rfc2544.py index 7df590fb3..89bb3ef7a 100644 --- a/yardstick/network_services/traffic_profile/ixia_rfc2544.py +++ b/yardstick/network_services/traffic_profile/ixia_rfc2544.py @@ -146,12 +146,16 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile): return result - def _ixia_traffic_generate(self, traffic, ixia_obj): + def _ixia_traffic_generate(self, traffic, ixia_obj, traffic_gen): ixia_obj.update_frame(traffic, self.config.duration) ixia_obj.update_ip_packet(traffic) ixia_obj.update_l4(traffic) + self._update_traffic_tracking_options(traffic_gen) ixia_obj.start_traffic() + def _update_traffic_tracking_options(self, traffic_gen): + traffic_gen.update_tracking_options() + def update_traffic_profile(self, traffic_generator): def port_generator(): for vld_id, intfs in sorted(traffic_generator.networks.items()): @@ -183,11 +187,12 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile): self.rate = self._get_next_rate() traffic = self._get_ixia_traffic_profile(self.full_profile, mac) - self._ixia_traffic_generate(traffic, ixia_obj) + self._ixia_traffic_generate(traffic, ixia_obj, traffic_generator) return first_run + # pylint: disable=unused-argument def get_drop_percentage(self, samples, tol_min, tolerance, precision, - resolution, first_run=False): + resolution, first_run=False, tc_rfc2544_opts=None): completed = False drop_percent = 100.0 num_ifaces = len(samples) @@ -275,12 +280,131 @@ class IXIARFC2544PppoeScenarioProfile(IXIARFC2544Profile): self.full_profile.update({downlink: self.params[downlink]}) def update_traffic_profile(self, traffic_generator): + + networks = collections.OrderedDict() + + # Sort network interfaces pairs + for i in range(len(traffic_generator.networks)): + uplink = '_'.join([self.UPLINK, str(i)]) + downlink = '_'.join([self.DOWNLINK, str(i)]) + if uplink in traffic_generator.networks: + networks[uplink] = traffic_generator.networks[uplink] + if downlink in traffic_generator.networks: + networks[downlink] = traffic_generator.networks[downlink] + def port_generator(): - for vld_id, intfs in sorted(traffic_generator.networks.items()): - if not vld_id.startswith((self.UPLINK, self.DOWNLINK)): - continue + for intfs in networks.values(): for intf in intfs: yield traffic_generator.vnfd_helper.port_num(intf) self._get_flow_groups_params() self.ports = [port for port in port_generator()] + + def _get_prio_flows_drop_percentage(self, stats): + 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']) + try: + drop_percent = round( + (sum_packet_drop / float(prio_flow['out_packets'])) * 100, + self.DROP_PERCENT_ROUND) + except ZeroDivisionError: + LOG.info('No traffic is flowing') + prio_flow['DropPercentage'] = drop_percent + return stats + + def _get_summary_pppoe_subs_counters(self, samples): + result = {} + keys = ['sessions_up', + 'sessions_down', + 'sessions_not_started', + 'sessions_total'] + for key in keys: + result[key] = \ + sum([samples[port][key] for port in samples + if key in samples[port]]) + return result + + def get_drop_percentage(self, samples, tol_min, tolerance, precision, + resolution, first_run=False, tc_rfc2544_opts=None): + completed = False + sum_drop_percent = 100 + num_ifaces = len(samples) + duration = self.config.duration + 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]) + out_packets_sum = sum( + [samples[iface]['out_packets'] for iface in samples]) + rx_throughput = round(float(in_packets_sum) / duration, 3) + tx_throughput = round(float(out_packets_sum) / duration, 3) + sum_packet_drop = abs(out_packets_sum - in_packets_sum) + + try: + sum_drop_percent = round( + (sum_packet_drop / float(out_packets_sum)) * 100, + self.DROP_PERCENT_ROUND) + 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 + + samples['TxThroughput'] = tx_throughput + samples['RxThroughput'] = rx_throughput + 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.update(summary_subs_stats) + + if tc_rfc2544_opts: + priority = tc_rfc2544_opts.get('priority') + if priority: + drop_percent = samples['priority'][priority]['DropPercentage'] + else: + drop_percent = sum_drop_percent + else: + drop_percent = sum_drop_percent + + if first_run: + completed = True if drop_percent <= tolerance else False + if (first_run and + self.rate_unit == tp_base.TrafficProfileConfig.RATE_FPS): + self.rate = float(out_packets_sum) / duration / num_ifaces + + if drop_percent > tolerance: + self.max_rate = self.rate + elif drop_percent < tol_min: + self.min_rate = self.rate + else: + completed = True + + next_rate = self._get_next_rate() + if abs(next_rate - self.rate) < resolution: + LOG.debug("rate=%s, next_rate=%s, resolution=%s", self.rate, + next_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("tolerance=%s, tolerance_precision=%s drop_percent=%s " + "completed=%s", tolerance, precision, drop_percent, + completed) + + samples['Status'] = self.STATUS_FAIL + if round(drop_percent, precision) <= tolerance: + samples['Status'] = self.STATUS_SUCCESS + + return completed, samples 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 2c3140f8c..f8eec4f4c 100644 --- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py +++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py @@ -15,6 +15,7 @@ import ipaddress import logging import six +import collections import os import time @@ -34,7 +35,7 @@ LOG = logging.getLogger(__name__) WAIT_AFTER_CFG_LOAD = 10 WAIT_FOR_TRAFFIC = 30 -WAIT_PROTOCOLS_STARTED = 360 +WAIT_PROTOCOLS_STARTED = 420 class IxiaBasicScenario(object): @@ -66,6 +67,47 @@ class IxiaBasicScenario(object): self.client.create_traffic_model(self._uplink_vports, self._downlink_vports) + def _get_stats(self): + return self.client.get_statistics() + + def generate_samples(self, resource_helper, ports, duration): + stats = self._get_stats() + + samples = {} + # this is not DPDK port num, but this is whatever number we gave + # when we selected ports and programmed the profile + for port_num in ports: + try: + # reverse lookup port name from port_num so the stats dict is descriptive + intf = resource_helper.vnfd_helper.find_interface_by_port(port_num) + 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]), + '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) + } + except IndexError: + pass + + return samples + + def update_tracking_options(self): + pass + + def get_tc_rfc2544_options(self): + pass + class IxiaL3Scenario(IxiaBasicScenario): """Ixia scenario for L3 flow between static ip's""" @@ -172,8 +214,12 @@ class IxiaPppoeClientScenario(object): traffic_profile.full_profile) endpoints_obj_pairs = \ self._get_endpoints_src_dst_obj_pairs(endpoints_id_pairs) - uplink_endpoints = endpoints_obj_pairs[::2] - downlink_endpoints = endpoints_obj_pairs[1::2] + if endpoints_obj_pairs: + uplink_endpoints = endpoints_obj_pairs[::2] + downlink_endpoints = endpoints_obj_pairs[1::2] + else: + uplink_endpoints = self._access_topologies + downlink_endpoints = self._core_topologies self.client.create_ipv4_traffic_model(uplink_endpoints, downlink_endpoints) @@ -266,18 +312,14 @@ class IxiaPppoeClientScenario(object): device groups pairs between which flow groups will be created: 1. In case uplink/downlink flows in traffic profile doesn't have - specified 'port' key, flows will be created between each device - group on access port and device group on corresponding core port. + specified 'port' key, flows will be created between topologies + on corresponding access and core port. E.g.: - Device groups created on access port xe0: dg1, dg2, dg3 - Device groups created on core port xe1: dg4 + Access topology on xe0: topology1 + Core topology on xe1: topology2 Flows will be created between: - dg1 -> dg4 - dg4 -> dg1 - dg2 -> dg4 - dg4 -> dg2 - dg3 -> dg4 - dg4 -> dg3 + topology1 -> topology2 + topology2 -> topology1 2. In case uplink/downlink flows in traffic profile have specified 'port' key, flows will be created between device groups on this @@ -338,13 +380,6 @@ class IxiaPppoeClientScenario(object): [endpoint_obj_pairs.extend([up, down]) for up, down in zip(uplink_dev_groups, downlink_dev_groups)] - if not endpoint_obj_pairs: - for up, down in zip(uplink_ports, downlink_ports): - uplink_dev_groups = port_to_dev_group_mapping[up] - downlink_dev_groups = \ - port_to_dev_group_mapping[down] * len(uplink_dev_groups) - [endpoint_obj_pairs.extend(list(i)) - for i in zip(uplink_dev_groups, downlink_dev_groups)] return endpoint_obj_pairs def _fill_ixia_config(self): @@ -438,6 +473,168 @@ class IxiaPppoeClientScenario(object): bgp_type=ipv4["bgp"].get("bgp_type")) self.protocols.append(bgp_peer_obj) + def update_tracking_options(self): + priority_map = { + 'raw': 'ipv4Raw0', + 'tos': {'precedence': 'ipv4Precedence0'}, + 'dscp': {'defaultPHB': 'ipv4DefaultPhb0', + 'selectorPHB': 'ipv4ClassSelectorPhb0', + 'assuredPHB': 'ipv4AssuredForwardingPhb0', + 'expeditedPHB': 'ipv4ExpeditedForwardingPhb0'} + } + + prio_trackby_key = 'ipv4Precedence0' + + try: + priority = list(self._ixia_cfg['priority'])[0] + if priority == 'raw': + prio_trackby_key = priority_map[priority] + elif priority in ['tos', 'dscp']: + priority_type = list(self._ixia_cfg['priority'][priority])[0] + prio_trackby_key = priority_map[priority][priority_type] + except KeyError: + pass + + tracking_options = ['flowGroup0', 'vlanVlanId0', prio_trackby_key] + self.client.set_flow_tracking(tracking_options) + + def get_tc_rfc2544_options(self): + return self._ixia_cfg.get('rfc2544') + + def _get_stats(self): + return self.client.get_pppoe_scenario_statistics() + + @staticmethod + def get_flow_id_data(stats, flow_id, key): + result = [float(flow.get(key)) for flow in stats if flow['id'] == flow_id] + return sum(result) / len(result) + + def get_priority_flows_stats(self, samples, duration): + results = {} + priorities = set([flow['IP_Priority'] for flow in samples]) + for priority in priorities: + tx_frames = sum( + [int(flow['Tx_Frames']) for flow in samples + if flow['IP_Priority'] == priority]) + rx_frames = sum( + [int(flow['Rx_Frames']) for flow in samples + if flow['IP_Priority'] == priority]) + prio_flows_num = len([flow for flow in samples + if flow['IP_Priority'] == priority]) + 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( + [int(flow['Store-Forward_Min_latency_ns']) for flow in samples + if flow['IP_Priority'] == priority]) / prio_flows_num + max_latency_ns = sum( + [int(flow['Store-Forward_Max_latency_ns']) for flow in samples + if flow['IP_Priority'] == priority]) / prio_flows_num + tx_throughput = float(tx_frames) / duration + rx_throughput = float(rx_frames) / duration + results[priority] = { + 'in_packets': rx_frames, + 'out_packets': 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) + } + return results + + def generate_samples(self, resource_helper, ports, duration): + + stats = self._get_stats() + samples = {} + ports_stats = stats['port_statistics'] + flows_stats = stats['flow_statistic'] + pppoe_subs_per_port = stats['pppox_client_per_port'] + + # Get sorted list of ixia ports names + ixia_port_names = sorted([data['port_name'] for data in ports_stats]) + + # Set 'port_id' key for ports stats items + for item in ports_stats: + port_id = item.pop('port_name').split('-')[-1].strip() + item['port_id'] = int(port_id) + + # Set 'id' key for flows stats items + for item in flows_stats: + flow_id = item.pop('Flow_Group').split('-')[1].strip() + item['id'] = int(flow_id) + + # Set 'port_id' key for pppoe subs per port stats + for item in pppoe_subs_per_port: + port_id = item.pop('subs_port').split('-')[-1].strip() + item['port_id'] = int(port_id) + + # Map traffic flows to ports + port_flow_map = collections.defaultdict(set) + for item in flows_stats: + tx_port = item.pop('Tx_Port') + tx_port_index = ixia_port_names.index(tx_port) + port_flow_map[tx_port_index].update([item['id']]) + + # Sort ports stats + ports_stats = sorted(ports_stats, key=lambda k: k['port_id']) + + # Get priority flows stats + prio_flows_stats = self.get_priority_flows_stats(flows_stats, duration) + samples['priority_stats'] = prio_flows_stats + + # this is not DPDK port num, but this is whatever number we gave + # when we selected ports and programmed the profile + for port_num in ports: + try: + # reverse lookup port name from port_num so the stats dict is descriptive + intf = resource_helper.vnfd_helper.find_interface_by_port(port_num) + port_name = intf['name'] + port_id = ports_stats[port_num]['port_id'] + port_subs_stats = \ + [port_data for port_data in pppoe_subs_per_port + if port_data.get('port_id') == port_id] + + avg_latency = \ + sum([float(self.get_flow_id_data( + 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( + flows_stats, flow, 'Store-Forward_Min_latency_ns')) + for flow in port_flow_map[port_num]]) / len(port_flow_map[port_num]) + max_latency = \ + sum([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]) + + 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']), + '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) + } + + 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'])} + ) + + except IndexError: + pass + + return samples + class IxiaRfc2544Helper(Rfc2544ResourceHelper): @@ -474,9 +671,6 @@ class IxiaResourceHelper(ClientResourceHelper): def _connect(self, client=None): self.client.connect(self.vnfd_helper) - def get_stats(self, *args, **kwargs): - return self.client.get_statistics() - def setup(self): super(IxiaResourceHelper, self).setup() self._init_ix_scenario() @@ -486,36 +680,7 @@ class IxiaResourceHelper(ClientResourceHelper): self._terminated.value = 1 def generate_samples(self, ports, duration): - stats = self.get_stats() - - samples = {} - # this is not DPDK port num, but this is whatever number we gave - # when we selected ports and programmed the profile - for port_num in ports: - 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'] - 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]), - '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) - } - except IndexError: - pass - - return samples + return self._ix_scenario.generate_samples(self, ports, duration) def _init_ix_scenario(self): ixia_config = self.scenario_helper.scenario_cfg.get('ixia_config', 'IxiaBasic') @@ -536,6 +701,9 @@ class IxiaResourceHelper(ClientResourceHelper): self._ix_scenario.apply_config() self._ix_scenario.create_traffic_model(traffic_profile) + def update_tracking_options(self): + self._ix_scenario.update_tracking_options() + def run_traffic(self, traffic_profile): if self._terminated.value: return @@ -570,12 +738,13 @@ class IxiaResourceHelper(ClientResourceHelper): # pylint: disable=unnecessary-lambda utils.wait_until_true(lambda: self.client.is_traffic_stopped(), timeout=traffic_profile.config.duration * 2) + rfc2544_opts = self._ix_scenario.get_tc_rfc2544_options() samples = self.generate_samples(traffic_profile.ports, traffic_profile.config.duration) completed, samples = traffic_profile.get_drop_percentage( samples, min_tol, max_tol, precision, resolution, - first_run=first_run) + first_run=first_run, tc_rfc2544_opts=rfc2544_opts) self._queue.put(samples) if completed: diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py index 8ad35aa51..304d05564 100644 --- a/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py +++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py @@ -640,6 +640,14 @@ class TestNetworkServiceTestCase(unittest.TestCase): self.assertEqual({'imix': {'64B': 100}}, self.s._get_traffic_imix()) + def test__get_ip_priority(self): + with mock.patch.dict(self.scenario_cfg["options"], + {'priority': {'raw': '0x01'}}): + self.assertEqual({'raw': '0x01'}, self.s._get_ip_priority()) + + def test__get_ip_priority_exception(self): + self.assertEqual({}, self.s._get_ip_priority()) + @mock.patch.object(base.TrafficProfile, 'get') @mock.patch.object(vnfdgen, 'generate_vnfd') def test__fill_traffic_profile(self, mock_generate, mock_tprofile_get): @@ -656,6 +664,7 @@ class TestNetworkServiceTestCase(unittest.TestCase): 'extra_args': {'arg1': 'value1', 'arg2': 'value2'}, 'flow': {'flow': {}}, 'imix': {'imix': {'64B': 100}}, + 'priority': {}, 'uplink': {}, 'duration': 30, 'simulated_users': { diff --git a/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py b/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py index 110224742..38ca26b08 100644 --- a/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py +++ b/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py @@ -15,8 +15,10 @@ import mock import IxNetwork import unittest +import re from copy import deepcopy +from collections import OrderedDict from yardstick.common import exceptions from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api @@ -633,9 +635,9 @@ class TestIxNextgen(unittest.TestCase): mock.call(self.ixnet_gen.FLOW_STATISTICS, self.ixnet_gen.LATENCY_NAME_MAP)]) - def test__set_flow_tracking(self): + def test_set_flow_tracking(self): self.ixnet_gen._ixnet.getList.return_value = ['traffic_item'] - self.ixnet_gen._set_flow_tracking(track_by=['vlanVlanId0']) + self.ixnet_gen.set_flow_tracking(track_by=['vlanVlanId0']) self.ixnet_gen.ixnet.setAttribute.assert_called_once_with( 'traffic_item/tracking', '-trackBy', ['vlanVlanId0']) self.assertEqual(self.ixnet.commit.call_count, 1) @@ -653,17 +655,77 @@ class TestIxNextgen(unittest.TestCase): 'encapsulation', '-offset', 'IPv4 TOS Precedence') self.assertEqual(self.ixnet.commit.call_count, 2) - def test_get_pppoe_scenario_statistics(self): - with mock.patch.object(self.ixnet_gen, '_build_stats_map') as \ - mock_build_stats: - self.ixnet_gen.get_pppoe_scenario_statistics() - - mock_build_stats.assert_any_call(self.ixnet_gen.PORT_STATISTICS, - self.ixnet_gen.PORT_STATS_NAME_MAP) - mock_build_stats.assert_any_call(self.ixnet_gen.FLOW_STATISTICS, - self.ixnet_gen.LATENCY_NAME_MAP) - mock_build_stats.assert_any_call(self.ixnet_gen.PPPOX_CLIENT_PER_PORT, - self.ixnet_gen.PPPOX_CLIENT_PER_PORT_NAME_MAP) + def test__get_view_page_stats(self): + expected_stats = [ + {'header1': 'row1_1', 'header2': 'row1_2'}, + {'header1': 'row2_1', 'header2': 'row2_2'} + ] + self.ixnet_gen._ixnet.getAttribute.side_effect = [ + ['header1', 'header2'], + [ + [['row1_1', 'row1_2']], + [['row2_1', 'row2_2']] + ] + ] + stats = self.ixnet_gen._get_view_page_stats('view_obj') + self.assertListEqual(stats, expected_stats) + + @mock.patch.object(ixnet_api.IxNextgen, '_get_view_page_stats') + def test_get_pppoe_scenario_statistics(self, mock_get_view): + + pattern = re.compile('Flow 2') + + expected_stats = { + 'port_statistics': [{ + 'port_1': 'port_stat1', + 'port_2': 'port_stat2' + }], + 'flow_statistic': [{ + 'flow_1': 'flow_stat1', + 'flow_2': 'flow_stat2' + }], + 'pppox_client_per_port': [{ + 'sub_1': 'sub_stat1', + 'sub_2': 'sub_stat2' + }] + } + + pppoe_scenario_stats = OrderedDict([ + ('port_statistics', 'view_obj'), + ('flow_statistic', 'view_obj'), + ('pppox_client_per_port', 'view_obj') + ]) + + pppoe_scenario_stats_map = { + 'port_statistics': {'port_1': 'Port 1', + 'port_2': 'Port 2'}, + 'flow_statistic': {'flow_1': 'Flow 1', + 'flow_2': pattern}, + 'pppox_client_per_port': {'sub_1': 'Sub 1', + 'sub_2': 'Sub 2'} + } + + # All stats keys + port_stats = [{'Port 1': 'port_stat1', + 'Port 2': 'port_stat2', + 'Port 3': 'port_stat3'}] + flows_stats = [{'Flow 1': 'flow_stat1', + 'Flow 2': 'flow_stat2', + 'Flow 3': 'flow_stat3'}] + pppoe_sub_stats = [{'Sub 1': 'sub_stat1', + 'Sub 2': 'sub_stat2', + 'Sub 3': 'sub_stat3'}] + + mock_get_view.side_effect = [port_stats, flows_stats, pppoe_sub_stats] + self.ixnet_gen._ixnet.getAttribute.return_value = '1' + + with mock.patch.multiple(ixnet_api.IxNextgen, + PPPOE_SCENARIO_STATS=pppoe_scenario_stats, + PPPOE_SCENARIO_STATS_MAP=pppoe_scenario_stats_map): + stats = self.ixnet_gen.get_pppoe_scenario_statistics() + self.assertDictEqual(stats, expected_stats) + self.assertEqual(self.ixnet_gen.ixnet.getAttribute.call_count, 6) + self.ixnet_gen.ixnet.setAttribute.assert_not_called() def test__update_ipv4_address(self): with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item', diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py b/yardstick/tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py index 3d12dddcf..a71a240a2 100644 --- a/yardstick/tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py +++ b/yardstick/tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py @@ -487,7 +487,9 @@ class TestIXIARFC2544Profile(unittest.TestCase): result = r_f_c2544_profile._get_ixia_traffic_profile({}) self.assertDictEqual(result, expected) - def test__ixia_traffic_generate(self): + @mock.patch.object(ixia_rfc2544.IXIARFC2544Profile, + '_update_traffic_tracking_options') + def test__ixia_traffic_generate(self, mock_upd_tracking_opts): traffic_generator = mock.Mock( autospec=trex_traffic_profile.TrexProfile) traffic_generator.networks = { @@ -502,8 +504,16 @@ class TestIXIARFC2544Profile(unittest.TestCase): r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile( self.TRAFFIC_PROFILE) r_f_c2544_profile.rate = 100 - result = r_f_c2544_profile._ixia_traffic_generate(traffic, ixia_obj) + result = r_f_c2544_profile._ixia_traffic_generate(traffic, ixia_obj, + traffic_generator) self.assertIsNone(result) + mock_upd_tracking_opts.assert_called_once_with(traffic_generator) + + def test__update_traffic_tracking_options(self): + mock_traffic_gen = mock.Mock() + rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE) + rfc2544_profile._update_traffic_tracking_options(mock_traffic_gen) + mock_traffic_gen.update_tracking_options.assert_called_once() def test_execute_traffic_first_run(self): rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE) @@ -741,6 +751,7 @@ class TestIXIARFC2544PppoeScenarioProfile(unittest.TestCase): def setUp(self): self.ixia_tp = ixia_rfc2544.IXIARFC2544PppoeScenarioProfile( self.TRAFFIC_PROFILE) + self.ixia_tp._get_next_rate = mock.Mock(return_value=0.1) def test___init__(self): self.assertIsInstance(self.ixia_tp.full_profile, @@ -755,3 +766,180 @@ class TestIXIARFC2544PppoeScenarioProfile(unittest.TestCase): self.ixia_tp._get_flow_groups_params() self.assertDictEqual(self.ixia_tp.full_profile, expected_tp) + + @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile, + '_get_flow_groups_params') + def test_update_traffic_profile(self, mock_get_flow_groups_params): + networks = { + 'uplink_0': 'data1', + 'downlink_0': 'data2', + 'uplink_1': 'data3', + 'downlink_1': 'data4' + } + ports = ['xe0', 'xe1', 'xe2', 'xe3'] + mock_traffic_gen = mock.Mock() + mock_traffic_gen.networks = networks + mock_traffic_gen.vnfd_helper.port_num.side_effect = ports + self.ixia_tp.update_traffic_profile(mock_traffic_gen) + mock_get_flow_groups_params.assert_called_once() + self.assertEqual(self.ixia_tp.ports, ports) + + def test__get_prio_flows_drop_percentage(self): + + input_stats = { + '0': { + 'in_packets': 50, + 'out_packets': 100, + 'Store-Forward_Avg_latency_ns': 10, + 'Store-Forward_Min_latency_ns': 10, + 'Store-Forward_Max_latency_ns': 10}} + + result = self.ixia_tp._get_prio_flows_drop_percentage(input_stats) + self.assertIsNotNone(result['0'].get('DropPercentage')) + self.assertEqual(result['0'].get('DropPercentage'), 50.0) + + def test__get_prio_flows_drop_percentage_traffic_not_flowing(self): + input_stats = { + '0': { + 'in_packets': 0, + 'out_packets': 0, + 'Store-Forward_Avg_latency_ns': 0, + 'Store-Forward_Min_latency_ns': 0, + 'Store-Forward_Max_latency_ns': 0}} + + result = self.ixia_tp._get_prio_flows_drop_percentage(input_stats) + self.assertIsNotNone(result['0'].get('DropPercentage')) + self.assertEqual(result['0'].get('DropPercentage'), 100) + + def test__get_summary_pppoe_subs_counters(self): + input_stats = { + 'xe0': { + 'out_packets': 100, + 'sessions_up': 4, + 'sessions_down': 0, + 'sessions_not_started': 0, + 'sessions_total': 4}, + 'xe1': { + 'out_packets': 100, + 'sessions_up': 4, + 'sessions_down': 0, + 'sessions_not_started': 0, + 'sessions_total': 4} + } + + expected_stats = { + 'sessions_up': 8, + 'sessions_down': 0, + 'sessions_not_started': 0, + 'sessions_total': 8 + } + + res = self.ixia_tp._get_summary_pppoe_subs_counters(input_stats) + self.assertDictEqual(res, expected_stats) + + @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile, + '_get_prio_flows_drop_percentage') + @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile, + '_get_summary_pppoe_subs_counters') + def test_get_drop_percentage(self, mock_get_pppoe_subs, + mock_sum_prio_drop_rate): + samples = { + 'priority_stats': { + '0': { + 'in_packets': 100, + 'out_packets': 100, + 'Store-Forward_Avg_latency_ns': 10, + 'Store-Forward_Min_latency_ns': 10, + 'Store-Forward_Max_latency_ns': 10}}, + 'xe0': { + 'in_packets': 100, + 'out_packets': 100, + 'Store-Forward_Avg_latency_ns': 10, + 'Store-Forward_Min_latency_ns': 10, + 'Store-Forward_Max_latency_ns': 10}} + + mock_get_pppoe_subs.return_value = {'sessions_up': 1} + mock_sum_prio_drop_rate.return_value = {'0': {'DropPercentage': 0.0}} + + status, res = self.ixia_tp.get_drop_percentage( + samples, tol_min=0.0, tolerance=0.0001, precision=0, + resolution=0.1, first_run=True) + self.assertIsNotNone(res.get('DropPercentage')) + self.assertIsNotNone(res.get('priority')) + self.assertIsNotNone(res.get('sessions_up')) + self.assertEqual(res['DropPercentage'], 0.0) + self.assertTrue(status) + mock_sum_prio_drop_rate.assert_called_once() + mock_get_pppoe_subs.assert_called_once() + + @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile, + '_get_prio_flows_drop_percentage') + @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile, + '_get_summary_pppoe_subs_counters') + def test_get_drop_percentage_failed_status(self, mock_get_pppoe_subs, + mock_sum_prio_drop_rate): + samples = { + 'priority_stats': { + '0': { + 'in_packets': 90, + 'out_packets': 100, + 'Store-Forward_Avg_latency_ns': 10, + 'Store-Forward_Min_latency_ns': 10, + 'Store-Forward_Max_latency_ns': 10}}, + 'xe0': { + 'in_packets': 90, + 'out_packets': 100, + 'Store-Forward_Avg_latency_ns': 10, + 'Store-Forward_Min_latency_ns': 10, + 'Store-Forward_Max_latency_ns': 10}} + + mock_get_pppoe_subs.return_value = {'sessions_up': 1} + mock_sum_prio_drop_rate.return_value = {'0': {'DropPercentage': 0.0}} + + status, res = self.ixia_tp.get_drop_percentage( + samples, tol_min=0.0, tolerance=0.0001, precision=0, + resolution=0.1, first_run=True) + self.assertIsNotNone(res.get('DropPercentage')) + self.assertIsNotNone(res.get('priority')) + self.assertIsNotNone(res.get('sessions_up')) + self.assertEqual(res['DropPercentage'], 10.0) + self.assertFalse(status) + mock_sum_prio_drop_rate.assert_called_once() + mock_get_pppoe_subs.assert_called_once() + + @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile, + '_get_prio_flows_drop_percentage') + @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile, + '_get_summary_pppoe_subs_counters') + def test_get_drop_percentage_priority_flow_check(self, mock_get_pppoe_subs, + mock_sum_prio_drop_rate): + samples = { + 'priority_stats': { + '0': { + 'in_packets': 100, + 'out_packets': 100, + 'Store-Forward_Avg_latency_ns': 10, + 'Store-Forward_Min_latency_ns': 10, + 'Store-Forward_Max_latency_ns': 10}}, + 'xe0': { + 'in_packets': 90, + 'out_packets': 100, + 'Store-Forward_Avg_latency_ns': 10, + 'Store-Forward_Min_latency_ns': 10, + 'Store-Forward_Max_latency_ns': 10 + }} + + mock_get_pppoe_subs.return_value = {'sessions_up': 1} + mock_sum_prio_drop_rate.return_value = {'0': {'DropPercentage': 0.0}} + + tc_rfc2544_opts = {'priority': '0', + 'allowed_drop_rate': '0.0001 - 0.0001'} + status, res = self.ixia_tp.get_drop_percentage( + samples, tol_min=15.0000, tolerance=15.0001, precision=0, + resolution=0.1, first_run=True, tc_rfc2544_opts=tc_rfc2544_opts) + self.assertIsNotNone(res.get('DropPercentage')) + self.assertIsNotNone(res.get('priority')) + self.assertIsNotNone(res.get('sessions_up')) + self.assertTrue(status) + mock_sum_prio_drop_rate.assert_called_once() + mock_get_pppoe_subs.assert_called_once() diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py index a8f697d4d..9db8b7b00 100644 --- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py +++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py @@ -491,6 +491,22 @@ class TestIXIATrafficGen(unittest.TestCase): class TestIxiaBasicScenario(unittest.TestCase): + + STATS = {'stat_name': ['Card01/Port01', + 'Card02/Port02'], + 'port_name': ['Ethernet - 001', 'Ethernet - 002'], + 'Frames_Tx': ['150', '150'], + 'Valid_Frames_Rx': ['150', '150'], + 'Frames_Tx_Rate': ['0.0', '0.0'], + 'Valid_Frames_Rx_Rate': ['0.0', '0.0'], + 'Tx_Rate_Kbps': ['0.0', '0.0'], + 'Rx_Rate_Mbps': ['0.0', '0.0'], + 'Tx_Rate_Mbps': ['0.0', '0.0'], + 'Rx_Rate_Kbps': ['0.0', '0.0'], + 'Store-Forward_Max_latency_ns': ['100', '200'], + 'Store-Forward_Min_latency_ns': ['100', '200'], + 'Store-Forward_Avg_latency_ns': ['100', '200']} + def setUp(self): self._mock_IxNextgen = mock.patch.object(ixnet_api, 'IxNextgen') self.mock_IxNextgen = self._mock_IxNextgen.start() @@ -523,6 +539,48 @@ class TestIxiaBasicScenario(unittest.TestCase): def test_stop_protocols(self): self.assertIsNone(self.scenario.stop_protocols()) + def test__get_stats(self): + self.scenario._get_stats() + self.scenario.client.get_statistics.assert_called_once() + + @mock.patch.object(tg_rfc2544_ixia.IxiaBasicScenario, '_get_stats') + def test_generate_samples(self, mock_get_stats): + + expected_samples = {'xe0': { + 'in_packets': 150, + 'out_packets': 150, + 'rx_throughput_mbps': 0.0, + 'rx_throughput_kps': 0.0, + 'RxThroughput': 5.0, + 'TxThroughput': 5.0, + 'tx_throughput_mbps': 0.0, + 'tx_throughput_kps': 0.0, + 'Store-Forward_Max_latency_ns': 100, + 'Store-Forward_Min_latency_ns': 100, + 'Store-Forward_Avg_latency_ns': 100}, + 'xe1': { + 'in_packets': 150, + 'out_packets': 150, + 'rx_throughput_mbps': 0.0, + 'rx_throughput_kps': 0.0, + 'RxThroughput': 5.0, + 'TxThroughput': 5.0, + 'tx_throughput_mbps': 0.0, + 'tx_throughput_kps': 0.0, + 'Store-Forward_Max_latency_ns': 200, + 'Store-Forward_Min_latency_ns': 200, + 'Store-Forward_Avg_latency_ns': 200}} + + res_helper = mock.Mock() + res_helper.vnfd_helper.find_interface_by_port.side_effect = \ + [{'name': 'xe0'}, {'name': 'xe1'}] + ports = [0, 1] + duration = 30 + mock_get_stats.return_value = self.STATS + samples = self.scenario.generate_samples(res_helper, ports, duration) + mock_get_stats.assert_called_once() + self.assertEqual(samples, expected_samples) + class TestIxiaL3Scenario(TestIxiaBasicScenario): IXIA_CFG = { @@ -632,6 +690,9 @@ class TestIxiaPppoeClientScenario(unittest.TestCase): 'gateway_ip': ['10.1.1.1', '10.2.2.1'], 'ip': ['10.1.1.1', '10.2.2.1'], 'prefix': ['24', '24'] + }, + 'priority': { + 'tos': {'precedence': [0, 4]} } } @@ -696,6 +757,30 @@ class TestIxiaPppoeClientScenario(unittest.TestCase): self.scenario.client.create_ipv4_traffic_model.assert_called_once_with( uplink_endpoints, downlink_endpoints) + @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, + '_get_endpoints_src_dst_id_pairs') + @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, + '_get_endpoints_src_dst_obj_pairs') + def test_create_traffic_model_topology_based_flows(self, mock_obj_pairs, + mock_id_pairs): + uplink_topologies = ['topology1', 'topology3'] + downlink_topologies = ['topology2', 'topology4'] + mock_id_pairs.return_value = [] + mock_obj_pairs.return_value = [] + mock_tp = mock.Mock() + mock_tp.full_profile = {'uplink_0': 'data', + 'downlink_0': 'data', + 'uplink_1': 'data', + 'downlink_1': 'data' + } + self.scenario._access_topologies = ['topology1', 'topology3'] + self.scenario._core_topologies = ['topology2', 'topology4'] + self.scenario.create_traffic_model(mock_tp) + mock_id_pairs.assert_called_once_with(mock_tp.full_profile) + mock_obj_pairs.assert_called_once_with([]) + self.scenario.client.create_ipv4_traffic_model.assert_called_once_with( + uplink_topologies, downlink_topologies) + def test__get_endpoints_src_dst_id_pairs(self): full_tp = OrderedDict([ ('uplink_0', {'ipv4': {'port': 'xe0'}}), @@ -765,22 +850,10 @@ class TestIxiaPppoeClientScenario(unittest.TestCase): } } - expected_result = ['tp1_dg1', 'tp3_dg1', 'tp1_dg2', 'tp3_dg1', - 'tp1_dg3', 'tp3_dg1', 'tp1_dg4', 'tp3_dg1', - 'tp2_dg1', 'tp4_dg1', 'tp2_dg2', 'tp4_dg1', - 'tp2_dg3', 'tp4_dg1', 'tp2_dg4', 'tp4_dg1'] - self.scenario._ixia_cfg = ixia_cfg - self.scenario._access_topologies = ['topology1', 'topology2'] - self.scenario._core_topologies = ['topology3', 'topology4'] - self.mock_IxNextgen.get_topology_device_groups.side_effect = \ - [['tp1_dg1', 'tp1_dg2', 'tp1_dg3', 'tp1_dg4'], - ['tp2_dg1', 'tp2_dg2', 'tp2_dg3', 'tp2_dg4'], - ['tp3_dg1'], - ['tp4_dg1']] res = self.scenario._get_endpoints_src_dst_obj_pairs( endpoints_id_pairs) - self.assertEqual(res, expected_result) + self.assertEqual(res, []) def test_run_protocols(self): self.scenario.client.is_protocols_running.return_value = True @@ -1017,3 +1090,161 @@ class TestIxiaPppoeClientScenario(unittest.TestCase): local_as=bgp_params["bgp"]["as_number"], bgp_type=bgp_params["bgp"]["bgp_type"]) ]) + + def test_update_tracking_options_raw_priority(self): + raw_priority = {'raw': 4} + self.scenario._ixia_cfg['priority'] = raw_priority + self.scenario.update_tracking_options() + self.scenario.client.set_flow_tracking.assert_called_once_with( + ['flowGroup0', 'vlanVlanId0', 'ipv4Raw0']) + + def test_update_tracking_options_tos_priority(self): + tos_priority = {'tos': {'precedence': [4, 7]}} + self.scenario._ixia_cfg['priority'] = tos_priority + self.scenario.update_tracking_options() + self.scenario.client.set_flow_tracking.assert_called_once_with( + ['flowGroup0', 'vlanVlanId0', 'ipv4Precedence0']) + + def test_update_tracking_options_dscp_priority(self): + dscp_priority = {'dscp': {'defaultPHB': [4, 7]}} + self.scenario._ixia_cfg['priority'] = dscp_priority + self.scenario.update_tracking_options() + self.scenario.client.set_flow_tracking.assert_called_once_with( + ['flowGroup0', 'vlanVlanId0', 'ipv4DefaultPhb0']) + + def test_update_tracking_options_invalid_priority_data(self): + invalid_priority = {'tos': {'inet-precedence': [4, 7]}} + self.scenario._ixia_cfg['priority'] = invalid_priority + self.scenario.update_tracking_options() + self.scenario.client.set_flow_tracking.assert_called_once_with( + ['flowGroup0', 'vlanVlanId0', 'ipv4Precedence0']) + + def test_get_tc_rfc2544_options(self): + rfc2544_tc_opts = {'allowed_drop_rate': '0.0001 - 0.0001'} + self.scenario._ixia_cfg['rfc2544'] = rfc2544_tc_opts + res = self.scenario.get_tc_rfc2544_options() + self.assertEqual(res, rfc2544_tc_opts) + + def test__get_stats(self): + self.scenario._get_stats() + self.scenario.client.get_pppoe_scenario_statistics.assert_called_once() + + def test_get_flow_id_data(self): + stats = [{'id': 1, 'in_packets': 10, 'out_packets': 20}] + key = "in_packets" + flow_id = 1 + res = self.scenario.get_flow_id_data(stats, flow_id, key) + self.assertEqual(res, 10) + + @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, '_get_stats') + @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, + 'get_priority_flows_stats') + def test_generate_samples(self, mock_prio_flow_statistics, + mock_get_stats): + ixia_stats = { + 'flow_statistic': [ + {'Flow_Group': 'RFC2544-1 - Flow Group 0001', + 'Frames_Delta': '0', + 'IP_Priority': '0', + 'Rx_Frames': '3000', + 'Tx_Frames': '3000', + 'VLAN-ID': '100', + 'Tx_Port': 'Ethernet - 001', + 'Store-Forward_Avg_latency_ns': '2', + 'Store-Forward_Min_latency_ns': '2', + 'Store-Forward_Max_latency_ns': '2'}, + {'Flow_Group': 'RFC2544-2 - Flow Group 0001', + 'Frames_Delta': '0', + 'IP_Priority': '0', + 'Rx_Frames': '3000', + 'Tx_Frames': '3000', + 'VLAN-ID': '101', + 'Tx_Port': 'Ethernet - 002', + 'Store-Forward_Avg_latency_ns': '2', + 'Store-Forward_Min_latency_ns': '2', + 'Store-Forward_Max_latency_ns': '2' + }], + 'port_statistics': [ + {'Frames_Tx': '3000', + 'Valid_Frames_Rx': '3000', + 'Rx_Rate_Kbps': '0.0', + 'Tx_Rate_Kbps': '0.0', + 'Rx_Rate_Mbps': '0.0', + 'Tx_Rate_Mbps': '0.0', + 'port_name': 'Ethernet - 001'}, + {'Frames_Tx': '3000', + 'Valid_Frames_Rx': '3000', + 'Rx_Rate_Kbps': '0.0', + 'Tx_Rate_Kbps': '0.0', + 'Rx_Rate_Mbps': '0.0', + 'Tx_Rate_Mbps': '0.0', + 'port_name': 'Ethernet - 002'}], + 'pppox_client_per_port': [ + {'Sessions_Down': '0', + 'Sessions_Not_Started': '0', + 'Sessions_Total': '1', + 'Sessions_Up': '1', + 'subs_port': 'Ethernet - 001'}]} + + prio_flows_stats = { + '0': { + 'in_packets': 6000, + 'out_packets': 6000, + 'RxThroughput': 200.0, + 'TxThroughput': 200.0, + 'avg_latency_ns': 2, + 'max_latency_ns': 2, + 'min_latency_ns': 2 + } + } + + expected_result = {'priority_stats': { + '0': {'RxThroughput': 200.0, + 'TxThroughput': 200.0, + 'avg_latency_ns': 2, + 'max_latency_ns': 2, + 'min_latency_ns': 2, + 'in_packets': 6000, + 'out_packets': 6000}}, + 'xe0': {'RxThroughput': 100.0, + 'Store-Forward_Avg_latency_ns': 2, + 'Store-Forward_Max_latency_ns': 2, + 'Store-Forward_Min_latency_ns': 2, + 'TxThroughput': 100.0, + 'in_packets': 3000, + 'out_packets': 3000, + 'rx_throughput_kps': 0.0, + 'rx_throughput_mbps': 0.0, + 'sessions_down': 0, + 'sessions_not_started': 0, + 'sessions_total': 1, + 'sessions_up': 1, + 'tx_throughput_kps': 0.0, + 'tx_throughput_mbps': 0.0}, + 'xe1': {'RxThroughput': 100.0, + 'Store-Forward_Avg_latency_ns': 2, + 'Store-Forward_Max_latency_ns': 2, + 'Store-Forward_Min_latency_ns': 2, + 'TxThroughput': 100.0, + 'in_packets': 3000, + 'out_packets': 3000, + 'rx_throughput_kps': 0.0, + 'rx_throughput_mbps': 0.0, + 'tx_throughput_kps': 0.0, + 'tx_throughput_mbps': 0.0}} + + mock_get_stats.return_value = ixia_stats + mock_prio_flow_statistics.return_value = prio_flows_stats + ports = [0, 1] + port_names = [{'name': 'xe0'}, {'name': 'xe1'}] + duration = 30 + res_helper = mock.Mock() + res_helper.vnfd_helper.find_interface_by_port.side_effect = \ + port_names + samples = self.scenario.generate_samples(res_helper, ports, duration) + self.assertIsNotNone(samples) + self.assertIsNotNone(samples.get('xe0')) + self.assertIsNotNone(samples.get('xe1')) + self.assertEqual(samples, expected_result) + mock_get_stats.assert_called_once() + mock_prio_flow_statistics.assert_called_once() |