aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorPavel Kotucek <pavel.kotucek@pantheon.tech>2018-11-28 07:42:11 +0100
committerOle Trøan <otroan@employees.org>2018-12-07 12:24:52 +0000
commite88865d7bc9cd45b044f8aeadf1916c38e0eb165 (patch)
treea6dfb198549ff9f2335724e3ea7b0f942ad08540 /test
parente6b58cf86affdf434a15f8833e959cded6c15784 (diff)
VPP-1506: dump local punts and registered punt sockets
Change-Id: If7835e9b80ec9402404bfc8d271eb11a10ef992b Signed-off-by: Pavel Kotucek <pavel.kotucek@pantheon.tech>
Diffstat (limited to 'test')
-rw-r--r--test/framework.py4
-rw-r--r--test/test_punt.py309
-rw-r--r--test/vpp_papi_provider.py28
3 files changed, 333 insertions, 8 deletions
diff --git a/test/framework.py b/test/framework.py
index 6c1ba5e3f33..8a1bfcb660b 100644
--- a/test/framework.py
+++ b/test/framework.py
@@ -193,6 +193,8 @@ class VppTestCase(unittest.TestCase):
classes. It provides methods to create and run test case.
"""
+ extra_vpp_punt_config = []
+
@property
def packet_infos(self):
"""List of packet infos"""
@@ -308,6 +310,8 @@ class VppTestCase(unittest.TestCase):
"{", "plugin", "dpdk_plugin.so", "{", "disable",
"}", "plugin", "unittest_plugin.so", "{", "enable",
"}", "}", ]
+ if cls.extra_vpp_punt_config is not None:
+ cls.vpp_cmdline.extend(cls.extra_vpp_punt_config)
if plugin_path is not None:
cls.vpp_cmdline.extend(["plugin_path", plugin_path])
cls.logger.info("vpp_cmdline args: %s" % cls.vpp_cmdline)
diff --git a/test/test_punt.py b/test/test_punt.py
new file mode 100644
index 00000000000..c31bdcfb2c5
--- /dev/null
+++ b/test/test_punt.py
@@ -0,0 +1,309 @@
+#!/usr/bin/env python
+import binascii
+import random
+import socket
+import unittest
+import os
+import scapy.layers.inet6 as inet6
+
+from util import ppp, ppc
+from re import compile
+from scapy.packet import Raw
+from scapy.layers.l2 import Ether
+from scapy.layers.inet import IP, UDP, ICMP
+from scapy.layers.inet6 import IPv6, ICMPv6DestUnreach
+from framework import VppTestCase, VppTestRunner
+
+
+class TestPuntSocket(VppTestCase):
+ """ Punt Socket """
+
+ tempdir = ""
+ sock = None
+ err_ptr = compile(r"^([\d]+)\s+([-\w]+)\s+([ -\.\w)(]+)$")
+
+ @classmethod
+ def setUpConstants(cls):
+ tempdir = cls.tempdir
+ cls.extra_vpp_punt_config = [
+ "punt", "{", "socket", cls.tempdir+"/socket_punt", "}"]
+ super(TestPuntSocket, cls).setUpConstants()
+
+ def process_cli(self, exp, ptr):
+ for line in self.vapi.cli(exp).split('\n')[1:]:
+ m = ptr.match(line.strip())
+ if m:
+ yield m.groups()
+
+ def show_errors(self):
+ for pack in self.process_cli("show errors", self.err_ptr):
+ try:
+ count, node, reason = pack
+ except ValueError:
+ pass
+ else:
+ yield count, node, reason
+
+ def get_punt_count(self, counter):
+ errors = list(self.show_errors())
+ for count, node, reason in errors:
+ if (node == counter and
+ reason == u'Socket TX'):
+ return int(count)
+ return 0
+
+ def socket_client_create(self, sock_name):
+ self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
+ try:
+ os.unlink(sock_name)
+ except:
+ self.logger.debug("Unlink socket faild")
+ self.sock.bind(sock_name)
+
+ def socket_client_close(self):
+ self.sock.close()
+
+
+class TestIP4PuntSocket(TestPuntSocket):
+ """ Punt Socket for IPv4 """
+
+ def setUp(self):
+ super(TestIP4PuntSocket, self).setUp()
+
+ self.create_pg_interfaces(range(2))
+
+ for i in self.pg_interfaces:
+ i.admin_up()
+ i.config_ip4()
+ i.resolve_arp()
+
+ def tearDown(self):
+ super(TestIP4PuntSocket, self).tearDown()
+ for i in self.pg_interfaces:
+ i.unconfig_ip4()
+ i.admin_down()
+
+ def test_punt_socket_dump(self):
+ """ Punt socket registration"""
+
+ punts = self.vapi.punt_socket_dump(0)
+ self.assertEqual(len(punts), 0)
+
+ #
+ # configure a punt socket
+ #
+ self.vapi.punt_socket_register(1111, self.tempdir+"/socket_punt_1111")
+ self.vapi.punt_socket_register(2222, self.tempdir+"/socket_punt_2222")
+ punts = self.vapi.punt_socket_dump(0)
+ self.assertEqual(len(punts), 2)
+ self.assertEqual(punts[0].punt.l4_port, 1111)
+ # self.assertEqual(punts[0].pathname, "/tmp/punt_socket_udp_1234")
+ self.assertEqual(punts[1].punt.l4_port, 2222)
+ # self.assertEqual(punts[1].pathname, "/tmp/punt_socket_udp_5678")
+
+ #
+ # deregister a punt socket
+ #
+ self.vapi.punt_socket_deregister(1111)
+ punts = self.vapi.punt_socket_dump(0)
+ self.assertEqual(len(punts), 1)
+
+ #
+ # configure a punt socket again
+ #
+ self.vapi.punt_socket_register(1111, self.tempdir+"/socket_punt_1111")
+ self.vapi.punt_socket_register(3333, self.tempdir+"/socket_punt_3333")
+ punts = self.vapi.punt_socket_dump(0)
+ self.assertEqual(len(punts), 3)
+
+ #
+ # deregister all punt socket
+ #
+ self.vapi.punt_socket_deregister(1111)
+ self.vapi.punt_socket_deregister(2222)
+ self.vapi.punt_socket_deregister(3333)
+ punts = self.vapi.punt_socket_dump(0)
+ self.assertEqual(len(punts), 0)
+
+ def test_punt_socket_traffic(self):
+ """ Punt socket traffic"""
+
+ nr_packets = 8
+ p = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
+ UDP(sport=9876, dport=1234) /
+ Raw('\xa5' * 100))
+
+ pkts = p * nr_packets
+
+ punts = self.vapi.punt_socket_dump(0)
+ self.assertEqual(len(punts), 0)
+
+ #
+ # expect ICMP - port unreachable for all packets
+ #
+ self.vapi.cli("clear trace")
+ self.pg0.add_stream(pkts)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ rx = self.pg0.get_capture(nr_packets)
+ for p in rx:
+ self.assertEqual(int(p[IP].proto), 1) # ICMP
+ self.assertEqual(int(p[ICMP].code), 3) # unreachable
+
+ #
+ # configure a punt socket
+ #
+ self.socket_client_create(self.tempdir+"/socket_punt_1234")
+ self.vapi.punt_socket_register(1234, self.tempdir+"/socket_punt_1234")
+ punts = self.vapi.punt_socket_dump(0)
+ self.assertEqual(len(punts), 1)
+
+ #
+ # expect punt socket and no packets on pg0
+ #
+ self.vapi.cli("clear errors")
+ self.pg0.add_stream(pkts)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg0.get_capture(0)
+ self.socket_client_close()
+
+ #
+ # remove punt socket. expect ICMP - port unreachable for all packets
+ #
+ self.vapi.punt_socket_deregister(1234)
+ punts = self.vapi.punt_socket_dump(0)
+ self.assertEqual(len(punts), 0)
+ self.pg0.add_stream(pkts)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ # FIXME - when punt socket deregister is implemented
+ # self.pg0.get_capture(nr_packets)
+
+
+class TestIP6PuntSocket(TestPuntSocket):
+ """ Punt Socket for IPv6"""
+
+ def setUp(self):
+ super(TestIP6PuntSocket, self).setUp()
+
+ self.create_pg_interfaces(range(2))
+
+ for i in self.pg_interfaces:
+ i.admin_up()
+ i.config_ip6()
+ i.resolve_ndp()
+
+ def tearDown(self):
+ super(TestIP6PuntSocket, self).tearDown()
+ for i in self.pg_interfaces:
+ i.unconfig_ip6()
+ i.admin_down()
+
+ def test_punt_socket_dump(self):
+ """ Punt socket registration """
+
+ punts = self.vapi.punt_socket_dump(0)
+ self.assertEqual(len(punts), 0)
+
+ #
+ # configure a punt socket
+ #
+ self.vapi.punt_socket_register(1111, self.tempdir+"/socket_punt_1111",
+ is_ip4=0)
+ self.vapi.punt_socket_register(2222, self.tempdir+"/socket_punt_2222",
+ is_ip4=0)
+ punts = self.vapi.punt_socket_dump(1)
+ self.assertEqual(len(punts), 2)
+ self.assertEqual(punts[0].punt.l4_port, 1111)
+ # self.assertEqual(punts[0].pathname, "/tmp/punt_socket_udp_1234")
+ self.assertEqual(punts[1].punt.l4_port, 2222)
+ # self.assertEqual(punts[1].pathname, "/tmp/punt_socket_udp_5678")
+
+ #
+ # deregister a punt socket
+ #
+ self.vapi.punt_socket_deregister(1111, is_ip4=0)
+ punts = self.vapi.punt_socket_dump(1)
+ self.assertEqual(len(punts), 1)
+
+ #
+ # configure a punt socket again
+ #
+ self.vapi.punt_socket_register(1111, self.tempdir+"/socket_punt_1111",
+ is_ip4=0)
+ punts = self.vapi.punt_socket_dump(1)
+ self.assertEqual(len(punts), 2)
+
+ #
+ # deregister all punt socket
+ #
+ self.vapi.punt_socket_deregister(1111, is_ip4=0)
+ self.vapi.punt_socket_deregister(2222, is_ip4=0)
+ self.vapi.punt_socket_deregister(3333, is_ip4=0)
+ punts = self.vapi.punt_socket_dump(1)
+ self.assertEqual(len(punts), 0)
+
+ def test_punt_socket_traffic(self):
+ """ Punt socket traffic"""
+
+ nr_packets = 2
+ p = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
+ inet6.UDP(sport=9876, dport=1234) /
+ Raw('\xa5' * 100))
+
+ pkts = p * nr_packets
+
+ punts = self.vapi.punt_socket_dump(1)
+ self.assertEqual(len(punts), 0)
+
+ #
+ # expect ICMPv6 - destination unreachable for all packets
+ #
+ self.vapi.cli("clear trace")
+ self.pg0.add_stream(pkts)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ rx = self.pg0.get_capture(nr_packets)
+ for p in rx:
+ self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
+ self.assertEqual(int(p[ICMPv6DestUnreach].code), 4) # unreachable
+
+ #
+ # configure a punt socket
+ #
+ self.socket_client_create(self.tempdir+"/socket_punt_1234")
+ self.vapi.punt_socket_register(1234, self.tempdir+"/socket_punt_1234",
+ is_ip4=0)
+ punts = self.vapi.punt_socket_dump(1)
+ self.assertEqual(len(punts), 1)
+
+ #
+ # expect punt socket and no packets on pg0
+ #
+ self.vapi.cli("clear errors")
+ self.pg0.add_stream(pkts)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg0.get_capture(0)
+ self.socket_client_close()
+
+ #
+ # remove punt socket. expect ICMP - dest. unreachable for all packets
+ #
+ self.vapi.punt_socket_deregister(1234, is_ip4=0)
+ punts = self.vapi.punt_socket_dump(1)
+ self.assertEqual(len(punts), 0)
+ self.pg0.add_stream(pkts)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ # FIXME - when punt socket deregister is implemented
+# self.pg0.get_capture(nr_packets)
+
+
+if __name__ == '__main__':
+ unittest.main(testRunner=VppTestRunner)
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index 8153e031607..612a678ae9d 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -3486,15 +3486,27 @@ class VppPapiProvider(object):
'namespace_id': namespace_id,
'namespace_id_len': len(namespace_id)})
- def punt_socket_register(self, l4_port, pathname, header_version=1,
- is_ip4=1, l4_protocol=0x11):
- """ Punt to socket """
+ def punt_socket_register(self, port, pathname, protocol=0x11,
+ header_version=1, is_ip4=1):
+ """ Register punt socket """
return self.api(self.papi.punt_socket_register,
- {'is_ip4': is_ip4,
- 'l4_protocol': l4_protocol,
- 'l4_port': l4_port,
- 'pathname': pathname,
- 'header_version': header_version})
+ {'header_version': header_version,
+ 'punt': {'ipv': is_ip4,
+ 'l4_protocol': protocol,
+ 'l4_port': port},
+ 'pathname': pathname})
+
+ def punt_socket_deregister(self, port, protocol=0x11, is_ip4=1):
+ """ Unregister punt socket """
+ return self.api(self.papi.punt_socket_deregister,
+ {'punt': {'ipv': is_ip4,
+ 'l4_protocol': protocol,
+ 'l4_port': port}})
+
+ def punt_socket_dump(self, is_ip6=1):
+ """ Dump punt socket"""
+ return self.api(self.papi.punt_socket_dump,
+ {'is_ipv6': is_ip6})
def ip_reassembly_set(self, timeout_ms, max_reassemblies,
expire_walk_interval_ms, is_ip6=0):