aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2016-11-01 10:05:08 +0000
committerDamjan Marion <dmarion.lists@gmail.com>2016-11-01 19:26:24 +0000
commit8fe8cc21d1e389d8e971a303e53c9e703aaaa0e0 (patch)
treedd42f4a0e7242ba9b2804dc2dd5619d2b837c13f /test
parent3b906b0d9b93a892831ce4d54d1d7ec3956ce2b4 (diff)
MPLS Exp-null Tests
Add some 'make test' unit tests for MPLS explicit NULL label handling. Fix the stacking of the MPLS load-balance result form the lookup onto the IPx lookup object. Change-Id: I890d1221b8e3dea99bcc714ed9d0154a5f602c52 Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'test')
-rw-r--r--test/framework.py3
-rw-r--r--test/test_mpls.py209
-rw-r--r--test/vpp_interface.py17
-rw-r--r--test/vpp_papi_provider.py23
4 files changed, 251 insertions, 1 deletions
diff --git a/test/framework.py b/test/framework.py
index 5f75e0107e7..8c39701ba4b 100644
--- a/test/framework.py
+++ b/test/framework.py
@@ -113,7 +113,8 @@ class VppTestCase(unittest.TestCase):
cls.set_debug_flags(d)
cls.vpp_bin = os.getenv('VPP_TEST_BIN', "vpp")
cls.plugin_path = os.getenv('VPP_TEST_PLUGIN_PATH')
- cls.vpp_cmdline = [cls.vpp_bin, "unix", "nodaemon",
+ cls.vpp_cmdline = [cls.vpp_bin, "unix", "{", "nodaemon",
+ "cli-listen localhost:5002", "}",
"api-segment", "{", "prefix", cls.shm_prefix, "}"]
if cls.plugin_path is not None:
cls.vpp_cmdline.extend(["plugin_path", cls.plugin_path])
diff --git a/test/test_mpls.py b/test/test_mpls.py
new file mode 100644
index 00000000000..45af470421e
--- /dev/null
+++ b/test/test_mpls.py
@@ -0,0 +1,209 @@
+#!/usr/bin/env python
+
+import unittest
+import socket
+from logging import *
+
+from framework import VppTestCase, VppTestRunner
+from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
+
+from scapy.packet import Raw
+from scapy.layers.l2 import Ether, Dot1Q, ARP
+from scapy.layers.inet import IP, UDP
+from scapy.layers.inet6 import ICMPv6ND_NS, IPv6, UDP
+from scapy.contrib.mpls import MPLS
+
+class TestMPLS(VppTestCase):
+ """ MPLS Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestMPLS, cls).setUpClass()
+
+ def setUp(self):
+ super(TestMPLS, self).setUp()
+
+ # create 2 pg interfaces
+ self.create_pg_interfaces(range(3))
+
+ # setup both interfaces
+ # assign them different tables.
+ table_id = 0
+
+ for i in self.pg_interfaces:
+ i.admin_up()
+ i.set_table_ip4(table_id)
+ i.set_table_ip6(table_id)
+ i.config_ip4()
+ i.config_ip6()
+ i.enable_mpls()
+ i.resolve_arp()
+ i.resolve_ndp()
+ table_id += 1
+
+ def tearDown(self):
+ super(TestMPLS, self).tearDown()
+
+ def create_stream_ip4(self, src_if, mpls_label, mpls_ttl):
+ pkts = []
+ for i in range(0, 257):
+ info = self.create_packet_info(src_if.sw_if_index,
+ src_if.sw_if_index)
+ payload = self.info_to_payload(info)
+ p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
+ MPLS(label=mpls_label, ttl=mpls_ttl) /
+ IP(src=src_if.remote_ip4, dst=src_if.remote_ip4) /
+ UDP(sport=1234, dport=1234) /
+ Raw(payload))
+ info.data = p.copy()
+ pkts.append(p)
+ return pkts
+
+ def create_stream_ip6(self, src_if, mpls_label, mpls_ttl):
+ pkts = []
+ for i in range(0, 257):
+ info = self.create_packet_info(src_if.sw_if_index,
+ src_if.sw_if_index)
+ payload = self.info_to_payload(info)
+ p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
+ MPLS(label=mpls_label, ttl=mpls_ttl) /
+ IPv6(src=src_if.remote_ip6, dst=src_if.remote_ip6) /
+ UDP(sport=1234, dport=1234) /
+ Raw(payload))
+ info.data = p.copy()
+ pkts.append(p)
+ return pkts
+
+ def verify_capture_ip4(self, src_if, capture, sent):
+ try:
+ self.assertEqual(len(capture), len(sent))
+
+ for i in range(len(capture)):
+ tx = sent[i]
+ rx = capture[i]
+
+ # the rx'd packet has the MPLS label popped
+ eth = rx[Ether];
+ self.assertEqual(eth.type, 0x800);
+
+ tx_ip = tx[IP]
+ rx_ip = rx[IP]
+
+ self.assertEqual(rx_ip.src, tx_ip.src)
+ self.assertEqual(rx_ip.dst, tx_ip.dst)
+ # IP processing post pop has decremented the TTL
+ self.assertEqual(rx_ip.ttl+1, tx_ip.ttl)
+
+ except:
+ raise;
+
+ def verify_capture_ip6(self, src_if, capture, sent):
+ try:
+ self.assertEqual(len(capture), len(sent))
+
+ for i in range(len(capture)):
+ tx = sent[i]
+ rx = capture[i]
+
+ # the rx'd packet has the MPLS label popped
+ eth = rx[Ether];
+ self.assertEqual(eth.type, 0x86DD);
+
+ tx_ip = tx[IPv6]
+ rx_ip = rx[IPv6]
+
+ self.assertEqual(rx_ip.src, tx_ip.src)
+ self.assertEqual(rx_ip.dst, tx_ip.dst)
+ # IP processing post pop has decremented the TTL
+ self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
+
+ except:
+ raise;
+
+
+ def test_v4_exp_null(self):
+ """ MPLS V4 Explicit NULL test """
+
+ #
+ # The first test case has an MPLS TTL of 0
+ # all packet should be dropped
+ #
+ tx = self.create_stream_ip4(self.pg0, 0, 0)
+ self.pg0.add_stream(tx)
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ rx = self.pg0.get_capture()
+
+ try:
+ self.assertEqual(0, len(rx));
+ except:
+ error("MPLS TTL=0 packets forwarded")
+ error(packet.show())
+ raise
+
+ #
+ # a stream with a non-zero MPLS TTL
+ # PG0 is in the default table
+ #
+ self.vapi.cli("clear trace")
+ tx = self.create_stream_ip4(self.pg0, 0, 2)
+ self.pg0.add_stream(tx)
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ rx = self.pg0.get_capture()
+ self.verify_capture_ip4(self.pg0, rx, tx)
+
+ #
+ # a stream with a non-zero MPLS TTL
+ # PG1 is in table 1
+ # we are ensuring the post-pop lookup occurs in the VRF table
+ #
+ self.vapi.cli("clear trace")
+ tx = self.create_stream_ip4(self.pg1, 0, 2)
+ self.pg1.add_stream(tx)
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ rx = self.pg1.get_capture()
+ self.verify_capture_ip4(self.pg0, rx, tx)
+
+ def test_v6_exp_null(self):
+ """ MPLS V6 Explicit NULL test """
+
+ #
+ # a stream with a non-zero MPLS TTL
+ # PG0 is in the default table
+ #
+ self.vapi.cli("clear trace")
+ tx = self.create_stream_ip6(self.pg0, 2, 2)
+ self.pg0.add_stream(tx)
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ rx = self.pg0.get_capture()
+ self.verify_capture_ip6(self.pg0, rx, tx)
+
+ #
+ # a stream with a non-zero MPLS TTL
+ # PG1 is in table 1
+ # we are ensuring the post-pop lookup occurs in the VRF table
+ #
+ self.vapi.cli("clear trace")
+ tx = self.create_stream_ip6(self.pg1, 2, 2)
+ self.pg1.add_stream(tx)
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ rx = self.pg1.get_capture()
+ self.verify_capture_ip6(self.pg0, rx, tx)
+
+
+if __name__ == '__main__':
+ unittest.main(testRunner=VppTestRunner)
diff --git a/test/vpp_interface.py b/test/vpp_interface.py
index c596ab5abf7..509ab952236 100644
--- a/test/vpp_interface.py
+++ b/test/vpp_interface.py
@@ -131,6 +131,18 @@ class VppInterface(object):
self.test.vapi.sw_interface_add_del_address(
self.sw_if_index, addr, addr_len, is_ipv6=1)
+ def set_table_ip4(self, table_id):
+ """Set the interface in a IPv4 Table.
+ Must be called before configuring IP4 addresses"""
+ self.test.vapi.sw_interface_set_table(
+ self.sw_if_index, 0, table_id)
+
+ def set_table_ip6(self, table_id):
+ """Set the interface in a IPv6 Table.
+ Must be called before configuring IP6 addresses"""
+ self.test.vapi.sw_interface_set_table(
+ self.sw_if_index, 1, table_id)
+
def disable_ipv6_ra(self):
"""Configure IPv6 RA suppress on the VPP interface"""
self.test.vapi.sw_interface_ra_suppress(self.sw_if_index)
@@ -238,3 +250,8 @@ class VppInterface(object):
self.sub_if.append(sub_if)
else:
self.sub_if = sub_if
+
+ def enable_mpls(self):
+ """Enable MPLS on the VPP interface"""
+ self.test.vapi.sw_interface_enable_disable_mpls(
+ self.sw_if_index)
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index 261a0f4aa4b..f0eb410bf30 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -106,6 +106,18 @@ class VppPapiProvider(object):
args = (0, b'')
return self.api(vpp_papi.sw_interface_dump, args)
+ def sw_interface_set_table(self, sw_if_index, is_ipv6, table_id):
+ """
+ Set the IPvX Table-id for the Interface
+
+ :param sw_if_index:
+ :param is_ipv6:
+ :param table_id:
+
+ """
+ return self.api(vpp_papi.sw_interface_set_table,
+ (sw_if_index, is_ipv6, table_id))
+
def sw_interface_add_del_address(self, sw_if_index, addr, addr_len,
is_ipv6=0, is_add=1, del_all=0):
"""
@@ -121,6 +133,17 @@ class VppPapiProvider(object):
return self.api(vpp_papi.sw_interface_add_del_address,
(sw_if_index, is_add, is_ipv6, del_all, addr_len, addr))
+ def sw_interface_enable_disable_mpls(self, sw_if_index,
+ is_enable=1):
+ """
+ Enable/Disable MPLS on the interface
+ :param sw_if_index:
+ :param is_enable: (Default value = 1)
+
+ """
+ return self.api(vpp_papi.sw_interface_set_mpls_enable,
+ (sw_if_index, is_enable))
+
def sw_interface_ra_suppress(self, sw_if_index):
suppress = 1
managed = 0