Migrate Trex TG to use new NSPerf-RFC2544 scenario 59/66859/6
authorMytnyk, Volodymyr <volodymyrx.mytnyk@intel.com>
Tue, 5 Feb 2019 09:48:01 +0000 (11:48 +0200)
committerMytnyk, Volodymyr <volodymyrx.mytnyk@intel.com>
Fri, 8 Feb 2019 13:53:44 +0000 (13:53 +0000)
JIRA: YARDSTICK-1592

Change-Id: Ic51a52385ac53df9b5f56387af4f1b661bb0d86f
Signed-off-by: Mytnyk, Volodymyr <volodymyrx.mytnyk@intel.com>
samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_trex.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/vfw/tc_baremetal_rfc2544_ipv4_trex.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_trex.yaml [new file with mode: 0644]
yardstick/network_services/traffic_profile/ixia_rfc2544.py
yardstick/network_services/traffic_profile/rfc2544.py
yardstick/network_services/traffic_profile/trex_traffic_profile.py
yardstick/network_services/vnf_generic/vnf/sample_vnf.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py

diff --git a/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_trex.yaml b/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_trex.yaml
new file mode 100644 (file)
index 0000000..44c7f6d
--- /dev/null
@@ -0,0 +1,46 @@
+# Copyright (c) 2019 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{% set framesize = framesize or "{64B: 100}" %}
+---
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf-RFC2544
+  traffic_profile: ../../traffic_profiles/ipv4_throughput.yaml
+  topology: agnostic_vnf_topology_trex_2ports.yaml
+  nodes:
+    tg__0: trafficgen_0.yardstick
+    vnf__0: vnf_0.yardstick
+  options:
+    framesize:
+      uplink: {{ framesize }}
+      downlink: {{ framesize }}
+    flow:
+      src_ip: [{'tg__0': 'xe0'}]
+      dst_ip: [{'tg__0': 'xe1'}]
+      count: 1
+    traffic_type: 4
+    rfc2544:
+      allowed_drop_rate: 0.0001 - 0.0001
+    vnf__0:
+        []
+  runner:
+    type: Iteration
+    iterations: 1
+    interval: 5
+context:
+  type: Node
+  name: yardstick
+  nfvi_type: baremetal
+  file: /etc/yardstick/nodes/pod_trex.yaml
diff --git a/samples/vnf_samples/nsut/vfw/tc_baremetal_rfc2544_ipv4_trex.yaml b/samples/vnf_samples/nsut/vfw/tc_baremetal_rfc2544_ipv4_trex.yaml
new file mode 100644 (file)
index 0000000..856a4aa
--- /dev/null
@@ -0,0 +1,48 @@
+# Copyright (c) 2019 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{% set framesize = framesize or "{64B: 100}" %}
+---
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf-RFC2544
+  traffic_profile: ../../traffic_profiles/ipv4_throughput.yaml
+  topology: vfw-tg-topology.yaml
+  nodes:
+    tg__0: trafficgen_0.yardstick
+    vnf__0: vnf_0.yardstick
+  options:
+    framesize:
+      uplink: {{ framesize }}
+      downlink: {{ framesize }}
+    flow:
+      src_ip: [{'tg__0': 'xe0'}]
+      dst_ip: [{'tg__0': 'xe1'}]
+      count: 1
+    traffic_type: 4
+    rfc2544:
+      allowed_drop_rate: 0.0001 - 0.0001
+    vnf__0:
+      rules: acl_1rule.yaml
+      vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1}
+      nfvi_enable: True
+  runner:
+    type: Iteration
+    iterations: 1
+    interval: 5
+context:
+  type: Node
+  name: yardstick
+  nfvi_type: baremetal
+  file: /etc/yardstick/nodes/pod_trex.yaml
diff --git a/samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_trex.yaml b/samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_trex.yaml
new file mode 100644 (file)
index 0000000..eadc6cc
--- /dev/null
@@ -0,0 +1,78 @@
+# Copyright (c) 2019 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{% set framesize = framesize or "{64B: 100}" %}
+---
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf-RFC2544
+  traffic_profile: ../../traffic_profiles/ipv4_throughput.yaml
+  topology: vfw-tg-topology.yaml
+  nodes:
+    tg__0: trafficgen_0.yardstick
+    vnf__0: vnf_0.yardstick
+  options:
+    framesize:
+      uplink: {{ framesize }}
+      downlink: {{ framesize }}
+    flow:
+      src_ip: [{'tg__0': 'xe0'}]
+      dst_ip: [{'tg__0': 'xe1'}]
+      count: 1
+    traffic_type: 4
+    rfc2544:
+      allowed_drop_rate: 0.0001 - 0.0001
+    vnf__0:
+      rules: acl_1rule.yaml
+      vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1}
+  runner:
+    type: Iteration
+    iterations: 1
+    interval: 5
+context:
+  # put node context first, so we don't HEAT deploy if node has errors
+  name: yardstick
+  image: yardstick-samplevnfs
+  flavor:
+    vcpus: 10
+    ram: 20480
+    disk: 6
+    extra_specs:
+      hw:cpu_sockets: 1
+      hw:cpu_cores: 10
+      hw:cpu_threads: 1
+  user: ubuntu
+  placement_groups:
+    pgrp1:
+      policy: "availability"
+  servers:
+    vnf_0:
+      floating_ip: true
+      placement: "pgrp1"
+    trafficgen_0:
+      floating_ip: true
+      placement: "pgrp1"
+  networks:
+    mgmt:
+      cidr: '10.0.1.0/24'
+    xe0:
+      cidr: '10.0.2.0/24'
+      gateway_ip: 'null'
+      port_security_enabled: False
+      enable_dhcp: 'false'
+    xe1:
+      cidr: '10.0.3.0/24'
+      gateway_ip: 'null'
+      port_security_enabled: False
+      enable_dhcp: 'false'
index ab347bc..c4664a3 100644 (file)
@@ -28,7 +28,6 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
     UPLINK = 'uplink'
     DOWNLINK = 'downlink'
     DROP_PERCENT_ROUND = 6
