Extend host topology with NIC type filtering 08/808/12
authorMiroslav Miklus <mmiklus@cisco.com>
Mon, 18 Apr 2016 15:15:40 +0000 (17:15 +0200)
committerStefan Kobza <skobza@cisco.com>
Tue, 26 Apr 2016 09:53:46 +0000 (09:53 +0000)
JIRA: CSIT-1
Changes to allow filtering based on NIC model.
Switched xconnect perf test to use filtered topology.

Change-Id: Id526f47dc28f92bf26d070e54819ad29bccc0440
Signed-off-by: Miroslav Miklus <mmiklus@cisco.com>
resources/libraries/python/NodePath.py
resources/libraries/python/topology.py
resources/libraries/robot/bridge_domain.robot
resources/libraries/robot/performance.robot
resources/topology_schemas/topology.sch.yaml
tests/suites/performance/short_xconnect_Intel-X520-DA2.robot [moved from tests/suites/performance/short_xconnect.robot with 98% similarity]
topologies/available/lf_testbed2-710-520.yaml
topologies/available/lf_testbed2.yaml

index bbc6d31..dfcee4d 100644 (file)
@@ -55,16 +55,20 @@ class NodePath(object):
 
     def __init__(self):
         self._nodes = []
+        self._nodes_filter = []
         self._links = []
         self._path = []
         self._path_iter = []
 
-    def append_node(self, node):
+    def append_node(self, node, filter_list=None):
         """Append node to the path.
 
         :param node: Node to append to the path.
+        :param filter_list: Filter criteria list.
         :type node: dict
+        :type filter_list: list of strings
         """
+        self._nodes_filter.append(filter_list)
         self._nodes.append(node)
 
     def append_nodes(self, *nodes):
@@ -81,6 +85,7 @@ class NodePath(object):
     def clear_path(self):
         """Clear path."""
         self._nodes = []
+        self._nodes_filter = []
         self._links = []
         self._path = []
         self._path_iter = []
@@ -96,6 +101,7 @@ class NodePath(object):
         .. note:: First add at least two nodes to the topology.
         """
         nodes = self._nodes
+        nodes_filer = self._nodes_filter
         if len(nodes) < 2:
             raise RuntimeError('Not enough nodes to compute path')
 
@@ -103,7 +109,11 @@ class NodePath(object):
             topo = Topology()
             node1 = nodes[idx]
             node2 = nodes[idx + 1]
-            links = topo.get_active_connecting_links(node1, node2)
+            n1_list = self._nodes_filter[idx]
+            n2_list = self._nodes_filter[idx + 1]
+            links = topo.get_active_connecting_links(node1, node2,
+                                                     filter_list_node1=n1_list,
+                                                     filter_list_node2=n2_list)
             if not links:
                 raise RuntimeError('No link between {0} and {1}'.format(
                     node1['host'], node2['host']))
index 20745eb..7e94007 100644 (file)
@@ -359,10 +359,13 @@ class Topology(object):
         return None
 
     @staticmethod
-    def _get_node_active_link_names(node):
+    def _get_node_active_link_names(node, filter_list=None):
         """Return list of link names that are other than mgmt links.
 
         :param node: Node topology dictionary.
+        :param filter_list: Link filter criteria.
+        :type node: dict
+        :type filter_list: list of strings
         :return: List of strings that represent link names occupied by the node.
         :rtype: list
         """
@@ -370,28 +373,53 @@ class Topology(object):
         link_names = []
         for interface in interfaces.values():
             if 'link' in interface:
-                link_names.append(interface['link'])
+                if (filter_list is not None) and ('model' in interface):
+                    for filt in filter_list:
+                        if filt == interface['model']:
+                            link_names.append(interface['link'])
+                elif (filter_list is not None) and ('model' not in interface):
+                    logger.trace("Cannot apply filter on interface: {}" \
+                                 .format(str(interface)))
+                else:
+                    link_names.append(interface['link'])
         if len(link_names) == 0:
             link_names = None
         return link_names
 
     @keyword('Get active links connecting "${node1}" and "${node2}"')
-    def get_active_connecting_links(self, node1, node2):
+    def get_active_connecting_links(self, node1, node2,
+                                    filter_list_node1=None,
+                                    filter_list_node2=None):
         """Return list of link names that connect together node1 and node2.
 
         :param node1: Node topology dictionary.
         :param node2: Node topology dictionary.
