diff options
author | Pavel Kotucek <pavel.kotucek@pantheon.tech> | 2018-11-28 07:42:11 +0100 |
---|---|---|
committer | Ole Trøan <otroan@employees.org> | 2018-12-07 12:24:52 +0000 |
commit | e88865d7bc9cd45b044f8aeadf1916c38e0eb165 (patch) | |
tree | a6dfb198549ff9f2335724e3ea7b0f942ad08540 /test | |
parent | e6b58cf86affdf434a15f8833e959cded6c15784 (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.py | 4 | ||||
-rw-r--r-- | test/test_punt.py | 309 | ||||
-rw-r--r-- | test/vpp_papi_provider.py | 28 |
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): |