From 2fa69effc844d7a27d46c0f163c0840df961eb2d Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sun, 10 Dec 2023 21:07:38 +0100 Subject: urpf: add interface dump to API Add an urpf_interface_dump() API call, with optional sw_if_index. If either a mode or a table is specified in any given interface address family and direction, return it in a list, otherwise omit it. TESTED: create loopback interface instance 0 create loopback interface instance 1 create loopback interface instance 2 create loopback interface instance 3 ip6 table add 8298 set urpf ip4 rx loose loop1 set urpf ip6 tx off loop2 table 8298 API call urpf_interface_dump(sw_if_index=~1) returns: [ urpf_interface_details(_0=658, context=2, sw_if_index=2, is_rx=True, mode=, af=, table_id=0), urpf_interface_details(_0=658, context=2, sw_if_index=3, is_rx=False, mode=, af=, table_id=8298) ] Type: improvement Change-Id: I1ded5c445dc07dab73ea41b817b5827b72ca79d4 Signed-off-by: pim@ipng.nl --- src/plugins/urpf/urpf.api | 24 ++++++++++++++++ src/plugins/urpf/urpf_api.c | 70 +++++++++++++++++++++++++++++++++++++++++++++ test/test_urpf.py | 55 +++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) diff --git a/src/plugins/urpf/urpf.api b/src/plugins/urpf/urpf.api index 4665743a57a..a4e897afd17 100644 --- a/src/plugins/urpf/urpf.api +++ b/src/plugins/urpf/urpf.api @@ -71,6 +71,30 @@ autoreply define urpf_update_v2 u32 table_id [default=0xffffffff]; }; +/** @brief Dump uRPF enabled interface(s) in zero or more urpf_interface_details replies + @param client_index - opaque cookie to identify the sender + @param sw_if_index - sw_if_index of a specific interface, or -1 (default) + to return all uRPF enabled interfaces +*/ +define urpf_interface_dump +{ + u32 client_index; + u32 context; + vl_api_interface_index_t sw_if_index [default=0xffffffff]; +}; + +/** @brief uRPF enabled interface details +*/ +define urpf_interface_details +{ + u32 context; + vl_api_interface_index_t sw_if_index; + bool is_input; + vl_api_urpf_mode_t mode; + vl_api_address_family_t af; + u32 table_id; +}; + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/plugins/urpf/urpf_api.c b/src/plugins/urpf/urpf_api.c index 472f0e4a7ff..f5d31e1fce6 100644 --- a/src/plugins/urpf/urpf_api.c +++ b/src/plugins/urpf/urpf_api.c @@ -111,6 +111,76 @@ done: REPLY_MACRO (VL_API_URPF_UPDATE_V2_REPLY); } +static void +send_urpf_interface_details (vpe_api_main_t *am, vl_api_registration_t *reg, + u32 context, const u32 sw_if_index, + const urpf_data_t *ud, + const ip_address_family_t af, + const vlib_dir_t dir) +{ + vl_api_urpf_interface_details_t *mp; + + mp = vl_msg_api_alloc_zero (sizeof (*mp)); + mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_URPF_INTERFACE_DETAILS); + mp->context = context; + + mp->sw_if_index = htonl (sw_if_index); + mp->table_id = htonl (fib_table_get_table_id ( + ud->fib_index, (af == AF_IP4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6))); + mp->af = (vl_api_address_family_t) af; + mp->mode = (vl_api_urpf_mode_t) ud->mode; + mp->is_input = (dir == VLIB_RX); + + vl_api_send_msg (reg, (u8 *) mp); +} + +static void +send_urpf_interface (vpe_api_main_t *am, vl_api_registration_t *reg, + u32 context, const u32 sw_if_index) +{ + urpf_data_t *ud; + vlib_dir_t dir; + ip_address_family_t af; + + FOR_EACH_IP_ADDRESS_FAMILY (af) + FOREACH_VLIB_DIR (dir) + if (sw_if_index < vec_len (urpf_cfgs[af][dir])) + { + ud = &urpf_cfgs[af][dir][sw_if_index]; + if (ud->mode || ud->fib_index_is_custom) + send_urpf_interface_details (am, reg, context, sw_if_index, ud, af, + dir); + } +} + +static void +vl_api_urpf_interface_dump_t_handler (vl_api_urpf_interface_dump_t *mp) +{ + vpe_api_main_t *am = &vpe_api_main; + vl_api_registration_t *reg; + vnet_interface_main_t *im = &vnet_main.interface_main; + vnet_sw_interface_t *si; + u32 sw_if_index = ~0; + int __attribute__ ((unused)) rv = 0; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + sw_if_index = ntohl (mp->sw_if_index); + + if (sw_if_index == ~0) + { + pool_foreach (si, im->sw_interfaces) + { + send_urpf_interface (am, reg, mp->context, si->sw_if_index); + } + return; + } + VALIDATE_SW_IF_INDEX (mp); + send_urpf_interface (am, reg, mp->context, sw_if_index); + BAD_SW_IF_INDEX_LABEL; +} + #include static clib_error_t * diff --git a/test/test_urpf.py b/test/test_urpf.py index 0eb8b055682..1e4a6c5bb34 100644 --- a/test/test_urpf.py +++ b/test/test_urpf.py @@ -317,6 +317,61 @@ class TestURPF(VppTestCase): sw_if_index=self.pg1.sw_if_index, ) + def test_interface_dump(self): + """uRPF Interface Dump""" + + self.create_loopback_interfaces(3) + e = VppEnum + self.vapi.urpf_update( + is_input=True, + mode=e.vl_api_urpf_mode_t.URPF_API_MODE_STRICT, + af=e.vl_api_address_family_t.ADDRESS_IP4, + sw_if_index=self.loop1.sw_if_index, + ) + self.vapi.urpf_update( + is_input=False, + mode=e.vl_api_urpf_mode_t.URPF_API_MODE_LOOSE, + af=e.vl_api_address_family_t.ADDRESS_IP6, + sw_if_index=self.loop2.sw_if_index, + ) + + ret = self.vapi.urpf_interface_dump() + self.assertEqual(len(ret), 2) + + dump_loop1 = ret[0] + dump_loop2 = ret[1] + self.assertEqual(dump_loop1.sw_if_index, self.loop1.sw_if_index) + self.assertTrue(dump_loop1.is_input) + self.assertEqual(dump_loop1.mode, e.vl_api_urpf_mode_t.URPF_API_MODE_STRICT) + self.assertEqual(dump_loop1.af, e.vl_api_address_family_t.ADDRESS_IP4) + self.assertEqual(dump_loop2.sw_if_index, self.loop2.sw_if_index) + self.assertFalse(dump_loop2.is_input) + self.assertEqual(dump_loop2.mode, e.vl_api_urpf_mode_t.URPF_API_MODE_LOOSE) + self.assertEqual(dump_loop2.af, e.vl_api_address_family_t.ADDRESS_IP6) + + ret = self.vapi.urpf_interface_dump(sw_if_index=self.loop1.sw_if_index) + self.assertEqual(len(ret), 1) + + dump_loop1 = ret[0] + self.assertEqual(dump_loop1.sw_if_index, self.loop1.sw_if_index) + self.assertTrue(dump_loop1.is_input) + self.assertEqual(dump_loop1.mode, e.vl_api_urpf_mode_t.URPF_API_MODE_STRICT) + self.assertEqual(dump_loop1.af, e.vl_api_address_family_t.ADDRESS_IP4) + + # cleanup + self.vapi.urpf_update( + is_input=False, + mode=e.vl_api_urpf_mode_t.URPF_API_MODE_OFF, + af=e.vl_api_address_family_t.ADDRESS_IP4, + sw_if_index=self.loop1.sw_if_index, + ) + self.vapi.urpf_update( + is_input=False, + mode=e.vl_api_urpf_mode_t.URPF_API_MODE_OFF, + af=e.vl_api_address_family_t.ADDRESS_IP6, + sw_if_index=self.loop2.sw_if_index, + ) + if __name__ == "__main__": unittest.main(testRunner=VppTestRunner) -- cgit 1.2.3-korg