+        :param filter_list_node1: Link filter criteria for node1.
+        :param filter_list_node2: Link filter criteria for node2.
         :type node1: dict
         :type node2: dict
+        :type filter_list1: list of strings
+        :type filter_list2: list of strings
         :return: List of strings that represent connecting link names.
         :rtype: list
         """
 
         logger.trace("node1: {}".format(str(node1)))
         logger.trace("node2: {}".format(str(node2)))
-        node1_links = self._get_node_active_link_names(node1)
-        node2_links = self._get_node_active_link_names(node2)
-        connecting_links = list(set(node1_links).intersection(node2_links))
+        node1_links = self._get_node_active_link_names(
+            node1,
+            filter_list=filter_list_node1)
+        node2_links = self._get_node_active_link_names(
+            node2,
+            filter_list=filter_list_node2)
+
+        connecting_links = None
+        if node1_links is None:
+            logger.error("Unable to find active links for node1")
+        elif node2_links is None:
+            logger.error("Unable to find active links for node2")
+        else:
+            connecting_links = list(set(node1_links).intersection(node2_links))
 
         return connecting_links
 
index cd3b626..8879f6f 100644 (file)
 | | Set Test Variable | ${tg_node}
 | | Set Test Variable | ${dut_node}
 
+| Vpp l2bd forwarding setup
+| | [Documentation] | Setup BD between 2 interfaces on VPP node and if learning
+| | ...             | is off set static L2FIB entry on second interface
+| | [Arguments] | ${node} | ${if1} | ${if2} | ${learn}=${TRUE} | ${mac}=${EMPTY}
+| | Set Interface State | ${node} | ${if1} | up
+| | Set Interface State | ${node} | ${if2} | up
+| | Vpp Add L2 Bridge Domain | ${node} | ${1} | ${if1} | ${if2} | ${learn}
+| | Run Keyword If | ${learn} == ${FALSE}
+| | ... | Vpp Add L2fib Entry | ${node} | ${mac} | ${if2} | ${1}
+| | All Vpp Interfaces Ready Wait | ${nodes}
+
 | Path for 3-node BD testing is set
 | | [Documentation] | Compute path for bridge domain testing on three given
 | | ...             | nodes and set corresponding test case variables.
index 804b643..de5067b 100644 (file)
 | | Set Suite Variable | ${dut2_if1}
 | | Set Suite Variable | ${dut2_if2}
 
+| 3-node circular Topology Variables Setup with DUT interface model
+| | [Documentation] | Find a path between TG-DUT1-DUT2-TG based on interface
+| | ...             | model provided as an argument. Set suite variables
+| | ...             | tg, tg_if1, tg_if2, dut1, dut1_if1, dut1_if2,
+| | ...             | dut2, dut2_if1, dut2_if2
+| | [Arguments] | ${iface_model}
+| | ${iface_model_list}= | Create list | ${iface_model}
+| | Append Node | ${nodes['TG']}
+| | Append Node | ${nodes['DUT1']} | filter_list=${iface_model_list}
+| | Append Node | ${nodes['DUT2']} | filter_list=${iface_model_list}
+| | Append Node | ${nodes['TG']}
+| | Compute Path
+| | ${tg_if1} | ${tg}= | Next Interface
+| | ${dut1_if1} | ${dut1}= | Next Interface
+| | ${dut1_if2} | ${dut1}= | Next Interface
+| | ${dut2_if1} | ${dut2}= | Next Interface
+| | ${dut2_if2} | ${dut2}= | Next Interface
+| | ${tg_if2} | ${tg}= | Next Interface
+| | Set Suite Variable | ${tg}
+| | Set Suite Variable | ${tg_if1}
+| | Set Suite Variable | ${tg_if2}
+| | Set Suite Variable | ${dut1}
+| | Set Suite Variable | ${dut1_if1}
+| | Set Suite Variable | ${dut1_if2}
+| | Set Suite Variable | ${dut2}
+| | Set Suite Variable | ${dut2_if1}
+| | Set Suite Variable | ${dut2_if2}
+
 | IPv4 forwarding initialized in a 3-node circular topology
 | | [Documentation] | Custom setup of IPv4 addresses on all DUT nodes and TG
 | | Set Interface State | ${dut1} | ${dut1_if1} | up
 | | ...                          | ${dut2} | ${dut2_if1} | ${dut2_if2}
 | | ...                          | ${topology_type}
 
+3-node Performance Suite Setup with DUT's NIC model
+| | [Arguments] | ${topology_type} | ${nic_model}
+| | 3-node circular Topology Variables Setup with DUT interface model
+| | ... | ${nic_model}
+| | Initialize traffic generator | ${tg} | ${tg_if1} | ${tg_if2}
+| | ...                          | ${dut1} | ${dut1_if1} | ${dut1_if2}
+| | ...                          | ${dut2} | ${dut2_if1} | ${dut2_if2}
+| | ...                          | ${topology_type}
+
 | 3-node Performance Suite Teardown
 | | Teardown traffic generator | ${tg}
 
index 1b16616..e48adac 100644 (file)
@@ -57,6 +57,10 @@ schema;type_interfaces:
           required: yes
         driver: &type_interface_mapping_driver
           type: str
+        model:
+          type: str
+          enum: [Cisco-VIC-1227, Cisco-VIC-1385, Intel-X520-DA2,
+                 Intel-X710, Intel-XL710]
 
 schema;type_interface_tg: &type_interface_tg
   type: map
@@ -15,7 +15,9 @@
 | Library | resources.libraries.python.InterfaceUtil
 | Library | resources.libraries.python.NodePath
 | Force Tags | 3_NODE_SINGLE_LINK_TOPO | PERFTEST | HW_ENV | PERFTEST_SHORT
-| Suite Setup | 3-node Performance Suite Setup | L2
+| ...        | NIC_Intel-X520-DA2
+| Suite Setup | 3-node Performance Suite Setup with DUT's NIC model
+| ... | L2 | Intel-X520-DA2
 | Suite Teardown | 3-node Performance Suite Teardown
 | Test Setup | Setup all DUTs before test
 | Test Teardown | Run Keywords | Show statistics on all DUTs
index b272387..8af6d4e 100644 (file)
@@ -20,11 +20,13 @@ nodes:
         pci_address: "0000:05:00.0"
         link: link1
         driver: i40e
+        model: Intel-X710
       port5:
         mac_address: "3c:fd:fe:9c:ed:5d"
         pci_address: "0000:05:00.1"
         link: link2
         driver: i40e
+        model: Intel-X710
   DUT1:
     type: DUT
     host: "10.30.51.21"
@@ -36,10 +38,12 @@ nodes:
         mac_address: "90:e2:ba:b5:02:b9"
         pci_address: "0000:0a:00.1"
         link: link1
+        model: Intel-X520-DA2
       port3:
         mac_address: "90:e2:ba:b5:02:b8"
         pci_address: "0000:0a:00.0"
         link: link3
+        model: Intel-X520-DA2
   DUT2:
     type: DUT
     host: "10.30.51.22"
@@ -51,7 +55,9 @@ nodes:
         mac_address: "90:e2:ba:b5:01:d8"
         pci_address: "0000:0a:00.0"
         link: link2
+        model: Intel-X520-DA2
       port3:
         mac_address: "90:e2:ba:b5:01:d9"
         pci_address: "0000:0a:00.1"
         link: link3
+        model: Intel-X520-DA2
index 0bd8935..ebce145 100644 (file)
@@ -20,11 +20,13 @@ nodes:
         pci_address: "0000:88:00.0"
         link: link1
         driver: i40e
+        model: Intel-X710
       port5:
         mac_address: "3c:fd:fe:9c:ed:7d"
         pci_address: "0000:88:00.1"
         link: link2
         driver: i40e
+        model: Intel-X710
   DUT1:
     type: DUT
     host: "10.30.51.21"
@@ -36,10 +38,12 @@ nodes:
         mac_address: "3c:fd:fe:9c:ee:ed"
         pci_address: "0000:87:00.1"
         link: link1
+        model: Intel-X710
       port3:
         mac_address: "3c:fd:fe:9c:ee:ec"
         pci_address: "0000:87:00.0"
         link: link3
+        model: Intel-X710
   DUT2:
     type: DUT
     host: "10.30.51.22"
@@ -51,7 +55,9 @@ nodes:
         mac_address: "3c:fd:fe:9c:ee:e4"
         pci_address: "0000:87:00.0"
         link: link2
+        model: Intel-X710
       port3:
         mac_address: "3c:fd:fe:9c:ee:e5"
         pci_address: "0000:87:00.1"
         link: link3
+        model: Intel-X710

©2016 FD.io a Linux Foundation Collaborative Project. All Rights Reserved.
Linux Foundation is a registered trademark of The Linux Foundation. Linux is a registered trademark of Linus Torvalds.
Please see our privacy policy and terms of use.