CSIT-229: ip4-lispgpe-ip4 82/2482/31
authorTibor Frank <tifrank@cisco.com>
Wed, 24 Aug 2016 14:09:20 +0000 (16:09 +0200)
committerTibor Frank <tifrank@cisco.com>
Mon, 5 Sep 2016 12:02:48 +0000 (14:02 +0200)
- main fib,
- vrf,
- phy2lisp

Change-Id: Ic9bacef4574dc07b25041c4cd0653825a65c94fb
Signed-off-by: Tibor Frank <tifrank@cisco.com>
13 files changed:
resources/libraries/python/IPUtil.py
resources/libraries/python/IPv4Util.py
resources/libraries/python/InterfaceUtil.py
resources/libraries/python/L2Util.py
resources/libraries/python/LispSetup.py
resources/libraries/python/LispUtil.py
resources/libraries/robot/lisp/lisp_api.robot
resources/libraries/robot/lisp/lispgpe.robot [new file with mode: 0644]
resources/templates/vat/lisp/lisp_gpe_status.vat [new file with mode: 0644]
resources/templates/vat/lisp/show_lisp_gpe_tunnel.vat [new file with mode: 0644]
resources/templates/vat/lisp/show_lisp_locator_set.vat
resources/test_data/lisp/ipv4_lispgpe_ipv4/ipv4_lispgpe_ipv4.py [new file with mode: 0644]
tests/func/lisp/lisp_ipv4_lispgpe_ipv4.robot [new file with mode: 0644]

index 5011708..ed38272 100644 (file)
@@ -17,7 +17,7 @@ from ipaddress import IPv4Network, ip_address
 
 from resources.libraries.python.ssh import SSH
 from resources.libraries.python.constants import Constants
-
+from resources.libraries.python.ssh import exec_cmd_no_error, exec_cmd
 from resources.libraries.python.topology import Topology
 
 
@@ -73,6 +73,72 @@ class IPUtil(object):
             raise AssertionError('IP addresses are not equal: {0} != {1}'.
                                  format(ip1, ip2))
 
