CSIT-24 Proxy ARP test 94/1494/12
authorPatrik Hrnciar <phrnciar@cisco.com>
Fri, 10 Jun 2016 06:09:56 +0000 (08:09 +0200)
committerDave Wallace <dwallacelf@gmail.com>
Thu, 30 Jun 2016 19:09:11 +0000 (19:09 +0000)
Change-Id: Ia41af7e29dcb8c41d58c07134a385428ac1b285c
Signed-off-by: Patrik Hrnciar <phrnciar@cisco.com>
resources/libraries/python/InterfaceUtil.py
resources/libraries/python/ProxyArp.py [new file with mode: 0644]
resources/libraries/python/TrafficScriptExecutor.py
resources/libraries/robot/traffic.robot
resources/templates/vat/add_proxy_arp.vat [new file with mode: 0644]
resources/templates/vat/proxy_arp_intfc_enable.vat [new file with mode: 0644]
resources/traffic_scripts/arp_request.py
tests/suites/ipv4/ipv4_proxy_arp_untagged.robot [new file with mode: 0644]

index 7bf0584..ace4453 100644 (file)
@@ -748,3 +748,22 @@ class InterfaceUtil(object):
             return {}
 
         return vxlan_gpe_data[0]
             return {}
 
         return vxlan_gpe_data[0]
+
+    @staticmethod
+    def vpp_proxy_arp_interface_enable(node, interface):
+        """Enable proxy ARP on interface.
+
+        :param node: VPP node to enable proxy ARP on interface.
+        :param interface: Interface to enable proxy ARP.
+        :type node: dict
+        :type interface: str or int
+        """
+        if isinstance(interface, basestring):
+            sw_if_index = InterfaceUtil.get_sw_if_index(node, interface)
+        else:
+            sw_if_index = interface
+
+        with VatTerminal(node) as vat:
+            vat.vat_terminal_exec_cmd_from_template(
+                "proxy_arp_intfc_enable.vat",
+                sw_if_index=sw_if_index)
diff --git a/resources/libraries/python/ProxyArp.py b/resources/libraries/python/ProxyArp.py
new file mode 100644 (file)
index 0000000..4879fe6
--- /dev/null
@@ -0,0 +1,36 @@
+# 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.
+
+"""Proxy ARP library"""
+
+from resources.libraries.python.VatExecutor import VatTerminal
+
+
+class ProxyArp(object):
+    """Proxy ARP utilities."""
+
+    @staticmethod
+    def vpp_add_proxy_arp(node, lo_ip4_addr, hi_ip4_addr):
+        """Enable proxy ARP for a range of IP addresses.
+
+        :param node: VPP node to enable proxy ARP.
+        :param lo_ip4_addr: The lower limit of the IP addresses.
+        :param hi_ip4_addr: The upper limit of the IP addresses.
+        :type node: dict
+        :type lo_ip4_addr: str
+        :type hi_ip4_addr: str
+        """
+        with VatTerminal(node) as vat:
+            vat.vat_terminal_exec_cmd_from_template("add_proxy_arp.vat",
+                                                    lo_ip4_addr=lo_ip4_addr,
+                                                    hi_ip4_addr=hi_ip4_addr)
index f730d3a..f4f026a 100644 (file)
@@ -51,6 +51,7 @@ class TrafficScriptExecutor(object):
         :raises RuntimeError: ICMP echo Rx timeout.
         :raises RuntimeError: DHCP REQUEST Rx timeout.
         :raises RuntimeError: TCP/UDP Rx timeout.
         :raises RuntimeError: ICMP echo Rx timeout.
         :raises RuntimeError: DHCP REQUEST Rx timeout.
         :raises RuntimeError: TCP/UDP Rx timeout.
+        :raises RuntimeError: ARP reply timeout.
         :raises RuntimeError: Traffic script execution failed.
         """
         logger.trace("{}".format(timeout))
         :raises RuntimeError: Traffic script execution failed.
         """
         logger.trace("{}".format(timeout))