-    RATE_ROUND = 5
     STATUS_SUCCESS = "Success"
     STATUS_FAIL = "Failure"
 
@@ -171,10 +170,6 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
 
         self.ports = [port for port in port_generator()]
 
-    def _get_next_rate(self):
-        rate = round(float(self.max_rate + self.min_rate)/2.0, self.RATE_ROUND)
-        return rate
-
     def _get_framesize(self):
         framesizes = []
         traffic = self._get_ixia_traffic_profile(self.full_profile)
index e33c437..86ef0db 100644 (file)
@@ -23,7 +23,7 @@ from yardstick.common import constants
 from yardstick.network_services.traffic_profile import trex_traffic_profile
 
 
-LOGGING = logging.getLogger(__name__)
+LOG = logging.getLogger(__name__)
 SRC_PORT = 'sport'
 DST_PORT = 'dport'
 
@@ -271,7 +271,7 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
         return streams
 
     def get_drop_percentage(self, samples, tol_low, tol_high,
-                            correlated_traffic):
+                            correlated_traffic, resolution):
         """Calculate the drop percentage and run the traffic"""
         completed = False
         out_pkt_end = sum(port['out_packets'] for port in samples[-1].values())
@@ -301,7 +301,13 @@ class RFC2544Profile(trex_traffic_profile.TrexProfile):
             completed = True
 
         last_rate = self.rate
-        self.rate = round(float(self.max_rate + self.min_rate) / 2.0, 5)
+        self.rate = self._get_next_rate()
+        if abs(last_rate - self.rate) < resolution:
+            # stop test if the difference between the rate transmission
+            # in two iterations is smaller than the value of the resolution
+            completed = True
+        LOG.debug("rate=%s, next_rate=%s, resolution=%s, completed=%s",
+                  last_rate, self.rate, resolution, completed)
 
         throughput = rx_rate_fps * 2 if correlated_traffic else rx_rate_fps
 
index ed0355f..2d2c2d8 100644 (file)
@@ -52,6 +52,7 @@ class TrexProfile(base.TrafficProfile):
         IPv6: ('ip6_packet', Pkt.IPv6),
         UDP: ('udp_packet', Pkt.UDP),
     }
+    RATE_ROUND = 5
 
     def _general_single_action_partial(self, protocol):
         def f(field):
