summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDave Wallace <dwallacelf@gmail.com>2020-11-16 15:08:14 -0500
committerPaul Vinciguerra <pvinci@vinciconsulting.com>2020-11-17 00:51:22 +0000
commitb5c6d08f037c277a961a40edaddf6a8d8cb9d55b (patch)
tree458f33c7ab23e7532da650de3413fc9bdf20f436 /src
parente1887c1765ef57d50986701f7a4563f1ad7df340 (diff)
tests: move classifier tests to src/vnet/classify/test
- Refactor make test code to be co-located with the vpp feature source code. Type: test Signed-off-by: Dave Wallace <dwallacelf@gmail.com> Change-Id: Ibae85a18df0d5a53e2a59c678a2a27499f54ce6d
Diffstat (limited to 'src')
-rw-r--r--src/vnet/classify/test/test_classifier.py569
-rw-r--r--src/vnet/classify/test/test_classifier_ip6.py490
2 files changed, 1059 insertions, 0 deletions
diff --git a/src/vnet/classify/test/test_classifier.py b/src/vnet/classify/test/test_classifier.py
new file mode 100644
index 00000000000..11c0985f4d4
--- /dev/null
+++ b/src/vnet/classify/test/test_classifier.py
@@ -0,0 +1,569 @@
+#!/usr/bin/env python3
+
+import binascii
+import socket
+import unittest
+
+from framework import VppTestCase, VppTestRunner
+
+from scapy.packet import Raw
+from scapy.layers.l2 import Ether
+from scapy.layers.inet import IP, UDP, TCP
+from util import ppp
+from template_classifier import TestClassifier
+from vpp_ip_route import VppIpRoute, VppRoutePath
+from vpp_ip import INVALID_INDEX
+
+
+# Tests split to different test case classes because of issue reported in
+# ticket VPP-1336
+class TestClassifierIP(TestClassifier):
+ """ Classifier IP Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierIP, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestClassifierIP, cls).tearDownClass()
+
+ def test_iacl_src_ip(self):
+ """ Source IP iACL test
+
+ Test scenario for basic IP ACL with source IP
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with source IP address.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with source IP
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'ip_src'
+ self.create_classify_table(key, self.build_ip_mask(src_ip='ffffffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(src_ip=self.pg0.remote_ip4))
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_dst_ip(self):
+ """ Destination IP iACL test
+
+ Test scenario for basic IP ACL with destination IP
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with destination IP address.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with destination IP
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'ip_dst'
+ self.create_classify_table(key, self.build_ip_mask(dst_ip='ffffffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(dst_ip=self.pg1.remote_ip4))
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_src_dst_ip(self):
+ """ Source and destination IP iACL test
+
+ Test scenario for basic IP ACL with source and destination IP
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with source and destination IP addresses.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with source and destination IP
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'ip'
+ self.create_classify_table(
+ key, self.build_ip_mask(src_ip='ffffffff', dst_ip='ffffffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(src_ip=self.pg0.remote_ip4,
+ dst_ip=self.pg1.remote_ip4))
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+
+class TestClassifierUDP(TestClassifier):
+ """ Classifier UDP proto Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierUDP, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestClassifierUDP, cls).tearDownClass()
+
+ def test_iacl_proto_udp(self):
+ """ UDP protocol iACL test
+
+ Test scenario for basic protocol ACL with UDP protocol
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with UDP IP protocol.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with UDP protocol
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'proto_udp'
+ self.create_classify_table(key, self.build_ip_mask(proto='ff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(proto=socket.IPPROTO_UDP))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_udp_sport(self):
+ """ UDP source port iACL test
+
+ Test scenario for basic protocol ACL with UDP and sport
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with UDP IP protocol and defined sport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with UDP and sport
+ sport = 38
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ UDP(sport=sport, dport=5678))
+ self.pg0.add_stream(pkts)
+
+ key = 'proto_udp_sport'
+ self.create_classify_table(
+ key, self.build_ip_mask(proto='ff', src_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(proto=socket.IPPROTO_UDP, src_port=sport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_udp_dport(self):
+ """ UDP destination port iACL test
+
+ Test scenario for basic protocol ACL with UDP and dport
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with UDP IP protocol and defined dport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with UDP and dport
+ dport = 427
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ UDP(sport=1234, dport=dport))
+ self.pg0.add_stream(pkts)
+
+ key = 'proto_udp_dport'
+ self.create_classify_table(
+ key, self.build_ip_mask(proto='ff', dst_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(proto=socket.IPPROTO_UDP, dst_port=dport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_udp_sport_dport(self):
+ """ UDP source and destination ports iACL test
+
+ Test scenario for basic protocol ACL with UDP and sport and dport
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with UDP IP protocol and defined sport and dport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with UDP and sport and dport
+ sport = 13720
+ dport = 9080
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ UDP(sport=sport, dport=dport))
+ self.pg0.add_stream(pkts)
+
+ key = 'proto_udp_ports'
+ self.create_classify_table(
+ key,
+ self.build_ip_mask(proto='ff', src_port='ffff', dst_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(proto=socket.IPPROTO_UDP, src_port=sport,
+ dst_port=dport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+
+class TestClassifierTCP(TestClassifier):
+ """ Classifier TCP proto Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierTCP, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestClassifierTCP, cls).tearDownClass()
+
+ def test_iacl_proto_tcp(self):
+ """ TCP protocol iACL test
+
+ Test scenario for basic protocol ACL with TCP protocol
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with TCP IP protocol.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with TCP protocol
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ TCP(sport=1234, dport=5678))
+ self.pg0.add_stream(pkts)
+
+ key = 'proto_tcp'
+ self.create_classify_table(key, self.build_ip_mask(proto='ff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(proto=socket.IPPROTO_TCP))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts, TCP)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_tcp_sport(self):
+ """ TCP source port iACL test
+
+ Test scenario for basic protocol ACL with TCP and sport
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with TCP IP protocol and defined sport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with TCP and sport
+ sport = 38
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ TCP(sport=sport, dport=5678))
+ self.pg0.add_stream(pkts)
+
+ key = 'proto_tcp_sport'
+ self.create_classify_table(
+ key, self.build_ip_mask(proto='ff', src_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(proto=socket.IPPROTO_TCP, src_port=sport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts, TCP)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_tcp_dport(self):
+ """ TCP destination port iACL test
+
+ Test scenario for basic protocol ACL with TCP and dport
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with TCP IP protocol and defined dport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with TCP and dport
+ dport = 427
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ TCP(sport=1234, dport=dport))
+ self.pg0.add_stream(pkts)
+
+ key = 'proto_tcp_sport'
+ self.create_classify_table(
+ key, self.build_ip_mask(proto='ff', dst_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(proto=socket.IPPROTO_TCP, dst_port=dport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts, TCP)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_tcp_sport_dport(self):
+ """ TCP source and destination ports iACL test
+
+ Test scenario for basic protocol ACL with TCP and sport and dport
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with TCP IP protocol and defined sport and dport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with TCP and sport and dport
+ sport = 13720
+ dport = 9080
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ TCP(sport=sport, dport=dport))
+ self.pg0.add_stream(pkts)
+
+ key = 'proto_tcp_ports'
+ self.create_classify_table(
+ key,
+ self.build_ip_mask(proto='ff', src_port='ffff', dst_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(proto=socket.IPPROTO_TCP, src_port=sport,
+ dst_port=dport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts, TCP)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+
+class TestClassifierIPOut(TestClassifier):
+ """ Classifier output IP Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierIPOut, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestClassifierIPOut, cls).tearDownClass()
+
+ def test_acl_ip_out(self):
+ """ Output IP ACL test
+
+ Test scenario for basic IP ACL with source IP
+ - Create IPv4 stream for pg1 -> pg0 interface.
+ - Create ACL with source IP address.
+ - Send and verify received packets on pg0 interface.
+ """
+
+ # Basic oACL testing with source IP
+ pkts = self.create_stream(self.pg1, self.pg0, self.pg_if_packet_sizes)
+ self.pg1.add_stream(pkts)
+
+ key = 'ip_out'
+ self.create_classify_table(
+ key, self.build_ip_mask(src_ip='ffffffff'), data_offset=0)
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(src_ip=self.pg1.remote_ip4))
+ self.output_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg0.get_capture(len(pkts))
+ self.verify_capture(self.pg0, pkts)
+ self.pg1.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+
+class TestClassifierMAC(TestClassifier):
+ """ Classifier MAC Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierMAC, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestClassifierMAC, cls).tearDownClass()
+
+ def test_acl_mac(self):
+ """ MAC ACL test
+
+ Test scenario for basic MAC ACL with source MAC
+ - Create IPv4 stream for pg0 -> pg2 interface.
+ - Create ACL with source MAC address.
+ - Send and verify received packets on pg2 interface.
+ """
+
+ # Basic iACL testing with source MAC
+ pkts = self.create_stream(self.pg0, self.pg2, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'mac'
+ self.create_classify_table(
+ key, self.build_mac_mask(src_mac='ffffffffffff'), data_offset=-14)
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_mac_match(src_mac=self.pg0.remote_mac))
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg2.get_capture(len(pkts))
+ self.verify_capture(self.pg2, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg1.assert_nothing_captured(remark="packets forwarded")
+ self.pg3.assert_nothing_captured(remark="packets forwarded")
+
+
+class TestClassifierPBR(TestClassifier):
+ """ Classifier PBR Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierPBR, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestClassifierPBR, cls).tearDownClass()
+
+ def test_acl_pbr(self):
+ """ IP PBR test
+
+ Test scenario for PBR with source IP
+ - Create IPv4 stream for pg0 -> pg3 interface.
+ - Configure PBR fib entry for packet forwarding.
+ - Send and verify received packets on pg3 interface.
+ """
+
+ # PBR testing with source IP
+ pkts = self.create_stream(self.pg0, self.pg3, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'pbr'
+ self.create_classify_table(key, self.build_ip_mask(src_ip='ffffffff'))
+ pbr_option = 1
+ # this will create the VRF/table in which we will insert the route
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(src_ip=self.pg0.remote_ip4),
+ pbr_option, self.pbr_vrfid)
+ self.assertTrue(self.verify_vrf(self.pbr_vrfid))
+ r = VppIpRoute(self, self.pg3.local_ip4, 24,
+ [VppRoutePath(self.pg3.remote_ip4,
+ INVALID_INDEX)],
+ table_id=self.pbr_vrfid)
+ r.add_vpp_config()
+
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg3.get_capture(len(pkts))
+ self.verify_capture(self.pg3, pkts)
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key), 0)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg1.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+ # remove the classify session and the route
+ r.remove_vpp_config()
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip_match(src_ip=self.pg0.remote_ip4),
+ pbr_option, self.pbr_vrfid, is_add=0)
+
+ # and the table should be gone.
+ self.assertFalse(self.verify_vrf(self.pbr_vrfid))
+
+if __name__ == '__main__':
+ unittest.main(testRunner=VppTestRunner)
diff --git a/src/vnet/classify/test/test_classifier_ip6.py b/src/vnet/classify/test/test_classifier_ip6.py
new file mode 100644
index 00000000000..211374b5ec6
--- /dev/null
+++ b/src/vnet/classify/test/test_classifier_ip6.py
@@ -0,0 +1,490 @@
+#!/usr/bin/env python3
+
+import unittest
+import socket
+import binascii
+
+from framework import VppTestCase, VppTestRunner
+
+from scapy.packet import Raw
+from scapy.layers.l2 import Ether
+from scapy.layers.inet6 import IPv6, UDP, TCP
+from util import ppp
+from template_classifier import TestClassifier
+
+
+class TestClassifierIP6(TestClassifier):
+ """ Classifier IP6 Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierIP6, cls).setUpClass()
+ cls.af = socket.AF_INET6
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestClassifierIP6, cls).tearDownClass()
+
+ def test_iacl_src_ip(self):
+ """ Source IP6 iACL test
+
+ Test scenario for basic IP ACL with source IP
+ - Create IPv6 stream for pg0 -> pg1 interface.
+ - Create iACL with source IP address.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with source IP
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'ip6_src'
+ self.create_classify_table(
+ key,
+ self.build_ip6_mask(src_ip='ffffffffffffffffffffffffffffffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(src_ip=self.pg0.remote_ip6))
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_dst_ip(self):
+ """ Destination IP6 iACL test
+
+ Test scenario for basic IP ACL with destination IP
+ - Create IPv6 stream for pg0 -> pg1 interface.
+ - Create iACL with destination IP address.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with destination IP
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'ip6_dst'
+ self.create_classify_table(
+ key,
+ self.build_ip6_mask(dst_ip='ffffffffffffffffffffffffffffffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(dst_ip=self.pg1.remote_ip6))
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_src_dst_ip(self):
+ """ Source and destination IP6 iACL test
+
+ Test scenario for basic IP ACL with source and destination IP
+ - Create IPv4 stream for pg0 -> pg1 interface.
+ - Create iACL with source and destination IP addresses.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with source and destination IP
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'ip6'
+ self.create_classify_table(
+ key,
+ self.build_ip6_mask(src_ip='ffffffffffffffffffffffffffffffff',
+ dst_ip='ffffffffffffffffffffffffffffffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(src_ip=self.pg0.remote_ip6,
+ dst_ip=self.pg1.remote_ip6))
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+
+# Tests split to different test case classes because of issue reported in
+# ticket VPP-1336
+class TestClassifierIP6UDP(TestClassifier):
+ """ Classifier IP6 UDP proto Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierIP6UDP, cls).setUpClass()
+ cls.af = socket.AF_INET6
+
+ def test_iacl_proto_udp(self):
+ """ IP6 UDP protocol iACL test
+
+ Test scenario for basic protocol ACL with UDP protocol
+ - Create IPv6 stream for pg0 -> pg1 interface.
+ - Create iACL with UDP IP protocol.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with UDP protocol
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'nh_udp'
+ self.create_classify_table(key, self.build_ip6_mask(nh='ff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(nh=socket.IPPROTO_UDP))
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_udp_sport(self):
+ """ IP6 UDP source port iACL test
+
+ Test scenario for basic protocol ACL with UDP and sport
+ - Create IPv6 stream for pg0 -> pg1 interface.
+ - Create iACL with UDP IP protocol and defined sport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with UDP and sport
+ sport = 38
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ UDP(sport=sport, dport=5678))
+ self.pg0.add_stream(pkts)
+
+ key = 'nh_udp_sport'
+ self.create_classify_table(
+ key, self.build_ip6_mask(nh='ff', src_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(nh=socket.IPPROTO_UDP, src_port=sport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_udp_dport(self):
+ """ IP6 UDP destination port iACL test
+
+ Test scenario for basic protocol ACL with UDP and dport
+ - Create IPv6 stream for pg0 -> pg1 interface.
+ - Create iACL with UDP IP protocol and defined dport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with UDP and dport
+ dport = 427
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ UDP(sport=1234, dport=dport))
+ self.pg0.add_stream(pkts)
+
+ key = 'nh_udp_dport'
+ self.create_classify_table(
+ key, self.build_ip6_mask(nh='ff', dst_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(nh=socket.IPPROTO_UDP, dst_port=dport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_udp_sport_dport(self):
+ """ IP6 UDP source and destination ports iACL test
+
+ Test scenario for basic protocol ACL with UDP and sport and dport
+ - Create IPv6 stream for pg0 -> pg1 interface.
+ - Create iACL with UDP IP protocol and defined sport and dport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with UDP and sport and dport
+ sport = 13720
+ dport = 9080
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ UDP(sport=sport, dport=dport))
+ self.pg0.add_stream(pkts)
+
+ key = 'nh_udp_ports'
+ self.create_classify_table(
+ key,
+ self.build_ip6_mask(nh='ff', src_port='ffff', dst_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(nh=socket.IPPROTO_UDP, src_port=sport,
+ dst_port=dport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+
+class TestClassifierIP6TCP(TestClassifier):
+ """ Classifier IP6 TCP proto Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierIP6TCP, cls).setUpClass()
+ cls.af = socket.AF_INET6
+
+ def test_iacl_proto_tcp(self):
+ """ IP6 TCP protocol iACL test
+
+ Test scenario for basic protocol ACL with TCP protocol
+ - Create IPv6 stream for pg0 -> pg1 interface.
+ - Create iACL with TCP IP protocol.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with TCP protocol
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ TCP(sport=1234, dport=5678))
+ self.pg0.add_stream(pkts)
+
+ key = 'nh_tcp'
+ self.create_classify_table(key, self.build_ip6_mask(nh='ff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(nh=socket.IPPROTO_TCP))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts, TCP)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_tcp_sport(self):
+ """ IP6 TCP source port iACL test
+
+ Test scenario for basic protocol ACL with TCP and sport
+ - Create IPv6 stream for pg0 -> pg1 interface.
+ - Create iACL with TCP IP protocol and defined sport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with TCP and sport
+ sport = 38
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ TCP(sport=sport, dport=5678))
+ self.pg0.add_stream(pkts)
+
+ key = 'nh_tcp_sport'
+ self.create_classify_table(
+ key, self.build_ip6_mask(nh='ff', src_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(nh=socket.IPPROTO_TCP, src_port=sport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts, TCP)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_tcp_dport(self):
+ """ IP6 TCP destination port iACL test
+
+ Test scenario for basic protocol ACL with TCP and dport
+ - Create IPv6 stream for pg0 -> pg1 interface.
+ - Create iACL with TCP IP protocol and defined dport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with TCP and dport
+ dport = 427
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ TCP(sport=1234, dport=dport))
+ self.pg0.add_stream(pkts)
+
+ key = 'nh_tcp_dport'
+ self.create_classify_table(
+ key, self.build_ip6_mask(nh='ff', dst_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(nh=socket.IPPROTO_TCP, dst_port=dport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts, TCP)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+ def test_iacl_proto_tcp_sport_dport(self):
+ """ IP6 TCP source and destination ports iACL test
+
+ Test scenario for basic protocol ACL with TCP and sport and dport
+ - Create IPv6 stream for pg0 -> pg1 interface.
+ - Create iACL with TCP IP protocol and defined sport and dport.
+ - Send and verify received packets on pg1 interface.
+ """
+
+ # Basic iACL testing with TCP and sport and dport
+ sport = 13720
+ dport = 9080
+ pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
+ TCP(sport=sport, dport=dport))
+ self.pg0.add_stream(pkts)
+
+ key = 'nh_tcp_ports'
+ self.create_classify_table(
+ key,
+ self.build_ip6_mask(nh='ff', src_port='ffff', dst_port='ffff'))
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(nh=socket.IPPROTO_TCP, src_port=sport,
+ dst_port=dport))
+ self.input_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg1.get_capture(len(pkts))
+ self.verify_capture(self.pg1, pkts, TCP)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+
+class TestClassifierIP6Out(TestClassifier):
+ """ Classifier output IP6 Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierIP6Out, cls).setUpClass()
+ cls.af = socket.AF_INET6
+
+ def test_acl_ip_out(self):
+ """ Output IP6 ACL test
+
+ Test scenario for basic IP ACL with source IP
+ - Create IPv6 stream for pg1 -> pg0 interface.
+ - Create ACL with source IP address.
+ - Send and verify received packets on pg0 interface.
+ """
+
+ # Basic oACL testing with source IP
+ pkts = self.create_stream(self.pg1, self.pg0, self.pg_if_packet_sizes)
+ self.pg1.add_stream(pkts)
+
+ key = 'ip6_out'
+ self.create_classify_table(
+ key,
+ self.build_ip6_mask(src_ip='ffffffffffffffffffffffffffffffff'),
+ data_offset=0)
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_ip6_match(src_ip=self.pg1.remote_ip6))
+ self.output_acl_set_interface(
+ self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg0.get_capture(len(pkts))
+ self.verify_capture(self.pg0, pkts)
+ self.pg1.assert_nothing_captured(remark="packets forwarded")
+ self.pg2.assert_nothing_captured(remark="packets forwarded")
+
+
+class TestClassifierIP6MAC(TestClassifier):
+ """ Classifier IP6 MAC Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestClassifierIP6MAC, cls).setUpClass()
+ cls.af = socket.AF_INET6
+
+ def test_acl_mac(self):
+ """ IP6 MAC iACL test
+
+ Test scenario for basic MAC ACL with source MAC
+ - Create IPv6 stream for pg0 -> pg2 interface.
+ - Create ACL with source MAC address.
+ - Send and verify received packets on pg2 interface.
+ """
+
+ # Basic iACL testing with source MAC
+ pkts = self.create_stream(self.pg0, self.pg2, self.pg_if_packet_sizes)
+ self.pg0.add_stream(pkts)
+
+ key = 'mac'
+ self.create_classify_table(
+ key, self.build_mac_mask(src_mac='ffffffffffff'), data_offset=-14)
+ self.create_classify_session(
+ self.acl_tbl_idx.get(key),
+ self.build_mac_match(src_mac=self.pg0.remote_mac))
+ self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
+ self.acl_active_table = key
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ pkts = self.pg2.get_capture(len(pkts))
+ self.verify_capture(self.pg2, pkts)
+ self.pg0.assert_nothing_captured(remark="packets forwarded")
+ self.pg1.assert_nothing_captured(remark="packets forwarded")
+
+
+if __name__ == '__main__':
+ unittest.main(testRunner=VppTestRunner)
/span> } const char *lcp_itf_l3_feat_names[N_LCP_ITF_HOST][N_AF] = { [LCP_ITF_HOST_TAP] = { [AF_IP4] = "linux-cp-xc-ip4", [AF_IP6] = "linux-cp-xc-ip6", }, [LCP_ITF_HOST_TUN] = { [AF_IP4] = "linux-cp-xc-l3-ip4", [AF_IP6] = "linux-cp-xc-l3-ip6", }, }; const fib_route_path_flags_t lcp_itf_route_path_flags[N_LCP_ITF_HOST] = { [LCP_ITF_HOST_TAP] = FIB_ROUTE_PATH_DVR, [LCP_ITF_HOST_TUN] = FIB_ROUTE_PATH_FLAG_NONE, }; static void lcp_itf_unset_adjs (lcp_itf_pair_t *lip) { adj_unlock (lip->lip_phy_adjs.adj_index[AF_IP4]); adj_unlock (lip->lip_phy_adjs.adj_index[AF_IP6]); } static void lcp_itf_set_adjs (lcp_itf_pair_t *lip) { if (lip->lip_host_type == LCP_ITF_HOST_TUN) { lip->lip_phy_adjs.adj_index[AF_IP4] = adj_nbr_add_or_lock ( FIB_PROTOCOL_IP4, VNET_LINK_IP4, &zero_addr, lip->lip_phy_sw_if_index); lip->lip_phy_adjs.adj_index[AF_IP6] = adj_nbr_add_or_lock ( FIB_PROTOCOL_IP6, VNET_LINK_IP6, &zero_addr, lip->lip_phy_sw_if_index); } else { lip->lip_phy_adjs.adj_index[AF_IP4] = adj_mcast_add_or_lock ( FIB_PROTOCOL_IP4, VNET_LINK_IP4, lip->lip_phy_sw_if_index); lip->lip_phy_adjs.adj_index[AF_IP6] = adj_mcast_add_or_lock ( FIB_PROTOCOL_IP6, VNET_LINK_IP6, lip->lip_phy_sw_if_index); } ip_adjacency_t *adj; adj = adj_get (lip->lip_phy_adjs.adj_index[AF_IP4]); lip->lip_rewrite_len = adj->rewrite_header.data_bytes; } int lcp_itf_pair_add (u32 host_sw_if_index, u32 phy_sw_if_index, u8 *host_name, u32 host_index, lip_host_type_t host_type, u8 *ns) { index_t lipi; lcp_itf_pair_t *lip; lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index); LCP_ITF_PAIR_INFO ("add: host:%U phy:%U, host_if:%v vif:%d ns:%s", format_vnet_sw_if_index_name, vnet_get_main (), host_sw_if_index, format_vnet_sw_if_index_name, vnet_get_main (), phy_sw_if_index, host_name, host_index, ns); if (lipi != INDEX_INVALID) return VNET_API_ERROR_VALUE_EXIST; /* * Create a new pair. */ pool_get (lcp_itf_pair_pool, lip); lipi = lip - lcp_itf_pair_pool; vec_validate_init_empty (lip_db_by_phy, phy_sw_if_index, INDEX_INVALID); vec_validate_init_empty (lip_db_by_host, host_sw_if_index, INDEX_INVALID); lip_db_by_phy[phy_sw_if_index] = lipi; lip_db_by_host[host_sw_if_index] = lipi; hash_set (lip_db_by_vif, host_index, lipi); lip->lip_host_sw_if_index = host_sw_if_index; lip->lip_phy_sw_if_index = phy_sw_if_index; lip->lip_host_name = vec_dup (host_name); lip->lip_host_type = host_type; lip->lip_vif_index = host_index; lip->lip_namespace = vec_dup (ns); if (lip->lip_host_sw_if_index == ~0) return 0; /* * First use of this host interface. * Enable the x-connect feature on the host to send * all packets to the phy. */ ip_address_family_t af; FOR_EACH_IP_ADDRESS_FAMILY (af) ip_feature_enable_disable (af, N_SAFI, IP_FEATURE_INPUT, lcp_itf_l3_feat_names[lip->lip_host_type][af], lip->lip_host_sw_if_index, 1, NULL, 0); /* * Configure passive punt to the host interface. */ fib_route_path_t *rpaths = NULL, rpath = { .frp_flags = lcp_itf_route_path_flags[lip->lip_host_type], .frp_proto = DPO_PROTO_IP4, .frp_sw_if_index = lip->lip_host_sw_if_index, .frp_weight = 1, .frp_fib_index = ~0, }; vec_add1 (rpaths, rpath); ip4_punt_redirect_add_paths (lip->lip_phy_sw_if_index, rpaths); rpaths[0].frp_proto = DPO_PROTO_IP6; ip6_punt_redirect_add_paths (lip->lip_phy_sw_if_index, rpaths); vec_free (rpaths); lcp_itf_set_adjs (lip); /* enable ARP feature node for broadcast interfaces */ if (lip->lip_host_type != LCP_ITF_HOST_TUN) { vnet_feature_enable_disable ("arp", "linux-cp-arp-phy", lip->lip_phy_sw_if_index, 1, NULL, 0); vnet_feature_enable_disable ("arp", "linux-cp-arp-host", lip->lip_host_sw_if_index, 1, NULL, 0); } else { vnet_feature_enable_disable ("ip4-punt", "linux-cp-punt-l3", 0, 1, NULL, 0); vnet_feature_enable_disable ("ip6-punt", "linux-cp-punt-l3", 0, 1, NULL, 0); } /* invoke registered callbacks for pair addition */ lcp_itf_pair_vft_t *vft; vec_foreach (vft, lcp_itf_vfts) { if (vft->pair_add_fn) vft->pair_add_fn (lip); } /* set timestamp when pair entered service */ lip->lip_create_ts = vlib_time_now (vlib_get_main ()); return 0; } static clib_error_t * lcp_netlink_add_link_vlan (int parent, u32 vlan, u16 proto, const char *name) { struct rtnl_link *link; struct nl_sock *sk; int err; sk = nl_socket_alloc (); if ((err = nl_connect (sk, NETLINK_ROUTE)) < 0) { LCP_ITF_PAIR_ERR ("netlink_add_link_vlan: connect error: %s", nl_geterror (err)); return clib_error_return (NULL, "Unable to connect socket: %d", err); } link = rtnl_link_vlan_alloc (); rtnl_link_set_link (link, parent); rtnl_link_set_name (link, name); rtnl_link_vlan_set_id (link, vlan); rtnl_link_vlan_set_protocol (link, htons (proto)); if ((err = rtnl_link_add (sk, link, NLM_F_CREATE)) < 0) { LCP_ITF_PAIR_ERR ("netlink_add_link_vlan: link add error: %s", nl_geterror (err)); return clib_error_return (NULL, "Unable to add link %s: %d", name, err); } rtnl_link_put (link); nl_close (sk); return NULL; } static clib_error_t * lcp_netlink_del_link (const char *name) { struct rtnl_link *link; struct nl_sock *sk; int err; sk = nl_socket_alloc (); if ((err = nl_connect (sk, NETLINK_ROUTE)) < 0) return clib_error_return (NULL, "Unable to connect socket: %d", err); link = rtnl_link_alloc (); rtnl_link_set_name (link, name); if ((err = rtnl_link_delete (sk, link)) < 0) return clib_error_return (NULL, "Unable to del link %s: %d", name, err); rtnl_link_put (link); nl_close (sk); return NULL; } int lcp_itf_pair_del (u32 phy_sw_if_index) { ip_address_family_t af; lcp_itf_pair_t *lip; u32 lipi; lcp_itf_pair_vft_t *vft; lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index); if (lipi == INDEX_INVALID) return VNET_API_ERROR_INVALID_SW_IF_INDEX; lip = lcp_itf_pair_get (lipi); LCP_ITF_PAIR_INFO ("pair delete: {%U, %U, %v}", format_vnet_sw_if_index_name, vnet_get_main (), lip->lip_phy_sw_if_index, format_vnet_sw_if_index_name, vnet_get_main (), lip->lip_host_sw_if_index, lip->lip_host_name); /* invoke registered callbacks for pair deletion */ vec_foreach (vft, lcp_itf_vfts) { if (vft->pair_del_fn) vft->pair_del_fn (lip); } FOR_EACH_IP_ADDRESS_FAMILY (af) ip_feature_enable_disable (af, N_SAFI, IP_FEATURE_INPUT, lcp_itf_l3_feat_names[lip->lip_host_type][af], lip->lip_host_sw_if_index, 0, NULL, 0); lcp_itf_unset_adjs (lip); ip4_punt_redirect_del (lip->lip_phy_sw_if_index); ip6_punt_redirect_del (lip->lip_phy_sw_if_index); /* disable ARP feature node for broadcast interfaces */ if (lip->lip_host_type != LCP_ITF_HOST_TUN) { vnet_feature_enable_disable ("arp", "linux-cp-arp-phy", lip->lip_phy_sw_if_index, 0, NULL, 0); vnet_feature_enable_disable ("arp", "linux-cp-arp-host", lip->lip_host_sw_if_index, 0, NULL, 0); } else { vnet_feature_enable_disable ("ip4-punt", "linux-cp-punt-l3", 0, 0, NULL, 0); vnet_feature_enable_disable ("ip6-punt", "linux-cp-punt-l3", 0, 0, NULL, 0); } lip_db_by_phy[phy_sw_if_index] = INDEX_INVALID; lip_db_by_host[lip->lip_host_sw_if_index] = INDEX_INVALID; hash_unset (lip_db_by_vif, lip->lip_vif_index); vec_free (lip->lip_host_name); vec_free (lip->lip_namespace); pool_put (lcp_itf_pair_pool, lip); return 0; } static void lcp_itf_pair_delete_by_index (index_t lipi) { u32 host_sw_if_index; lcp_itf_pair_t *lip; u8 *host_name; lip = lcp_itf_pair_get (lipi); host_name = vec_dup (lip->lip_host_name); host_sw_if_index = lip->lip_host_sw_if_index; lcp_itf_pair_del (lip->lip_phy_sw_if_index); if (vnet_sw_interface_is_sub (vnet_get_main (), host_sw_if_index)) { lcp_netlink_del_link ((const char *) host_name); vnet_delete_sub_interface (host_sw_if_index); } else tap_delete_if (vlib_get_main (), host_sw_if_index); vec_free (host_name); } int lcp_itf_pair_delete (u32 phy_sw_if_index) { index_t lipi; lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index); if (lipi == INDEX_INVALID) return VNET_API_ERROR_INVALID_SW_IF_INDEX; lcp_itf_pair_delete_by_index (lipi); return 0; } void lcp_itf_pair_walk (lcp_itf_pair_walk_cb_t cb, void *ctx) { u32 api; pool_foreach_index (api, lcp_itf_pair_pool) { if (!cb (api, ctx)) break; }; } typedef struct lcp_itf_pair_names_t_ { u8 *lipn_host_name; u8 *lipn_phy_name; u8 *lipn_namespace; u32 lipn_phy_sw_if_index; } lcp_itf_pair_names_t; static lcp_itf_pair_names_t *lipn_names; static clib_error_t * lcp_itf_pair_config (vlib_main_t *vm, unformat_input_t *input) { u8 *host, *phy; u8 *ns; u8 *default_ns; host = phy = ns = default_ns = NULL; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { vec_reset_length (host); if (unformat (input, "pair %s %s %s", &phy, &host, &ns)) { lcp_itf_pair_names_t *lipn; if (vec_len (ns) > LCP_NS_LEN) { return clib_error_return (0, "linux-cp namespace must" " be less than %d characters", LCP_NS_LEN); } vec_add2 (lipn_names, lipn, 1); lipn->lipn_host_name = vec_dup (host); lipn->lipn_phy_name = vec_dup (phy); lipn->lipn_namespace = vec_dup (ns); } else if (unformat (input, "pair %v %v", &phy, &host)) { lcp_itf_pair_names_t *lipn; vec_add2 (lipn_names, lipn, 1); lipn->lipn_host_name = vec_dup (host); lipn->lipn_phy_name = vec_dup (phy); lipn->lipn_namespace = 0; } else if (unformat (input, "default netns %v", &default_ns)) { vec_add1 (default_ns, 0); if (lcp_set_default_ns (default_ns) < 0) { return clib_error_return (0, "linux-cp default namespace must" " be less than %d characters", LCP_NS_LEN); } } else if (unformat (input, "interface-auto-create")) lcp_set_auto_intf (1 /* is_auto */); else return clib_error_return (0, "interfaces not found"); } vec_free (host); vec_free (phy); vec_free (default_ns); return NULL; } VLIB_EARLY_CONFIG_FUNCTION (lcp_itf_pair_config, "linux-cp"); /* * Returns 1 if the tap name is valid. * Returns 0 if the tap name is invalid. */ static int lcp_validate_if_name (u8 *name) { int len; char *p; p = (char *) name; len = clib_strnlen (p, IFNAMSIZ); if (len >= IFNAMSIZ) return 0; for (; *p; ++p) { if (isalnum (*p)) continue; switch (*p) { case '-': case '_': case '%': case '@': case ':': case '.': continue; } return 0; } return 1; } static void lcp_itf_set_link_state (const lcp_itf_pair_t *lip, u8 state) { int curr_ns_fd, vif_ns_fd; if (!lip) return; curr_ns_fd = vif_ns_fd = -1; if (lip->lip_namespace) { curr_ns_fd = clib_netns_open (NULL /* self */); vif_ns_fd = clib_netns_open (lip->lip_namespace); if (vif_ns_fd != -1) clib_setns (vif_ns_fd); } vnet_netlink_set_link_state (lip->lip_vif_index, state); if (vif_ns_fd != -1) close (vif_ns_fd); if (curr_ns_fd != -1) { clib_setns (curr_ns_fd); close (curr_ns_fd); } return; } typedef struct { u32 vlan; bool dot1ad; u32 matched_sw_if_index; } lcp_itf_match_t; static walk_rc_t lcp_itf_pair_find_walk (vnet_main_t *vnm, u32 sw_if_index, void *arg) { lcp_itf_match_t *match = arg; const vnet_sw_interface_t *sw; sw = vnet_get_sw_interface (vnm, sw_if_index); if (sw && (sw->sub.eth.inner_vlan_id == 0) && (sw->sub.eth.outer_vlan_id == match->vlan) && (sw->sub.eth.flags.dot1ad == match->dot1ad)) { LCP_ITF_PAIR_DBG ("find_walk: found match outer %d dot1ad %d " "inner-dot1q %d: interface %U", sw->sub.eth.outer_vlan_id, sw->sub.eth.flags.dot1ad, sw->sub.eth.inner_vlan_id, format_vnet_sw_if_index_name, vnet_get_main (), sw->sw_if_index); match->matched_sw_if_index = sw->sw_if_index; return WALK_STOP; } return WALK_CONTINUE; } /* Return the index of the sub-int on the phy that has the given vlan and * proto, */ static index_t lcp_itf_pair_find_by_outer_vlan (u32 sup_if_index, u16 vlan, bool dot1ad) { lcp_itf_match_t match; const vnet_hw_interface_t *hw; match.vlan = vlan; match.dot1ad = dot1ad; match.matched_sw_if_index = INDEX_INVALID; hw = vnet_get_sup_hw_interface (vnet_get_main (), sup_if_index); vnet_hw_interface_walk_sw (vnet_get_main (), hw->hw_if_index, lcp_itf_pair_find_walk, &match); if (match.matched_sw_if_index >= vec_len (lip_db_by_phy)) return INDEX_INVALID; return lip_db_by_phy[match.matched_sw_if_index]; } int lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name, lip_host_type_t host_if_type, u8 *ns, u32 *host_sw_if_indexp) { vlib_main_t *vm; vnet_main_t *vnm; u32 vif_index = 0, host_sw_if_index; const vnet_sw_interface_t *sw; const vnet_hw_interface_t *hw; const lcp_itf_pair_t *lip; if (!vnet_sw_if_index_is_api_valid (phy_sw_if_index)) { LCP_ITF_PAIR_ERR ("pair_create: invalid phy index %u", phy_sw_if_index); return VNET_API_ERROR_INVALID_SW_IF_INDEX; } if (!lcp_validate_if_name (host_if_name)) { LCP_ITF_PAIR_ERR ("pair_create: invalid host-if-name '%s'", host_if_name); return VNET_API_ERROR_INVALID_ARGUMENT; } vnm = vnet_get_main (); sw = vnet_get_sw_interface (vnm, phy_sw_if_index); hw = vnet_get_sup_hw_interface (vnm, phy_sw_if_index); if (!sw || !hw) { LCP_ITF_PAIR_ERR ("pair_create: invalid interface"); return VNET_API_ERROR_INVALID_SW_IF_INDEX; } /* * Use interface-specific netns if supplied. * Otherwise, use netns if defined, otherwise use the OS default. */ if (ns == 0 || ns[0] == 0) ns = lcp_get_default_ns (); /* sub interfaces do not need a tap created */ if (vnet_sw_interface_is_sub (vnm, phy_sw_if_index)) { index_t parent_if_index; int orig_ns_fd, ns_fd; clib_error_t *err; u16 outer_vlan, inner_vlan; u16 outer_proto, inner_proto; u16 vlan, proto; u32 parent_vif_index; // TODO(pim) replace with vnet_sw_interface_supports_addressing() if (sw->type == VNET_SW_INTERFACE_TYPE_SUB && sw->sub.eth.flags.exact_match == 0) { LCP_ITF_PAIR_ERR ("pair_create: can't create LCP for a " "sub-interface without exact-match set"); return VNET_API_ERROR_INVALID_ARGUMENT; } outer_vlan = sw->sub.eth.outer_vlan_id; inner_vlan = sw->sub.eth.inner_vlan_id; outer_proto = inner_proto = ETH_P_8021Q; if (1 == sw->sub.eth.flags.dot1ad) outer_proto = ETH_P_8021AD; LCP_ITF_PAIR_INFO ("pair_create: subif: dot1%s outer %d inner %d on %U", sw->sub.eth.flags.dot1ad ? "ad" : "q", outer_vlan, inner_vlan, format_vnet_sw_if_index_name, vnm, hw->sw_if_index); parent_if_index = lcp_itf_pair_find_by_phy (sw->sup_sw_if_index); if (INDEX_INVALID == parent_if_index) { LCP_ITF_PAIR_ERR ("pair_create: can't find LCP for %U", format_vnet_sw_if_index_name, vnet_get_main (), sw->sup_sw_if_index); return VNET_API_ERROR_INVALID_SW_IF_INDEX; } lip = lcp_itf_pair_get (parent_if_index); if (!lip) { LCP_ITF_PAIR_ERR ("pair_create: can't create LCP for a " "sub-interface without an LCP on the parent"); return VNET_API_ERROR_INVALID_ARGUMENT; } LCP_ITF_PAIR_DBG ("pair_create: parent %U", format_lcp_itf_pair, lip); parent_vif_index = lip->lip_vif_index; /* * see if the requested host interface has already been created */ orig_ns_fd = ns_fd = -1; err = NULL; if (ns && ns[0] != 0) { orig_ns_fd = clib_netns_open (NULL /* self */); ns_fd = clib_netns_open (ns); if (orig_ns_fd == -1 || ns_fd == -1) goto socket_close; clib_setns (ns_fd); } vif_index = if_nametoindex ((const char *) host_if_name); if (!vif_index) { /* * no existing host interface, create it now */ /* * Find the parent tap: * - if this is an outer VLAN, use the pair from the parent phy * - if this is an inner VLAN, find the pair from the outer sub-int, * which must exist. */ if (inner_vlan) { index_t linux_parent_if_index; const lcp_itf_pair_t *llip; vlan = inner_vlan; proto = inner_proto; linux_parent_if_index = lcp_itf_pair_find_by_outer_vlan ( hw->sw_if_index, sw->sub.eth.outer_vlan_id, sw->sub.eth.flags.dot1ad); if (INDEX_INVALID == linux_parent_if_index || !(llip = lcp_itf_pair_get (linux_parent_if_index))) { LCP_ITF_PAIR_ERR ( "pair_create: can't find LCP for outer vlan %d " "proto %s on %U", outer_vlan, outer_proto == ETH_P_8021AD ? "dot1ad" : "dot1q", format_vnet_sw_if_index_name, vnm, hw->sw_if_index); err = clib_error_return (0, "parent pair not found"); goto socket_close; } LCP_ITF_PAIR_DBG ("pair_create: linux parent %U", format_lcp_itf_pair, llip); parent_vif_index = llip->lip_vif_index; } else { vlan = outer_vlan; proto = outer_proto; } err = lcp_netlink_add_link_vlan (parent_vif_index, vlan, proto, (const char *) host_if_name); if (err != 0) { LCP_ITF_PAIR_ERR ("pair_create: cannot create link " "outer(proto:0x%04x,vlan:%u).inner(proto:0x%" "04x,vlan:%u) name:'%s'", outer_proto, outer_vlan, inner_proto, inner_vlan, host_if_name); } if (!err) vif_index = if_nametoindex ((char *) host_if_name); } /* * create a sub-interface on the tap */ if (!err && vnet_create_sub_interface (lip->lip_host_sw_if_index, sw->sub.id, sw->sub.eth.raw_flags, inner_vlan, outer_vlan, &host_sw_if_index)) { LCP_ITF_PAIR_ERR ( "pair_create: failed to create tap subint: %d.%d on %U", outer_vlan, inner_vlan, format_vnet_sw_if_index_name, vnm, lip->lip_host_sw_if_index); err = clib_error_return ( 0, "failed to create tap subinti: %d.%d. on %U", outer_vlan, inner_vlan, format_vnet_sw_if_index_name, vnm, lip->lip_host_sw_if_index); } socket_close: if (orig_ns_fd != -1) { clib_setns (orig_ns_fd); close (orig_ns_fd); } if (ns_fd != -1) close (ns_fd); if (err) return VNET_API_ERROR_INVALID_ARGUMENT; } else { tap_create_if_args_t args = { .num_rx_queues = clib_max (1, vlib_num_workers ()), .id = hw->hw_if_index, .sw_if_index = ~0, .rx_ring_sz = 256, .tx_ring_sz = 256, .host_if_name = host_if_name, .host_namespace = 0, }; ethernet_interface_t *ei; if (host_if_type == LCP_ITF_HOST_TUN) args.tap_flags |= TAP_FLAG_TUN; else { ei = pool_elt_at_index (ethernet_main.interfaces, hw->hw_instance); mac_address_copy (&args.host_mac_addr, &ei->address.mac); } if (sw->mtu[VNET_MTU_L3]) { args.host_mtu_set = 1; args.host_mtu_size = sw->mtu[VNET_MTU_L3]; } if (ns && ns[0] != 0) args.host_namespace = ns; vm = vlib_get_main (); tap_create_if (vm, &args); if (args.rv < 0) { LCP_ITF_PAIR_ERR ("pair_create: could not create tap, retval:%d", args.rv); return args.rv; } /* * The TAP interface does copy forward the host MTU based on the VPP * interface's L3 MTU, but it should also ensure that the VPP tap * interface has an MTU that is greater-or-equal to those. Considering * users can set the interfaces at runtime (set interface mtu packet ...) * ensure that the tap MTU is large enough, taking the VPP interface L3 * if it's set, and otherwise a sensible default. */ if (sw->mtu[VNET_MTU_L3]) vnet_sw_interface_set_mtu (vnm, args.sw_if_index, sw->mtu[VNET_MTU_L3]); else vnet_sw_interface_set_mtu (vnm, args.sw_if_index, ETHERNET_MAX_PACKET_BYTES); /* * get the hw and ethernet of the tap */ hw = vnet_get_sup_hw_interface (vnm, args.sw_if_index); virtio_main_t *mm = &virtio_main; virtio_if_t *vif = pool_elt_at_index (mm->interfaces, hw->dev_instance); /* * Leave the TAP permanently up on the VPP side. * This TAP will be shared by many sub-interface. * Therefore we can't use it to manage admin state. * force the tap in promiscuous mode. */ if (host_if_type == LCP_ITF_HOST_TAP) { ei = pool_elt_at_index (ethernet_main.interfaces, hw->hw_instance); ei->flags |= ETHERNET_INTERFACE_FLAG_STATUS_L3; } vif_index = vif->ifindex; host_sw_if_index = args.sw_if_index; } if (!vif_index) { LCP_ITF_PAIR_INFO ("failed pair add (no vif index): {%U, %U, %s}", format_vnet_sw_if_index_name, vnet_get_main (), phy_sw_if_index, format_vnet_sw_if_index_name, vnet_get_main (), host_sw_if_index, host_if_name); return -1; } LCP_ITF_PAIR_INFO ("pair create: {%U, %U, %s}", format_vnet_sw_if_index_name, vnet_get_main (), phy_sw_if_index, format_vnet_sw_if_index_name, vnet_get_main (), host_sw_if_index, host_if_name); lcp_itf_pair_add (host_sw_if_index, phy_sw_if_index, host_if_name, vif_index, host_if_type, ns); /* * Copy the link state from VPP into the host side. * The TAP is shared by many interfaces, always keep it up. * This controls whether the host can RX/TX. */ lip = lcp_itf_pair_get (lcp_itf_pair_find_by_vif (vif_index)); LCP_ITF_PAIR_INFO ("pair create: %U sw-flags %u hw-flags %u", format_lcp_itf_pair, lip, sw->flags, hw->flags); vnet_sw_interface_admin_up (vnm, host_sw_if_index); lcp_itf_set_link_state (lip, sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP); if (host_sw_if_indexp) *host_sw_if_indexp = host_sw_if_index; return 0; } static walk_rc_t lcp_itf_pair_walk_mark (index_t lipi, void *ctx) { lcp_itf_pair_t *lip; lip = lcp_itf_pair_get (lipi); lip->lip_flags |= LIP_FLAG_STALE; return (WALK_CONTINUE); } int lcp_itf_pair_replace_begin (void) { lcp_itf_pair_walk (lcp_itf_pair_walk_mark, NULL); return (0); } typedef struct lcp_itf_pair_sweep_ctx_t_ { index_t *indicies; } lcp_itf_pair_sweep_ctx_t; static walk_rc_t lcp_itf_pair_walk_sweep (index_t lipi, void *arg) { lcp_itf_pair_sweep_ctx_t *ctx = arg; lcp_itf_pair_t *lip; lip = lcp_itf_pair_get (lipi); if (lip->lip_flags & LIP_FLAG_STALE) vec_add1 (ctx->indicies, lipi); return (WALK_CONTINUE); } int lcp_itf_pair_replace_end (void) { lcp_itf_pair_sweep_ctx_t ctx = { .indicies = NULL, }; index_t *lipi; lcp_itf_pair_walk (lcp_itf_pair_walk_sweep, &ctx); vec_foreach (lipi, ctx.indicies) lcp_itf_pair_delete_by_index (*lipi); vec_free (ctx.indicies); return (0); } static uword lcp_itf_pair_process (vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f) { uword *event_data = 0; uword *lipn_index; while (1) { vlib_process_wait_for_event (vm); vlib_process_get_events (vm, &event_data); vec_foreach (lipn_index, event_data) { lcp_itf_pair_names_t *lipn; lipn = &lipn_names[*lipn_index]; lcp_itf_pair_create (lipn->lipn_phy_sw_if_index, lipn->lipn_host_name, LCP_ITF_HOST_TAP, lipn->lipn_namespace, NULL); } vec_reset_length (event_data); } return 0; } VLIB_REGISTER_NODE (lcp_itf_pair_process_node, static) = { .function = lcp_itf_pair_process, .name = "linux-cp-itf-process", .type = VLIB_NODE_TYPE_PROCESS, }; static clib_error_t * lcp_itf_phy_add (vnet_main_t *vnm, u32 sw_if_index, u32 is_create) { lcp_itf_pair_names_t *lipn; vlib_main_t *vm = vlib_get_main (); vnet_hw_interface_t *hw; if (!is_create || vnet_sw_interface_is_sub (vnm, sw_if_index)) return NULL; hw = vnet_get_sup_hw_interface (vnm, sw_if_index); vec_foreach (lipn, lipn_names) { if (!vec_cmp (hw->name, lipn->lipn_phy_name)) { lipn->lipn_phy_sw_if_index = sw_if_index; vlib_process_signal_event (vm, lcp_itf_pair_process_node.index, 0, lipn - lipn_names); break; } } return NULL; } VNET_SW_INTERFACE_ADD_DEL_FUNCTION (lcp_itf_phy_add); static clib_error_t * lcp_itf_pair_link_up_down (vnet_main_t *vnm, u32 hw_if_index, u32 flags) { vnet_hw_interface_t *hi; vnet_sw_interface_t *si; index_t lipi; lcp_itf_pair_t *lip; hi = vnet_get_hw_interface_or_null (vnm, hw_if_index); if (!hi) return 0; lipi = lcp_itf_pair_find_by_phy (hi->sw_if_index); if (lipi == INDEX_INVALID) return 0; lip = lcp_itf_pair_get (lipi); si = vnet_get_sw_interface_or_null (vnm, lip->lip_host_sw_if_index); if (!si) return 0; if (!lcp_main.test_mode) { tap_set_carrier (si->hw_if_index, (flags & VNET_HW_INTERFACE_FLAG_LINK_UP)); if (flags & VNET_HW_INTERFACE_FLAG_LINK_UP) { tap_set_speed (si->hw_if_index, hi->link_speed / 1000); } } return 0; } VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (lcp_itf_pair_link_up_down); static clib_error_t * lcp_itf_pair_init (vlib_main_t *vm) { vlib_punt_hdl_t punt_hdl = vlib_punt_client_register ("linux-cp"); /* punt IKE */ vlib_punt_register (punt_hdl, ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0], "linux-cp-punt"); /* punt all unknown ports */ udp_punt_unknown (vm, 0, 1); udp_punt_unknown (vm, 1, 1); tcp_punt_unknown (vm, 0, 1); tcp_punt_unknown (vm, 1, 1); lcp_itf_pair_logger = vlib_log_register_class ("linux-cp", "itf"); return NULL; } VLIB_INIT_FUNCTION (lcp_itf_pair_init) = { .runs_after = VLIB_INITS ("vnet_interface_init", "tcp_init", "udp_init"), }; /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */