aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorSteven Luong <sluong@cisco.com>2024-11-18 12:08:57 -0800
committerFlorin Coras <florin.coras@gmail.com>2024-12-23 21:28:08 +0000
commit6d4dbd4f29d6789cf4ea799d0b2eb9d489fa339d (patch)
tree3c1b6b1d56bd86a1d6a99e36c020a81f54a43f8b /test
parent755690c6c31671bdce4771db04199e151c32c5d0 (diff)
session: add auto sdl
New CLI to enable/disable auto-sdl (requires session enable rt-backend sdl) auto-sdl <enable|disable> [threshold <n>] [remove-timeout <t>] threshold is defined as the number of packets before the SDL entry is created to deny the source. remove-timeout is defined as the duration to remove the SDL entry which was created earlier. Type: feature Change-Id: I513094a59663970beae33257006c652674643764 Signed-off-by: Steven Luong <sluong@cisco.com>
Diffstat (limited to 'test')
-rw-r--r--test/asf/asfframework.py5
-rw-r--r--test/asf/test_auto_sdl.py593
2 files changed, 598 insertions, 0 deletions
diff --git a/test/asf/asfframework.py b/test/asf/asfframework.py
index c9c20106086..841a923dc79 100644
--- a/test/asf/asfframework.py
+++ b/test/asf/asfframework.py
@@ -459,6 +459,11 @@ class VppAsfTestCase(CPUInterface, unittest.TestCase):
"{",
"enable",
"}",
+ "plugin",
+ "auto_sdl_unittest_plugin.so",
+ "{",
+ "enable",
+ "}",
]
+ cls.extra_vpp_plugin_config
+ [
diff --git a/test/asf/test_auto_sdl.py b/test/asf/test_auto_sdl.py
new file mode 100644
index 00000000000..6b101c54e5c
--- /dev/null
+++ b/test/asf/test_auto_sdl.py
@@ -0,0 +1,593 @@
+#!/usr/bin/env python3
+
+import subprocess
+import socket
+
+import unittest
+
+from asfframework import (
+ VppAsfTestCase,
+ VppTestRunner,
+ tag_fixme_vpp_workers,
+ tag_run_solo,
+)
+from config import config
+from ipaddress import IPv4Network, IPv6Network
+from vpp_acl import AclRule, VppAcl, VppAclInterface
+
+from vpp_ip_route import (
+ VppIpRoute,
+ VppRoutePath,
+ VppIpTable,
+)
+
+from vpp_papi import VppEnum
+
+
+VPP_TAP_IP4 = "8.8.8.1"
+VPP_TAP_IP6 = "2001::1"
+
+HOST_TAP_IP4 = "8.8.8.2"
+HOST_TAP_IP6 = "2001::2"
+SCALE_COUNT = 10
+
+
+@tag_fixme_vpp_workers
+class TestAutoSDLUnitTests(VppAsfTestCase):
+ """Auto SDL Unit Tests Case"""
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestAutoSDLUnitTests, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestAutoSDLUnitTests, cls).tearDownClass()
+
+ def setUp(self):
+ super(TestAutoSDLUnitTests, self).setUp()
+ self.vapi.session_enable_disable(is_enable=1)
+
+ def test_session(self):
+ """Auto SDL Unit Tests"""
+ error = self.vapi.cli("test auto-sdl all")
+
+ if error:
+ self.logger.critical(error)
+ self.assertNotIn("failed", error)
+
+ def tearDown(self):
+ super(TestAutoSDLUnitTests, self).tearDown()
+ self.vapi.session_enable_disable(is_enable=0)
+
+
+@tag_fixme_vpp_workers
+@unittest.skipUnless(config.extended, "part of extended tests")
+class TestAutoSDL(VppAsfTestCase):
+ """Auto SDL Baasic Test Case"""
+
+ tcp_startup = ["syn-rcvd-time 1"]
+
+ @classmethod
+ def setUpClass(cls):
+ if cls.tcp_startup:
+ conf = "tcp {" + " ".join(cls.tcp_startup) + "}"
+ cls.extra_vpp_config = [conf]
+ super(TestAutoSDL, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestAutoSDL, cls).tearDownClass()
+
+ def setUp(self):
+ super(TestAutoSDL, self).setUp()
+
+ self.vapi.session_enable_disable_v2(
+ rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_SDL
+ )
+
+ # self.logger.info(self.vapi.cli("create tap host-ip4-addr HOST_TAP_IP/24"))
+ self.tap0 = self.vapi.tap_create_v3(
+ id=0,
+ host_ip4_prefix=HOST_TAP_IP4 + "/24",
+ host_ip4_prefix_set=True,
+ host_ip6_prefix=HOST_TAP_IP6 + "/64",
+ host_ip6_prefix_set=True,
+ )
+
+ # self.logger.info(self.vapi.cli("set interface state tap0 up"))
+ self.vapi.sw_interface_set_flags(sw_if_index=self.tap0.sw_if_index, flags=1)
+
+ def tearDown(self):
+ self.logger.info(
+ self.vapi.sw_interface_add_del_address(
+ is_add=0,
+ sw_if_index=self.tap0.sw_if_index,
+ prefix=VPP_TAP_IP4 + "/24",
+ del_all=1,
+ )
+ )
+ # self.logger.info(self.vapi.cli("set interface ip address tap0 VPP_TAP_IP6/64"))
+ self.logger.info(
+ self.vapi.sw_interface_add_del_address(
+ is_add=0,
+ sw_if_index=self.tap0.sw_if_index,
+ prefix=VPP_TAP_IP6 + "/64",
+ del_all=1,
+ )
+ )
+ self.logger.info(self.vapi.tap_delete_v2(self.tap0.sw_if_index))
+ self.logger.info(
+ self.vapi.session_enable_disable_v2(
+ rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_DISABLE
+ )
+ )
+ dump = self.vapi.session_sdl_v3_dump()
+ self.assertTrue(len(dump) == 0)
+ super(TestAutoSDL, self).tearDown()
+
+ def test_auto_sdl(self):
+ """Auto SDL test"""
+
+ # self.logger.info(self.vapi.cli("set interface ip address tap0 VPP_TAP_IP/24"))
+ self.vapi.sw_interface_add_del_address(
+ sw_if_index=self.tap0.sw_if_index, prefix=VPP_TAP_IP4 + "/24"
+ )
+ # self.logger.info(self.vapi.cli("set interface ip address tap0 VPP_TAP_IP6/64"))
+ self.vapi.sw_interface_add_del_address(
+ sw_if_index=self.tap0.sw_if_index, prefix=VPP_TAP_IP6 + "/64"
+ )
+
+ # start the cli server
+ self.logger.info("Starting cli sever")
+ self.logger.info(self.vapi.cli("http cli server"))
+
+ self.logger.info(
+ self.vapi.cli("http cli server uri http://::0/80 listener add")
+ )
+
+ # Test 1. No ACL. curl should work.
+ self.logger.info("Starting test 1")
+ for i in range(10):
+ try:
+ process = subprocess.run(
+ [
+ "curl",
+ "--noproxy",
+ "'*'",
+ "http://" + VPP_TAP_IP4 + ":80/sh/version",
+ ],
+ capture_output=True,
+ timeout=2,
+ )
+ except:
+ self.logger.info("timeout")
+ else:
+ break
+ self.assertEqual(0, process.returncode)
+ self.logger.info("Test 1 passed")
+
+ # Test 2. Add ACL to block the source.
+ rule = AclRule(
+ is_permit=0,
+ proto=6,
+ src_prefix=IPv4Network("8.8.0.0/16"),
+ dst_prefix=IPv4Network(VPP_TAP_IP4 + "/32"),
+ ports=80,
+ )
+ acl = VppAcl(self, rules=[rule])
+ acl.add_vpp_config()
+
+ # Apply the ACL on the interface output
+ # Auto SDL entry should be created and timed out accordingly
+ acl_if_e = VppAclInterface(
+ self, sw_if_index=self.tap0.sw_if_index, n_input=0, acls=[acl]
+ )
+ acl_if_e.add_vpp_config()
+
+ self.vapi.auto_sdl_config(threshold=2, remove_timeout=3, enable=True)
+
+ for i in range(2):
+ try:
+ process = subprocess.run(
+ [
+ "curl",
+ "--noproxy",
+ "'*'",
+ "http://" + VPP_TAP_IP4 + ":80/sh/version",
+ ],
+ capture_output=True,
+ timeout=2,
+ )
+ except:
+ self.logger.info("curl timeout -- as exepcted")
+
+ # check for the SDL entry
+ for i in range(10):
+ dump = self.vapi.session_sdl_v3_dump()
+ if len(dump) == 0:
+ self.sleep(1)
+ self.assertTrue(len(dump) > 0)
+ self.assertEqual(dump[0].rmt, IPv4Network(HOST_TAP_IP4 + "/32"))
+
+ # verify entry is timed out and removed eventually
+ for i in range(10):
+ dump = self.vapi.session_sdl_v3_dump()
+ if len(dump) > 0:
+ self.sleep(1)
+ self.assertTrue(len(dump) == 0)
+
+ acl_if_e.remove_vpp_config()
+ acl.remove_vpp_config()
+ self.logger.info("Test 2 passed")
+
+ # Test 3: Do the same for IPv6
+ process = subprocess.run(
+ [
+ "curl",
+ "-6",
+ "--noproxy",
+ "'*'",
+ "http://" + "[" + VPP_TAP_IP6 + "]" + ":80/sh/version",
+ ],
+ capture_output=True,
+ )
+ self.assertEqual(0, process.returncode)
+
+ rule = AclRule(
+ is_permit=0,
+ proto=6,
+ src_prefix=IPv6Network(HOST_TAP_IP6 + "/128"),
+ dst_prefix=IPv6Network(VPP_TAP_IP6 + "/128"),
+ ports=80,
+ )
+ acl = VppAcl(self, rules=[rule])
+ acl.add_vpp_config()
+
+ # Apply the ACL on the interface output
+ acl_if_e = VppAclInterface(
+ self, sw_if_index=self.tap0.sw_if_index, n_input=0, acls=[acl]
+ )
+ acl_if_e.add_vpp_config()
+
+ for i in range(2):
+ try:
+ process = subprocess.run(
+ [
+ "curl",
+ "-6",
+ "--noproxy",
+ "'*'",
+ "http://" + "[" + VPP_TAP_IP6 + "]" + ":80/sh/version",
+ ],
+ capture_output=True,
+ timeout=2,
+ )
+ except:
+ self.logger.info("curl timeout -- as exepcted")
+
+ acl_if_e.remove_vpp_config()
+ acl.remove_vpp_config()
+
+ # verify the SDL entry is added
+ for i in range(5):
+ dump = self.vapi.session_sdl_v3_dump()
+ if len(dump) == 0:
+ self.sleep(1)
+ self.assertTrue(len(dump) > 0)
+ self.assertEqual(dump[0].rmt, IPv6Network(HOST_TAP_IP6 + "/128"))
+
+ # verify the entry is removed after timeout
+ for i in range(10):
+ dump = self.vapi.session_sdl_v3_dump()
+ if len(dump) > 0:
+ self.sleep(1)
+ self.assertEqual(len(dump), 0)
+ self.logger.info("Test 3 passed")
+
+ self.vapi.auto_sdl_config(enable=False)
+
+ # bring down the cli server
+ self.logger.info(self.vapi.cli("http cli server listener del"))
+ self.logger.info(
+ self.vapi.cli("http cli server uri http://::0/80 listener del")
+ )
+
+ def test_auto_sdl_appns_ip4(self):
+ """Auto SDL with appns test -- ip4"""
+
+ # Test tap0 in appns 1
+ table_id = 1
+ tbl = VppIpTable(self, table_id)
+ tbl.add_vpp_config()
+
+ # place tap0 to vrf 1
+ self.vapi.sw_interface_set_table(
+ self.tap0.sw_if_index, is_ipv6=0, vrf_id=table_id
+ )
+
+ # place tap0 to appns 1
+ self.vapi.app_namespace_add_del_v4(
+ namespace_id="1", secret=1, sw_if_index=self.tap0.sw_if_index
+ )
+ # configure ip4 address on tap0
+ self.vapi.sw_interface_add_del_address(
+ sw_if_index=self.tap0.sw_if_index, prefix=VPP_TAP_IP4 + "/24"
+ )
+
+ # start http cli server in appns 1
+ self.logger.info(self.vapi.cli("http cli server appns 1 secret 1"))
+
+ process = subprocess.run(
+ [
+ "curl",
+ "--noproxy",
+ "'*'",
+ "http://" + VPP_TAP_IP4 + ":80/sh/version",
+ ],
+ timeout=1,
+ capture_output=True,
+ )
+ self.assertEqual(0, process.returncode)
+
+ # Apply the ACL on the interface output
+ rule = AclRule(
+ is_permit=0,
+ proto=6,
+ src_prefix=IPv4Network("8.8.0.0/16"),
+ dst_prefix=IPv4Network(VPP_TAP_IP4 + "/32"),
+ ports=80,
+ )
+ acl = VppAcl(self, rules=[rule])
+ acl.add_vpp_config()
+
+ acl_if_e = VppAclInterface(
+ self, sw_if_index=self.tap0.sw_if_index, n_input=0, acls=[acl]
+ )
+ acl_if_e.add_vpp_config()
+
+ self.vapi.auto_sdl_config(threshold=1, remove_timeout=60, enable=True)
+ for i in range(10):
+ try:
+ process = subprocess.run(
+ [
+ "curl",
+ "--noproxy",
+ "'*'",
+ "http://" + VPP_TAP_IP4 + ":80/sh/version",
+ ],
+ capture_output=True,
+ timeout=1,
+ )
+ except:
+ self.logger.info("connect timeout -- as expected")
+ else:
+ dump = self.vapi.session_sdl_v3_dump()
+ if len(dump) == 0:
+ self.sleep(1)
+ else:
+ break
+
+ for i in range(60):
+ dump = self.vapi.session_sdl_v3_dump()
+ if len(dump) != 1:
+ self.sleep(1)
+ self.assertEqual(len(dump), 1)
+ self.assertEqual(dump[0].rmt, IPv4Network(HOST_TAP_IP4 + "/32"))
+ self.logger.info("Test 6 passed")
+
+ acl_if_e.remove_vpp_config()
+ acl.remove_vpp_config()
+
+ # bring down the cli server
+ self.logger.info(self.vapi.cli("http cli server listener del"))
+
+ # delete namespace
+ self.vapi.app_namespace_add_del_v4(
+ namespace_id="1",
+ secret=1,
+ sw_if_index=self.tap0.sw_if_index,
+ is_add=0,
+ )
+
+ # Disable auto sdl -- quicker than waiting the entry to timeout
+ self.vapi.auto_sdl_config(enable=False)
+
+ # disable session sdl
+ self.vapi.session_enable_disable_v2(
+ rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_DISABLE
+ )
+
+ dump = self.vapi.session_sdl_v3_dump()
+ self.assertTrue(len(dump) == 0)
+
+ def test_auto_sdl_appns_ip6(self):
+ """Auto SDL with appns test -- ip6"""
+
+ # Test tap0 in appns 1
+ table_id = 1
+ tbl = VppIpTable(self, table_id, is_ip6=1)
+ tbl.add_vpp_config()
+
+ # place tap0 to vrf 1
+ self.vapi.sw_interface_set_table(
+ self.tap0.sw_if_index, is_ipv6=1, vrf_id=table_id
+ )
+
+ # place tap0 to appns 1
+ self.vapi.app_namespace_add_del_v4(
+ namespace_id="1", secret=1, sw_if_index=self.tap0.sw_if_index
+ )
+ # configure ip6 address on tap0
+ self.vapi.sw_interface_add_del_address(
+ sw_if_index=self.tap0.sw_if_index, prefix=VPP_TAP_IP6 + "/64"
+ )
+
+ # start http cli server in appns 1
+ self.logger.info(
+ self.vapi.cli("http cli server appns 1 secret 1 uri http://::0/80")
+ )
+
+ self.sleep(3)
+ process = subprocess.run(
+ [
+ "curl",
+ "-6",
+ "--noproxy",
+ "'*'",
+ "http://" + "[" + VPP_TAP_IP6 + "]" + ":80/sh/version",
+ ],
+ timeout=5,
+ capture_output=True,
+ )
+ self.assertEqual(0, process.returncode)
+
+ # Apply the ACL on the interface output
+ rule = AclRule(
+ is_permit=0,
+ proto=6,
+ src_prefix=IPv6Network(HOST_TAP_IP6 + "/128"),
+ dst_prefix=IPv6Network(VPP_TAP_IP6 + "/128"),
+ ports=80,
+ )
+ acl = VppAcl(self, rules=[rule])
+ acl.add_vpp_config()
+
+ acl_if_e = VppAclInterface(
+ self, sw_if_index=self.tap0.sw_if_index, n_input=0, acls=[acl]
+ )
+ acl_if_e.add_vpp_config()
+
+ self.vapi.auto_sdl_config(threshold=1, remove_timeout=60, enable=True)
+ for i in range(10):
+ try:
+ process = subprocess.run(
+ [
+ "curl",
+ "-6",
+ "--noproxy",
+ "'*'",
+ "http://" + "[" + VPP_TAP_IP6 + "]" + ":80/sh/version",
+ ],
+ capture_output=True,
+ timeout=1,
+ )
+ except:
+ self.logger.info("connect timeout -- as expected")
+ else:
+ dump = self.vapi.session_sdl_v3_dump()
+ if len(dump) == 0:
+ self.sleep(1)
+ else:
+ break
+
+ for i in range(60):
+ dump = self.vapi.session_sdl_v3_dump()
+ if len(dump) != 1:
+ self.sleep(1)
+ self.assertEqual(len(dump), 1)
+ self.assertEqual(dump[0].rmt, IPv6Network(HOST_TAP_IP6 + "/128"))
+ self.logger.info("Test 6 passed")
+
+ acl_if_e.remove_vpp_config()
+ acl.remove_vpp_config()
+
+ # bring down the cli server
+ self.logger.info(
+ self.vapi.cli("http cli server uri http://::0/80 listener del")
+ )
+
+ # delete namespace
+ self.vapi.app_namespace_add_del_v4(
+ namespace_id="1",
+ secret=1,
+ sw_if_index=self.tap0.sw_if_index,
+ is_add=0,
+ )
+
+ @unittest.skip("test disabled for auto sdl")
+ def test_auto_sdl_scale(self):
+ """Auto SDL scale test"""
+
+ # Test 4: Scale
+ # Send 250 packets from different sources. Should create 250 auto-SDL
+ # and SDL entries
+ # self.logger.info(self.vapi.cli("set interface ip address tap0 VPP_TAP_IP/24"))
+
+ self.vapi.sw_interface_add_del_address(
+ sw_if_index=self.tap0.sw_if_index, prefix=VPP_TAP_IP4 + "/24"
+ )
+
+ # start the cli server
+ self.logger.info("Starting cli sever")
+ self.logger.info(self.vapi.cli("http cli server"))
+
+ rule = AclRule(
+ is_permit=0,
+ proto=6,
+ src_prefix=IPv4Network("8.8.0.0/16"),
+ dst_prefix=IPv4Network(VPP_TAP_IP4 + "/32"),
+ ports=80,
+ )
+ acl = VppAcl(self, rules=[rule])
+ acl.add_vpp_config()
+
+ # Apply the ACL on the interface output
+ acl_if_e = VppAclInterface(
+ self, sw_if_index=self.tap0.sw_if_index, n_input=0, acls=[acl]
+ )
+ acl_if_e.add_vpp_config()
+
+ # set the remove_timeout to a large value. Otherwise, some entries may
+ # get timed out before we accumulate all of them for verification
+ self.vapi.auto_sdl_config(threshold=1, remove_timeout=300, enable=True)
+
+ for i in range(SCALE_COUNT):
+ prefix = "8.8.8.{0}".format(i + 3)
+ prefix_mask = "8.8.8.{0}/24".format(i + 3)
+ prefix_port = (prefix, 5000)
+ process = subprocess.run(
+ [
+ "ip",
+ "address",
+ "add",
+ prefix_mask,
+ "dev",
+ "tap0",
+ ],
+ capture_output=True,
+ )
+ self.assertEqual(process.returncode, 0)
+ for i in range(2):
+ try:
+ s = socket.create_connection(
+ (VPP_TAP_IP4, 80), timeout=0.5, source_address=prefix_port
+ )
+ except:
+ self.logger.info("connect timeout -- as exepcted")
+
+ # check for the SDL entry
+ for i in range(60):
+ dump = self.vapi.session_sdl_v3_dump()
+ if len(dump) != SCALE_COUNT:
+ self.sleep(1)
+
+ self.assertEqual(len(dump), SCALE_COUNT)
+ self.logger.info("Test 4 passed")
+
+ # Test 5: Disable auto-sdl
+ # It should clean up the Auto SDL and SDL entries immediately
+ self.logger.info(self.vapi.auto_sdl_config(enable=False))
+ dump = self.vapi.session_sdl_v3_dump()
+ self.assertEqual(len(dump), 0)
+
+ acl_if_e.remove_vpp_config()
+ acl.remove_vpp_config()
+ self.logger.info("Test 5 passed")
+
+ # bring down the cli server
+ self.vapi.cli("http cli server listener del")
+
+
+if __name__ == "__main__":
+ unittest.main(testRunner=VppTestRunner)