diff options
author | Steven Luong <sluong@cisco.com> | 2024-07-30 13:44:01 -0700 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2024-09-06 18:26:56 +0000 |
commit | c4b5d10115d4370488ac14eb0ba7295b049a0615 (patch) | |
tree | 9c8bdf757de6d995e051959d1c11bded0b9267a6 /src/vnet/session/session_sdl.c | |
parent | 2a5bb3b5ab3e05cee0da6a78b77e67fbc3bdca75 (diff) |
session: add Source Deny List
With this feature, session enable is now modified to have 3 modes of operation
session enable -- only enable session
session enable rt-backend sdl -- enable session with sdl
session enable rt-backend rule-table -- enable session with rule-table
session rule tables are now created on demand, upon adding first rule
to the rule table.
refactor session table to remove depenency from sesssion rules table. Now
session rules table APIs take srtg_handle and transport
proto instead of srt pointer.
Type: feature
Change-Id: Idde6a9b2f46b29bb931f9039636562575572aa14
Signed-off-by: Steven Luong <sluong@cisco.com>
Diffstat (limited to 'src/vnet/session/session_sdl.c')
-rw-r--r-- | src/vnet/session/session_sdl.c | 768 |
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: + */ |