From eca860c856c265089789f32e04e5c2b51594caf9 Mon Sep 17 00:00:00 2001 From: Hadi Rayan Al-Sandid Date: Wed, 23 Apr 2025 12:19:13 +0200 Subject: [PATCH] ip_session_redirect: add dump api for session redirects Type: improvement Change-Id: Icd6e94535d388e4c2c08c8ab383fea8cac324d66 Signed-off-by: Hadi Rayan Al-Sandid --- src/plugins/ip_session_redirect/api.c | 64 +++++++++++++++++++ .../ip_session_redirect/ip_session_redirect.api | 41 ++++++++++++ .../ip_session_redirect/ip_session_redirect.h | 24 +++++++ src/plugins/ip_session_redirect/redirect.c | 24 +------ src/plugins/ip_session_redirect/test_api.c | 74 ++++++++++++++++++++++ test/test_ip_session_redirect.py | 69 ++++++++++++++++++++ 6 files changed, 273 insertions(+), 23 deletions(-) diff --git a/src/plugins/ip_session_redirect/api.c b/src/plugins/ip_session_redirect/api.c index 1d17d55b5b4..5c7bc65771f 100644 --- a/src/plugins/ip_session_redirect/api.c +++ b/src/plugins/ip_session_redirect/api.c @@ -12,8 +12,10 @@ * limitations under the License. */ #include +#include #include #include +#include #include #include @@ -105,6 +107,68 @@ vl_api_ip_session_redirect_del_t_handler (vl_api_ip_session_redirect_del_t *mp) REPLY_MACRO (VL_API_IP_SESSION_REDIRECT_DEL_REPLY); } +static void +send_ip_session_redirect_details (vl_api_registration_t *reg, u32 table_index, + u32 context) +{ + ip_session_redirect_main_t *im = &ip_session_redirect_main; + ip_session_redirect_t *ipr; + ip_session_redirect_t *iprs = im->pool; + + pool_foreach (ipr, iprs) + { + if (~0 == table_index || ipr->table_index == table_index) + { + vl_api_ip_session_redirect_details_t *rmp; + vl_api_fib_path_t *fp; + fib_route_path_t *rpath; + fib_path_encode_ctx_t walk_ctx = { + .rpaths = NULL, + }; + u8 n_paths = fib_path_list_get_n_paths (ipr->pl); + /* match_len is computed without table index at the end of the match + * string */ + u32 match_len = vec_len (ipr->match_and_table_index) - 4; + + rmp = vl_msg_api_alloc_zero (sizeof (*rmp) + + sizeof (rmp->paths[0]) * n_paths); + rmp->_vl_msg_id = + ntohs (REPLY_MSG_ID_BASE + VL_API_IP_SESSION_REDIRECT_DETAILS); + rmp->context = context; + rmp->opaque_index = htonl (ipr->opaque_index); + rmp->table_index = htonl (ipr->table_index); + rmp->match_length = htonl (match_len); + rmp->is_punt = ipr->is_punt; + rmp->is_ip6 = ipr->is_ip6; + clib_memcpy (rmp->match, ipr->match_and_table_index, match_len); + rmp->n_paths = n_paths; + fp = rmp->paths; + rmp->retval = 0; + fib_path_list_walk_w_ext (ipr->pl, NULL, fib_path_encode, &walk_ctx); + vec_foreach (rpath, walk_ctx.rpaths) + { + fib_api_path_encode (rpath, fp); + fp++; + } + + vl_api_send_msg (reg, (u8 *) rmp); + } + } +} + +static void +vl_api_ip_session_redirect_dump_t_handler ( + vl_api_ip_session_redirect_dump_t *mp) +{ + vl_api_registration_t *reg; + u32 table_index = ntohl (mp->table_index); + reg = vl_api_client_index_to_registration (mp->client_index); + if (reg == 0) + return; + + send_ip_session_redirect_details (reg, table_index, mp->context); +} + #include "ip_session_redirect.api.c" static clib_error_t * ip_session_redirect_plugin_api_hookup (vlib_main_t *vm) diff --git a/src/plugins/ip_session_redirect/ip_session_redirect.api b/src/plugins/ip_session_redirect/ip_session_redirect.api index 2bf2373dbd2..769d15b4751 100644 --- a/src/plugins/ip_session_redirect/ip_session_redirect.api +++ b/src/plugins/ip_session_redirect/ip_session_redirect.api @@ -99,6 +99,47 @@ autoreply define ip_session_redirect_del option status="in_progress"; }; +/** \brief Dump available session redirections + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param table_index - classifier table index +*/ + +define ip_session_redirect_dump +{ + u32 client_index; + u32 context; + u32 table_index; +}; + +/** \brief Session redirection operational state response + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param table_index - classifier table index + @param opaque_index - classifier session opaque index + @param is_punt - true = punted traffic, false = forwarded traffic + @param is_ip6 - true = payload proto is ip6, false = payload proto is ip4 + @param match_len - classifier session match length in bytes (max is 80-bytes) + @param match - classifier session match + @param n_paths - number of paths + @param paths - the paths of the redirect +*/ + +define ip_session_redirect_details +{ + u32 context; + i32 retval; + u32 table_index; + u32 opaque_index; + bool is_punt; + bool is_ip6; + u32 match_length; + u8 match[80]; + u8 n_paths; + vl_api_fib_path_t paths[n_paths]; +}; + + /* * Local Variables: * eval: (c-set-style "gnu") diff --git a/src/plugins/ip_session_redirect/ip_session_redirect.h b/src/plugins/ip_session_redirect/ip_session_redirect.h index 45f64eebba1..800527618f4 100644 --- a/src/plugins/ip_session_redirect/ip_session_redirect.h +++ b/src/plugins/ip_session_redirect/ip_session_redirect.h @@ -16,6 +16,30 @@ #include +typedef struct +{ + u8 *match_and_table_index; + dpo_id_t dpo; /* forwarding dpo */ + fib_node_t node; /* linkage into the FIB graph */ + fib_node_index_t pl; + u32 sibling; + u32 parent_node_index; + u32 opaque_index; + u32 table_index; + fib_forward_chain_type_t payload_type; + u8 is_punt : 1; + u8 is_ip6 : 1; +} ip_session_redirect_t; + +typedef struct +{ + ip_session_redirect_t *pool; + u32 *session_by_match_and_table_index; + fib_node_type_t fib_node_type; +} ip_session_redirect_main_t; + +extern ip_session_redirect_main_t ip_session_redirect_main; + int ip_session_redirect_add (vlib_main_t *vm, u32 table_index, u32 opaque_index, dpo_proto_t proto, int is_punt, const u8 *match, const fib_route_path_t *rpaths); diff --git a/src/plugins/ip_session_redirect/redirect.c b/src/plugins/ip_session_redirect/redirect.c index ea18182e309..b8442ef8c67 100644 --- a/src/plugins/ip_session_redirect/redirect.c +++ b/src/plugins/ip_session_redirect/redirect.c @@ -18,29 +18,7 @@ #include #include "ip_session_redirect.h" -typedef struct -{ - u8 *match_and_table_index; - dpo_id_t dpo; /* forwarding dpo */ - fib_node_t node; /* linkage into the FIB graph */ - fib_node_index_t pl; - u32 sibling; - u32 parent_node_index; - u32 opaque_index; - u32 table_index; - fib_forward_chain_type_t payload_type; - u8 is_punt : 1; - u8 is_ip6 : 1; -} ip_session_redirect_t; - -typedef struct -{ - ip_session_redirect_t *pool; - u32 *session_by_match_and_table_index; - fib_node_type_t fib_node_type; -} ip_session_redirect_main_t; - -static ip_session_redirect_main_t ip_session_redirect_main; +ip_session_redirect_main_t ip_session_redirect_main; static int ip_session_redirect_stack (ip_session_redirect_t *ipr) diff --git a/src/plugins/ip_session_redirect/test_api.c b/src/plugins/ip_session_redirect/test_api.c index e4026a673ff..850a61d5f32 100644 --- a/src/plugins/ip_session_redirect/test_api.c +++ b/src/plugins/ip_session_redirect/test_api.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -184,6 +185,79 @@ api_ip_session_redirect_del (vat_main_t *vam) return ret; } +static int +api_ip_session_redirect_dump (vat_main_t *vam) +{ + unformat_input_t *i = vam->input; + vl_api_ip_session_redirect_dump_t *mp; + u32 table_index = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "table %d", &table_index)) + ; + else + break; + } + + /* Construct the API message */ + M (IP_SESSION_REDIRECT_DUMP, mp); + mp->table_index = htonl (table_index); + + S (mp) + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static void +vl_api_ip_session_redirect_details_t_handler ( + vl_api_ip_session_redirect_details_t *mp) +{ + vat_main_t *vam = ip_session_redirect_test_main.vat_main; + int rv; + u32 table_index; + u32 opaque_index; + u32 match_len; + u8 match[80]; + u8 n_paths; + fib_route_path_t *paths_ = 0; + u8 *out = 0; + + table_index = ntohl (mp->table_index); + opaque_index = ntohl (mp->opaque_index); + match_len = ntohl (mp->match_length); + const char *type = mp->is_punt ? "[punt]" : "[acl]"; + const char *ip = mp->is_ip6 ? "[ip6]" : "[ip4]"; + clib_memcpy (match, mp->match, match_len); + n_paths = mp->n_paths; + + for (int i = 0; i < n_paths; i++) + { + fib_route_path_t path; + if ((rv = fib_api_path_decode (&mp->paths[i], &path))) + goto err; + vec_add1 (paths_, path); + } + + out = + format (out, "table %d match %U %s %s opaque_index 0x%x\n", table_index, + format_hex_bytes, match, match_len, type, ip, opaque_index); + out = format (out, " via:\n"); + for (int i = 0; i < n_paths; i++) + { + fib_route_path_t *path = &paths_[i]; + out = format (out, " %U", format_fib_route_path, path); + } + + fformat (vam->ofp, (char *) out); +err: + vec_free (out); +} + #include "ip_session_redirect.api_test.c" /* diff --git a/test/test_ip_session_redirect.py b/test/test_ip_session_redirect.py index 3fed62bfade..5e1bee9058f 100644 --- a/test/test_ip_session_redirect.py +++ b/test/test_ip_session_redirect.py @@ -2,6 +2,7 @@ import unittest +import ipaddress import socket from scapy.packet import Raw @@ -83,6 +84,33 @@ class TestIpSessionRedirect(VppTestCase): ) return r.new_table_index + def verify_session_dump_entry( + self, + sess, + table_index, + is_punt, + is_ip6, + match_len, + match, + n_paths, + sess_path_ip, + ): + self.assertEqual(sess.table_index, table_index) + self.assertEqual(sess.is_punt, is_punt) + self.assertEqual(sess.is_ip6, is_ip6) + self.assertEqual(sess.match_length, match_len) + self.assertEqual(sess.match[:match_len], match) + self.assertEqual(sess.n_paths, n_paths) + for i, ip in enumerate(sess_path_ip): + if is_ip6: + self.assertEqual( + sess.paths[i].nh.address.ip6, ipaddress.IPv6Address(ip) + ) + else: + self.assertEqual( + sess.paths[i].nh.address.ip4, ipaddress.IPv4Address(ip) + ) + def __test_redirect(self, sport, dport, is_punt, is_ip6): if is_ip6: af = VppEnum.vl_api_address_family_t.ADDRESS_IP6 @@ -194,6 +222,47 @@ class TestIpSessionRedirect(VppTestCase): t = self.vapi.classify_table_info(table_id=table_index) self.assertEqual(t.active_sessions, 2) + # update matching entry so that it is multi-path + paths = [ + VppRoutePath(nh1, 0xFFFFFFFF).encode(), + VppRoutePath(nh2, 0xFFFFFFFF).encode(), + ] + self.vapi.ip_session_redirect_add_v2( + table_index=table_index, + match_len=len(match2), + match=match2, + is_punt=is_punt, + n_paths=2, + paths=paths, + proto=proto, + ) + + # verify that session dump has 2 entries + sessions_dump = self.vapi.ip_session_redirect_dump(table_index=table_index) + self.assertEqual(len(sessions_dump), 2) + + # verify session dump entries + self.verify_session_dump_entry( + sessions_dump[0], + table_index, + is_punt, + is_ip6, + len(match1), + match1, + 1, + [nh1], + ) + self.verify_session_dump_entry( + sessions_dump[1], + table_index, + is_punt, + is_ip6, + len(match2), + match2, + 2, + [nh1, nh2], + ) + # cleanup self.vapi.ip_session_redirect_del(table_index, len(match2), match2) self.vapi.ip_session_redirect_del(table_index, len(match1), match1) -- 2.16.6