@@ -186,6 +187,8 @@ class TrexProfile(base.TrafficProfile):
         self.qinq = False
         self.vm_flow_vars = []
         self.packets = []
+        self.max_rate = 0
+        self.min_rate = 0
 
         self._map_proto_actions = {
             # the tuple is (single value function, range value function, if the values should be
@@ -337,6 +340,10 @@ class TrexProfile(base.TrafficProfile):
         if 'dstport' in outer_l4:
             self._set_proto_addr(UDP, DST_PORT, outer_l4['dstport'], outer_l4['count'])
 
+    def _get_next_rate(self):
+        rate = round(float(self.max_rate + self.min_rate)/2.0, self.RATE_ROUND)
+        return rate
+
     @classmethod
     def _count_ip(cls, start_ip, end_ip):
         start = ipaddress.ip_address(six.u(start_ip))
index aec0850..743aed0 100644 (file)
@@ -14,7 +14,7 @@
 
 import logging
 import decimal
-from multiprocessing import Queue, Value, Process
+from multiprocessing import Queue, Value, Process, JoinableQueue
 import os
 import posixpath
 import re
@@ -948,6 +948,39 @@ class SampleVNFTrafficGen(GenericTrafficGen):
         self.traffic_finished = False
         self._tg_process = None
         self._traffic_process = None
+        self._tasks_queue = JoinableQueue()
+        self._result_queue = Queue()
+
+    def _test_runner(self, traffic_profile, tasks, results):
+        self.resource_helper.run_test(traffic_profile, tasks, results)
+
+    def _init_traffic_process(self, traffic_profile):
+        name = '{}-{}-{}-{}'.format(self.name, self.APP_NAME,
+                                    traffic_profile.__class__.__name__,
+                                    os.getpid())
+        self._traffic_process = Process(name=name, target=self._test_runner,
+                                        args=(
+                                        traffic_profile, self._tasks_queue,
+                                        self._result_queue))
+
+        self._traffic_process.start()
+        while self.resource_helper.client_started.value == 0:
+            time.sleep(1)
+            if not self._traffic_process.is_alive():
+                break
+
+    def run_traffic_once(self, traffic_profile):
+        if self.resource_helper.client_started.value == 0:
+            self._init_traffic_process(traffic_profile)
+
+        # continue test - run next iteration
+        LOG.info("Run next iteration ...")
+        self._tasks_queue.put('RUN_TRAFFIC')
+
+    def wait_on_traffic(self):
+        self._tasks_queue.join()
+        result = self._result_queue.get()
+        return result
 
     def _start_server(self):
         # we can't share ssh paramiko objects to force new connection
index d3a2d94..2f9eb3f 100644 (file)
@@ -16,13 +16,8 @@ import ipaddress
 import logging
 import six
 import collections
-import os
-import time
 
 from six import moves
-
-from multiprocessing import Queue, Process, JoinableQueue
-
 from yardstick.common import utils
 from yardstick.common import exceptions
 from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
@@ -844,9 +839,6 @@ class IxiaTrafficGen(SampleVNFTrafficGen):
         self._ixia_traffic_gen = None
         self.ixia_file_name = ''
         self.vnf_port_pairs = []
-        self._traffic_process = None
-        self._tasks_queue = JoinableQueue()
-        self._result_queue = Queue()
 
     def _check_status(self):
         pass
@@ -854,34 +846,3 @@ class IxiaTrafficGen(SampleVNFTrafficGen):
     def terminate(self):
         self.resource_helper.stop_collect()
         super(IxiaTrafficGen, self).terminate()
-
-    def _test_runner(self, traffic_profile, tasks, results):
-        self.resource_helper.run_test(traffic_profile, tasks, results)
-
-    def _init_traffic_process(self, traffic_profile):
-        name = '{}-{}-{}-{}'.format(self.name, self.APP_NAME,
-                                    traffic_profile.__class__.__name__,
-                                    os.getpid())
-        self._traffic_process = Process(name=name, target=self._test_runner,
-                                        args=(
-                                        traffic_profile, self._tasks_queue,
-                                        self._result_queue))
-
-        self._traffic_process.start()
-        while self.resource_helper.client_started.value == 0:
-            time.sleep(1)
-            if not self._traffic_process.is_alive():
-                break
-
-    def run_traffic_once(self, traffic_profile):
-        if self.resource_helper.client_started.value == 0:
-            self._init_traffic_process(traffic_profile)
-
-        # continue test - run next iteration
-        LOG.info("Run next iteration ...")
-        self._tasks_queue.put('RUN_TRAFFIC')
-
-    def wait_on_traffic(self):
-        self._tasks_queue.join()
-        result = self._result_queue.get()
-        return result
index 24ee313..a9c0222 100644 (file)
 import logging
 import time
 
+from six import moves
 from yardstick.common import utils
 from yardstick.network_services.vnf_generic.vnf import sample_vnf
 from yardstick.network_services.vnf_generic.vnf import tg_trex
+from trex_stl_lib.trex_stl_exceptions import STLError
 
 
-LOGGING = logging.getLogger(__name__)
+LOG = logging.getLogger(__name__)
 
 
 class TrexRfcResourceHelper(tg_trex.TrexResourceHelper):
@@ -48,7 +50,8 @@ class TrexRfcResourceHelper(tg_trex.TrexResourceHelper):
         completed, output = traffic_profile.get_drop_percentage(
             samples, self.rfc2544_helper.tolerance_low,
             self.rfc2544_helper.tolerance_high,
-            self.rfc2544_helper.correlated_traffic)
+            self.rfc2544_helper.correlated_traffic,
+            self.rfc2544_helper.resolution)
         self._queue.put(output)
         return completed
 