@@ -75,6 +76,8 @@ class TrafficScriptExecutor(object):
                 raise RuntimeError("DHCP REQUEST Rx timeout")
             elif "RuntimeError: TCP/UDP Rx timeout" in stderr:
                 raise RuntimeError("TCP/UDP Rx timeout")
                 raise RuntimeError("DHCP REQUEST Rx timeout")
             elif "RuntimeError: TCP/UDP Rx timeout" in stderr:
                 raise RuntimeError("TCP/UDP Rx timeout")
+            elif "Error occurred: ARP reply timeout" in stdout:
+                raise RuntimeError("ARP reply timeout")
             else:
                 raise RuntimeError("Traffic script execution failed")
 
             else:
                 raise RuntimeError("Traffic script execution failed")
 
index 90f7ab2..e468700 100644 (file)
 | | ${rx_port_name}= | Get interface name | ${node} | ${rx_port}
 | | ${args}= | Catenate | --rx_if | ${rx_port_name} | --src_mac | ${src_mac}
 | | Run Traffic Script On Node | check_ra_packet.py | ${node} | ${args}
 | | ${rx_port_name}= | Get interface name | ${node} | ${rx_port}
 | | ${args}= | Catenate | --rx_if | ${rx_port_name} | --src_mac | ${src_mac}
 | | Run Traffic Script On Node | check_ra_packet.py | ${node} | ${args}
+
+| Send ARP Request
+| | [Documentation] | Send ARP Request and check if the ARP Response is received.
+| | ...
+| | ... | *Arguments:*
+| | ...
+| | ... | _NOTE:_ Arguments are based on topology:
+| | ...             | TG(if1)<->(if1)DUT
+| | ...
+| | ... | - tg_node - Node to execute scripts on (TG). Type: dictionary
+| | ... | - tx_port - Interface from which the ARP packet is sent (TG-if1).
+| | ... |             Type: string
+| | ... | - src_mac - Source MAC address of ARP packet (TG-if1).
+| | ... |             Type: string
+| | ... | - tgt_mac - Target MAC address which is expected in the response
+| | ... |             (DUT-if1). Type: string
+| | ... | - src_ip - Source IP address of ARP packet (TG-if1).
+| | ... |            Type: string
+| | ... | - tgt_ip - Target IP address of ARP packet (DUT-if1).
+| | ... |            Type: string
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Send ARP Request \| ${nodes['TG']} \| eth3 \
+| | ... | \| 08:00:27:cc:4f:54 \| 08:00:27:c9:6a:d5 \
+| | ... | \| 10.0.0.100 \| 192.168.1.5 \|
+| | ...
+| | [Arguments] | ${tg_node} | ${tx_port}
+| | ...         | ${src_mac} | ${tgt_mac}
+| | ...         | ${src_ip} | ${tgt_ip}
+| | ${args}= | Catenate | --tx_if | ${tx_port}
+| | ...                 | --src_mac | ${src_mac} | --dst_mac | ${tgt_mac}
+| | ...                 | --src_ip | ${src_ip} | --dst_ip | ${tgt_ip}
+| | Run Traffic Script On Node | arp_request.py | ${tg_node} | ${args}
+
+| Send ARP Request should failed
+| | [Documentation] | Send ARP Request and
+| | ...             | the ARP Response should not be received.
+| | ...
+| | ... | *Arguments:*
+| | ...
+| | ... | _NOTE:_ Arguments are based on topology:
+| | ...             | TG(if1)<->(if1)DUT
+| | ...
+| | ... | - tg_node - Node to execute scripts on (TG). Type: dictionary
+| | ... | - tx_port - Interface from which the ARP packet is sent (TG-if1).
+| | ... |             Type: string
+| | ... | - src_mac - Source MAC address of ARP packet (TG-if1).
+| | ... |             Type: string
+| | ... | - tgt_mac - Target MAC address which is expected in the response
+| | ... |             (DUT-if1). Type: string
+| | ... | - src_ip - Source IP address of ARP packet (TG-if1).
+| | ... |            Type: string
+| | ... | - tgt_ip - Target IP address of ARP packet (DUT-if1).
+| | ... |            Type: string
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Send ARP Request should failed \| ${nodes['TG']} \| eth3 \
+| | ... | \| 08:00:27:cc:4f:54 \| 08:00:27:c9:6a:d5 \
+| | ... | \| 10.0.0.100 \| 192.168.1.5 \|
+| | ...
+| | [Arguments] | ${tg_node} | ${tx_port}
+| | ...         | ${src_mac} | ${tgt_mac}
+| | ...         | ${src_ip} | ${tgt_ip}
+| | ${args}= | Catenate | --tx_if | ${tx_port}
+| | ...                 | --src_mac | ${src_mac} | --dst_mac | ${tgt_mac}
+| | ...                 | --src_ip | ${src_ip} | --dst_ip | ${tgt_ip}
+| | Run Keyword And Expect Error | ARP reply timeout
+| | ... | Run Traffic Script On Node | arp_request.py | ${tg_node} | ${args}
diff --git a/resources/templates/vat/add_proxy_arp.vat b/resources/templates/vat/add_proxy_arp.vat
new file mode 100644 (file)
index 0000000..42dd399
--- /dev/null
@@ -0,0 +1 @@
+proxy_arp_add_del {lo_ip4_addr} - {hi_ip4_addr}
\ No newline at end of file
diff --git a/resources/templates/vat/proxy_arp_intfc_enable.vat b/resources/templates/vat/proxy_arp_intfc_enable.vat
new file mode 100644 (file)
index 0000000..e4d2313
--- /dev/null
@@ -0,0 +1 @@
+proxy_arp_intfc_enable_disable sw_if_index {sw_if_index} enable
\ No newline at end of file
index 94d5dea..8c5b9c7 100755 (executable)
@@ -47,6 +47,7 @@ def arp_request_test():
     """Send ARP request, expect a reply and verify its fields.
 
     returns: test status
     """Send ARP request, expect a reply and verify its fields.
 
     returns: test status
+    :raises RuntimeError: ARP reply timeout.
     """
     test_passed = False
     (src_if, src_mac, dst_mac, src_ip, dst_ip) = parse_arguments()
     """
     test_passed = False
     (src_if, src_mac, dst_mac, src_ip, dst_ip) = parse_arguments()
@@ -65,6 +66,9 @@ def arp_request_test():
         # wait for APR reply
         ether = interface.recv_pkt()
 
         # wait for APR reply
         ether = interface.recv_pkt()
 
+        if not ether:
+            raise RuntimeError("ARP reply timeout")
+
         # verify received packet
 
         if not ether.haslayer(ARP):
         # verify received packet
 
         if not ether.haslayer(ARP):
diff --git a/tests/suites/ipv4/ipv4_proxy_arp_untagged.robot b/tests/suites/ipv4/ipv4_proxy_arp_untagged.robot
new file mode 100644 (file)
index 0000000..716a84b
--- /dev/null
@@ -0,0 +1,158 @@
+# 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 ***
+| 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/traffic.robot
+| Library | resources.libraries.python.Trace
+| Library | resources.libraries.python.ProxyArp
+| Force Tags | HW_ENV | VM_ENV | 3_NODE_SINGLE_LINK_TOPO
+| Suite Setup | Run Keywords | Setup all TGs before traffic script
+| ...         | AND          | Update All Interface Data On All Nodes | ${nodes}
+| Test Setup | Setup all DUTs before test
+| Test Teardown | Show packet trace on all DUTs | ${nodes}
+| Documentation | *RFC1027 Proxy ARP test cases*
+| ...
+| ... | *[Top] Network topologies:* TG-DUT1 2-node topology with
+| ... | single link between nodes.
+| ... | *[Cfg] DUT configuration:* DUT1 is configured with Proxy ARP
+| ... | *[Ver] TG verification:* Test ARP Request packet is sent
+| ... | from TG on link to DUT1; on receive TG verifies ARP reply packet
+| ... | for correctness and their IPv4 src-addr, dst-addr and MAC addresses.
+| ... | *[Ref] Applicable standard specifications:* RFC1027.
+
+*** Variables ***
+| ${tg_to_dut1_ip}= | 10.0.0.100
+| ${dut1_to_tg_ip}= | 10.0.0.1
+| ${prefix_length}= | 24
+| ${lo_ip4_addr}= | 192.168.1.2
+| ${hi_ip4_addr}= | 192.168.1.10
+| ${pass_test_ip}= | 192.168.1.5
+| ${pass_test_lo_ip}= | 192.168.1.2
+| ${pass_test_hi_ip}= | 192.168.1.10
+| ${fail_test_lo_ip}= | 192.168.1.1
+| ${fail_test_hi_ip}= | 192.168.1.11
+
+*** Test Cases ***
+| TC01: DUT sends ARP reply on behalf of another machine from the IP range
+| | [Documentation]
+| | ... | [Top] TG-DUT1.
+| | ... | [Ref] RFC1027.
+| | ... | [Cfg] On DUT1 configure interface IPv4 address and proxy ARP
+| | ... | for IP range.
+| | ... | [Ver] Make TG send ARP request to DUT1 interface,
+| | ... | verify if DUT1 sends correct ARP reply on behalf of machine which
+| | ... | IP is in range.
+| | Given Path for 3-node testing is set
+| | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['DUT2']} | ${nodes['TG']}
+| | And Interfaces in 3-node path are up
+| | ${dut1_to_tg_name}= | Get interface name | ${dut1_node} | ${dut1_to_tg}
+| | ${tg_to_dut1_name}= | Get interface name | ${tg_node} | ${tg_to_dut1}
+| | When Set Interface Address | ${dut1_node}
+| | ... | ${dut1_to_tg} | ${dut1_to_tg_ip} | ${prefix_length}
+| | And Vpp Add Proxy ARP | ${dut1_node} | ${lo_ip4_addr} | ${hi_ip4_addr}
+| | And Vpp Proxy ARP Interface Enable | ${dut1_node} | ${dut1_to_tg_name}
+| | Then Send ARP Request | ${tg_node} | ${tg_to_dut1_name}
+| | ...                   | ${tg_to_dut1_mac} | ${dut1_to_tg_mac}
+| | ...                   | ${tg_to_dut1_ip} | ${pass_test_ip}
+
+| TC02: DUT sends ARP reply on behalf of another machine from beginning of the IP range
+| | [Documentation]
+| | ... | [Top] TG-DUT1.
+| | ... | [Ref] RFC1027.
+| | ... | [Cfg] On DUT1 configure interface IPv4 address and proxy ARP
+| | ... | for IP range.
+| | ... | [Ver] Make TG send ARP request to DUT1 interface,
+| | ... | verify if DUT1 sends correct ARP reply on behalf of machine which
+| | ... | IP is from beginning of the IP range.
+| | Given Path for 3-node testing is set
+| | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['DUT2']} | ${nodes['TG']}
+| | And Interfaces in 3-node path are up
+| | ${dut1_to_tg_name}= | Get interface name | ${dut1_node} | ${dut1_to_tg}
+| | ${tg_to_dut1_name}= | Get interface name | ${tg_node} | ${tg_to_dut1}
+| | When Set Interface Address | ${dut1_node}
+| | ... | ${dut1_to_tg} | ${dut1_to_tg_ip} | ${prefix_length}
+| | And Vpp Add Proxy ARP | ${dut1_node} | ${lo_ip4_addr} | ${hi_ip4_addr}
+| | And Vpp Proxy ARP Interface Enable | ${dut1_node} | ${dut1_to_tg_name}
+| | Then Send ARP Request | ${tg_node} | ${tg_to_dut1_name}
+| | ...                   | ${tg_to_dut1_mac} | ${dut1_to_tg_mac}
+| | ...                   | ${tg_to_dut1_ip} | ${pass_test_lo_ip}
+
+| TC03: DUT sends ARP reply on behalf of another machine from end of the IP range
+| | [Documentation]
+| | ... | [Top] TG-DUT1.
+| | ... | [Ref] RFC1027.
+| | ... | [Cfg] On DUT1 configure interface IPv4 address and proxy ARP
+| | ... | for IP range.
+| | ... | [Ver] Make TG send ARP request to DUT1 interface,
+| | ... | verify if DUT1 sends correct ARP reply on behalf of machine which
+| | ... | IP is from end of the IP range.
+| | Given Path for 3-node testing is set
+| | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['DUT2']} | ${nodes['TG']}
+| | And Interfaces in 3-node path are up
+| | ${dut1_to_tg_name}= | Get interface name | ${dut1_node} | ${dut1_to_tg}
+| | ${tg_to_dut1_name}= | Get interface name | ${tg_node} | ${tg_to_dut1}
+| | When Set Interface Address | ${dut1_node}
+| | ... | ${dut1_to_tg} | ${dut1_to_tg_ip} | ${prefix_length}
+| | And Vpp Add Proxy ARP | ${dut1_node} | ${lo_ip4_addr} | ${hi_ip4_addr}
+| | And Vpp Proxy ARP Interface Enable | ${dut1_node} | ${dut1_to_tg_name}
+| | Then Send ARP Request | ${tg_node} | ${tg_to_dut1_name}
+| | ...                   | ${tg_to_dut1_mac} | ${dut1_to_tg_mac}
+| | ...                   | ${tg_to_dut1_ip} | ${pass_test_hi_ip}
+
+| TC04: DUT does not send ARP reply on behalf of another machine from below of the IP range
+| | [Documentation]
+| | ... | [Top] TG-DUT1.
+| | ... | [Ref] RFC1027.
+| | ... | [Cfg] On DUT1 configure interface IPv4 address and proxy ARP
+| | ... | for IP range.
+| | ... | [Ver] Make TG send ARP request to DUT1 interface,
+| | ... | verify if DUT1 does not send ARP reply on behalf of machine which
+| | ... | IP is from below of the IP range.
+| | Given Path for 3-node testing is set
+| | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['DUT2']} | ${nodes['TG']}
+| | And Interfaces in 3-node path are up
+| | ${dut1_to_tg_name}= | Get interface name | ${dut1_node} | ${dut1_to_tg}
+| | ${tg_to_dut1_name}= | Get interface name | ${tg_node} | ${tg_to_dut1}
+| | When Set Interface Address | ${dut1_node}
+| | ... | ${dut1_to_tg} | ${dut1_to_tg_ip} | ${prefix_length}
+| | And Vpp Add Proxy ARP | ${dut1_node} | ${lo_ip4_addr} | ${hi_ip4_addr}
+| | And Vpp Proxy ARP Interface Enable | ${dut1_node} | ${dut1_to_tg_name}
+| | Then Send ARP Request should failed | ${tg_node} | ${tg_to_dut1_name}
+| | ...                                 | ${tg_to_dut1_mac} | ${dut1_to_tg_mac}
+| | ...                                 | ${tg_to_dut1_ip} | ${fail_test_lo_ip}
+
+| TC05: DUT does not send ARP reply on behalf of another machine from above of the IP range
+| | [Documentation]
+| | ... | [Top] TG-DUT1.
+| | ... | [Ref] RFC1027.
+| | ... | [Cfg] On DUT1 configure interface IPv4 address and proxy ARP
+| | ... | for IP range.
+| | ... | [Ver] Make TG send ARP request to DUT1 interface,
+| | ... | verify if DUT1 does not send ARP reply on behalf of machine which
+| | ... | IP is from above of the IP range.
+| | Given Path for 3-node testing is set
+| | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['DUT2']} | ${nodes['TG']}
+| | And Interfaces in 3-node path are up
+| | ${dut1_to_tg_name}= | Get interface name | ${dut1_node} | ${dut1_to_tg}
+| | ${tg_to_dut1_name}= | Get interface name | ${tg_node} | ${tg_to_dut1}
+| | When Set Interface Address | ${dut1_node}
+| | ... | ${dut1_to_tg} | ${dut1_to_tg_ip} | ${prefix_length}
+| | And Vpp Add Proxy ARP | ${dut1_node} | ${lo_ip4_addr} | ${hi_ip4_addr}
+| | And Vpp Proxy ARP Interface Enable | ${dut1_node} | ${dut1_to_tg_name}
+| | Then Send ARP Request should failed | ${tg_node} | ${tg_to_dut1_name}
+| | ...                                 | ${tg_to_dut1_mac} | ${dut1_to_tg_mac}
+| | ...                                 | ${tg_to_dut1_ip} | ${fail_test_hi_ip}