+    @staticmethod
+    def setup_network_namespace(node, namespace_name, interface_name,
+                                ip_address, prefix):
+        """Setup namespace on given node and attach interface and IP to
+        this namespace. Applicable also on TG node.
+
+        :param node: Node to set namespace on.
+        :param namespace_name: Namespace name.
+        :param interface_name: Interface name.
+        :param ip_address: IP address of namespace's interface.
+        :param prefix: IP address prefix length.
+        :type node: dict
+        :type namespace_name: str
+        :type vhost_if: str
+        :type ip_address: str
+        :type prefix: int
+        """
+        cmd = ('ip netns add {0}'.format(namespace_name))
+        exec_cmd_no_error(node, cmd, sudo=True)
+
+        cmd = ('ip link set dev {0} up netns {1}'.format(interface_name,
+                                                         namespace_name))
+        exec_cmd_no_error(node, cmd, sudo=True)
+
+        cmd = ('ip netns exec {0} ip addr add {1}/{2} dev {3}'.format(
+            namespace_name, ip_address, prefix, interface_name))
+        exec_cmd_no_error(node, cmd, sudo=True)
+
+    @staticmethod
+    def linux_enable_forwarding(node, ip_ver='ipv4'):
+        """Enable forwarding on a Linux node, e.g. VM.
+
+        :param node: Node to enable forwarding on.
+        :param ip_ver: IP version, 'ipv4' or 'ipv6'.
+        :type node: dict
+        :type ip_ver: str
+        """
+        cmd = 'sysctl -w net.{0}.ip_forward=1'.format(ip_ver)
+        exec_cmd_no_error(node, cmd, sudo=True)
+
+    @staticmethod
+    def set_linux_interface_ip(node, interface, ip, prefix, namespace=None):
+        """Set IP address to interface in linux.
+
+        :param node: Node where to execute command.
+        :param interface: Interface in namespace.
+        :param ip: IP to be set on interface.
+        :param prefix: IP prefix.
+        :param namespace: Execute command in namespace. Optional
+        :type node: dict
+        :type interface: str
+        :type ip: str
+        :type prefix: int
+        :type namespace: str
+        :raises RuntimeError: IP could not be set.
+        """
+        if namespace is not None:
+            cmd = 'ip netns exec {} ip addr add {}/{} dev {}'.format(
+                namespace, ip, prefix, interface)
+        else:
+            cmd = 'ip addr add {}/{} dev {}'.format(ip, prefix, interface)
+        (rc, _, stderr) = exec_cmd(node, cmd, timeout=5, sudo=True)
+        if rc != 0:
+            raise RuntimeError(
+                'Could not set IP for interface, reason:{}'.format(stderr))
+
 
 def convert_ipv4_netmask_prefix(network):
     """Convert network mask to equivalent network prefix length or vice versa.
index 3043f23..ca5a1b5 100644 (file)
@@ -218,29 +218,3 @@ class IPv4Util(object):
         if rc != 0:
             raise RuntimeError("Arp set not successful, reason:{}".
                                format(stderr))
-
-    @staticmethod
-    def set_linux_interface_ip(node, interface, ip, prefix, namespace=None):
-        """Set IP address to interface in linux.
-
-        :param node: Node where to execute command.
-        :param interface: Interface in namespace.
-        :param ip: IP to be set on interface.
-        :param prefix: IP prefix.
-        :param namespace: Execute command in namespace. Optional
-        :type node: dict
-        :type interface: str
-        :type ip: str
-        :type prefix: int
-        :type namespace: str
-        :raises RuntimeError: IP could not be set.
-        """
-        if namespace is not None:
-            cmd = 'ip netns exec {} ip addr add {}/{} dev {}'.format(
-                namespace, ip, prefix, interface)
-        else:
-            cmd = 'ip addr add {}/{} dev {}'.format(ip, prefix, interface)
-        (rc, _, stderr) = exec_cmd(node, cmd, timeout=5, sudo=True)
-        if rc != 0:
-            raise RuntimeError(
-                'Could not set IP for interface, reason:{}'.format(stderr))
index f5f1ce3..11600a1 100644 (file)
@@ -212,6 +212,28 @@ class InterfaceUtil(object):
             return dict()
         return data
 
+    @staticmethod
+    def vpp_get_interface_mac(node, interface=None):
+        """Get MAC address for the given interface from actual interface dump.
+
+        :param node: VPP node to get interface data from.
+        :param interface: Numeric index or name string of a specific interface.
+        :type node: dict
+        :type interface: int or str
+        :return: MAC address.
+        :rtype: str
+        """
+
+        if_data = InterfaceUtil.vpp_get_interface_data(node, interface)
+        mac_data = [str(hex(item))[2:] for item in if_data['l2_address'][:6]]
+        mac_data_nice = []
+        for item in mac_data:
+            if len(item) == 1:
+                item = '0' + item
+            mac_data_nice.append(item)
+        mac = ":".join(mac_data_nice)
+        return mac
+
     @staticmethod
     def vpp_get_interface_ip_addresses(node, interface, ip_version):
         """Get list of IP addresses from an interface on a VPP node.
index 566b69b..a909e86 100644 (file)
@@ -217,35 +217,6 @@ class L2Util(object):
             cmd = 'ip link set dev {0} up'.format(br_name)
             exec_cmd_no_error(node, cmd, sudo=True)
 
-    @staticmethod
-    def setup_network_namespace(node, namespace_name, interface_name,
-                                ip_address, prefix):
-        """Setup namespace on given node and attach interface and IP to
-        this namespace. Applicable also on TG node.
-
-        :param node: Node to set namespace on.
-        :param namespace_name: Namespace name.
-        :param interface_name: Interface name.
-        :param ip_address: IP address of namespace's interface.
-        :param prefix: IP address prefix length.
-        :type node: dict
-        :type namespace_name: str
-        :type vhost_if: str
-        :type ip_address: str
-        :type prefix: int
-
-        """
-        cmd = ('ip netns add {0}'.format(namespace_name))
-        exec_cmd_no_error(node, cmd, sudo=True)
-
-        cmd = ('ip link set dev {0} up netns {1}'.format(interface_name,
-                                                         namespace_name))
-        exec_cmd_no_error(node, cmd, sudo=True)
-
-        cmd = ('ip netns exec {0} ip addr add {1}/{2} dev {3}'.format(
-            namespace_name, ip_address, prefix, interface_name))
-        exec_cmd_no_error(node, cmd, sudo=True)
-
     @staticmethod
     def linux_del_bridge(node, br_name, set_down=True):
         """Delete bridge from linux node.
index 5315101..ee2ae5d 100644 (file)
@@ -164,6 +164,26 @@ class LispAdjacency(object):
                                       seid_prefix=seid_prefix)
 
 
+class LispGpeStatus(object):
+    """Clas for LISP GPE status manipulation."""
+
+    def __init__(self):
+        pass
+
+    @staticmethod
+    def vpp_lisp_gpe_enable_disable(node, state):
+        """Change the state of LISP GPE - enable or disable.
+
+        :param node: VPP node.
+        :param state: Requested state - enable or disable.
+        :type node: dict
+        :type state: str
+        """
+
+        VatExecutor.cmd_from_template(node, 'lisp/lisp_gpe_status.vat',
+                                      state=state)
+
+
 class LispGpeIface(object):
     """Class for Lisp gpe interface API."""
 
@@ -180,11 +200,31 @@ class LispGpeIface(object):
         :type state: str
         """
 
