| /* |
| * 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: |
| */ |