blob: 45ab705fb62b01cf4373fd2106b19b5d07eaccbb [file] [log] [blame]
Steven Luongc4b5d102024-07-30 13:44:01 -07001/*
2 * Copyright (c) 2024 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/session/session.h>
17#include <vnet/ip/ip4_forward.h>
18#include <vnet/ip/ip6_forward.h>
19#include <vnet/session/session_rules_table.h>
20#include <vnet/session/session_sdl.h>
21
22VLIB_REGISTER_LOG_CLASS (session_sdl_log, static) = { .class_name = "session",
23 .subclass_name = "sdl" };
24
25#define log_debug(fmt, ...) \
26 vlib_log_debug (session_sdl_log.class, "%s: " fmt, __func__, __VA_ARGS__)
27#define log_warn(fmt, ...) \
28 vlib_log_warn (session_sdl_log.class, fmt, __VA_ARGS__)
29#define log_err(fmt, ...) \
30 vlib_log_err (session_sdl_log.class, fmt, __VA_ARGS__)
31
32static fib_source_t sdl_fib_src;
33static dpo_type_t sdl_dpo_type;
34
35const static char *const *const session_sdl_dpo_nodes[DPO_PROTO_NUM] = {
36 [DPO_PROTO_IP4] = (const char *const[]){ "ip4-drop", 0 },
37 [DPO_PROTO_IP6] = (const char *const[]){ "ip6-drop", 0 },
38};
39
40static fib_route_path_t *
41session_sdl_fib_create_route_paths (u32 fib_index, dpo_proto_t dpo_proto)
42{
43 fib_route_path_t *paths = 0;
44 fib_route_path_t path = {
45 .frp_proto = dpo_proto,
46 .frp_flags = FIB_ROUTE_PATH_EXCLUSIVE,
47 .frp_fib_index = fib_index,
48 .frp_sw_if_index = ~0,
49 .frp_weight = 1,
50 };
51 vec_add1 (paths, path);
52 return paths;
53}
54
55static void
56session_sdl_dpo_lock (dpo_id_t *dpo)
57{
58}
59
60static void
61session_sdl_dpo_unlock (dpo_id_t *dpo)
62{
63}
64
65static u8 *
66format_session_sdl_dpo (u8 *s, va_list *va)
67{
68 index_t index = va_arg (*va, index_t);
69
70 return format (s, "sdl: [index: %u, deny]", index);
71}
72
73static const dpo_vft_t session_sdl_dpo_vft = {
74 .dv_lock = session_sdl_dpo_lock,
75 .dv_unlock = session_sdl_dpo_unlock,
76 .dv_format = format_session_sdl_dpo,
77};
78
79static u32
80session_sdl_lookup6 (u32 srtg_handle, u32 proto, ip6_address_t *lcl_ip,
81 ip6_address_t *rmt_ip, u16 lcl_port, u16 rmt_port)
82{
83 session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
84 session_sdl_block_t *sdlb = &srt->sdl_block;
85 index_t lbi;
86 const dpo_id_t *dpo;
87
88 if (sdlb->ip6_fib_index == ~0)
89 return SESSION_TABLE_INVALID_INDEX;
90 lbi = ip6_fib_table_fwding_lookup (sdlb->ip6_fib_index, lcl_ip);
91 dpo = load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
92 if (dpo->dpoi_type != sdl_dpo_type)
93 return SESSION_TABLE_INVALID_INDEX;
94 return (dpo->dpoi_index);
95}
96
97static u32
98session_sdl_lookup4 (u32 srtg_handle, u32 proto, ip4_address_t *lcl_ip,
99 ip4_address_t *rmt_ip, u16 lcl_port, u16 rmt_port)
100{
101 session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
102 session_sdl_block_t *sdlb = &srt->sdl_block;
103 index_t lbi;
104 const dpo_id_t *dpo;
105
106 if (sdlb->ip_fib_index == ~0)
107 return SESSION_TABLE_INVALID_INDEX;
108 lbi = ip4_fib_forwarding_lookup (sdlb->ip_fib_index, lcl_ip);
109 dpo = load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
110 if (dpo->dpoi_type != sdl_dpo_type)
111 return SESSION_TABLE_INVALID_INDEX;
112 return (dpo->dpoi_index);
113}
114
115typedef struct session_sdl4_fib_show_walk_ctx_t_
116{
117 fib_node_index_t *ifsw_indicies;
118} session_sdl4_fib_show_walk_ctx_t;
119
120static fib_table_walk_rc_t
121session_sdl4_fib_show_walk_cb (fib_node_index_t fei, void *arg)
122{
123 session_sdl4_fib_show_walk_ctx_t *ctx = arg;
124
125 vec_add1 (ctx->ifsw_indicies, fei);
126
127 return (FIB_TABLE_WALK_CONTINUE);
128}
129
130typedef struct session_sdl6_fib_show_ctx_t_
131{
132 fib_node_index_t *entries;
133} session_sdl6_fib_show_ctx_t;
134
135static fib_table_walk_rc_t
136session_sdl6_fib_table_show_walk (fib_node_index_t fei, void *arg)
137{
138 session_sdl6_fib_show_ctx_t *ctx = arg;
139
140 vec_add1 (ctx->entries, fei);
141
142 return (FIB_TABLE_WALK_CONTINUE);
143}
144
145static void
146session_sdl_fib_table_show (u32 fei, ip46_address_t *lcl_ip, u16 fp_len,
147 u32 action_index, u32 fp_proto, u8 *tag,
148 void *args)
149{
150 vlib_main_t *vm = args;
151 u32 type = (fp_proto == FIB_PROTOCOL_IP4) ? IP46_TYPE_IP4 : IP46_TYPE_IP6;
152
153 vlib_cli_output (vm, "[%d] rule: %U/%d action: %d tag %U", fei,
154 format_ip46_address, lcl_ip, type, fp_len, action_index,
155 format_session_rule_tag, tag);
156}
157
158static void
159session_sdl_cli_dump (vlib_main_t *vm, u32 srtg_handle, u32 proto,
160 u8 fib_proto)
161{
162 session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
163 session_sdl_block_t *sdlb = &srt->sdl_block;
164
165 if (fib_proto == FIB_PROTOCOL_IP4)
166 {
167 vlib_cli_output (vm, "IP4 rules, fib index %d", sdlb->ip_fib_index);
168 session_sdl_table_walk4 (srtg_handle, session_sdl_fib_table_show, vm);
169 }
170 else if (fib_proto == FIB_PROTOCOL_IP6)
171 {
172 vlib_cli_output (vm, "IP6 rules, fib index %d", sdlb->ip6_fib_index);
173 session_sdl_table_walk6 (srtg_handle, session_sdl_fib_table_show, vm);
174 }
175}
176
177static void
178session_sdl4_fib_table_show_one (session_rules_table_t *srt, u32 fib_index,
179 vlib_main_t *vm, ip4_address_t *address,
180 u32 mask_len)
181{
182 ip4_fib_t *fib;
183 fib_node_index_t fei;
184
185 fib = ip4_fib_get (fib_index);
186 fei = ip4_fib_table_lookup (fib, address, mask_len);
187 if (fei != FIB_NODE_INDEX_INVALID && fib_entry_is_sourced (fei, sdl_fib_src))
188 {
189 u8 *tag = session_rules_table_rule_tag (srt, fei, 1);
190 fib_entry_t *fib_entry = fib_entry_get (fei);
191 fib_prefix_t pfx = fib_entry->fe_prefix;
192 index_t lbi = ip4_fib_forwarding_lookup (fib_index, &pfx.fp_addr.ip4);
193 const dpo_id_t *dpo =
194 load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
195
196 session_sdl_fib_table_show (fei, &pfx.fp_addr, pfx.fp_len,
197 dpo->dpoi_index, FIB_PROTOCOL_IP4, tag, vm);
198 }
199}
200
201static void
202session_sdl6_fib_table_show_one (session_rules_table_t *srt, u32 fib_index,
203 vlib_main_t *vm, ip6_address_t *address,
204 u32 mask_len)
205{
206 fib_node_index_t fei;
207
208 fei = ip6_fib_table_lookup (fib_index, address, mask_len);
209 if (fei != FIB_NODE_INDEX_INVALID && fib_entry_is_sourced (fei, sdl_fib_src))
210 {
211 u8 *tag = session_rules_table_rule_tag (srt, fei, 0);
212 fib_entry_t *fib_entry = fib_entry_get (fei);
213 fib_prefix_t pfx = fib_entry->fe_prefix;
214 index_t lbi = ip6_fib_table_fwding_lookup (fib_index, &pfx.fp_addr.ip6);
215 const dpo_id_t *dpo =
216 load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
217
218 session_sdl_fib_table_show (fei, &pfx.fp_addr, pfx.fp_len,
219 dpo->dpoi_index, FIB_PROTOCOL_IP6, tag, vm);
220 }
221}
222
223static void
224session_sdl_show_rule (vlib_main_t *vm, u32 srtg_handle, u32 proto,
225 ip46_address_t *lcl_ip, u16 lcl_port,
226 ip46_address_t *rmt_ip, u16 rmt_port, u8 is_ip4)
227{
228 session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
229 session_sdl_block_t *sdlb;
230
231 sdlb = &srt->sdl_block;
232 if (is_ip4)
233 session_sdl4_fib_table_show_one (srt, sdlb->ip_fib_index, vm, &lcl_ip->ip4,
234 32);
235 else
236 session_sdl6_fib_table_show_one (srt, sdlb->ip6_fib_index, vm,
237 &lcl_ip->ip6, 128);
238}
239
240static void
241session_sdl_table_init (session_table_t *st, u8 fib_proto)
242{
243 session_rules_table_t *srt;
244 session_sdl_block_t *sdlb;
245 u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0;
246 char name[80];
247 app_namespace_t *app_ns = app_namespace_get (st->appns_index);
248 session_rules_table_group_t *srtg;
249
250 /* Don't support local table */
251 if (st->is_local == 1)
252 return;
253
254 srtg = srtg_instance_alloc (st, 0);
255 srt = srtg->session_rules;
256 sdlb = &srt->sdl_block;
257
258 if (fib_proto == FIB_PROTOCOL_IP4 || all)
259 {
260 snprintf (name, sizeof (name), "sdl4 %s", app_ns->ns_id);
261 sdlb->ip_table_id = ip_table_get_unused_id (FIB_PROTOCOL_IP4);
262 sdlb->ip_fib_index = fib_table_find_or_create_and_lock_w_name (
263 FIB_PROTOCOL_IP4, sdlb->ip_table_id, sdl_fib_src, (const u8 *) name);
264 }
265
266 if (fib_proto == FIB_PROTOCOL_IP6 || all)
267 {
268 snprintf (name, sizeof (name), "sdl6 %s", app_ns->ns_id);
269 sdlb->ip6_table_id = ip_table_get_unused_id (FIB_PROTOCOL_IP6);
270 sdlb->ip6_fib_index = fib_table_find_or_create_and_lock_w_name (
271 FIB_PROTOCOL_IP6, sdlb->ip6_table_id, sdl_fib_src, (const u8 *) name);
272 }
273
274 srt->rules_by_tag = hash_create_vec (0, sizeof (u8), sizeof (uword));
275 srt->tags_by_rules = hash_create (0, sizeof (uword));
276}
277
278static void
279session_sdl_table_free (session_table_t *st, u8 fib_proto)
280{
281 session_rules_table_t *srt = srtg_handle_to_srt (st->srtg_handle, 0);
282 session_sdl_block_t *sdlb;
283 u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0;
284
285 ASSERT (st->is_local == 0);
286 sdlb = &srt->sdl_block;
287 if ((fib_proto == FIB_PROTOCOL_IP4 || all) && (sdlb->ip_fib_index != ~0))
288 {
289 fib_table_flush (sdlb->ip_fib_index, FIB_PROTOCOL_IP4, sdl_fib_src);
290 fib_table_unlock (sdlb->ip_fib_index, FIB_PROTOCOL_IP4, sdl_fib_src);
291 }
292 if ((fib_proto == FIB_PROTOCOL_IP6 || all) && (sdlb->ip6_fib_index != ~0))
293 {
294 fib_table_flush (sdlb->ip6_fib_index, FIB_PROTOCOL_IP6, sdl_fib_src);
295 fib_table_unlock (sdlb->ip6_fib_index, FIB_PROTOCOL_IP6, sdl_fib_src);
296 }
297
298 hash_free (srt->tags_by_rules);
299 hash_free (srt->rules_by_tag);
300
301 srtg_instance_free (st);
302}
303
304static session_error_t
305session_sdl_add_del (u32 srtg_handle, u32 proto,
306 session_rule_table_add_del_args_t *args)
307{
308 session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
309 session_sdl_block_t *sdlb = &srt->sdl_block;
310 u32 fib_index;
311 dpo_proto_t dpo_proto;
312 fib_route_path_t *paths = 0;
313 fib_prefix_t pfx = args->lcl;
314 session_error_t err = SESSION_E_NONE;
315 fib_node_index_t fei;
316 int is_ip4;
317
318 if (!(args->lcl_port == 0 && args->rmt_port == 0 &&
319 args->rmt.fp_addr.ip4.as_u32 == 0))
320 return SESSION_E_NOSUPPORT;
321
322 fei = session_rules_table_rule_for_tag (srt, args->tag);
323 if (args->is_add && fei != SESSION_RULES_TABLE_INVALID_INDEX)
324 return SESSION_E_INVALID;
325
326 if (args->lcl.fp_proto == FIB_PROTOCOL_IP4)
327 {
328 fib_index = sdlb->ip_fib_index;
329 dpo_proto = DPO_PROTO_IP4;
330 is_ip4 = 1;
331 }
332 else
333 {
334 fib_index = sdlb->ip6_fib_index;
335 dpo_proto = DPO_PROTO_IP6;
336 is_ip4 = 0;
337 }
338
339 paths = session_sdl_fib_create_route_paths (fib_index, dpo_proto);
340 if (args->is_add)
341 {
342 fei = fib_table_lookup_exact_match (fib_index, &pfx);
343 if (fei != FIB_NODE_INDEX_INVALID)
344 {
345 err = SESSION_E_IPINUSE;
346 goto done;
347 }
348 dpo_set (&paths->dpo, sdl_dpo_type, dpo_proto, args->action_index);
349 fei = fib_table_entry_path_add2 (fib_index, &pfx, sdl_fib_src,
350 FIB_ENTRY_FLAG_EXCLUSIVE, paths);
351 session_rules_table_add_tag (srt, args->tag, fei, is_ip4);
352 dpo_reset (&paths->dpo);
353 }
354 else
355 {
356 if (fei == SESSION_RULES_TABLE_INVALID_INDEX)
357 {
358 fei = fib_table_lookup_exact_match (fib_index, &pfx);
359
360 if (fei == FIB_NODE_INDEX_INVALID)
361 {
362 err = SESSION_E_NOROUTE;
363 goto done;
364 }
365 }
366
367 if (!fib_entry_is_sourced (fei, sdl_fib_src))
368 {
369 err = SESSION_E_NOROUTE;
370 goto done;
371 }
372
373 fib_entry_t *fib_entry = fib_entry_get (fei);
374 pfx = fib_entry->fe_prefix;
375 fib_table_entry_special_remove (fib_index, &pfx, sdl_fib_src);
376 session_rules_table_del_tag (srt, args->tag, is_ip4);
377 }
378done:
379 vec_free (paths);
380
381 return err;
382}
383
384static const session_rt_engine_vft_t session_sdl_vft = {
385 .backend_engine = RT_BACKEND_ENGINE_SDL,
386 .table_lookup4 = session_sdl_lookup4,
387 .table_lookup6 = session_sdl_lookup6,
388 .table_cli_dump = session_sdl_cli_dump,
389 .table_show_rule = session_sdl_show_rule,
390 .table_add_del = session_sdl_add_del,
391 .table_init = session_sdl_table_init,
392 .table_free = session_sdl_table_free,
393};
394
395static void
396session_sdl_fib_init (void)
397{
398 static u32 session_fib_inited = 0;
399
400 if (session_fib_inited)
401 return;
402 session_fib_inited = 1;
403 sdl_fib_src = fib_source_allocate ("session sdl", FIB_SOURCE_PRIORITY_LOW,
404 FIB_SOURCE_BH_SIMPLE);
405 sdl_dpo_type =
406 dpo_register_new_type (&session_sdl_dpo_vft, session_sdl_dpo_nodes);
407}
408
409static void
410session_sdl_app_namespace_walk_cb (app_namespace_t *app_ns, void *ctx)
411{
412 u32 fib_index, table_index;
413 session_table_t *st;
414
415 log_debug ("disable app_ns %s", app_ns->ns_id);
416
417 fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP4);
418 table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP4, fib_index);
419 st = session_table_get (table_index);
420 if (st)
421 session_rules_table_free (st, FIB_PROTOCOL_IP4);
422
423 fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP6);
424 table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP6, fib_index);
425 st = session_table_get (table_index);
426 if (st)
427 session_rules_table_free (st, FIB_PROTOCOL_IP6);
428}
429
430clib_error_t *
431session_sdl_enable_disable (int enable)
432{
433 clib_error_t *error = 0;
434
435 if (enable)
436 {
437 error = session_rule_table_register_engine (&session_sdl_vft);
438 if (error)
439 {
440 log_err ("error in enabling sdl: %U", format_clib_error, error);
441 return error;
442 }
443 session_sdl_fib_init ();
444 }
445 else
446 {
447 app_namespace_walk (session_sdl_app_namespace_walk_cb, 0);
448
449 error = session_rule_table_deregister_engine (&session_sdl_vft);
450 if (error)
451 log_err ("error in disabling sdl: %U", format_clib_error, error);
452 }
453
454 return error;
455}
456
457/*
458 * Source Deny List
459 */
460static clib_error_t *
461session_sdl_command_fn (vlib_main_t *vm, unformat_input_t *input,
462 vlib_cli_command_t *cmd)
463{
464 u32 appns_index;
465 app_namespace_t *app_ns;
466 u32 lcl_plen = 0, action = 0;
467 clib_error_t *error = 0;
468 ip46_address_t lcl_ip;
469 u8 conn_set = 0;
470 u8 fib_proto = -1, is_add = 1, *ns_id = 0;
471 u8 *tag = 0, tag_only = 0;
472 int rv;
473 session_rule_add_del_args_t args;
474
475 session_cli_return_if_not_enabled ();
476
477 if (session_sdl_is_enabled () == 0)
478 return clib_error_return (0, "session sdl engine is not enabled");
479
480 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
481 {
482 if (unformat (input, "del"))
483 is_add = 0;
484 else if (unformat (input, "add"))
485 ;
486 else if (unformat (input, "appns %_%v%_", &ns_id))
487 ;
488 else if (unformat (input, "%U/%d", unformat_ip4_address, &lcl_ip.ip4,
489 &lcl_plen))
490 {
491 fib_proto = FIB_PROTOCOL_IP4;
492 conn_set = 1;
493 }
494 else if (unformat (input, "%U/%d", unformat_ip6_address, &lcl_ip.ip6,
495 &lcl_plen))
496 {
497 fib_proto = FIB_PROTOCOL_IP6;
498 conn_set = 1;
499 }
500 else if (unformat (input, "action %d", &action))
501 ;
502 else if (unformat (input, "tag %_%v%_", &tag))
503 ;
504 else
505 {
506 error = clib_error_return (0, "unknown input `%U'",
507 format_unformat_error, input);
508 goto done;
509 }
510 }
511
512 if (ns_id)
513 {
514 app_ns = app_namespace_get_from_id (ns_id);
515 if (!app_ns)
516 {
517 vlib_cli_output (vm, "namespace %v does not exist", ns_id);
518 goto done;
519 }
520 }
521 else
522 {
523 app_ns = app_namespace_get_default ();
524 }
525 appns_index = app_namespace_index (app_ns);
526
527 if (is_add && !conn_set && action == 0)
528 {
529 vlib_cli_output (vm, "connection and action must be set for add");
530 goto done;
531 }
532 if (!is_add && !tag && !conn_set)
533 {
534 vlib_cli_output (vm, "connection or tag must be set for delete");
535 goto done;
536 }
537 if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN)
538 {
539 vlib_cli_output (vm, "tag too long (max u64)");
540 goto done;
541 }
542
543 /* Delete with only tag entered. Try v4 first and then v6 if failed */
544 if ((is_add == 0) && (fib_proto == (u8) ~0))
545 {
546 fib_proto = FIB_PROTOCOL_IP4;
547 tag_only = 1;
548 }
549
550 memset (&args, 0, sizeof (args));
551 args.transport_proto = TRANSPORT_PROTO_TCP;
552 args.table_args.lcl.fp_addr = lcl_ip;
553 args.table_args.lcl.fp_len = lcl_plen;
554 args.table_args.lcl.fp_proto = fib_proto;
555 args.table_args.rmt.fp_proto = fib_proto;
556 args.table_args.action_index = action;
557 args.table_args.is_add = is_add;
558 args.table_args.tag = tag;
559 args.appns_index = appns_index;
560 args.scope = SESSION_RULE_SCOPE_GLOBAL;
561
562 if ((rv = vnet_session_rule_add_del (&args)))
563 {
564 /* Try tag only delete on v6 */
565 if (rv && tag_only)
566 {
567 args.table_args.rmt.fp_proto = FIB_PROTOCOL_IP6;
568 args.table_args.lcl.fp_proto = FIB_PROTOCOL_IP6;
569 if ((rv = vnet_session_rule_add_del (&args)))
570 {
571 error = clib_error_return (0, "sdl add del returned %u", rv);
572 }
573 }
574 else
575 {
576 error = clib_error_return (0, "sdl add del returned %u", rv);
577 }
578 }
579
580done:
581 vec_free (ns_id);
582 vec_free (tag);
583 return error;
584}
585
586VLIB_CLI_COMMAND (session_sdl_command, static) = {
587 .path = "session sdl",
588 .short_help = "session sdl [add|del] [appns <ns_id>] <lcl-ip/plen> action "
589 "<action> [tag <tag>]",
590 .function = session_sdl_command_fn,
591 .is_mp_safe = 1,
592};
593
594static clib_error_t *
595show_session_sdl_command_fn (vlib_main_t *vm, unformat_input_t *input,
596 vlib_cli_command_t *cmd)
597{
598 u32 fib_index;
599 ip46_address_t lcl_ip;
600 u8 show_one = 0;
601 app_namespace_t *app_ns;
602 session_table_t *st;
603 u8 *ns_id = 0, fib_proto = FIB_PROTOCOL_IP4;
604
605 session_cli_return_if_not_enabled ();
606
607 clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
608 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
609 {
610 if (unformat (input, "appns %_%s%_", &ns_id))
611 ;
612 else if (unformat (input, "%U", unformat_ip4_address, &lcl_ip.ip4))
613 {
614 fib_proto = FIB_PROTOCOL_IP4;
615 show_one = 1;
616 }
617 else if (unformat (input, "%U", unformat_ip6_address, &lcl_ip.ip6))
618 {
619 fib_proto = FIB_PROTOCOL_IP6;
620 show_one = 1;
621 }
622 else
623 {
624 vec_free (ns_id);
625 return clib_error_return (0, "unknown input `%U'",
626 format_unformat_error, input);
627 }
628 }
629
630 if (ns_id)
631 {
632 app_ns = app_namespace_get_from_id (ns_id);
633 if (!app_ns)
634 {
635 vlib_cli_output (vm, "appns %v doesn't exist", ns_id);
636 goto done;
637 }
638 }
639 else
640 {
641 app_ns = app_namespace_get_default ();
642 }
643
644 if (session_sdl_is_enabled () == 0)
645 {
646 vlib_cli_output (vm, "session sdl engine is not enabled");
647 goto done;
648 }
649
650 if (show_one)
651 {
652 fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
653 st = session_table_get_for_fib_index (fib_proto, fib_index);
654 if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID))
655 session_rules_table_show_rule (vm, st->srtg_handle, 0, &lcl_ip, 0, 0,
656 0, (fib_proto == FIB_PROTOCOL_IP4));
657 goto done;
658 }
659
660 /* 2 separate session tables for global entries, 1 for ip4 and 1 for ip6 */
661 fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP4);
662 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
663 if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID))
664 session_rules_table_cli_dump (vm, st->srtg_handle, 0, FIB_PROTOCOL_IP4);
665
666 fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP6);
667 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
668 if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID))
669 session_rules_table_cli_dump (vm, st->srtg_handle, 0, FIB_PROTOCOL_IP6);
670done:
671 vec_free (ns_id);
672 return 0;
673}
674
675void
676session_sdl_table_walk4 (u32 srtg_handle, session_sdl_table_walk_fn_t fn,
677 void *args)
678{
679 ip4_fib_t *fib;
680 session_sdl4_fib_show_walk_ctx_t ctx = {
681 .ifsw_indicies = NULL,
682 };
683 fib_node_index_t *fei;
684 session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
685 session_sdl_block_t *sdlb = &srt->sdl_block;
686 u32 fib_index = sdlb->ip_fib_index;
687
688 if (fib_index == ~0)
689 return;
690 fib = ip4_fib_get (fib_index);
691 ip4_fib_table_walk (fib, session_sdl4_fib_show_walk_cb, &ctx);
692 vec_sort_with_function (ctx.ifsw_indicies, fib_entry_cmp_for_sort);
693
694 vec_foreach (fei, ctx.ifsw_indicies)
695 {
696 if (*fei != FIB_NODE_INDEX_INVALID &&
697 fib_entry_is_sourced (*fei, sdl_fib_src))
698 {
699 u8 *tag = session_rules_table_rule_tag (srt, *fei, 1);
700 fib_entry_t *fib_entry = fib_entry_get (*fei);
701 fib_prefix_t pfx = fib_entry->fe_prefix;
702 index_t lbi =
703 ip4_fib_forwarding_lookup (fib_index, &pfx.fp_addr.ip4);
704 const dpo_id_t *dpo =
705 load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
706
707 fn (*fei, &pfx.fp_addr, pfx.fp_len, dpo->dpoi_index,
708 FIB_PROTOCOL_IP4, tag, args);
709 }
710 }
711
712 vec_free (ctx.ifsw_indicies);
713}
714
715void
716session_sdl_table_walk6 (u32 srtg_handle, session_sdl_table_walk_fn_t fn,
717 void *args)
718{
719 ip6_fib_t *fib;
720 fib_node_index_t *fei;
721 session_sdl6_fib_show_ctx_t ctx = {
722 .entries = NULL,
723 };
724 session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0);
725 session_sdl_block_t *sdlb = &srt->sdl_block;
726 u32 fib_index = sdlb->ip6_fib_index;
727
728 if (fib_index == ~0)
729 return;
730 fib = ip6_fib_get (fib_index);
731 ip6_fib_table_walk (fib->index, session_sdl6_fib_table_show_walk, &ctx);
732 vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort);
733
734 vec_foreach (fei, ctx.entries)
735 {
736 if (*fei != FIB_NODE_INDEX_INVALID &&
737 fib_entry_is_sourced (*fei, sdl_fib_src))
738 {
739 u8 *tag = session_rules_table_rule_tag (srt, *fei, 0);
740 fib_entry_t *fib_entry = fib_entry_get (*fei);
741 fib_prefix_t pfx = fib_entry->fe_prefix;
742 index_t lbi =
743 ip6_fib_table_fwding_lookup (fib_index, &pfx.fp_addr.ip6);
744 const dpo_id_t *dpo =
745 load_balance_get_fwd_bucket (load_balance_get (lbi), 0);
746
747 fn (*fei, &pfx.fp_addr, pfx.fp_len, dpo->dpoi_index,
748 FIB_PROTOCOL_IP6, tag, args);
749 }
750 }
751
752 vec_free (ctx.entries);
753}
754
755VLIB_CLI_COMMAND (show_session_sdl_command, static) = {
756 .path = "show session sdl",
757 .short_help = "show session sdl [appns <id> <lcl-ip>]",
758 .function = show_session_sdl_command_fn,
759 .is_mp_safe = 1,
760};
761
762/*
763 * fd.io coding-style-patch-verification: ON
764 *
765 * Local Variables:
766 * eval: (c-set-style "gnu")
767 * End:
768 */