NSB TRex: convert DPDK port number to logical TRex port number 99/46599/10
authorRoss Brattain <ross.b.brattain@intel.com>
Thu, 2 Nov 2017 23:54:56 +0000 (16:54 -0700)
committerRoss Brattain <ross.b.brattain@intel.com>
Tue, 14 Nov 2017 14:40:10 +0000 (14:40 +0000)
when we create TRex config we sort based on PCI bus address
and create a logical port ordering.

We need to save this port ordering and re-use it everywhere.

redirect vnfd_helper.port_num() to resource_helper.port_num() to
use the logical mapping

Change-Id: Ibff628556d5e11e686e15716a66a3210758c4ff0
Signed-off-by: Ross Brattain <ross.b.brattain@intel.com>
tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py
yardstick/network_services/traffic_profile/rfc2544.py
yardstick/network_services/vnf_generic/vnf/sample_vnf.py
yardstick/network_services/vnf_generic/vnf/tg_trex.py

index d08c62e..a2a5058 100644 (file)
@@ -18,6 +18,8 @@
 from __future__ import absolute_import
 
 import unittest
+
+import copy
 import mock
 
 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
@@ -75,6 +77,8 @@ class TestTrexTrafficGen(unittest.TestCase):
                                         'driver': "i40e",
                                         'dst_ip': '152.16.100.20',
                                         'local_iface_name': 'xe0',
+                                        'vld_id': 'downlink_0',
+                                        'ifname': 'xe0',
                                         'local_mac': '00:00:00:00:00:02'},
                                    'vnfd-connection-point-ref': 'xe0',
                                    'name': 'xe0'},
@@ -89,6 +93,8 @@ class TestTrexTrafficGen(unittest.TestCase):
                                         'bandwidth': '10 Gbps',
                                         'dst_ip': '152.16.40.20',
                                         'local_iface_name': 'xe1',
+                                        'vld_id': 'uplink_0',
+                                        'ifname': 'xe1',
                                         'local_mac': '00:00:00:00:00:01'},
                                    'vnfd-connection-point-ref': 'xe1',
                                    'name': 'xe1'}]}],
@@ -386,6 +392,8 @@ class TestTrexTrafficGen(unittest.TestCase):
         self.sut._connect_client.get_stats = mock.Mock(return_value="0")
         self.sut.resource_helper.RUN_DURATION = 0
         self.sut.resource_helper.QUEUE_WAIT_TIME = 0
+        # must generate cfg before we can run traffic so Trex port mapping is created
+        self.sut.resource_helper.generate_cfg()
         self.sut._traffic_runner(mock_traffic_profile)
 
     @mock.patch(SSH_HELPER)
@@ -396,6 +404,52 @@ class TestTrexTrafficGen(unittest.TestCase):
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
 
+    @mock.patch(SSH_HELPER)
+    def test_build_ports_reversed_pci_ordering(self, ssh):
+        mock_ssh(ssh)
+        vnfd = copy.deepcopy(self.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+        vnfd['vdu'][0]['external-interface'] = [
+            {'virtual-interface':
+                 {'dst_mac': '00:00:00:00:00:04',
+                  'vpci': '0000:05:00.0',
+                  'local_ip': '152.16.100.19',
+                  'type': 'PCI-PASSTHROUGH',
+                  'netmask': '255.255.255.0',
+                  'dpdk_port_num': 2,
+                  'bandwidth': '10 Gbps',
+                  'driver': "i40e",
+                  'dst_ip': '152.16.100.20',
+                  'local_iface_name': 'xe0',
+                  'vld_id': 'downlink_0',
+                  'ifname': 'xe0',
+                  'local_mac': '00:00:00:00:00:02'},
+             'vnfd-connection-point-ref': 'xe0',
+             'name': 'xe0'},
+            {'virtual-interface':
+                 {'dst_mac': '00:00:00:00:00:03',
+                  'vpci': '0000:04:00.0',
+                  'local_ip': '152.16.40.19',
+                  'type': 'PCI-PASSTHROUGH',
+                  'driver': "i40e",
+                  'netmask': '255.255.255.0',
+                  'dpdk_port_num': 0,
+                  'bandwidth': '10 Gbps',
+                  'dst_ip': '152.16.40.20',
+                  'local_iface_name': 'xe1',
+                  'vld_id': 'uplink_0',
+                  'ifname': 'xe1',
+                  'local_mac': '00:00:00:00:00:01'},
+             'vnfd-connection-point-ref': 'xe1',
+             'name': 'xe1'}]
+        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+        trex_traffic_gen.resource_helper.generate_cfg()
+        trex_traffic_gen.resource_helper._build_ports()
+        self.assertEqual(sorted(trex_traffic_gen.resource_helper.all_ports), [0, 1])
+        # there is a gap in ordering
+        self.assertEqual(dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map),
+                         {0: 0, 2: 1})
+
     @mock.patch(SSH_HELPER)
     def test_run_traffic(self, ssh):
         mock_ssh(ssh)
index 16e809b..b1ca8a3 100644 (file)
@@ -62,7 +62,7 @@ class RFC2544Profile(TrexProfile):
                 self.generator.rfc2544_helper.correlated_traffic:
                 continue
             for intf in intfs:
-                port = self.generator.vnfd_helper.port_num(intf)
+                port = self.generator.port_num(intf)
                 self.ports.append(port)
                 self.generator.client.add_streams(self.get_streams(profile_data), ports=port)
 
@@ -170,7 +170,7 @@ class RFC2544Profile(TrexProfile):
                 self.generator.rfc2544_helper.correlated_traffic:
                 continue
             for intf in intfs:
-                port = self.generator.vnfd_helper.port_num(intf)
+                port = self.generator.port_num(intf)
                 self.ports.append(port)
                 self.generator.client.add_streams(self.get_streams(profile_data), ports=port)
 
index 75ed622..ff81b5f 100644 (file)
@@ -391,6 +391,10 @@ class ClientResourceHelper(ResourceHelper):
             self.vnfd_helper.port_nums(self.vnfd_helper.port_pairs.downlink_ports)
         self.all_ports = self.vnfd_helper.port_nums(self.vnfd_helper.port_pairs.all_ports)
 
+    def port_num(self, intf):
+        # by default return port num
+        return self.vnfd_helper.port_num(intf)
+
     def get_stats(self, *args, **kwargs):
         try:
             return self.client.get_stats(*args, **kwargs)
index 458f1b8..93ba855 100644 (file)
@@ -48,27 +48,38 @@ class TrexResourceHelper(ClientResourceHelper):
     ASYNC_PORT = 4500
     SYNC_PORT = 4501
 
+    def __init__(self, setup_helper):
+        super(TrexResourceHelper, self).__init__(setup_helper)
+        self.port_map = {}
+        self.dpdk_to_trex_port_map = {}
+
     def generate_cfg(self):
         port_names = self.vnfd_helper.port_pairs.all_ports
         vpci_list = []
         port_list = []
+        self.port_map = {}
+        self.dpdk_to_trex_port_map = {}
 
-        port_nums = sorted(self.vnfd_helper.port_nums(port_names))
-        for port_num in port_nums:
-            interface = self.vnfd_helper.find_interface_by_port(port_num)
+        sorted_ports = sorted((self.vnfd_helper.port_num(port_name), port_name) for port_name in
+                              port_names)
+        for index, (port_num, port_name) in enumerate(sorted_ports):
+            interface = self.vnfd_helper.find_interface(name=port_name)
             virtual_interface = interface['virtual-interface']
             dst_mac = virtual_interface["dst_mac"]
 
-            # why skip?, ordering is based on DPDK port number so we can't skip
+            # this is to check for unused ports, all ports in the topology
+            # will always have dst_mac
             if not dst_mac:
                 continue
-            # TRex ports must be in DPDK port number, so order of append matters
+            # TRex ports are in logical order roughly based on DPDK port number sorting
             vpci_list.append(virtual_interface["vpci"])
             local_mac = virtual_interface["local_mac"]
             port_list.append({
                 "src_mac": mac_address_to_hex_list(local_mac),
                 "dest_mac": mac_address_to_hex_list(dst_mac),
             })
+            self.port_map[port_name] = index
+            self.dpdk_to_trex_port_map[port_num] = index
         trex_cfg = {
             'interfaces': vpci_list,
             'port_info': port_list,
@@ -80,6 +91,17 @@ class TrexResourceHelper(ClientResourceHelper):
         cfg_str = yaml.safe_dump(cfg_file, default_flow_style=False, explicit_start=True)
         self.ssh_helper.upload_config_file(os.path.basename(self.CONF_FILE), cfg_str)
 
+    def _build_ports(self):
+        super(TrexResourceHelper, self)._build_ports()
+        # override with TRex logic port number
+        self.uplink_ports = [self.dpdk_to_trex_port_map[p] for p in self.uplink_ports]
+        self.downlink_ports = [self.dpdk_to_trex_port_map[p] for p in self.downlink_ports]
+        self.all_ports = [self.dpdk_to_trex_port_map[p] for p in self.all_ports]
+
+    def port_num(self, intf):
+        # return logical TRex port
+        return self.port_map[intf]
+
     def check_status(self):
         status, _, _ = self.ssh_helper.execute("sudo lsof -i:%s" % self.SYNC_PORT)
         return status