-        VatExecutor.cmd_from_template(node,
-                                      'lisp/lisp_gpe_iface.vat',
+        VatExecutor.cmd_from_template(node, 'lisp/lisp_gpe_iface.vat',
                                       state=state)
 
 
+class LispGpeForwardEntry(object):
+    """The functionality needed for these methods is not implemented in VPP
+    (VAT). Bug https://jira.fd.io/browse/VPP-334 was open to cover this issue.
+
+    TODO: Implement when VPP-334 is fixed.
+    """
+
+    def __init__(self):
+        pass
+
+    @staticmethod
+    def add_lisp_gpe_forward_entry(node, *args):
+        # TODO: Implement when VPP-334 is fixed.
+        pass
+
+    @staticmethod
+    def del_lisp_gpe_forward_entry(node, *args):
+        # TODO: Implement when VPP-334 is fixed.
+        pass
+
+
 class LispMapResolver(object):
     """Class for Lisp map resolver API."""
 
index 8a83dc4..c50e626 100644 (file)
@@ -15,7 +15,7 @@
 
 from resources.libraries.python.parsers.JsonParser import JsonParser
 from resources.libraries.python.topology import Topology
-from resources.libraries.python.VatExecutor import VatExecutor
+from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal
 
 
 class LispUtil(object):
@@ -40,18 +40,25 @@ class LispUtil(object):
         return JsonParser().parse_data(vat.get_script_stdout())
 
     @staticmethod
-    def vpp_show_lisp_locator_set(node):
+    def vpp_show_lisp_locator_set(node, items_filter):
         """Get lisp locator_set from VPP node.
 
         :param node: VPP node.
+        :param items_filter: Filter which specifies which items should be
+        retrieved - local, remote, empty string = both.
         :type node: dict
+        :type items_filter: str
         :return: Lisp locator_set data as python list.
         :rtype: list
         """
 
-        vat = VatExecutor()
-        vat.execute_script_json_out('lisp/show_lisp_locator_set.vat', node)
-        return JsonParser().parse_data(vat.get_script_stdout())
+        try:
+            with VatTerminal(node) as vat:
+                response = vat.vat_terminal_exec_cmd_from_template(
+                    'lisp/show_lisp_locator_set.vat', filter=items_filter)
+            return response[0]
+        except ValueError:
+            return []
 
     @staticmethod
     def vpp_show_lisp_eid_table(node):
index 8094d08..4bd22bc 100644 (file)
@@ -16,6 +16,7 @@
 | Library  | resources.libraries.python.NodePath
 | Library  | resources.libraries.python.LispSetup.LispStatus
 | Library  | resources.libraries.python.LispSetup.LispSetup
+| Library  | resources.libraries.python.LispSetup.LispGpeStatus
 | Library  | resources.libraries.python.LispUtil
 
 *** Keywords ***
@@ -82,7 +83,7 @@
 | | ... | \| Then Lisp locator_set is set correctly \| ${nodes['DUT1']} \|
 | | ...
 | | [Arguments] | ${dut_node}
-| | ${show_locator_set}= | Vpp Show Lisp Locator Set | ${dut_node}
+| | ${show_locator_set}= | Vpp Show Lisp Locator Set | ${dut_node} | local
 | | Lisp Locator S Should Be Equal
 | | ... | ${locator_set_values} | ${show_locator_set}
 
 | | ... | \| Then Lisp locator_set should be unset \| ${nodes['DUT1']} \|
 | | ...
 | | [Arguments] | ${dut_node}
-| | ${show_locator_set}= | Vpp Show Lisp Locator Set | ${dut_node}
+| | ${show_locator_set}= | Vpp Show Lisp Locator Set | ${dut_node} | ${EMPTY}
 | | Lisp Is Empty | ${show_locator_set}
 
 | Lisp locator_set data use for test reset locator_set are prepared
 | | [Arguments] | ${dut_node} | ${lisp_status_data}
 | | ${show_lisp_stat}= | Vpp Show Lisp State | ${dut_node}
 | | Lisp Should Be Equal | ${show_lisp_stat} | ${lisp_status_data[0]}
+
+| Enable Lisp Gpe
+| | [Documentation] | Enable Lisp Gpe on VPP node.
+| | ...
+| | ... | *Arguments:*
+| | ... | - dut_node - DUT node. Type: dictionary
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ... | \| Enable Lisp Gpe \| ${nodes['DUT1']} \|
+| | ...
+| | [Arguments] | ${dut_node}
+| | Vpp Lisp Gpe Enable Disable | ${dut_node} | enable
+
+| Disable Lisp Gpe
+| | [Documentation] | Disable Lisp Gpe on VPP node.
+| | ...
+| | ... | *Arguments:*
+| | ... | - dut_node - DUT node. Type: dictionary
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ... | \| Disable Lisp Gpe \| ${nodes['DUT1']} \|
+| | ...
+| | [Arguments] | ${dut_node}
+| | Vpp Lisp Gpe Enable Disable | ${dut_node} | disable
diff --git a/resources/libraries/robot/lisp/lispgpe.robot b/resources/libraries/robot/lisp/lispgpe.robot
new file mode 100644 (file)
index 0000000..a5ab102
--- /dev/null
@@ -0,0 +1,118 @@
+# Copyright (c) 2016 Cisco and/or its affiliates.
+# 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.
+
+*** Settings ***
+| Documentation | LISP-gpe encapsulation suite keywords
+| Library | resources.libraries.python.topology.Topology
+| Resource | resources/libraries/robot/lisp/lisp_api.robot
+| Library  | resources.libraries.python.LispSetup.LispLocatorSet
+| Library  | resources.libraries.python.LispSetup.LispLocator
+| Library  | resources.libraries.python.LispSetup.LispLocalEid
+| Library  | resources.libraries.python.LispSetup.LispAdjacency
+| Library  | resources.libraries.python.LispSetup.LispRemoteMapping
+
+*** Keywords ***
+| Set up LISP GPE topology
+| | [Documentation] | Set up LISP GPE topology.
+| | ...
+| | ... | *Arguments:*
+| | ... | - dut1_node - DUT1 node. Type: dictionary
+| | ... | - dut1_if - DUT1 node interface. Type: string
+| | ... | - dut1_int_index - DUT1 node interface index. Type: integer
+| | ... | - dut2_node - DUT2 node. Type: dictionary
+| | ... | - dut2_if - DUT2 node interface. Type: string
+| | ... | - dut2_int_index - DUT2 node interface index. Type: integer
+| | ... | - locator_set - Locator set values. Type: dictionary
+| | ... | - dut1_eid - DUT1 node eid address. Type: dictionary
+| | ... | - dut2_eid - DUT2 node eid address. Type: dictionary
+| | ... | - dut1_static_adjacency - DUT1 static adjacency. Type: dictionary
+| | ... | - dut2_static_adjacency - DUT2 static adjacency. Type: dictionary
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ... | \| Set up LISP GPE topology \| ${dut1_node} \| ${interface_name} \
+| | ... | \| None \| ${dut2_node} \| ${interface_name} \| None \
+| | ... | \| ${locator_set} \| ${dut1_eid} \| ${dut2_eid} \
+| | ... | \| ${dut1_static_adjacency} \| ${dut2_static_adjacency} \|
+| | ...
+| | [Arguments]
+| | ... | ${dut1_node} | ${dut1_if} | ${dut1_int_index}
+| | ... | ${dut2_node} | ${dut2_if} | ${dut2_int_index}
+| | ... | ${locator_set} | ${dut1_eid} | ${dut2_eid}
+| | ... | ${dut1_static_adjacency} | ${dut2_static_adjacency}
+| | ...
+# DUT1 settings:
+| | ${dut1_int_index}= | Run Keyword If | ${dut1_int_index} is None
+| | | ... | Get Interface Sw Index | ${dut1_node} | ${dut1_if}
+| | | ... | ELSE | Set Variable | ${dut1_int_index}
+| | Enable Lisp | ${dut1_node}
+| | Enable Lisp GPE | ${dut1_node}
+| | Vpp Add Lisp Locator Set | ${dut1_node}
+| | ... | ${locator_set['locator_name']}
+| | Vpp Add Lisp Locator | ${dut1_node}
+| | ... | ${locator_set['locator_name']}
+| | ... | ${dut1_int_index}
+| | ... | ${locator_set['priority']}
+| | ... | ${locator_set['weight']}
+| | Vpp Add Lisp Local Eid | ${dut1_node}
+| | ... | ${dut1_eid['locator_name']}
+| | ... | ${dut1_eid['vni']}
+| | ... | ${dut1_eid['eid']}
+| | ... | ${dut1_eid['prefix']}
+| | Vpp Add Lisp Remote Mapping | ${dut1_node}
+| | ... | ${dut1_static_adjacency['vni']}
+| | ... | ${dut1_static_adjacency['deid']}
+| | ... | ${dut1_static_adjacency['prefix']}
+| | ... | ${dut1_static_adjacency['seid']}
+| | ... | ${dut1_static_adjacency['prefix']}
+| | ... | ${dut1_static_adjacency['rloc']}
+| | Vpp Add Lisp Adjacency | ${dut1_node}
+| | ... | ${dut1_static_adjacency['vni']}
+| | ... | ${dut1_static_adjacency['deid']}
+| | ... | ${dut1_static_adjacency['prefix']}
+| | ... | ${dut1_static_adjacency['seid']}
+| | ... | ${dut1_static_adjacency['prefix']}
+| | ...
+# DUT2 settings:
+| | ${dut2_int_index}= | Run Keyword If | ${dut2_int_index} is None
+| | | ... | Get Interface Sw Index | ${dut2_node} | ${dut2_if}
+| | | ... | ELSE | Set Variable | ${dut2_int_index}
+| | Enable Lisp | ${dut2_node}
+| | Enable Lisp GPE | ${dut2_node}
+| | Vpp Add Lisp Locator Set | ${dut2_node}
+| | ... | ${locator_set['locator_name']}
+| | Vpp Add Lisp Locator | ${dut2_node}
+| | ... | ${locator_set['locator_name']}
+| | ... | ${dut2_int_index}
+| | ... | ${locator_set['priority']}
+| | ... | ${locator_set['weight']}
+| | Vpp Add Lisp Local Eid | ${dut2_node}
+| | ... | ${dut2_eid['locator_name']}
+| | ... | ${dut2_eid['vni']}
+| | ... | ${dut2_eid['eid']}
+| | ... | ${dut2_eid['prefix']}
+| | Vpp Add Lisp Remote Mapping | ${dut2_node}
+| | ... | ${dut2_static_adjacency['vni']}
+| | ... | ${dut2_static_adjacency['deid']}
+| | ... | ${dut2_static_adjacency['prefix']}
+| | ... | ${dut2_static_adjacency['seid']}
+| | ... | ${dut2_static_adjacency['prefix']}
+| | ... | ${dut2_static_adjacency['rloc']}
+| | Vpp Add Lisp Adjacency | ${dut2_node}
+| | ... | ${dut2_static_adjacency['vni']}
+| | ... | ${dut2_static_adjacency['deid']}
+| | ... | ${dut2_static_adjacency['prefix']}
+| | ... | ${dut2_static_adjacency['seid']}
+| | ... | ${dut2_static_adjacency['prefix']}
diff --git a/resources/templates/vat/lisp/lisp_gpe_status.vat b/resources/templates/vat/lisp/lisp_gpe_status.vat
new file mode 100644 (file)
index 0000000..5c4080a
--- /dev/null
@@ -0,0 +1 @@
+lisp_gpe_enable_disable {state}
diff --git a/resources/templates/vat/lisp/show_lisp_gpe_tunnel.vat b/resources/templates/vat/lisp/show_lisp_gpe_tunnel.vat
new file mode 100644 (file)
index 0000000..802cfbb
--- /dev/null
@@ -0,0 +1 @@
+# TODO: Implement when VPP-334 is fixed.
\ No newline at end of file
index 43768ec..4f775ff 100644 (file)
@@ -1 +1 @@
-lisp_locator_set_dump
\ No newline at end of file
+lisp_locator_set_dump {filter}
\ No newline at end of file
diff --git a/resources/test_data/lisp/ipv4_lispgpe_ipv4/ipv4_lispgpe_ipv4.py b/resources/test_data/lisp/ipv4_lispgpe_ipv4/ipv4_lispgpe_ipv4.py
new file mode 100644 (file)
index 0000000..cd1b638
--- /dev/null
@@ -0,0 +1,54 @@
+# Copyright (c) 2016 Cisco and/or its affiliates.
+# 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.
+
+"""Test variables for ip4-lispgpe-ip4 encapsulation test suite."""
+
+# Lisp default global value
+locator_name = 'tst_locator'
+
+# Lisp default locator_set value
+duts_locator_set = {'locator_name': locator_name,
+                    'priority': 1,
+                    'weight': 1}
+
+# IPv4 Lisp static mapping configuration
+dut1_to_dut2_ip4 = '6.0.3.1'
+dut2_to_dut1_ip4 = '6.0.3.2'
+dut1_to_tg_ip4 = '6.0.1.1'
+dut2_to_tg_ip4 = '6.0.2.1'
+tg1_ip4 = '6.0.1.2'
+tg2_ip4 = '6.0.2.2'
+prefix4 = 24
+
+dut1_to_dut2_ip4_static_adjacency = {'vni': 0,
+                                     'deid': '6.0.2.0',
+                                     'seid': '6.0.1.0',
+                                     'rloc': '6.0.3.2',
+                                     'prefix': 24}
+dut2_to_dut1_ip4_static_adjacency = {'vni': 0,
+                                     'deid': '6.0.1.0',
+                                     'seid': '6.0.2.0',
+                                     'rloc': '6.0.3.1',
+                                     'prefix': 24}
+
+dut1_ip4_eid = {'locator_name': locator_name,
+                'vni': 0,
+                'eid': '6.0.1.0',
+                'prefix': 24}
+dut2_ip4_eid = {'locator_name': locator_name,
+                'vni': 0,
+                'eid': '6.0.2.0',
+                'prefix': 24}
+
+dut1_fib_table = '1'
+dut2_fib_table = '2'
diff --git a/tests/func/lisp/lisp_ipv4_lispgpe_ipv4.robot b/tests/func/lisp/lisp_ipv4_lispgpe_ipv4.robot
new file mode 100644 (file)
index 0000000..8a18962
--- /dev/null
@@ -0,0 +1,179 @@
+# Copyright (c) 2016 Cisco and/or its affiliates.
+# 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.
+
+*** Settings ***
+| Library | resources.libraries.python.topology.Topology
+| Library | resources.libraries.python.NodePath
+| Library | resources.libraries.python.Trace
+| Library | resources.libraries.python.IPUtil
+| Library | resources.libraries.python.LispUtil
+| Resource | resources/libraries/robot/traffic.robot
+| Resource | resources/libraries/robot/default.robot
+| Resource | resources/libraries/robot/interfaces.robot
+| Resource | resources/libraries/robot/testing_path.robot
+| Resource | resources/libraries/robot/ipv4.robot
+| Resource | resources/libraries/robot/lisp/lispgpe.robot
+# Import configuration and test data:
+| Variables | resources/test_data/lisp/ipv4_lispgpe_ipv4/ipv4_lispgpe_ipv4.py
+| ...
+| Force Tags | 3_NODE_SINGLE_LINK_TOPO | VM_ENV | EXPECTED_FAILING
+| ...
+| Test Setup | Run Keywords | Setup all DUTs before test
+| ...        | AND          | Setup all TGs before traffic script
+| ...        | AND          | Update All Interface Data On All Nodes | ${nodes}
+| Test Teardown | Run Keywords | Show Packet Trace on All DUTs | ${nodes}
+| ...           | AND          | Show vpp trace dump on all DUTs
+| ...           | AND          | VPP Show Errors | ${nodes['DUT1']}
+| ...           | AND          | VPP Show Errors | ${nodes['DUT2']}
+| ...
+| Documentation | *ip4-lispgpe-ip4 encapsulation test cases*
+| ...
+| ... | *[Top] Network Topologies:* TG-DUT1-DUT2-TG 3-node circular topology
+| ... | with single links between nodes.
+| ... | *[Enc] Packet Encapsulations:* Eth-IPv4-LISP-IPv4-ICMPv4 on DUT1-DUT2,
+| ... | Eth-IPv4-ICMPv4 on TG-DUTn for IPv4 routing over LISPoIPv4 tunnel.
+| ... | *[Cfg] DUT configuration:* DUT1 and DUT2 are configured with IPv4
+| ... | routing and static routes. LISPoIPv4 tunnel is configured between
+| ... | DUT1 and DUT2.
+| ... | *[Ver] TG verification:* Test ICMPv4 Echo Request packets are sent in
+| ... | both directions by TG on links to DUT1 and DUT2; on receive
+| ... | TG verifies packets for correctness and their IPv4 src-addr, dst-addr
+| ... | and MAC addresses.
+| ... | *[Ref] Applicable standard specifications:* RFC6830.
+
+*** Test Cases ***
+| TC01: DUT1 and DUT2 route IPv4 bidirectionally over LISP GPE tunnel using physical interfaces
+| | [Documentation]
+| | ... | Case: ip4-lispgpe-ip4 - phy2lisp \
+| | ... | [Top] TG-DUT1-DUT2-TG.
+| | ... | [Enc] Eth-IPv4-LISPGPE-IPv4-ICMPv4 on DUT1-DUT2, Eth-IPv4-ICMPv4 on
+| | ... | TG-DUTn.
+| | ... | [Cfg] Configure IPv4 LISP static adjacencies on DUT1 and DUT2.
+| | ... | [Ver] Make TG send ICMPv4 Echo Req between its interfaces across both
+| | ... | DUTs and LISP GPE tunnel between them; verify IPv4 headers on received
+| | ... | packets are correct.
+| | ... | [Ref] RFC6830.
+| | ...
+| | Given Path for 3-node testing is set
+| | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['DUT2']} | ${nodes['TG']}
+| | And Interfaces in 3-node path are up
+| | And IP addresses are set on interfaces
+| | ... | ${dut1_node} | ${dut1_to_dut2} | ${dut1_to_dut2_ip4} | ${prefix4}
+| | ... | ${dut1_node} | ${dut1_to_tg} | ${dut1_to_tg_ip4} | ${prefix4}
+| | ... | ${dut2_node} | ${dut2_to_dut1} | ${dut2_to_dut1_ip4} | ${prefix4}
+| | ... | ${dut2_node} | ${dut2_to_tg} | ${dut2_to_tg_ip4} | ${prefix4}
+| | And VPP IP Probe | ${dut1_node} | ${dut1_to_dut2} | ${dut2_to_dut1_ip4}
+| | And VPP IP Probe | ${dut2_node} | ${dut2_to_dut1} | ${dut1_to_dut2_ip4}
+| | And Add Arp On Dut | ${dut2_node} | ${dut2_to_tg} | ${tg2_ip4}
+| | ... | ${tg_to_dut2_mac}
+| | And Add Arp On Dut | ${dut1_node} | ${dut1_to_tg} | ${tg1_ip4}
+| | ... | ${tg_to_dut1_mac}
+| | When Set up LISP GPE topology
+| | ... | ${dut1_node} | ${dut1_to_dut2} | ${NONE}
+| | ... | ${dut2_node} | ${dut2_to_dut1} | ${NONE}
+| | ... | ${duts_locator_set} | ${dut1_ip4_eid} | ${dut2_ip4_eid}
+| | ... | ${dut1_to_dut2_ip4_static_adjacency}
+| | ... | ${dut2_to_dut1_ip4_static_adjacency}
+| | Then Send Packet And Check Headers
+| | ... | ${tg_node} | ${tg1_ip4} | ${tg2_ip4}
+| | ... | ${tg_to_dut1} | ${tg_to_dut1_mac} | ${dut1_to_tg_mac}
+| | ... | ${tg_to_dut2} | ${dut2_to_tg_mac} | ${tg_to_dut2_mac}
+| | And Send Packet And Check Headers
+| | ... | ${tg_node} | ${tg2_ip4} | ${tg1_ip4}
+| | ... | ${tg_to_dut2} | ${tg_to_dut2_mac} | ${dut2_to_tg_mac}
+| | ... | ${tg_to_dut1} | ${dut1_to_tg_mac} | ${tg_to_dut1_mac}
+
+| TC02: DUT1 and DUT2 route IPv4 bidirectionally over LISP GPE tunnel using physical interfaces and VRF is enabled
+| | [Documentation]
+| | ... | Case: ip4-lispgpe-ip4 - vrf, phy2lisp \
+| | ... | [Top] TG-DUT1-DUT2-TG.
+| | ... | [Enc] Eth-IPv4-LISPGPE-IPv4-ICMPv4 on DUT1-DUT2, Eth-IPv4-ICMPv4 on
+| | ... | TG-DUTn.
+| | ... | [Cfg] Configure IPv4 LISP static adjacencies on DUT1 and DUT2.
+| | ... | [Ver] Make TG send ICMPv4 Echo Req between its interfaces across both
+| | ... | DUTs and LISP GPE tunnel between them; verify IPv4 headers on received
+| | ... | packets are correct.
+| | ... | [Ref] RFC6830.
+| | ...
+| | Given Path for 3-node testing is set
+| | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['DUT2']} | ${nodes['TG']}
+| | And Interfaces in 3-node path are up
+| | When Setup VRF on DUT | ${dut1_node} | ${dut1_fib_table} | ${dut1_to_dut2}
+| | ... | ${dut2_to_dut1_ip4} | ${dut2_to_dut1_mac} | ${tg2_ip4} | ${dut1_to_tg}
+| | ... | ${tg1_ip4} | ${tg_to_dut1_mac} | ${prefix4}
+| | And Setup VRF on DUT | ${dut2_node} | ${dut2_fib_table} | ${dut2_to_dut1}
+| | ... | ${dut1_to_dut2_ip4} | ${dut1_to_dut2_mac} | ${tg1_ip4} | ${dut2_to_tg}
+| | ... | ${tg2_ip4} | ${tg_to_dut2_mac} | ${prefix4}
+| | And IP addresses are set on interfaces
+| | ... | ${dut1_node} | ${dut1_to_dut2} | ${dut1_to_dut2_ip4} | ${prefix4}
+| | ... | ${dut1_node} | ${dut1_to_tg} | ${dut1_to_tg_ip4} | ${prefix4}
+| | ... | ${dut2_node} | ${dut2_to_dut1} | ${dut2_to_dut1_ip4} | ${prefix4}
+| | ... | ${dut2_node} | ${dut2_to_tg} | ${dut2_to_tg_ip4} | ${prefix4}
+| | And Set up LISP GPE topology
+| | ... | ${dut1_node} | ${dut1_to_dut2} | ${NONE}
+| | ... | ${dut2_node} | ${dut2_to_dut1} | ${NONE}
+| | ... | ${duts_locator_set} | ${dut1_ip4_eid} | ${dut2_ip4_eid}
+| | ... | ${dut1_to_dut2_ip4_static_adjacency}
+| | ... | ${dut2_to_dut1_ip4_static_adjacency}
+| | Then Send Packet And Check Headers
+| | ... | ${tg_node} | ${tg1_ip4} | ${tg2_ip4}
+| | ... | ${tg_to_dut1} | ${tg_to_dut1_mac} | ${dut1_to_tg_mac}
+| | ... | ${tg_to_dut2} | ${dut2_to_tg_mac} | ${tg_to_dut2_mac}
+| | And Send Packet And Check Headers
+| | ... | ${tg_node} | ${tg2_ip4} | ${tg1_ip4}
+| | ... | ${tg_to_dut2} | ${tg_to_dut2_mac} | ${dut2_to_tg_mac}
+| | ... | ${tg_to_dut1} | ${dut1_to_tg_mac} | ${tg_to_dut1_mac}
+
+*** Keywords ***
+| Setup VRF on DUT
+| | [Documentation]
+| | ... | The keyword sets a FIB table on a DUT, assigns two interfaces to it,\
+| | ... | adds two ARP items and a route, see example.
+| | ...
+| | ... | *Example:*
+| | ... | Three-node topology:
+| | ... | TG_if1 - DUT1_if1-DUT1_if2 - DUT2_if1-DUT2_if2 - TG_if2
+| | ... | Create one VRF on each DUT:
+| | ... | \| Setup VRF on DUT \| ${dut1_node} \| ${dut1_fib_table} \
+| | ... | \| ${dut1_to_dut2} \| ${dut2_to_dut1_ip4} \| ${dut2_to_dut1_mac} \
+| | ... | \| ${tg2_ip4} \| ${dut1_to_tg} \| ${tg1_ip4} \| ${tg_to_dut1_mac} \
+| | ... | \| 24 \|
+| | ... | \| Setup VRF on DUT \| ${dut2_node} \| ${dut2_fib_table} \
+| | ... | \| ${dut2_to_dut1} \| ${dut1_to_dut2_ip4} \| ${dut1_to_dut2_mac} \
+| | ... | \| ${tg1_ip4} \| ${dut2_to_tg} \| ${tg2_ip4} \| ${tg_to_dut2_mac} \
+| | ... | \| 24 \|
+| | ...
+| | [Arguments]
+| | ... | ${node} | ${table} | ${route_interface} | ${route_gateway_ip}
+| | ... | ${route_gateway_mac} | ${route_dst_ip} | ${vrf_src_if} | ${src_if_ip}
+| | ... | ${src_if_mac} | ${prefix_len}
+| | ...
+| | ${route_interface_idx}= | Get Interface SW Index
+| | ... | ${node} | ${route_interface}
+| | ...
+| | Add fib table | ${node}
+| | ... | ${route_dst_ip} | ${prefix_len} | ${table}
+| | ... | via ${route_gateway_ip} sw_if_index ${route_interface_idx} multipath
+| | ...
+| | Assign Interface To Fib Table
+| | ... | ${node} | ${route_interface} | ${table}
+| | Assign Interface To Fib Table
+| | ... | ${node} | ${vrf_src_if} | ${table}
+| | ...
+| | Add Arp On Dut | ${node} | ${vrf_src_if}
+| | ... | ${src_if_ip} | ${src_if_mac} | vrf=${table}
+| | Add Arp On Dut | ${node} | ${route_interface}
+| | ... | ${route_gateway_ip} | ${route_gateway_mac} | vrf=${table}
+| | ...
+| | Vpp Route Add | ${node} | ${route_dst_ip} | ${prefix_len}
+| | ... | ${route_gateway_ip} | ${route_interface} | vrf=${table}