Add vBNG test cases stats processing functionality 07/65207/19
authorOleksandr Naumets <oleksandrx.naumets@intel.com>
Mon, 19 Nov 2018 13:45:32 +0000 (13:45 +0000)
committerOleksandr Naumets <oleksandrx.naumets@intel.com>
Fri, 1 Feb 2019 14:58:54 +0000 (14:58 +0000)
JIRA: YARDSTICK-1546

Change-Id: I3575223ef8231fb4d574e961360b0f2d90a71749
Signed-off-by: Oleksandr Naumets <oleksandrx.naumets@intel.com>
12 files changed:
samples/vnf_samples/nsut/bng/tc_bng_pppoe_rfc2544_ixia_8ports_1port_congested_IMIX.yaml
samples/vnf_samples/nsut/bng/tc_bng_pppoe_rfc2544_ixia_IMIX_scale_up.yaml
samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vbng_1port_congested-8.yaml
samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vbng_scale_up.yaml
yardstick/benchmark/scenarios/networking/vnf_generic.py
yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
yardstick/network_services/traffic_profile/ixia_rfc2544.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py
yardstick/tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py

index 2c2010a..4418862 100644 (file)
@@ -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
index f0696ab..afd60cc 100644 (file)
 ---
 {% 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
index a317004..77bc557 100644 (file)
@@ -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
index 4f427b7..91658a5 100644 (file)
@@ -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 %}
index 3fd1845..dd5f472 100644 (file)
@@ -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,
index cc627ef..e0b7aa0 100644 (file)
@@ -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')
index 7df590f..89bb3ef 100644 (file)
@@ -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
index 2c3140f..f8eec4f 100644 (file)
@@ -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:
index 8ad35aa..304d055 100644 (file)
@@ -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': {
index 1102247..38ca26b 100644 (file)
 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',
index 3d12ddd..a71a240 100644 (file)
@@ -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()
index a8f697d..9db8b7b 100644 (file)
@@ -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()