@@ -58,6 +61,56 @@ class TrexRfcResourceHelper(tg_trex.TrexResourceHelper):
     def clear_client_stats(self, ports):
         self.client.clear_stats(ports=ports)
 
+    def run_test(self, traffic_profile, tasks_queue, results_queue, *args): # pragma: no cover
+        LOG.debug("Trex resource_helper run_test")
+        if self._terminated.value:
+            return
+        # if we don't do this we can hang waiting for the queue to drain
+        # have to do this in the subprocess
+        self._queue.cancel_join_thread()
+        try:
+            self._build_ports()
+            self.client = self._connect()
+            self.client.reset(ports=self.all_ports)
+            self.client.remove_all_streams(self.all_ports)  # remove all streams
+            traffic_profile.register_generator(self)
+
+            completed = False
+            self.rfc2544_helper.iteration.value = 0
+            self.client_started.value = 1
+            while completed is False and not self._terminated.value:
+                LOG.debug("Wait for task ...")
+                try:
+                    task = tasks_queue.get(True, 5)
+                except moves.queue.Empty:
+                    LOG.debug("Wait for task timeout, continue waiting...")
+                    continue
+                else:
+                    if task != 'RUN_TRAFFIC':
+                        continue
+                self.rfc2544_helper.iteration.value += 1
+                LOG.info("Got %s task, start iteration %d", task,
+                         self.rfc2544_helper.iteration.value)
+                completed = self._run_traffic_once(traffic_profile)
+                if completed:
+                    LOG.debug("%s::run_test - test completed",
+                              self.__class__.__name__)
+                    results_queue.put('COMPLETE')
+                else:
+                    results_queue.put('CONTINUE')
+                tasks_queue.task_done()
+
+            self.client.stop(self.all_ports)
+            self.client.disconnect()
+            self._terminated.value = 0
+        except STLError:
+            if self._terminated.value:
+                LOG.debug("traffic generator is stopped")
+                return  # return if trex/tg server is stopped.
+            raise
+
+        self.client_started.value = 0
+        LOG.debug("%s::run_test done", self.__class__.__name__)
 
 class TrexTrafficGenRFC(tg_trex.TrexTrafficGen):
     """
index b8fbc63..fdcd36f 100644 (file)
@@ -275,7 +275,7 @@ class TestRFC2544Profile(base.BaseUnitTestCase):
                      'timestamp': datetime.datetime(2000, 1, 1, 1, 1, 1, 31)}}
         ]
         completed, output = rfc2544_profile.get_drop_percentage(
-            samples, 0, 0, False)
+            samples, 0, 0, False, 0.1)
         expected = {'DropPercentage': 50.0,
                     'Latency': {'xe1': 'Latency1', 'xe2': 'Latency2'},
                     'RxThroughput': 1000000.0,