summaryrefslogtreecommitdiffstats
path: root/src/vnet/session/session_sdl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/session/session_sdl.c')
-rw-r--r--src/vnet/session/session_sdl.c768
1 files changed, 768 insertions, 0 deletions
diff --git a/src/vnet/session/session_sdl.c b/src/vnet/session/session_sdl.c
new file mode 100644
index 00000000000..45ab705fb62
--- /dev/null
+++ b/src/vnet/session/session_sdl.c
@@ -0,0 +1,768 @@
+/*
+ * Copyright (c) 2024 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vnet/session/session.h>
+#include <vnet/ip/ip4_forward.h>
+#include <vnet/ip/ip6_forward.h>
+#include <vnet/session/session_rules_table.h>
+#include <vnet/session/session_sdl.h>
+
+VLIB_REGISTER_LOG_CLASS (session_sdl_log, static) = { .class_name = "session",
+ .subclass_name = "sdl" };
+
+#define log_debug(fmt, ...) \
+ vlib_log_debug (session_sdl_log.class, "%s: " fmt, __func__, __VA_ARGS__)
+#define log_warn(fmt, ...) \
+ vlib_log_warn (session_sdl_log.class, fmt, __VA_ARGS__)
+#define log_err(fmt, ...) \
+ vlib_log_err (session_sdl_log.class, fmt, __VA_ARGS__)
+
+static fib_source_t sdl_fib_src;
+static dpo_type_t sdl_dpo_type;
+
+const static char *const *const session_sdl_dpo_nodes[DPO_PROTO_NUM] = {
+ [DPO_PROTO_IP4] = (const char *const[]){ "ip4-drop", 0 },
+ [DPO_PROTO_IP6] = (const char *const[]){ "ip6-drop", 0 },
+};
+
+static fib_route_path_t *
+session_sdl_fib_create_route_paths (u32 fib_index, dpo_proto_t dpo_proto)
+{
+ fib_route_path_t *paths = 0;
+ fib_route_path_t path = {
+ .frp_proto = dpo_proto,
+ .frp_flags = FIB_ROUTE_PATH_EXCLUSIVE,
+ .frp_fib_index = fib_index,
+ .frp_sw_if_index = ~0,
+ .frp_weight = 1,
+ };
+ vec_add1 (paths, path);
+ return paths;
+}
+
+static void
+session_sdl_dpo_lock (dpo_id_t *dpo)
+{
+}
+
+static void
+session_sdl_dpo_unlock (dpo_id_t *dpo)
+{
+}
+
+static u8 *
+format_session_sdl_dpo (u8 *s, va_list *va)
+{
+ index_t index = va_arg (*va, index_t);
+
+ return format (s, "sdl: [index: %u, deny]", index);
+}
+
+static const dpo_vft_t session_sdl_dpo_vft = {
+ .dv_lock = session_sdl_dpo_lock,
+ .dv_unlock = session_sdl_dpo_unlock,
+ .dv_format = format_session_sdl_dpo,
+};
+
+static u32
+session_sdl_lookup6 (u32 srtg_handle, u32 proto, ip6_address_t *lcl_ip,
+ ip6_address_t *rmt_ip, u16 lcl_port, u16 rmt_port)
+{
+ session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
+ session_sdl_block_t *sdlb = &srt->sdl_block;
+ index_t lbi;
+ const dpo_id_t *dpo;
+
+ if (sdlb->ip6_fib_index == ~0)
+ return SESSION_TABLE_INVALID_INDEX;
+ lbi = ip6_fib_table_fwding_lookup (sdlb->ip6_fib_index, lcl_ip);
+ dpo = load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
+ if (dpo->dpoi_type != sdl_dpo_type)
+ return SESSION_TABLE_INVALID_INDEX;
+ return (dpo->dpoi_index);
+}
+
+static u32
+session_sdl_lookup4 (u32 srtg_handle, u32 proto, ip4_address_t *lcl_ip,
+ ip4_address_t *rmt_ip, u16 lcl_port, u16 rmt_port)
+{
+ session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
+ session_sdl_block_t *sdlb = &srt->sdl_block;
+ index_t lbi;
+ const dpo_id_t *dpo;
+
+ if (sdlb->ip_fib_index == ~0)
+ return SESSION_TABLE_INVALID_INDEX;
+ lbi = ip4_fib_forwarding_lookup (sdlb->ip_fib_index, lcl_ip);
+ dpo = load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
+ if (dpo->dpoi_type != sdl_dpo_type)
+ return SESSION_TABLE_INVALID_INDEX;
+ return (dpo->dpoi_index);
+}
+
+typedef struct session_sdl4_fib_show_walk_ctx_t_
+{
+ fib_node_index_t *ifsw_indicies;
+} session_sdl4_fib_show_walk_ctx_t;
+
+static fib_table_walk_rc_t
+session_sdl4_fib_show_walk_cb (fib_node_index_t fei, void *arg)
+{
+ session_sdl4_fib_show_walk_ctx_t *ctx = arg;
+
+ vec_add1 (ctx->ifsw_indicies, fei);
+
+ return (FIB_TABLE_WALK_CONTINUE);
+}
+
+typedef struct session_sdl6_fib_show_ctx_t_
+{
+ fib_node_index_t *entries;
+} session_sdl6_fib_show_ctx_t;
+
+static fib_table_walk_rc_t
+session_sdl6_fib_table_show_walk (fib_node_index_t fei, void *arg)
+{
+ session_sdl6_fib_show_ctx_t *ctx = arg;
+
+ vec_add1 (ctx->entries, fei);
+
+ return (FIB_TABLE_WALK_CONTINUE);
+}
+
+static void
+session_sdl_fib_table_show (u32 fei, ip46_address_t *lcl_ip, u16 fp_len,
+ u32 action_index, u32 fp_proto, u8 *tag,
+ void *args)
+{
+ vlib_main_t *vm = args;
+ u32 type = (fp_proto == FIB_PROTOCOL_IP4) ? IP46_TYPE_IP4 : IP46_TYPE_IP6;
+
+ vlib_cli_output (vm, "[%d] rule: %U/%d action: %d tag %U", fei,
+ format_ip46_address, lcl_ip, type, fp_len, action_index,
+ format_session_rule_tag, tag);
+}
+
+static void
+session_sdl_cli_dump (vlib_main_t *vm, u32 srtg_handle, u32 proto,
+ u8 fib_proto)
+{
+ session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
+ session_sdl_block_t *sdlb = &srt->sdl_block;
+
+ if (fib_proto == FIB_PROTOCOL_IP4)
+ {
+ vlib_cli_output (vm, "IP4 rules, fib index %d", sdlb->ip_fib_index);
+ session_sdl_table_walk4 (srtg_handle, session_sdl_fib_table_show, vm);
+ }
+ else if (fib_proto == FIB_PROTOCOL_IP6)
+ {
+ vlib_cli_output (vm, "IP6 rules, fib index %d", sdlb->ip6_fib_index);
+ session_sdl_table_walk6 (srtg_handle, session_sdl_fib_table_show, vm);
+ }
+}
+
+static void
+session_sdl4_fib_table_show_one (session_rules_table_t *srt, u32 fib_index,
+ vlib_main_t *vm, ip4_address_t *address,
+ u32 mask_len)
+{
+ ip4_fib_t *fib;
+ fib_node_index_t fei;
+
+ fib = ip4_fib_get (fib_index);
+ fei = ip4_fib_table_lookup (fib, address, mask_len);
+ if (fei != FIB_NODE_INDEX_INVALID && fib_entry_is_sourced (fei, sdl_fib_src))
+ {
+ u8 *tag = session_rules_table_rule_tag (srt, fei, 1);
+ fib_entry_t *fib_entry = fib_entry_get (fei);
+ fib_prefix_t pfx = fib_entry->fe_prefix;
+ index_t lbi = ip4_fib_forwarding_lookup (fib_index, &pfx.fp_addr.ip4);
+ const dpo_id_t *dpo =
+ load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
+
+ session_sdl_fib_table_show (fei, &pfx.fp_addr, pfx.fp_len,
+ dpo->dpoi_index, FIB_PROTOCOL_IP4, tag, vm);
+ }
+}
+
+static void
+session_sdl6_fib_table_show_one (session_rules_table_t *srt, u32 fib_index,
+ vlib_main_t *vm, ip6_address_t *address,
+ u32 mask_len)
+{
+ fib_node_index_t fei;
+
+ fei = ip6_fib_table_lookup (fib_index, address, mask_len);
+ if (fei != FIB_NODE_INDEX_INVALID && fib_entry_is_sourced (fei, sdl_fib_src))
+ {
+ u8 *tag = session_rules_table_rule_tag (srt, fei, 0);
+ fib_entry_t *fib_entry = fib_entry_get (fei);
+ fib_prefix_t pfx = fib_entry->fe_prefix;
+ index_t lbi = ip6_fib_table_fwding_lookup (fib_index, &pfx.fp_addr.ip6);
+ const dpo_id_t *dpo =
+ load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
+
+ session_sdl_fib_table_show (fei, &pfx.fp_addr, pfx.fp_len,
+ dpo->dpoi_index, FIB_PROTOCOL_IP6, tag, vm);
+ }
+}
+
+static void
+session_sdl_show_rule (vlib_main_t *vm, u32 srtg_handle, u32 proto,
+ ip46_address_t *lcl_ip, u16 lcl_port,
+ ip46_address_t *rmt_ip, u16 rmt_port, u8 is_ip4)
+{
+ session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
+ session_sdl_block_t *sdlb;
+
+ sdlb = &srt->sdl_block;
+ if (is_ip4)
+ session_sdl4_fib_table_show_one (srt, sdlb->ip_fib_index, vm, &lcl_ip->ip4,
+ 32);
+ else
+ session_sdl6_fib_table_show_one (srt, sdlb->ip6_fib_index, vm,
+ &lcl_ip->ip6, 128);
+}
+
+static void
+session_sdl_table_init (session_table_t *st, u8 fib_proto)
+{
+ session_rules_table_t *srt;
+ session_sdl_block_t *sdlb;
+ u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0;
+ char name[80];
+ app_namespace_t *app_ns = app_namespace_get (st->appns_index);
+ session_rules_table_group_t *srtg;
+
+ /* Don't support local table */
+ if (st->is_local == 1)
+ return;
+
+ srtg = srtg_instance_alloc (st, 0);
+ srt = srtg->session_rules;
+ sdlb = &srt->sdl_block;
+
+ if (fib_proto == FIB_PROTOCOL_IP4 || all)
+ {
+ snprintf (name, sizeof (name), "sdl4 %s", app_ns->ns_id);
+ sdlb->ip_table_id = ip_table_get_unused_id (FIB_PROTOCOL_IP4);
+ sdlb->ip_fib_index = fib_table_find_or_create_and_lock_w_name (
+ FIB_PROTOCOL_IP4, sdlb->ip_table_id, sdl_fib_src, (const u8 *) name);
+ }
+
+ if (fib_proto == FIB_PROTOCOL_IP6 || all)
+ {
+ snprintf (name, sizeof (name), "sdl6 %s", app_ns->ns_id);
+ sdlb->ip6_table_id = ip_table_get_unused_id (FIB_PROTOCOL_IP6);
+ sdlb->ip6_fib_index = fib_table_find_or_create_and_lock_w_name (
+ FIB_PROTOCOL_IP6, sdlb->ip6_table_id, sdl_fib_src, (const u8 *) name);
+ }
+
+ srt->rules_by_tag = hash_create_vec (0, sizeof (u8), sizeof (uword));
+ srt->tags_by_rules = hash_create (0, sizeof (uword));
+}
+
+static void
+session_sdl_table_free (session_table_t *st, u8 fib_proto)
+{
+ session_rules_table_t *srt = srtg_handle_to_srt (st->srtg_handle, 0);
+ session_sdl_block_t *sdlb;
+ u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0;
+
+ ASSERT (st->is_local == 0);
+ sdlb = &srt->sdl_block;
+ if ((fib_proto == FIB_PROTOCOL_IP4 || all) && (sdlb->ip_fib_index != ~0))
+ {
+ fib_table_flush (sdlb->ip_fib_index, FIB_PROTOCOL_IP4, sdl_fib_src);
+ fib_table_unlock (sdlb->ip_fib_index, FIB_PROTOCOL_IP4, sdl_fib_src);
+ }
+ if ((fib_proto == FIB_PROTOCOL_IP6 || all) && (sdlb->ip6_fib_index != ~0))
+ {
+ fib_table_flush (sdlb->ip6_fib_index, FIB_PROTOCOL_IP6, sdl_fib_src);
+ fib_table_unlock (sdlb->ip6_fib_index, FIB_PROTOCOL_IP6, sdl_fib_src);
+ }
+
+ hash_free (srt->tags_by_rules);
+ hash_free (srt->rules_by_tag);
+
+ srtg_instance_free (st);
+}
+
+static session_error_t
+session_sdl_add_del (u32 srtg_handle, u32 proto,
+ session_rule_table_add_del_args_t *args)
+{
+ session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
+ session_sdl_block_t *sdlb = &srt->sdl_block;
+ u32 fib_index;
+ dpo_proto_t dpo_proto;
+ fib_route_path_t *paths = 0;
+ fib_prefix_t pfx = args->lcl;
+ session_error_t err = SESSION_E_NONE;
+ fib_node_index_t fei;
+ int is_ip4;
+
+ if (!(args->lcl_port == 0 && args->rmt_port == 0 &&
+ args->rmt.fp_addr.ip4.as_u32 == 0))
+ return SESSION_E_NOSUPPORT;
+
+ fei = session_rules_table_rule_for_tag (srt, args->tag);
+ if (args->is_add && fei != SESSION_RULES_TABLE_INVALID_INDEX)
+ return SESSION_E_INVALID;
+
+ if (args->lcl.fp_proto == FIB_PROTOCOL_IP4)
+ {
+ fib_index = sdlb->ip_fib_index;
+ dpo_proto = DPO_PROTO_IP4;
+ is_ip4 = 1;
+ }
+ else
+ {
+ fib_index = sdlb->ip6_fib_index;
+ dpo_proto = DPO_PROTO_IP6;
+ is_ip4 = 0;
+ }
+
+ paths = session_sdl_fib_create_route_paths (fib_index, dpo_proto);
+ if (args->is_add)
+ {
+ fei = fib_table_lookup_exact_match (fib_index, &pfx);
+ if (fei != FIB_NODE_INDEX_INVALID)
+ {
+ err = SESSION_E_IPINUSE;
+ goto done;
+ }
+ dpo_set (&paths->dpo, sdl_dpo_type, dpo_proto, args->action_index);
+ fei = fib_table_entry_path_add2 (fib_index, &pfx, sdl_fib_src,
+ FIB_ENTRY_FLAG_EXCLUSIVE, paths);
+ session_rules_table_add_tag (srt, args->tag, fei, is_ip4);
+ dpo_reset (&paths->dpo);
+ }
+ else
+ {
+ if (fei == SESSION_RULES_TABLE_INVALID_INDEX)
+ {
+ fei = fib_table_lookup_exact_match (fib_index, &pfx);
+
+ if (fei == FIB_NODE_INDEX_INVALID)
+ {
+ err = SESSION_E_NOROUTE;
+ goto done;
+ }
+ }
+
+ if (!fib_entry_is_sourced (fei, sdl_fib_src))
+ {
+ err = SESSION_E_NOROUTE;
+ goto done;
+ }
+
+ fib_entry_t *fib_entry = fib_entry_get (fei);
+ pfx = fib_entry->fe_prefix;
+ fib_table_entry_special_remove (fib_index, &pfx, sdl_fib_src);
+ session_rules_table_del_tag (srt, args->tag, is_ip4);
+ }
+done:
+ vec_free (paths);
+
+ return err;
+}
+
+static const session_rt_engine_vft_t session_sdl_vft = {
+ .backend_engine = RT_BACKEND_ENGINE_SDL,
+ .table_lookup4 = session_sdl_lookup4,
+ .table_lookup6 = session_sdl_lookup6,
+ .table_cli_dump = session_sdl_cli_dump,
+ .table_show_rule = session_sdl_show_rule,
+ .table_add_del = session_sdl_add_del,
+ .table_init = session_sdl_table_init,
+ .table_free = session_sdl_table_free,
+};
+
+static void
+session_sdl_fib_init (void)
+{
+ static u32 session_fib_inited = 0;
+
+ if (session_fib_inited)
+ return;
+ session_fib_inited = 1;
+ sdl_fib_src = fib_source_allocate ("session sdl", FIB_SOURCE_PRIORITY_LOW,
+ FIB_SOURCE_BH_SIMPLE);
+ sdl_dpo_type =
+ dpo_register_new_type (&session_sdl_dpo_vft, session_sdl_dpo_nodes);
+}
+
+static void
+session_sdl_app_namespace_walk_cb (app_namespace_t *app_ns, void *ctx)
+{
+ u32 fib_index, table_index;
+ session_table_t *st;
+
+ log_debug ("disable app_ns %s", app_ns->ns_id);
+
+ fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP4);
+ table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP4, fib_index);
+ st = session_table_get (table_index);
+ if (st)
+ session_rules_table_free (st, FIB_PROTOCOL_IP4);
+
+ fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP6);
+ table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP6, fib_index);
+ st = session_table_get (table_index);
+ if (st)
+ session_rules_table_free (st, FIB_PROTOCOL_IP6);
+}
+
+clib_error_t *
+session_sdl_enable_disable (int enable)
+{
+ clib_error_t *error = 0;
+
+ if (enable)
+ {
+ error = session_rule_table_register_engine (&session_sdl_vft);
+ if (error)
+ {
+ log_err ("error in enabling sdl: %U", format_clib_error, error);
+ return error;
+ }
+ session_sdl_fib_init ();
+ }
+ else
+ {
+ app_namespace_walk (session_sdl_app_namespace_walk_cb, 0);
+
+ error = session_rule_table_deregister_engine (&session_sdl_vft);
+ if (error)
+ log_err ("error in disabling sdl: %U", format_clib_error, error);
+ }
+
+ return error;
+}
+
+/*
+ * Source Deny List
+ */
+static clib_error_t *
+session_sdl_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
+{
+ u32 appns_index;
+ app_namespace_t *app_ns;
+ u32 lcl_plen = 0, action = 0;
+ clib_error_t *error = 0;
+ ip46_address_t lcl_ip;
+ u8 conn_set = 0;
+ u8 fib_proto = -1, is_add = 1, *ns_id = 0;
+ u8 *tag = 0, tag_only = 0;
+ int rv;
+ session_rule_add_del_args_t args;
+
+ session_cli_return_if_not_enabled ();
+
+ if (session_sdl_is_enabled () == 0)
+ return clib_error_return (0, "session sdl engine is not enabled");
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "del"))
+ is_add = 0;
+ else if (unformat (input, "add"))
+ ;
+ else if (unformat (input, "appns %_%v%_", &ns_id))
+ ;
+ else if (unformat (input, "%U/%d", unformat_ip4_address, &lcl_ip.ip4,
+ &lcl_plen))
+ {
+ fib_proto = FIB_PROTOCOL_IP4;
+ conn_set = 1;
+ }
+ else if (unformat (input, "%U/%d", unformat_ip6_address, &lcl_ip.ip6,
+ &lcl_plen))
+ {
+ fib_proto = FIB_PROTOCOL_IP6;
+ conn_set = 1;
+ }
+ else if (unformat (input, "action %d", &action))
+ ;
+ else if (unformat (input, "tag %_%v%_", &tag))
+ ;
+ else
+ {
+ error = clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+ }
+
+ if (ns_id)
+ {
+ app_ns = app_namespace_get_from_id (ns_id);
+ if (!app_ns)
+ {
+ vlib_cli_output (vm, "namespace %v does not exist", ns_id);
+ goto done;
+ }
+ }
+ else
+ {
+ app_ns = app_namespace_get_default ();
+ }
+ appns_index = app_namespace_index (app_ns);
+
+ if (is_add && !conn_set && action == 0)
+ {
+ vlib_cli_output (vm, "connection and action must be set for add");
+ goto done;
+ }
+ if (!is_add && !tag && !conn_set)
+ {
+ vlib_cli_output (vm, "connection or tag must be set for delete");
+ goto done;
+ }
+ if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN)
+ {
+ vlib_cli_output (vm, "tag too long (max u64)");
+ goto done;
+ }
+
+ /* Delete with only tag entered. Try v4 first and then v6 if failed */
+ if ((is_add == 0) && (fib_proto == (u8) ~0))
+ {
+ fib_proto = FIB_PROTOCOL_IP4;
+ tag_only = 1;
+ }
+
+ memset (&args, 0, sizeof (args));
+ args.transport_proto = TRANSPORT_PROTO_TCP;
+ args.table_args.lcl.fp_addr = lcl_ip;
+ args.table_args.lcl.fp_len = lcl_plen;
+ args.table_args.lcl.fp_proto = fib_proto;
+ args.table_args.rmt.fp_proto = fib_proto;
+ args.table_args.action_index = action;
+ args.table_args.is_add = is_add;
+ args.table_args.tag = tag;
+ args.appns_index = appns_index;
+ args.scope = SESSION_RULE_SCOPE_GLOBAL;
+
+ if ((rv = vnet_session_rule_add_del (&args)))
+ {
+ /* Try tag only delete on v6 */
+ if (rv && tag_only)
+ {
+ args.table_args.rmt.fp_proto = FIB_PROTOCOL_IP6;
+ args.table_args.lcl.fp_proto = FIB_PROTOCOL_IP6;
+ if ((rv = vnet_session_rule_add_del (&args)))
+ {
+ error = clib_error_return (0, "sdl add del returned %u", rv);
+ }
+ }
+ else
+ {
+ error = clib_error_return (0, "sdl add del returned %u", rv);
+ }
+ }
+
+done:
+ vec_free (ns_id);
+ vec_free (tag);
+ return error;
+}
+
+VLIB_CLI_COMMAND (session_sdl_command, static) = {
+ .path = "session sdl",
+ .short_help = "session sdl [add|del] [appns <ns_id>] <lcl-ip/plen> action "
+ "<action> [tag <tag>]",
+ .function = session_sdl_command_fn,
+ .is_mp_safe = 1,
+};
+
+static clib_error_t *
+show_session_sdl_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
+{
+ u32 fib_index;
+ ip46_address_t lcl_ip;
+ u8 show_one = 0;
+ app_namespace_t *app_ns;
+ session_table_t *st;
+ u8 *ns_id = 0, fib_proto = FIB_PROTOCOL_IP4;
+
+ session_cli_return_if_not_enabled ();
+
+ clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "appns %_%s%_", &ns_id))
+ ;
+ else if (unformat (input, "%U", unformat_ip4_address, &lcl_ip.ip4))
+ {
+ fib_proto = FIB_PROTOCOL_IP4;
+ show_one = 1;
+ }
+ else if (unformat (input, "%U", unformat_ip6_address, &lcl_ip.ip6))
+ {
+ fib_proto = FIB_PROTOCOL_IP6;
+ show_one = 1;
+ }
+ else
+ {
+ vec_free (ns_id);
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+ }
+
+ if (ns_id)
+ {
+ app_ns = app_namespace_get_from_id (ns_id);
+ if (!app_ns)
+ {
+ vlib_cli_output (vm, "appns %v doesn't exist", ns_id);
+ goto done;
+ }
+ }
+ else
+ {
+ app_ns = app_namespace_get_default ();
+ }
+
+ if (session_sdl_is_enabled () == 0)
+ {
+ vlib_cli_output (vm, "session sdl engine is not enabled");
+ goto done;
+ }
+
+ if (show_one)
+ {
+ fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
+ st = session_table_get_for_fib_index (fib_proto, fib_index);
+ if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID))
+ session_rules_table_show_rule (vm, st->srtg_handle, 0, &lcl_ip, 0, 0,
+ 0, (fib_proto == FIB_PROTOCOL_IP4));
+ goto done;
+ }
+
+ /* 2 separate session tables for global entries, 1 for ip4 and 1 for ip6 */
+ fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP4);
+ st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
+ if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID))
+ session_rules_table_cli_dump (vm, st->srtg_handle, 0, FIB_PROTOCOL_IP4);
+
+ fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP6);
+ st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
+ if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID))
+ session_rules_table_cli_dump (vm, st->srtg_handle, 0, FIB_PROTOCOL_IP6);
+done:
+ vec_free (ns_id);
+ return 0;
+}
+
+void
+session_sdl_table_walk4 (u32 srtg_handle, session_sdl_table_walk_fn_t fn,
+ void *args)
+{
+ ip4_fib_t *fib;
+ session_sdl4_fib_show_walk_ctx_t ctx = {
+ .ifsw_indicies = NULL,
+ };
+ fib_node_index_t *fei;
+ session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
+ session_sdl_block_t *sdlb = &srt->sdl_block;
+ u32 fib_index = sdlb->ip_fib_index;
+
+ if (fib_index == ~0)
+ return;
+ fib = ip4_fib_get (fib_index);
+ ip4_fib_table_walk (fib, session_sdl4_fib_show_walk_cb, &ctx);
+ vec_sort_with_function (ctx.ifsw_indicies, fib_entry_cmp_for_sort);
+
+ vec_foreach (fei, ctx.ifsw_indicies)
+ {
+ if (*fei != FIB_NODE_INDEX_INVALID &&
+ fib_entry_is_sourced (*fei, sdl_fib_src))
+ {
+ u8 *tag = session_rules_table_rule_tag (srt, *fei, 1);
+ fib_entry_t *fib_entry = fib_entry_get (*fei);
+ fib_prefix_t pfx = fib_entry->fe_prefix;
+ index_t lbi =
+ ip4_fib_forwarding_lookup (fib_index, &pfx.fp_addr.ip4);
+ const dpo_id_t *dpo =
+ load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
+
+ fn (*fei, &pfx.fp_addr, pfx.fp_len, dpo->dpoi_index,
+ FIB_PROTOCOL_IP4, tag, args);
+ }
+ }
+
+ vec_free (ctx.ifsw_indicies);
+}
+
+void
+session_sdl_table_walk6 (u32 srtg_handle, session_sdl_table_walk_fn_t fn,
+ void *args)
+{
+ ip6_fib_t *fib;
+ fib_node_index_t *fei;
+ session_sdl6_fib_show_ctx_t ctx = {
+ .entries = NULL,
+ };
+ session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
+ session_sdl_block_t *sdlb = &srt->sdl_block;
+ u32 fib_index = sdlb->ip6_fib_index;
+
+ if (fib_index == ~0)
+ return;
+ fib = ip6_fib_get (fib_index);
+ ip6_fib_table_walk (fib->index, session_sdl6_fib_table_show_walk, &ctx);
+ vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort);
+
+ vec_foreach (fei, ctx.entries)
+ {
+ if (*fei != FIB_NODE_INDEX_INVALID &&
+ fib_entry_is_sourced (*fei, sdl_fib_src))
+ {
+ u8 *tag = session_rules_table_rule_tag (srt, *fei, 0);
+ fib_entry_t *fib_entry = fib_entry_get (*fei);
+ fib_prefix_t pfx = fib_entry->fe_prefix;
+ index_t lbi =
+ ip6_fib_table_fwding_lookup (fib_index, &pfx.fp_addr.ip6);
+ const dpo_id_t *dpo =
+ load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
+
+ fn (*fei, &pfx.fp_addr, pfx.fp_len, dpo->dpoi_index,
+ FIB_PROTOCOL_IP6, tag, args);
+ }
+ }
+
+ vec_free (ctx.entries);
+}
+
+VLIB_CLI_COMMAND (show_session_sdl_command, static) = {
+ .path = "show session sdl",
+ .short_help = "show session sdl [appns <id> <lcl-ip>]",
+ .function = show_session_sdl_command_fn,
+ .is_mp_safe = 1,
+};
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */