blob: 0d580ba35c6a4a2d55045c3df8c9ded664332df0 [file] [log] [blame]
Florin Coras04e53442017-07-16 17:12:15 -07001/*
Florin Coras288eaab2019-02-03 15:26:14 -08002 * Copyright (c) 2017-2019 Cisco and/or its affiliates.
Florin Coras04e53442017-07-16 17:12:15 -07003 * 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/** Generate typed init functions for multiple hash table styles... */
17#include <vppinfra/bihash_16_8.h>
18#include <vppinfra/bihash_template.h>
19
20#include <vppinfra/bihash_template.c>
21
22#undef __included_bihash_template_h__
23
24#include <vppinfra/bihash_48_8.h>
25#include <vppinfra/bihash_template.h>
26
27#include <vppinfra/bihash_template.c>
28#include <vnet/session/session_lookup.h>
29#include <vnet/session/session.h>
Florin Corascea194d2017-10-02 00:18:51 -070030#include <vnet/session/application.h>
Steven Luongc4b5d102024-07-30 13:44:01 -070031#include <vnet/session/session_rules_table.h>
Florin Coras04e53442017-07-16 17:12:15 -070032
Florin Corasf9bdc032024-02-02 13:01:07 -080033static session_lookup_main_t sl_main;
34
Florin Corascea194d2017-10-02 00:18:51 -070035/**
Florin Corascea194d2017-10-02 00:18:51 -070036 * Network namespace index (i.e., fib index) to session lookup table. We
37 * should have one per network protocol type but for now we only support IP4/6
38 */
39static u32 *fib_index_to_table_index[2];
40
Steven Luong5682ca82024-07-17 16:16:05 -070041static u32 *fib_index_to_lock_count[2];
42
Florin Coras04e53442017-07-16 17:12:15 -070043/* 16 octets */
44typedef CLIB_PACKED (struct {
45 union
46 {
47 struct
48 {
49 ip4_address_t src;
50 ip4_address_t dst;
51 u16 src_port;
52 u16 dst_port;
53 /* align by making this 4 octets even though its a 1-bit field
54 * NOTE: avoid key overlap with other transports that use 5 tuples for
55 * session identification.
56 */
57 u32 proto;
58 };
59 u64 as_u64[2];
60 };
61}) v4_connection_key_t;
62
63typedef CLIB_PACKED (struct {
64 union
65 {
66 struct
67 {
68 /* 48 octets */
69 ip6_address_t src;
70 ip6_address_t dst;
71 u16 src_port;
72 u16 dst_port;
73 u32 proto;
74 u64 unused;
75 };
76 u64 as_u64[6];
77 };
78}) v6_connection_key_t;
Florin Coras04e53442017-07-16 17:12:15 -070079
80typedef clib_bihash_kv_16_8_t session_kv4_t;
81typedef clib_bihash_kv_48_8_t session_kv6_t;
82
83always_inline void
84make_v4_ss_kv (session_kv4_t * kv, ip4_address_t * lcl, ip4_address_t * rmt,
85 u16 lcl_port, u16 rmt_port, u8 proto)
86{
Florin Coras9679c812018-06-21 08:14:34 -070087 kv->key[0] = (u64) rmt->as_u32 << 32 | (u64) lcl->as_u32;
88 kv->key[1] = (u64) proto << 32 | (u64) rmt_port << 16 | (u64) lcl_port;
Florin Coras04e53442017-07-16 17:12:15 -070089 kv->value = ~0ULL;
90}
91
92always_inline void
93make_v4_listener_kv (session_kv4_t * kv, ip4_address_t * lcl, u16 lcl_port,
94 u8 proto)
95{
Florin Coras9679c812018-06-21 08:14:34 -070096 kv->key[0] = (u64) lcl->as_u32;
97 kv->key[1] = (u64) proto << 32 | (u64) lcl_port;
Florin Coras04e53442017-07-16 17:12:15 -070098 kv->value = ~0ULL;
99}
100
101always_inline void
Florin Corasdbd44562017-11-09 19:30:17 -0800102make_v4_proxy_kv (session_kv4_t * kv, ip4_address_t * lcl, u8 proto)
103{
Florin Coras9679c812018-06-21 08:14:34 -0700104 kv->key[0] = (u64) lcl->as_u32;
105 kv->key[1] = (u64) proto << 32;
Florin Corasdbd44562017-11-09 19:30:17 -0800106 kv->value = ~0ULL;
107}
108
109always_inline void
Florin Coras561af9b2017-12-09 10:19:43 -0800110make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700111{
Florin Coras561af9b2017-12-09 10:19:43 -0800112 make_v4_ss_kv (kv, &tc->lcl_ip.ip4, &tc->rmt_ip.ip4, tc->lcl_port,
113 tc->rmt_port, tc->proto);
Florin Coras04e53442017-07-16 17:12:15 -0700114}
115
116always_inline void
117make_v6_ss_kv (session_kv6_t * kv, ip6_address_t * lcl, ip6_address_t * rmt,
118 u16 lcl_port, u16 rmt_port, u8 proto)
119{
Florin Coras9679c812018-06-21 08:14:34 -0700120 kv->key[0] = lcl->as_u64[0];
121 kv->key[1] = lcl->as_u64[1];
122 kv->key[2] = rmt->as_u64[0];
123 kv->key[3] = rmt->as_u64[1];
124 kv->key[4] = (u64) proto << 32 | (u64) rmt_port << 16 | (u64) lcl_port;
125 kv->key[5] = 0;
Florin Coras04e53442017-07-16 17:12:15 -0700126 kv->value = ~0ULL;
127}
128
129always_inline void
130make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port,
131 u8 proto)
132{
Florin Coras9679c812018-06-21 08:14:34 -0700133 kv->key[0] = lcl->as_u64[0];
134 kv->key[1] = lcl->as_u64[1];
135 kv->key[2] = 0;
136 kv->key[3] = 0;
137 kv->key[4] = (u64) proto << 32 | (u64) lcl_port;
138 kv->key[5] = 0;
Florin Coras04e53442017-07-16 17:12:15 -0700139 kv->value = ~0ULL;
140}
141
142always_inline void
Florin Corasdbd44562017-11-09 19:30:17 -0800143make_v6_proxy_kv (session_kv6_t * kv, ip6_address_t * lcl, u8 proto)
144{
Florin Coras9679c812018-06-21 08:14:34 -0700145 kv->key[0] = lcl->as_u64[0];
146 kv->key[1] = lcl->as_u64[1];
147 kv->key[2] = 0;
148 kv->key[3] = 0;
149 kv->key[4] = (u64) proto << 32;
150 kv->key[5] = 0;
Florin Corasdbd44562017-11-09 19:30:17 -0800151 kv->value = ~0ULL;
152}
153
154always_inline void
Florin Coras561af9b2017-12-09 10:19:43 -0800155make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700156{
Florin Coras561af9b2017-12-09 10:19:43 -0800157 make_v6_ss_kv (kv, &tc->lcl_ip.ip6, &tc->rmt_ip.ip6, tc->lcl_port,
158 tc->rmt_port, tc->proto);
Florin Coras04e53442017-07-16 17:12:15 -0700159}
160
Florin Corasf9bdc032024-02-02 13:01:07 -0800161static inline u8
162session_table_alloc_needs_sync (void)
163{
164 return !vlib_thread_is_main_w_barrier () && (vlib_num_workers () > 1);
165}
166
Florin Coras5bd96b72024-03-20 16:31:38 -0700167static_always_inline u8
168session_table_is_alloced (u8 fib_proto, u32 fib_index)
169{
170 return (vec_len (fib_index_to_table_index[fib_proto]) > fib_index &&
171 fib_index_to_table_index[fib_proto][fib_index] != ~0);
172}
173
Florin Corascea194d2017-10-02 00:18:51 -0700174static session_table_t *
Andreas Schultz30a28c12020-04-23 10:41:50 +0200175session_table_get_or_alloc (u8 fib_proto, u32 fib_index)
Florin Coras04e53442017-07-16 17:12:15 -0700176{
Florin Corascea194d2017-10-02 00:18:51 -0700177 session_table_t *st;
Florin Coras6c36f532017-11-03 18:32:34 -0700178 u32 table_index;
Florin Coras5bd96b72024-03-20 16:31:38 -0700179
Andreas Schultz30a28c12020-04-23 10:41:50 +0200180 ASSERT (fib_index != ~0);
Florin Coras5bd96b72024-03-20 16:31:38 -0700181
182 if (session_table_is_alloced (fib_proto, fib_index))
Andreas Schultz30a28c12020-04-23 10:41:50 +0200183 {
184 table_index = fib_index_to_table_index[fib_proto][fib_index];
185 return session_table_get (table_index);
186 }
Florin Coras5bd96b72024-03-20 16:31:38 -0700187
188 u8 needs_sync = session_table_alloc_needs_sync ();
189 session_lookup_main_t *slm = &sl_main;
190
191 /* Stop workers, otherwise consumers might be affected. This is
192 * acceptable because new tables should seldom be allocated */
193 if (needs_sync)
194 {
195 vlib_workers_sync ();
196
197 /* We might have a race, only one worker allowed at once */
198 clib_spinlock_lock (&slm->st_alloc_lock);
199 }
200
201 /* Another worker just allocated this table */
202 if (session_table_is_alloced (fib_proto, fib_index))
203 {
204 table_index = fib_index_to_table_index[fib_proto][fib_index];
205 st = session_table_get (table_index);
206 }
Andreas Schultz30a28c12020-04-23 10:41:50 +0200207 else
Florin Corascea194d2017-10-02 00:18:51 -0700208 {
209 st = session_table_alloc ();
Florin Coras6c36f532017-11-03 18:32:34 -0700210 st->active_fib_proto = fib_proto;
Florin Corasb795bd02017-12-14 11:30:48 -0800211 session_table_init (st, fib_proto);
Florin Coras5bd96b72024-03-20 16:31:38 -0700212 vec_validate_init_empty (fib_index_to_table_index[fib_proto], fib_index,
213 ~0);
214 table_index = session_table_index (st);
215 fib_index_to_table_index[fib_proto][fib_index] = table_index;
Florin Corascea194d2017-10-02 00:18:51 -0700216 }
Florin Coras5bd96b72024-03-20 16:31:38 -0700217
218 if (needs_sync)
219 {
220 clib_spinlock_unlock (&slm->st_alloc_lock);
221 vlib_workers_continue ();
222 }
223
224 return st;
Florin Corascea194d2017-10-02 00:18:51 -0700225}
226
227static session_table_t *
Florin Coras6c36f532017-11-03 18:32:34 -0700228session_table_get_or_alloc_for_connection (transport_connection_t * tc)
229{
230 u32 fib_proto;
231 fib_proto = transport_connection_fib_proto (tc);
232 return session_table_get_or_alloc (fib_proto, tc->fib_index);
233}
234
235static session_table_t *
Florin Corascea194d2017-10-02 00:18:51 -0700236session_table_get_for_connection (transport_connection_t * tc)
237{
238 u32 fib_proto = transport_connection_fib_proto (tc);
239 if (vec_len (fib_index_to_table_index[fib_proto]) <= tc->fib_index)
240 return 0;
241 return
242 session_table_get (fib_index_to_table_index[fib_proto][tc->fib_index]);
243}
244
Steven Luongc4b5d102024-07-30 13:44:01 -0700245session_table_t *
Florin Corascea194d2017-10-02 00:18:51 -0700246session_table_get_for_fib_index (u32 fib_proto, u32 fib_index)
247{
248 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
249 return 0;
250 return session_table_get (fib_index_to_table_index[fib_proto][fib_index]);
251}
252
253u32
254session_lookup_get_index_for_fib (u32 fib_proto, u32 fib_index)
255{
256 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
257 return SESSION_TABLE_INVALID_INDEX;
258 return fib_index_to_table_index[fib_proto][fib_index];
259}
260
Florin Corasa4d09562021-07-08 08:25:09 -0700261u32
262session_lookup_get_or_alloc_index_for_fib (u32 fib_proto, u32 fib_index)
263{
264 session_table_t *st;
265 st = session_table_get_or_alloc (fib_proto, fib_index);
266 return session_table_index (st);
267}
268
Florin Corascea194d2017-10-02 00:18:51 -0700269/**
270 * Add transport connection to a session table
271 *
272 * Session lookup 5-tuple (src-ip, dst-ip, src-port, dst-port, session-type)
273 * is added to requested session table.
274 *
275 * @param tc transport connection to be added
276 * @param value value to be stored
277 *
278 * @return non-zero if failure
279 */
280int
281session_lookup_add_connection (transport_connection_t * tc, u64 value)
282{
283 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700284 session_kv4_t kv4;
285 session_kv6_t kv6;
286
Florin Corascea194d2017-10-02 00:18:51 -0700287 st = session_table_get_or_alloc_for_connection (tc);
288 if (!st)
289 return -1;
Florin Coras68810622017-07-24 17:40:28 -0700290 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700291 {
Florin Coras04e53442017-07-16 17:12:15 -0700292 make_v4_ss_kv_from_tc (&kv4, tc);
293 kv4.value = value;
Florin Corascea194d2017-10-02 00:18:51 -0700294 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4,
295 1 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700296 }
297 else
298 {
Florin Coras04e53442017-07-16 17:12:15 -0700299 make_v6_ss_kv_from_tc (&kv6, tc);
300 kv6.value = value;
Florin Corascea194d2017-10-02 00:18:51 -0700301 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6,
302 1 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700303 }
304}
305
Florin Coras04e53442017-07-16 17:12:15 -0700306int
Florin Corascea194d2017-10-02 00:18:51 -0700307session_lookup_add_session_endpoint (u32 table_index,
308 session_endpoint_t * sep, u64 value)
Florin Coras04e53442017-07-16 17:12:15 -0700309{
Florin Corascea194d2017-10-02 00:18:51 -0700310 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700311 session_kv4_t kv4;
312 session_kv6_t kv6;
Florin Coras68810622017-07-24 17:40:28 -0700313
Florin Corascea194d2017-10-02 00:18:51 -0700314 st = session_table_get (table_index);
315 if (!st)
316 return -1;
317 if (sep->is_ip4)
318 {
319 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
320 sep->transport_proto);
321 kv4.value = value;
322 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 1);
323 }
324 else
325 {
326 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
327 sep->transport_proto);
328 kv6.value = value;
329 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 1);
330 }
331}
332
333int
334session_lookup_del_session_endpoint (u32 table_index,
335 session_endpoint_t * sep)
336{
337 session_table_t *st;
338 session_kv4_t kv4;
339 session_kv6_t kv6;
340
341 st = session_table_get (table_index);
342 if (!st)
343 return -1;
344 if (sep->is_ip4)
345 {
346 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
347 sep->transport_proto);
348 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 0);
349 }
350 else
351 {
352 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
353 sep->transport_proto);
354 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 0);
355 }
356}
357
Florin Corasaab06042020-02-26 02:56:14 +0000358int
359session_lookup_del_session_endpoint2 (session_endpoint_t * sep)
360{
361 fib_protocol_t fib_proto;
362 session_table_t *st;
363 session_kv4_t kv4;
364 session_kv6_t kv6;
365
366 fib_proto = sep->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
367 st = session_table_get_for_fib_index (fib_proto, sep->fib_index);
368 if (!st)
369 return -1;
370 if (sep->is_ip4)
371 {
372 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
373 sep->transport_proto);
374 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 0);
375 }
376 else
377 {
378 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
379 sep->transport_proto);
380 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 0);
381 }
382}
383
Florin Corascea194d2017-10-02 00:18:51 -0700384/**
385 * Delete transport connection from session table
386 *
387 * @param table_index session table index
388 * @param tc transport connection to be removed
389 *
390 * @return non-zero if failure
391 */
392int
393session_lookup_del_connection (transport_connection_t * tc)
394{
395 session_table_t *st;
396 session_kv4_t kv4;
397 session_kv6_t kv6;
398
399 st = session_table_get_for_connection (tc);
400 if (!st)
401 return -1;
Florin Coras68810622017-07-24 17:40:28 -0700402 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700403 {
Florin Coras04e53442017-07-16 17:12:15 -0700404 make_v4_ss_kv_from_tc (&kv4, tc);
Florin Corascea194d2017-10-02 00:18:51 -0700405 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4,
Florin Coras04e53442017-07-16 17:12:15 -0700406 0 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700407 }
408 else
409 {
Florin Coras04e53442017-07-16 17:12:15 -0700410 make_v6_ss_kv_from_tc (&kv6, tc);
Florin Corascea194d2017-10-02 00:18:51 -0700411 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6,
Florin Coras04e53442017-07-16 17:12:15 -0700412 0 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700413 }
Florin Coras04e53442017-07-16 17:12:15 -0700414}
415
416int
Florin Coras288eaab2019-02-03 15:26:14 -0800417session_lookup_del_session (session_t * s)
Florin Coras04e53442017-07-16 17:12:15 -0700418{
419 transport_connection_t *ts;
Florin Coras1ee78302019-02-05 15:51:15 -0800420 ts = transport_get_connection (session_get_transport_proto (s),
421 s->connection_index, s->thread_index);
Florin Corase1e7fb82019-09-25 07:28:34 -0700422 if (!ts || (ts->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
Nathan Skrzypczak2eed1a12019-07-04 14:26:21 +0200423 return 0;
Florin Corascea194d2017-10-02 00:18:51 -0700424 return session_lookup_del_connection (ts);
Florin Coras04e53442017-07-16 17:12:15 -0700425}
426
Florin Corasdff48db2017-11-19 18:06:58 -0800427static u8
428session_lookup_action_index_is_valid (u32 action_index)
Florin Corasf0c1c962017-11-02 21:31:46 -0700429{
Florin Corasdff48db2017-11-19 18:06:58 -0800430 if (action_index == SESSION_RULES_TABLE_ACTION_ALLOW
431 || action_index == SESSION_RULES_TABLE_INVALID_INDEX)
432 return 0;
433 return 1;
434}
435
Florin Corasf8f516a2018-02-08 15:10:09 -0800436static u64
437session_lookup_action_to_handle (u32 action_index)
Florin Corasdff48db2017-11-19 18:06:58 -0800438{
439 switch (action_index)
440 {
441 case SESSION_RULES_TABLE_ACTION_DROP:
Florin Corasf8f516a2018-02-08 15:10:09 -0800442 return SESSION_DROP_HANDLE;
Florin Corasdff48db2017-11-19 18:06:58 -0800443 case SESSION_RULES_TABLE_ACTION_ALLOW:
444 case SESSION_RULES_TABLE_INVALID_INDEX:
Florin Corasf8f516a2018-02-08 15:10:09 -0800445 return SESSION_INVALID_HANDLE;
Florin Corasdff48db2017-11-19 18:06:58 -0800446 default:
Florin Corasf8f516a2018-02-08 15:10:09 -0800447 /* application index */
Florin Corasdff48db2017-11-19 18:06:58 -0800448 return action_index;
449 }
Florin Corasf0c1c962017-11-02 21:31:46 -0700450}
451
Florin Coras288eaab2019-02-03 15:26:14 -0800452static session_t *
Florin Coras7999e832017-10-31 01:51:04 -0700453session_lookup_app_listen_session (u32 app_index, u8 fib_proto,
454 u8 transport_proto)
Florin Coras1c710452017-10-17 00:03:13 -0700455{
456 application_t *app;
Florin Corasdff48db2017-11-19 18:06:58 -0800457 app = application_get_if_valid (app_index);
Florin Coras1c710452017-10-17 00:03:13 -0700458 if (!app)
459 return 0;
460
Florin Coras15531972018-08-12 23:50:53 -0700461 return app_worker_first_listener (application_get_default_worker (app),
462 fib_proto, transport_proto);
Florin Coras1c710452017-10-17 00:03:13 -0700463}
464
Florin Coras288eaab2019-02-03 15:26:14 -0800465static session_t *
Florin Corasa2ff7b82017-11-08 17:55:03 -0800466session_lookup_action_to_session (u32 action_index, u8 fib_proto,
467 u8 transport_proto)
468{
Florin Corasdff48db2017-11-19 18:06:58 -0800469 u32 app_index;
Florin Corasf8f516a2018-02-08 15:10:09 -0800470 app_index = session_lookup_action_to_handle (action_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800471 /* Nothing sophisticated for now, action index is app index */
Florin Corasdff48db2017-11-19 18:06:58 -0800472 return session_lookup_app_listen_session (app_index, fib_proto,
Florin Corasa2ff7b82017-11-08 17:55:03 -0800473 transport_proto);
474}
475
Florin Corasf8f516a2018-02-08 15:10:09 -0800476/** UNUSED */
Florin Coras288eaab2019-02-03 15:26:14 -0800477session_t *
Florin Corasa2ff7b82017-11-08 17:55:03 -0800478session_lookup_rules_table_session4 (session_table_t * st, u8 proto,
479 ip4_address_t * lcl, u16 lcl_port,
480 ip4_address_t * rmt, u16 rmt_port)
Florin Coras1c710452017-10-17 00:03:13 -0700481{
Florin Corasdff48db2017-11-19 18:06:58 -0800482 u32 action_index, app_index;
Steven Luongc4b5d102024-07-30 13:44:01 -0700483
484 action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl, rmt,
485 lcl_port, rmt_port);
Florin Corasf8f516a2018-02-08 15:10:09 -0800486 app_index = session_lookup_action_to_handle (action_index);
Florin Coras1c710452017-10-17 00:03:13 -0700487 /* Nothing sophisticated for now, action index is app index */
Florin Corasdff48db2017-11-19 18:06:58 -0800488 return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP4,
Florin Coras7999e832017-10-31 01:51:04 -0700489 proto);
Florin Coras1c710452017-10-17 00:03:13 -0700490}
491
Florin Corasf8f516a2018-02-08 15:10:09 -0800492/** UNUSED */
Florin Coras288eaab2019-02-03 15:26:14 -0800493session_t *
Florin Corasdff48db2017-11-19 18:06:58 -0800494session_lookup_rules_table_session6 (session_table_t * st, u8 proto,
495 ip6_address_t * lcl, u16 lcl_port,
496 ip6_address_t * rmt, u16 rmt_port)
Florin Coras1c710452017-10-17 00:03:13 -0700497{
Florin Corasdff48db2017-11-19 18:06:58 -0800498 u32 action_index, app_index;
Steven Luongc4b5d102024-07-30 13:44:01 -0700499
500 action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl, rmt,
501 lcl_port, rmt_port);
Florin Corasf8f516a2018-02-08 15:10:09 -0800502 app_index = session_lookup_action_to_handle (action_index);
Florin Corasdff48db2017-11-19 18:06:58 -0800503 return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP6,
Florin Coras7999e832017-10-31 01:51:04 -0700504 proto);
Florin Coras1c710452017-10-17 00:03:13 -0700505}
506
Florin Corasa2ff7b82017-11-08 17:55:03 -0800507/**
508 * Lookup listener for session endpoint in table
509 *
510 * @param table_index table where the endpoint should be looked up
511 * @param sep session endpoint to be looked up
512 * @param use_rules flag that indicates if the session rules of the table
513 * should be used
514 * @return invalid handle if nothing is found, the handle of a valid listener
Florin Corasf8f516a2018-02-08 15:10:09 -0800515 * or an action derived handle if a rule is hit
Florin Corasa2ff7b82017-11-08 17:55:03 -0800516 */
Florin Coras3cbc04b2017-10-02 00:18:51 -0700517u64
Florin Corasa2ff7b82017-11-08 17:55:03 -0800518session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
519 u8 use_rules)
Florin Coras04e53442017-07-16 17:12:15 -0700520{
Florin Corascea194d2017-10-02 00:18:51 -0700521 session_table_t *st;
Florin Corasf0c1c962017-11-02 21:31:46 -0700522 u32 ai;
Florin Corascea194d2017-10-02 00:18:51 -0700523 int rv;
Florin Coras04e53442017-07-16 17:12:15 -0700524
Florin Corascea194d2017-10-02 00:18:51 -0700525 st = session_table_get (table_index);
526 if (!st)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700527 return SESSION_INVALID_HANDLE;
Florin Corascea194d2017-10-02 00:18:51 -0700528 if (sep->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700529 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800530 session_kv4_t kv4;
531 ip4_address_t lcl4;
532
Florin Coras561af9b2017-12-09 10:19:43 -0800533 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
534 sep->transport_proto);
Florin Corascea194d2017-10-02 00:18:51 -0700535 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
536 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700537 return kv4.value;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800538 if (use_rules)
539 {
Steven Luongc4b5d102024-07-30 13:44:01 -0700540 if (st->srtg_handle == SESSION_SRTG_HANDLE_INVALID)
541 return SESSION_INVALID_HANDLE;
Dave Barachb7b92992018-10-17 10:38:51 -0400542 clib_memset (&lcl4, 0, sizeof (lcl4));
Steven Luongc4b5d102024-07-30 13:44:01 -0700543 ai =
544 session_rules_table_lookup4 (st->srtg_handle, sep->transport_proto,
545 &lcl4, &sep->ip.ip4, 0, sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800546 if (session_lookup_action_index_is_valid (ai))
Florin Corasf8f516a2018-02-08 15:10:09 -0800547 return session_lookup_action_to_handle (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800548 }
Florin Coras68810622017-07-24 17:40:28 -0700549 }
550 else
551 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800552 session_kv6_t kv6;
553 ip6_address_t lcl6;
554
Florin Coras561af9b2017-12-09 10:19:43 -0800555 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
556 sep->transport_proto);
Florin Corascea194d2017-10-02 00:18:51 -0700557 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
558 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700559 return kv6.value;
Florin Coras1c710452017-10-17 00:03:13 -0700560
Florin Corasa2ff7b82017-11-08 17:55:03 -0800561 if (use_rules)
562 {
Steven Luongc4b5d102024-07-30 13:44:01 -0700563 if (st->srtg_handle == SESSION_SRTG_HANDLE_INVALID)
564 return SESSION_INVALID_HANDLE;
Dave Barachb7b92992018-10-17 10:38:51 -0400565 clib_memset (&lcl6, 0, sizeof (lcl6));
Steven Luongc4b5d102024-07-30 13:44:01 -0700566 ai =
567 session_rules_table_lookup6 (st->srtg_handle, sep->transport_proto,
568 &lcl6, &sep->ip.ip6, 0, sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800569 if (session_lookup_action_index_is_valid (ai))
Florin Corasf8f516a2018-02-08 15:10:09 -0800570 return session_lookup_action_to_handle (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800571 }
Florin Coras68810622017-07-24 17:40:28 -0700572 }
Florin Coras3cbc04b2017-10-02 00:18:51 -0700573 return SESSION_INVALID_HANDLE;
574}
575
Florin Corasa2ff7b82017-11-08 17:55:03 -0800576/**
577 * Look up endpoint in local session table
578 *
579 * The result, for now, is an application index and it may in the future
580 * be extended to a more complicated "action object". The only action we
581 * emulate now is "drop" and for that we return a special app index.
582 *
583 * Lookup logic is to check in order:
584 * - the rules in the table (connect acls)
585 * - session sub-table for a listener
586 * - session sub-table for a local listener (zeroed addr)
587 *
588 * @param table_index table where the lookup should be done
589 * @param sep session endpoint to be looked up
Florin Corasf8f516a2018-02-08 15:10:09 -0800590 * @return session handle that can be interpreted as an adjacency
Florin Corasa2ff7b82017-11-08 17:55:03 -0800591 */
Florin Corasf8f516a2018-02-08 15:10:09 -0800592u64
Florin Corasa2ff7b82017-11-08 17:55:03 -0800593session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
Florin Coras68810622017-07-24 17:40:28 -0700594{
Florin Corascea194d2017-10-02 00:18:51 -0700595 session_table_t *st;
Florin Corasf0c1c962017-11-02 21:31:46 -0700596 u32 ai;
Florin Corascea194d2017-10-02 00:18:51 -0700597 int rv;
Florin Coras68810622017-07-24 17:40:28 -0700598
Florin Corascea194d2017-10-02 00:18:51 -0700599 st = session_table_get (table_index);
600 if (!st)
Steven Luongfc3464d2024-08-05 14:58:19 -0700601 return SESSION_INVALID_HANDLE;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800602 ASSERT (st->is_local);
603
Florin Corascea194d2017-10-02 00:18:51 -0700604 if (sep->is_ip4)
Florin Coras68810622017-07-24 17:40:28 -0700605 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800606 session_kv4_t kv4;
607 ip4_address_t lcl4;
608
Steven Luongc4b5d102024-07-30 13:44:01 -0700609 if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)
610 {
611 /*
612 * Check if endpoint has special rules associated
613 */
614 clib_memset (&lcl4, 0, sizeof (lcl4));
615 ai =
616 session_rules_table_lookup4 (st->srtg_handle, sep->transport_proto,
617 &lcl4, &sep->ip.ip4, 0, sep->port);
618 if (session_lookup_action_index_is_valid (ai))
619 return session_lookup_action_to_handle (ai);
620 }
Florin Corasa2ff7b82017-11-08 17:55:03 -0800621
622 /*
623 * Check if session endpoint is a listener
624 */
Florin Corascea194d2017-10-02 00:18:51 -0700625 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
626 sep->transport_proto);
627 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
628 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800629 return kv4.value;
Florin Corascea194d2017-10-02 00:18:51 -0700630
631 /*
632 * Zero out the ip. Logic is that connect to local ips, say
633 * 127.0.0.1:port, can match 0.0.0.0:port
634 */
Florin Coras477e91a2018-02-27 10:05:57 -0800635 if (ip4_is_local_host (&sep->ip.ip4))
636 {
637 kv4.key[0] = 0;
638 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
639 if (rv == 0)
640 return kv4.value;
641 }
642 else
643 {
644 kv4.key[0] = 0;
645 }
Florin Corasdbd44562017-11-09 19:30:17 -0800646
647 /*
648 * Zero out the port and check if we have proxy
649 */
650 kv4.key[1] = 0;
651 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
652 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800653 return kv4.value;
Florin Coras68810622017-07-24 17:40:28 -0700654 }
655 else
656 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800657 session_kv6_t kv6;
658 ip6_address_t lcl6;
659
Steven Luongc4b5d102024-07-30 13:44:01 -0700660 if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)
661 {
662 clib_memset (&lcl6, 0, sizeof (lcl6));
663 ai =
664 session_rules_table_lookup6 (st->srtg_handle, sep->transport_proto,
665 &lcl6, &sep->ip.ip6, 0, sep->port);
666 if (session_lookup_action_index_is_valid (ai))
667 return session_lookup_action_to_handle (ai);
668 }
Florin Corasa2ff7b82017-11-08 17:55:03 -0800669
Florin Corascea194d2017-10-02 00:18:51 -0700670 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
671 sep->transport_proto);
672 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
673 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800674 return kv6.value;
Florin Corascea194d2017-10-02 00:18:51 -0700675
676 /*
677 * Zero out the ip. Same logic as above.
678 */
Florin Coras477e91a2018-02-27 10:05:57 -0800679
680 if (ip6_is_local_host (&sep->ip.ip6))
681 {
682 kv6.key[0] = kv6.key[1] = 0;
683 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
684 if (rv == 0)
685 return kv6.value;
686 }
687 else
688 {
689 kv6.key[0] = kv6.key[1] = 0;
690 }
Florin Corasdbd44562017-11-09 19:30:17 -0800691
692 /*
693 * Zero out the port. Same logic as above.
694 */
695 kv6.key[4] = kv6.key[5] = 0;
696 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
697 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800698 return kv6.value;
Florin Coras04e53442017-07-16 17:12:15 -0700699 }
Florin Corasf8f516a2018-02-08 15:10:09 -0800700 return SESSION_INVALID_HANDLE;
Florin Coras04e53442017-07-16 17:12:15 -0700701}
702
Florin Coras288eaab2019-02-03 15:26:14 -0800703static inline session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700704session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl,
Florin Coras477e91a2018-02-27 10:05:57 -0800705 u16 lcl_port, u8 proto, u8 use_wildcard)
Florin Coras04e53442017-07-16 17:12:15 -0700706{
Florin Coras04e53442017-07-16 17:12:15 -0700707 session_kv4_t kv4;
708 int rv;
709
Florin Corasdbd44562017-11-09 19:30:17 -0800710 /*
711 * First, try a fully formed listener
712 */
Florin Coras04e53442017-07-16 17:12:15 -0700713 make_v4_listener_kv (&kv4, lcl, lcl_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700714 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700715 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700716 return listen_session_get ((u32) kv4.value);
Florin Coras04e53442017-07-16 17:12:15 -0700717
Florin Corasdbd44562017-11-09 19:30:17 -0800718 /*
719 * Zero out the lcl ip and check if any 0/0 port binds have been done
720 */
Florin Coras477e91a2018-02-27 10:05:57 -0800721 if (use_wildcard)
722 {
723 kv4.key[0] = 0;
724 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
725 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700726 return listen_session_get ((u32) kv4.value);
Florin Coras477e91a2018-02-27 10:05:57 -0800727 }
728 else
729 {
730 kv4.key[0] = 0;
731 }
Florin Coras04e53442017-07-16 17:12:15 -0700732
Florin Corasdbd44562017-11-09 19:30:17 -0800733 /*
734 * Zero out port and check if we have a proxy set up for our ip
735 */
736 make_v4_proxy_kv (&kv4, lcl, proto);
737 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
738 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700739 return listen_session_get ((u32) kv4.value);
Florin Corasdbd44562017-11-09 19:30:17 -0800740
Florin Coras04e53442017-07-16 17:12:15 -0700741 return 0;
742}
743
Florin Coras288eaab2019-02-03 15:26:14 -0800744session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700745session_lookup_listener4 (u32 fib_index, ip4_address_t * lcl, u16 lcl_port,
Yu Pingb092b772019-12-27 04:04:33 +0800746 u8 proto, u8 use_wildcard)
Florin Coras04e53442017-07-16 17:12:15 -0700747{
Florin Corascea194d2017-10-02 00:18:51 -0700748 session_table_t *st;
749 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
750 if (!st)
751 return 0;
Yu Pingb092b772019-12-27 04:04:33 +0800752 return session_lookup_listener4_i (st, lcl, lcl_port, proto, use_wildcard);
Florin Coras04e53442017-07-16 17:12:15 -0700753}
754
Florin Coras288eaab2019-02-03 15:26:14 -0800755static session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700756session_lookup_listener6_i (session_table_t * st, ip6_address_t * lcl,
Florin Coras477e91a2018-02-27 10:05:57 -0800757 u16 lcl_port, u8 proto, u8 ip_wildcard)
Florin Coras04e53442017-07-16 17:12:15 -0700758{
Florin Coras04e53442017-07-16 17:12:15 -0700759 session_kv6_t kv6;
760 int rv;
761
762 make_v6_listener_kv (&kv6, lcl, lcl_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700763 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700764 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700765 return listen_session_get ((u32) kv6.value);
Florin Coras04e53442017-07-16 17:12:15 -0700766
767 /* Zero out the lcl ip */
Florin Coras477e91a2018-02-27 10:05:57 -0800768 if (ip_wildcard)
769 {
770 kv6.key[0] = kv6.key[1] = 0;
771 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
772 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700773 return listen_session_get ((u32) kv6.value);
Florin Coras477e91a2018-02-27 10:05:57 -0800774 }
775 else
776 {
777 kv6.key[0] = kv6.key[1] = 0;
778 }
Florin Coras04e53442017-07-16 17:12:15 -0700779
Florin Corasdbd44562017-11-09 19:30:17 -0800780 make_v6_proxy_kv (&kv6, lcl, proto);
781 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
782 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700783 return listen_session_get ((u32) kv6.value);
Florin Coras04e53442017-07-16 17:12:15 -0700784 return 0;
785}
786
Florin Coras288eaab2019-02-03 15:26:14 -0800787session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700788session_lookup_listener6 (u32 fib_index, ip6_address_t * lcl, u16 lcl_port,
Yu Pingb092b772019-12-27 04:04:33 +0800789 u8 proto, u8 use_wildcard)
Florin Coras04e53442017-07-16 17:12:15 -0700790{
Florin Corascea194d2017-10-02 00:18:51 -0700791 session_table_t *st;
792 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
793 if (!st)
794 return 0;
Yu Pingb092b772019-12-27 04:04:33 +0800795 return session_lookup_listener6_i (st, lcl, lcl_port, proto, use_wildcard);
Florin Coras04e53442017-07-16 17:12:15 -0700796}
797
Florin Coras477e91a2018-02-27 10:05:57 -0800798/**
799 * Lookup listener, exact or proxy (inaddr_any:0) match
800 */
Florin Coras288eaab2019-02-03 15:26:14 -0800801session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700802session_lookup_listener (u32 table_index, session_endpoint_t * sep)
Florin Coras04e53442017-07-16 17:12:15 -0700803{
Florin Corascea194d2017-10-02 00:18:51 -0700804 session_table_t *st;
805 st = session_table_get (table_index);
806 if (!st)
807 return 0;
808 if (sep->is_ip4)
809 return session_lookup_listener4_i (st, &sep->ip.ip4, sep->port,
Florin Coras477e91a2018-02-27 10:05:57 -0800810 sep->transport_proto, 0);
Florin Corascea194d2017-10-02 00:18:51 -0700811 else
812 return session_lookup_listener6_i (st, &sep->ip.ip6, sep->port,
Florin Coras477e91a2018-02-27 10:05:57 -0800813 sep->transport_proto, 0);
Florin Coras04e53442017-07-16 17:12:15 -0700814 return 0;
815}
816
Florin Coras9f1a5432019-03-10 21:03:20 -0700817/**
818 * Lookup listener wildcard match
819 */
820session_t *
821session_lookup_listener_wildcard (u32 table_index, session_endpoint_t * sep)
822{
823 session_table_t *st;
824 st = session_table_get (table_index);
825 if (!st)
826 return 0;
827 if (sep->is_ip4)
828 return session_lookup_listener4_i (st, &sep->ip.ip4, sep->port,
829 sep->transport_proto,
830 1 /* use_wildcard */ );
831 else
832 return session_lookup_listener6_i (st, &sep->ip.ip6, sep->port,
833 sep->transport_proto,
834 1 /* use_wildcard */ );
835 return 0;
836}
837
Florin Corascea194d2017-10-02 00:18:51 -0700838int
839session_lookup_add_half_open (transport_connection_t * tc, u64 value)
840{
841 session_table_t *st;
842 session_kv4_t kv4;
843 session_kv6_t kv6;
844
845 st = session_table_get_or_alloc_for_connection (tc);
846 if (!st)
847 return 0;
848 if (tc->is_ip4)
849 {
850 make_v4_ss_kv_from_tc (&kv4, tc);
851 kv4.value = value;
852 return clib_bihash_add_del_16_8 (&st->v4_half_open_hash, &kv4,
853 1 /* is_add */ );
854 }
855 else
856 {
857 make_v6_ss_kv_from_tc (&kv6, tc);
858 kv6.value = value;
859 return clib_bihash_add_del_48_8 (&st->v6_half_open_hash, &kv6,
860 1 /* is_add */ );
861 }
862}
863
864int
865session_lookup_del_half_open (transport_connection_t * tc)
866{
867 session_table_t *st;
868 session_kv4_t kv4;
869 session_kv6_t kv6;
870
871 st = session_table_get_for_connection (tc);
872 if (!st)
873 return -1;
874 if (tc->is_ip4)
875 {
876 make_v4_ss_kv_from_tc (&kv4, tc);
877 return clib_bihash_add_del_16_8 (&st->v4_half_open_hash, &kv4,
878 0 /* is_add */ );
879 }
880 else
881 {
882 make_v6_ss_kv_from_tc (&kv6, tc);
883 return clib_bihash_add_del_48_8 (&st->v6_half_open_hash, &kv6,
884 0 /* is_add */ );
885 }
886}
887
Florin Coras04e53442017-07-16 17:12:15 -0700888u64
Florin Corascea194d2017-10-02 00:18:51 -0700889session_lookup_half_open_handle (transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700890{
Florin Corascea194d2017-10-02 00:18:51 -0700891 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700892 session_kv4_t kv4;
893 session_kv6_t kv6;
894 int rv;
895
Florin Corascea194d2017-10-02 00:18:51 -0700896 st = session_table_get_for_fib_index (transport_connection_fib_proto (tc),
897 tc->fib_index);
898 if (!st)
899 return HALF_OPEN_LOOKUP_INVALID_VALUE;
900 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700901 {
Florin Corascea194d2017-10-02 00:18:51 -0700902 make_v4_ss_kv (&kv4, &tc->lcl_ip.ip4, &tc->rmt_ip.ip4, tc->lcl_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700903 tc->rmt_port, tc->proto);
Florin Corascea194d2017-10-02 00:18:51 -0700904 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700905 if (rv == 0)
906 return kv4.value;
Florin Corascea194d2017-10-02 00:18:51 -0700907 }
908 else
909 {
910 make_v6_ss_kv (&kv6, &tc->lcl_ip.ip6, &tc->rmt_ip.ip6, tc->lcl_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700911 tc->rmt_port, tc->proto);
Florin Corascea194d2017-10-02 00:18:51 -0700912 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700913 if (rv == 0)
914 return kv6.value;
Florin Coras04e53442017-07-16 17:12:15 -0700915 }
916 return HALF_OPEN_LOOKUP_INVALID_VALUE;
917}
918
919transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700920session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700921{
Florin Coras04e53442017-07-16 17:12:15 -0700922 if (handle != HALF_OPEN_LOOKUP_INVALID_VALUE)
Florin Corascea194d2017-10-02 00:18:51 -0700923 {
Florin Coras1ee78302019-02-05 15:51:15 -0800924 u32 sst = session_type_from_proto_and_ip (proto, is_ip4);
925 return transport_get_half_open (sst, handle & 0xFFFFFFFF);
Florin Corascea194d2017-10-02 00:18:51 -0700926 }
Florin Coras04e53442017-07-16 17:12:15 -0700927 return 0;
928}
929
Florin Corascea194d2017-10-02 00:18:51 -0700930/**
931 * Lookup connection with ip4 and transport layer information
932 *
933 * This is used on the fast path so it needs to be fast. Thereby,
934 * duplication of code and 'hacks' allowed.
935 *
936 * The lookup is incremental and returns whenever something is matched. The
937 * steps are:
938 * - Try to find an established session
Florin Corascea194d2017-10-02 00:18:51 -0700939 * - Try to find a half-open connection
Florin Coras1c710452017-10-17 00:03:13 -0700940 * - Try session rules table
Florin Corasa2ff7b82017-11-08 17:55:03 -0800941 * - Try to find a fully-formed or local source wildcarded (listener bound to
942 * all interfaces) listener session
Florin Corascea194d2017-10-02 00:18:51 -0700943 * - return 0
944 *
945 * @param fib_index index of fib wherein the connection was received
946 * @param lcl local ip4 address
947 * @param rmt remote ip4 address
948 * @param lcl_port local port
949 * @param rmt_port remote port
950 * @param proto transport protocol (e.g., tcp, udp)
951 * @param thread_index thread index for request
Florin Corasdff48db2017-11-19 18:06:58 -0800952 * @param is_filtered return flag that indicates if connection was filtered.
Florin Corascea194d2017-10-02 00:18:51 -0700953 *
954 * @return pointer to transport connection, if one is found, 0 otherwise
955 */
Florin Coras04e53442017-07-16 17:12:15 -0700956transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700957session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl,
958 ip4_address_t * rmt, u16 lcl_port,
Florin Corasdff48db2017-11-19 18:06:58 -0800959 u16 rmt_port, u8 proto, u32 thread_index,
Florin Corasb5e55a22019-01-10 12:42:47 -0800960 u8 * result)
Florin Coras04e53442017-07-16 17:12:15 -0700961{
Florin Corascea194d2017-10-02 00:18:51 -0700962 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700963 session_kv4_t kv4;
Florin Coras288eaab2019-02-03 15:26:14 -0800964 session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800965 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -0700966 int rv;
967
Florin Corascea194d2017-10-02 00:18:51 -0700968 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
969 if (PREDICT_FALSE (!st))
970 return 0;
971
Florin Corasa2ff7b82017-11-08 17:55:03 -0800972 /*
973 * Lookup session amongst established ones
974 */
Florin Coras04e53442017-07-16 17:12:15 -0700975 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700976 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700977 if (rv == 0)
978 {
Florin Corasb5e55a22019-01-10 12:42:47 -0800979 if (PREDICT_FALSE ((u32) (kv4.value >> 32) != thread_index))
980 {
981 *result = SESSION_LOOKUP_RESULT_WRONG_THREAD;
982 return 0;
983 }
Florin Corascea194d2017-10-02 00:18:51 -0700984 s = session_get (kv4.value & 0xFFFFFFFFULL, thread_index);
Florin Coras1ee78302019-02-05 15:51:15 -0800985 return transport_get_connection (proto, s->connection_index,
986 thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700987 }
988
Florin Corasa2ff7b82017-11-08 17:55:03 -0800989 /*
990 * Try half-open connections
991 */
Florin Corascea194d2017-10-02 00:18:51 -0700992 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700993 if (rv == 0)
Florin Coras1ee78302019-02-05 15:51:15 -0800994 return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF);
Florin Coras1c710452017-10-17 00:03:13 -0700995
Steven Luongc4b5d102024-07-30 13:44:01 -0700996 if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)
Florin Corasa2ff7b82017-11-08 17:55:03 -0800997 {
Steven Luongc4b5d102024-07-30 13:44:01 -0700998 /*
999 * Check the session rules table
1000 */
1001 action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl,
1002 rmt, lcl_port, rmt_port);
1003 if (session_lookup_action_index_is_valid (action_index))
Florin Corasb5e55a22019-01-10 12:42:47 -08001004 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001005 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1006 {
1007 *result = SESSION_LOOKUP_RESULT_FILTERED;
1008 return 0;
1009 }
1010 if ((s = session_lookup_action_to_session (action_index,
1011 FIB_PROTOCOL_IP4, proto)))
1012 return transport_get_listener (proto, s->connection_index);
Florin Corasb5e55a22019-01-10 12:42:47 -08001013 return 0;
1014 }
Florin Corasa2ff7b82017-11-08 17:55:03 -08001015 }
1016
1017 /*
1018 * If nothing is found, check if any listener is available
1019 */
Florin Coras477e91a2018-02-27 10:05:57 -08001020 s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001021 if (s)
Florin Coras1ee78302019-02-05 15:51:15 -08001022 return transport_get_listener (proto, s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001023
1024 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001025}
1026
Florin Corascea194d2017-10-02 00:18:51 -07001027/**
1028 * Lookup connection with ip4 and transport layer information
1029 *
Florin Corasb5e55a22019-01-10 12:42:47 -08001030 * Not optimized. Lookup logic is identical to that of
1031 * @ref session_lookup_connection_wt4
Florin Corascea194d2017-10-02 00:18:51 -07001032 *
1033 * @param fib_index index of the fib wherein the connection was received
1034 * @param lcl local ip4 address
1035 * @param rmt remote ip4 address
1036 * @param lcl_port local port
1037 * @param rmt_port remote port
1038 * @param proto transport protocol (e.g., tcp, udp)
1039 *
1040 * @return pointer to transport connection, if one is found, 0 otherwise
1041 */
Florin Coras04e53442017-07-16 17:12:15 -07001042transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -07001043session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl,
1044 ip4_address_t * rmt, u16 lcl_port, u16 rmt_port,
1045 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -07001046{
Florin Corascea194d2017-10-02 00:18:51 -07001047 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -07001048 session_kv4_t kv4;
Florin Coras288eaab2019-02-03 15:26:14 -08001049 session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001050 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -07001051 int rv;
1052
Florin Corascea194d2017-10-02 00:18:51 -07001053 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
1054 if (PREDICT_FALSE (!st))
1055 return 0;
1056
Florin Corasa2ff7b82017-11-08 17:55:03 -08001057 /*
1058 * Lookup session amongst established ones
1059 */
Florin Coras04e53442017-07-16 17:12:15 -07001060 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -07001061 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -07001062 if (rv == 0)
1063 {
Florin Corascea194d2017-10-02 00:18:51 -07001064 s = session_get_from_handle (kv4.value);
Florin Coras1ee78302019-02-05 15:51:15 -08001065 return transport_get_connection (proto, s->connection_index,
1066 s->thread_index);
Florin Coras04e53442017-07-16 17:12:15 -07001067 }
1068
Florin Corasa2ff7b82017-11-08 17:55:03 -08001069 /*
1070 * Try half-open connections
1071 */
Florin Corascea194d2017-10-02 00:18:51 -07001072 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -07001073 if (rv == 0)
Florin Coras1ee78302019-02-05 15:51:15 -08001074 return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001075
Steven Luongc4b5d102024-07-30 13:44:01 -07001076 if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)
Florin Corasa2ff7b82017-11-08 17:55:03 -08001077 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001078 /*
1079 * Check the session rules table
1080 */
1081 action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl,
1082 rmt, lcl_port, rmt_port);
1083 if (session_lookup_action_index_is_valid (action_index))
1084 {
1085 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1086 return 0;
1087 if ((s = session_lookup_action_to_session (action_index,
1088 FIB_PROTOCOL_IP4, proto)))
1089 return transport_get_listener (proto, s->connection_index);
1090 return 0;
1091 }
Florin Corasa2ff7b82017-11-08 17:55:03 -08001092 }
1093
1094 /*
1095 * If nothing is found, check if any listener is available
1096 */
Florin Coras477e91a2018-02-27 10:05:57 -08001097 s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001098 if (s)
Florin Coras1ee78302019-02-05 15:51:15 -08001099 return transport_get_listener (proto, s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001100
1101 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001102}
1103
Florin Corascea194d2017-10-02 00:18:51 -07001104/**
1105 * Lookup session with ip4 and transport layer information
1106 *
Florin Coras6bd8d3f2022-03-14 21:17:25 -07001107 * Important note: this may look into another thread's pool table
Florin Coras3cbc04b2017-10-02 00:18:51 -07001108 *
1109 * Lookup logic is similar to that of @ref session_lookup_connection_wt4 but
1110 * this returns a session as opposed to a transport connection and it does not
1111 * try to lookup half-open sessions.
1112 *
1113 * Typically used by dgram connections
Florin Corascea194d2017-10-02 00:18:51 -07001114 */
Florin Coras288eaab2019-02-03 15:26:14 -08001115session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001116session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt,
1117 u16 lcl_port, u16 rmt_port, u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -07001118{
Florin Corascea194d2017-10-02 00:18:51 -07001119 session_table_t *st;
1120 session_kv4_t kv4;
Florin Coras288eaab2019-02-03 15:26:14 -08001121 session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001122 u32 action_index;
Florin Corascea194d2017-10-02 00:18:51 -07001123 int rv;
1124
1125 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
1126 if (PREDICT_FALSE (!st))
1127 return 0;
1128
Florin Corasa2ff7b82017-11-08 17:55:03 -08001129 /*
1130 * Lookup session amongst established ones
1131 */
Florin Corascea194d2017-10-02 00:18:51 -07001132 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
1133 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
1134 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001135 return session_get_from_handle_safe (kv4.value);
Florin Corascea194d2017-10-02 00:18:51 -07001136
Steven Luongc4b5d102024-07-30 13:44:01 -07001137 if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)
Florin Corasa2ff7b82017-11-08 17:55:03 -08001138 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001139 /*
1140 * Check the session rules table
1141 */
1142 action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl,
1143 rmt, lcl_port, rmt_port);
1144 if (session_lookup_action_index_is_valid (action_index))
1145 {
1146 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1147 return 0;
1148 return session_lookup_action_to_session (action_index,
1149 FIB_PROTOCOL_IP4, proto);
1150 }
Florin Corasa2ff7b82017-11-08 17:55:03 -08001151 }
1152
1153 /*
1154 * If nothing is found, check if any listener is available
1155 */
Florin Coras477e91a2018-02-27 10:05:57 -08001156 if ((s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1)))
Florin Corascea194d2017-10-02 00:18:51 -07001157 return s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001158
1159 return 0;
Florin Corascea194d2017-10-02 00:18:51 -07001160}
1161
1162/**
1163 * Lookup connection with ip6 and transport layer information
1164 *
1165 * This is used on the fast path so it needs to be fast. Thereby,
1166 * duplication of code and 'hacks' allowed.
1167 *
1168 * The lookup is incremental and returns whenever something is matched. The
1169 * steps are:
1170 * - Try to find an established session
Florin Corascea194d2017-10-02 00:18:51 -07001171 * - Try to find a half-open connection
Florin Coras1c710452017-10-17 00:03:13 -07001172 * - Try session rules table
Florin Corasa2ff7b82017-11-08 17:55:03 -08001173 * - Try to find a fully-formed or local source wildcarded (listener bound to
1174 * all interfaces) listener session
Florin Corascea194d2017-10-02 00:18:51 -07001175 * - return 0
1176 *
1177 * @param fib_index index of the fib wherein the connection was received
1178 * @param lcl local ip6 address
1179 * @param rmt remote ip6 address
1180 * @param lcl_port local port
1181 * @param rmt_port remote port
1182 * @param proto transport protocol (e.g., tcp, udp)
1183 * @param thread_index thread index for request
1184 *
1185 * @return pointer to transport connection, if one is found, 0 otherwise
1186 */
1187transport_connection_t *
1188session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl,
1189 ip6_address_t * rmt, u16 lcl_port,
Florin Corasdff48db2017-11-19 18:06:58 -08001190 u16 rmt_port, u8 proto, u32 thread_index,
Florin Corasb5e55a22019-01-10 12:42:47 -08001191 u8 * result)
Florin Corascea194d2017-10-02 00:18:51 -07001192{
1193 session_table_t *st;
Florin Coras288eaab2019-02-03 15:26:14 -08001194 session_t *s;
Florin Coras04e53442017-07-16 17:12:15 -07001195 session_kv6_t kv6;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001196 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -07001197 int rv;
1198
Florin Corascea194d2017-10-02 00:18:51 -07001199 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1200 if (PREDICT_FALSE (!st))
1201 return 0;
1202
Florin Coras04e53442017-07-16 17:12:15 -07001203 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -07001204 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001205 if (rv == 0)
1206 {
Florin Corasb5e55a22019-01-10 12:42:47 -08001207 if (PREDICT_FALSE ((u32) (kv6.value >> 32) != thread_index))
1208 {
1209 *result = SESSION_LOOKUP_RESULT_WRONG_THREAD;
1210 return 0;
1211 }
Florin Corascea194d2017-10-02 00:18:51 -07001212 s = session_get (kv6.value & 0xFFFFFFFFULL, thread_index);
Florin Coras1ee78302019-02-05 15:51:15 -08001213 return transport_get_connection (proto, s->connection_index,
1214 thread_index);
Florin Coras04e53442017-07-16 17:12:15 -07001215 }
1216
Florin Corasa2ff7b82017-11-08 17:55:03 -08001217 /* Try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -07001218 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001219 if (rv == 0)
Florin Coras1ee78302019-02-05 15:51:15 -08001220 return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF);
Florin Coras04e53442017-07-16 17:12:15 -07001221
Steven Luongc4b5d102024-07-30 13:44:01 -07001222 if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)
Florin Corasa2ff7b82017-11-08 17:55:03 -08001223 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001224 /* Check the session rules table */
1225 action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl,
1226 rmt, lcl_port, rmt_port);
1227 if (session_lookup_action_index_is_valid (action_index))
Florin Corasb5e55a22019-01-10 12:42:47 -08001228 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001229 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1230 {
1231 *result = SESSION_LOOKUP_RESULT_FILTERED;
1232 return 0;
1233 }
1234 if ((s = session_lookup_action_to_session (action_index,
1235 FIB_PROTOCOL_IP6, proto)))
1236 return transport_get_listener (proto, s->connection_index);
Florin Corasb5e55a22019-01-10 12:42:47 -08001237 return 0;
1238 }
Florin Corasa2ff7b82017-11-08 17:55:03 -08001239 }
1240
1241 /* If nothing is found, check if any listener is available */
Florin Coras477e91a2018-02-27 10:05:57 -08001242 s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001243 if (s)
Florin Coras1ee78302019-02-05 15:51:15 -08001244 return transport_get_listener (proto, s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001245
1246 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001247}
1248
Florin Corascea194d2017-10-02 00:18:51 -07001249/**
1250 * Lookup connection with ip6 and transport layer information
1251 *
1252 * Not optimized. This is used on the fast path so it needs to be fast.
1253 * Thereby, duplication of code and 'hacks' allowed. Lookup logic is identical
1254 * to that of @ref session_lookup_connection_wt4
1255 *
1256 * @param fib_index index of the fib wherein the connection was received
1257 * @param lcl local ip6 address
1258 * @param rmt remote ip6 address
1259 * @param lcl_port local port
1260 * @param rmt_port remote port
1261 * @param proto transport protocol (e.g., tcp, udp)
1262 *
1263 * @return pointer to transport connection, if one is found, 0 otherwise
1264 */
Florin Coras04e53442017-07-16 17:12:15 -07001265transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -07001266session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl,
1267 ip6_address_t * rmt, u16 lcl_port, u16 rmt_port,
1268 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -07001269{
Florin Corascea194d2017-10-02 00:18:51 -07001270 session_table_t *st;
Florin Coras288eaab2019-02-03 15:26:14 -08001271 session_t *s;
Florin Coras04e53442017-07-16 17:12:15 -07001272 session_kv6_t kv6;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001273 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -07001274 int rv;
1275
Florin Corascea194d2017-10-02 00:18:51 -07001276 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1277 if (PREDICT_FALSE (!st))
1278 return 0;
1279
Florin Coras04e53442017-07-16 17:12:15 -07001280 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -07001281 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001282 if (rv == 0)
1283 {
Florin Corascea194d2017-10-02 00:18:51 -07001284 s = session_get_from_handle (kv6.value);
Florin Coras1ee78302019-02-05 15:51:15 -08001285 return transport_get_connection (proto, s->connection_index,
1286 s->thread_index);
Florin Coras04e53442017-07-16 17:12:15 -07001287 }
1288
Florin Corasa2ff7b82017-11-08 17:55:03 -08001289 /* Try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -07001290 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001291 if (rv == 0)
Florin Coras1ee78302019-02-05 15:51:15 -08001292 return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF);
Florin Coras04e53442017-07-16 17:12:15 -07001293
Steven Luongc4b5d102024-07-30 13:44:01 -07001294 if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)
Florin Corasa2ff7b82017-11-08 17:55:03 -08001295 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001296 /* Check the session rules table */
1297 action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl,
1298 rmt, lcl_port, rmt_port);
1299 if (session_lookup_action_index_is_valid (action_index))
1300 {
1301 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1302 return 0;
1303 if ((s = session_lookup_action_to_session (action_index,
1304 FIB_PROTOCOL_IP6, proto)))
1305 return transport_get_listener (proto, s->connection_index);
1306 return 0;
1307 }
Florin Corasa2ff7b82017-11-08 17:55:03 -08001308 }
1309
1310 /* If nothing is found, check if any listener is available */
Florin Coras477e91a2018-02-27 10:05:57 -08001311 s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001312 if (s)
Florin Coras1ee78302019-02-05 15:51:15 -08001313 return transport_get_listener (proto, s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001314
1315 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001316}
1317
Florin Corascea194d2017-10-02 00:18:51 -07001318/**
1319 * Lookup session with ip6 and transport layer information
1320 *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001321 * Important note: this may look into another thread's pool table and
1322 * register as 'peeker'. Caller should call @ref session_pool_remove_peeker as
1323 * if needed as soon as possible.
1324 *
1325 * Lookup logic is similar to that of @ref session_lookup_connection_wt6 but
1326 * this returns a session as opposed to a transport connection and it does not
1327 * try to lookup half-open sessions.
1328 *
1329 * Typically used by dgram connections
Florin Corascea194d2017-10-02 00:18:51 -07001330 */
Florin Coras288eaab2019-02-03 15:26:14 -08001331session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001332session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt,
1333 u16 lcl_port, u16 rmt_port, u8 proto)
Florin Corascea194d2017-10-02 00:18:51 -07001334{
1335 session_table_t *st;
1336 session_kv6_t kv6;
Florin Coras288eaab2019-02-03 15:26:14 -08001337 session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001338 u32 action_index;
Florin Corascea194d2017-10-02 00:18:51 -07001339 int rv;
1340
1341 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1342 if (PREDICT_FALSE (!st))
1343 return 0;
1344
1345 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
1346 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
1347 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001348 return session_get_from_handle_safe (kv6.value);
Florin Corascea194d2017-10-02 00:18:51 -07001349
Steven Luongc4b5d102024-07-30 13:44:01 -07001350 if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)
Florin Corasa2ff7b82017-11-08 17:55:03 -08001351 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001352 /* Check the session rules table */
1353 action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl,
1354 rmt, lcl_port, rmt_port);
1355 if (session_lookup_action_index_is_valid (action_index))
1356 {
1357 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1358 return 0;
1359 return session_lookup_action_to_session (action_index,
1360 FIB_PROTOCOL_IP6, proto);
1361 }
Florin Corasa2ff7b82017-11-08 17:55:03 -08001362 }
1363
Florin Corascea194d2017-10-02 00:18:51 -07001364 /* If nothing is found, check if any listener is available */
Florin Coras477e91a2018-02-27 10:05:57 -08001365 if ((s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1)))
Florin Corascea194d2017-10-02 00:18:51 -07001366 return s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001367 return 0;
Florin Corascea194d2017-10-02 00:18:51 -07001368}
1369
Florin Coras57660d92020-04-04 22:45:34 +00001370transport_connection_t *
1371session_lookup_connection (u32 fib_index, ip46_address_t * lcl,
1372 ip46_address_t * rmt, u16 lcl_port, u16 rmt_port,
1373 u8 proto, u8 is_ip4)
1374{
1375 if (is_ip4)
1376 return session_lookup_connection4 (fib_index, &lcl->ip4, &rmt->ip4,
1377 lcl_port, rmt_port, proto);
1378 else
1379 return session_lookup_connection6 (fib_index, &lcl->ip6, &rmt->ip6,
1380 lcl_port, rmt_port, proto);
1381}
1382
Filip Tehlar0028e6f2023-06-28 10:47:32 +02001383session_error_t
1384vnet_session_rule_add_del (session_rule_add_del_args_t *args)
Florin Coras1c710452017-10-17 00:03:13 -07001385{
1386 app_namespace_t *app_ns = app_namespace_get (args->appns_index);
1387 session_table_t *st;
1388 u32 fib_index;
1389 u8 fib_proto;
Florin Corasc1a42652019-02-08 18:27:29 -08001390 int rv = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001391
1392 if (!app_ns)
Filip Tehlar0028e6f2023-06-28 10:47:32 +02001393 return SESSION_E_INVALID_NS;
Florin Corasc1a42652019-02-08 18:27:29 -08001394
Florin Coras1c710452017-10-17 00:03:13 -07001395 if (args->scope > 3)
Filip Tehlar0028e6f2023-06-28 10:47:32 +02001396 return SESSION_E_INVALID;
Florin Corasc1a42652019-02-08 18:27:29 -08001397
Florin Corasc97a7392017-11-05 23:07:07 -08001398 if (args->transport_proto != TRANSPORT_PROTO_TCP
1399 && args->transport_proto != TRANSPORT_PROTO_UDP)
Filip Tehlar0028e6f2023-06-28 10:47:32 +02001400 return SESSION_E_INVALID;
Florin Corasc1a42652019-02-08 18:27:29 -08001401
Florin Coras1c710452017-10-17 00:03:13 -07001402 if ((args->scope & SESSION_RULE_SCOPE_GLOBAL) || args->scope == 0)
1403 {
1404 fib_proto = args->table_args.rmt.fp_proto;
1405 fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1406 st = session_table_get_for_fib_index (fib_proto, fib_index);
Steven Luongc4b5d102024-07-30 13:44:01 -07001407 session_rules_table_init (st, fib_proto);
1408 if ((rv = session_rules_table_add_del (
1409 st->srtg_handle, args->transport_proto, &args->table_args)))
Florin Corasc1a42652019-02-08 18:27:29 -08001410 return rv;
Florin Coras1c710452017-10-17 00:03:13 -07001411 }
1412 if (args->scope & SESSION_RULE_SCOPE_LOCAL)
1413 {
Dave Barachb7b92992018-10-17 10:38:51 -04001414 clib_memset (&args->table_args.lcl, 0, sizeof (args->table_args.lcl));
Florin Corasa2ff7b82017-11-08 17:55:03 -08001415 args->table_args.lcl.fp_proto = args->table_args.rmt.fp_proto;
1416 args->table_args.lcl_port = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001417 st = app_namespace_get_local_table (app_ns);
Steven Luongc4b5d102024-07-30 13:44:01 -07001418 session_rules_table_init (st, args->table_args.rmt.fp_proto);
1419 rv = session_rules_table_add_del (st->srtg_handle, args->transport_proto,
1420 &args->table_args);
Florin Coras1c710452017-10-17 00:03:13 -07001421 }
Florin Corasc1a42652019-02-08 18:27:29 -08001422 return rv;
Florin Coras1c710452017-10-17 00:03:13 -07001423}
1424
Steven Luong5682ca82024-07-17 16:16:05 -07001425static void
1426session_lookup_fib_table_lock (u32 fib_index, u32 protocol)
1427{
1428 fib_table_lock (fib_index, protocol, sl_main.fib_src);
1429 vec_validate (fib_index_to_lock_count[protocol], fib_index);
1430 fib_index_to_lock_count[protocol][fib_index]++;
1431 ASSERT (fib_index_to_lock_count[protocol][fib_index] > 0);
1432}
1433
1434static void
1435session_lookup_fib_table_unlock (u32 fib_index, u32 protocol)
1436{
1437 fib_table_unlock (fib_index, protocol, sl_main.fib_src);
1438 ASSERT (fib_index_to_lock_count[protocol][fib_index] > 0);
1439 fib_index_to_lock_count[protocol][fib_index]--;
1440}
1441
Florin Coras6c36f532017-11-03 18:32:34 -07001442/**
1443 * Mark (global) tables as pertaining to app ns
1444 */
1445void
1446session_lookup_set_tables_appns (app_namespace_t * app_ns)
1447{
1448 session_table_t *st;
1449 u32 fib_index;
1450 u8 fp;
1451
1452 for (fp = 0; fp < ARRAY_LEN (fib_index_to_table_index); fp++)
1453 {
1454 fib_index = app_namespace_get_fib_index (app_ns, fp);
Florin Coras95cd8642019-12-30 21:53:19 -08001455 st = session_table_get_or_alloc (fp, fib_index);
Florin Coras6c36f532017-11-03 18:32:34 -07001456 if (st)
Steven Luong5682ca82024-07-17 16:16:05 -07001457 {
1458 st->appns_index = app_namespace_index (app_ns);
1459 session_lookup_fib_table_lock (fib_index, fp);
1460 }
Florin Coras6c36f532017-11-03 18:32:34 -07001461 }
1462}
1463
Florin Corascea194d2017-10-02 00:18:51 -07001464u8 *
1465format_ip4_session_lookup_kvp (u8 * s, va_list * args)
1466{
1467 clib_bihash_kv_16_8_t *kvp = va_arg (*args, clib_bihash_kv_16_8_t *);
Florin Coras2b81e3c2019-02-27 07:55:46 -08001468 u32 is_local = va_arg (*args, u32);
Florin Coras15531972018-08-12 23:50:53 -07001469 v4_connection_key_t *key = (v4_connection_key_t *) kvp->key;
Florin Coras288eaab2019-02-03 15:26:14 -08001470 session_t *session;
Florin Coras15531972018-08-12 23:50:53 -07001471 app_worker_t *app_wrk;
Florin Coras053a0e42018-11-13 15:52:38 -08001472 const u8 *app_name;
1473 u8 *str = 0;
Florin Corascea194d2017-10-02 00:18:51 -07001474
Florin Corascea194d2017-10-02 00:18:51 -07001475 if (!is_local)
1476 {
1477 session = session_get_from_handle (kvp->value);
Florin Coras15531972018-08-12 23:50:53 -07001478 app_wrk = app_worker_get (session->app_wrk_index);
1479 app_name = application_name_from_index (app_wrk->app_index);
Florin Coras561af9b2017-12-09 10:19:43 -08001480 str = format (0, "[%U] %U:%d->%U:%d", format_transport_proto_short,
1481 key->proto, format_ip4_address, &key->src,
1482 clib_net_to_host_u16 (key->src_port), format_ip4_address,
1483 &key->dst, clib_net_to_host_u16 (key->dst_port));
Florin Corascea194d2017-10-02 00:18:51 -07001484 s = format (s, "%-40v%-30v", str, app_name);
1485 }
1486 else
1487 {
Florin Coras2b81e3c2019-02-27 07:55:46 -08001488 session = session_get_from_handle (kvp->value);
1489 app_wrk = app_worker_get (session->app_wrk_index);
Florin Coras15531972018-08-12 23:50:53 -07001490 app_name = application_name_from_index (app_wrk->app_index);
Florin Coras561af9b2017-12-09 10:19:43 -08001491 str = format (0, "[%U] %U:%d", format_transport_proto_short, key->proto,
1492 format_ip4_address, &key->src,
1493 clib_net_to_host_u16 (key->src_port));
Florin Corascea194d2017-10-02 00:18:51 -07001494 s = format (s, "%-30v%-30v", str, app_name);
1495 }
Florin Corascea194d2017-10-02 00:18:51 -07001496 return s;
1497}
1498
1499typedef struct _ip4_session_table_show_ctx_t
1500{
1501 vlib_main_t *vm;
1502 u8 is_local;
1503} ip4_session_table_show_ctx_t;
1504
1505static int
1506ip4_session_table_show (clib_bihash_kv_16_8_t * kvp, void *arg)
1507{
1508 ip4_session_table_show_ctx_t *ctx = arg;
1509 vlib_cli_output (ctx->vm, "%U", format_ip4_session_lookup_kvp, kvp,
1510 ctx->is_local);
1511 return 1;
1512}
1513
1514void
1515session_lookup_show_table_entries (vlib_main_t * vm, session_table_t * table,
1516 u8 type, u8 is_local)
1517{
1518 ip4_session_table_show_ctx_t ctx = {
1519 .vm = vm,
1520 .is_local = is_local,
1521 };
1522 if (!is_local)
1523 vlib_cli_output (vm, "%-40s%-30s", "Session", "Application");
1524 else
1525 vlib_cli_output (vm, "%-30s%-30s", "Listener", "Application");
1526 switch (type)
1527 {
1528 /* main table v4 */
1529 case 0:
1530 ip4_session_table_walk (&table->v4_session_hash, ip4_session_table_show,
1531 &ctx);
1532 break;
1533 default:
1534 clib_warning ("not supported");
1535 }
1536}
Florin Coras66b11312017-07-31 17:18:03 -07001537
Florin Coras1c710452017-10-17 00:03:13 -07001538static clib_error_t *
1539session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
1540 vlib_cli_command_t * cmd)
1541{
Florin Corasc97a7392017-11-05 23:07:07 -08001542 u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen = 0, rmt_plen = 0;
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001543 clib_error_t *error = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001544 u32 appns_index, scope = 0;
1545 ip46_address_t lcl_ip, rmt_ip;
1546 u8 is_ip4 = 1, conn_set = 0;
1547 u8 fib_proto, is_add = 1, *ns_id = 0;
Florin Corasc97a7392017-11-05 23:07:07 -08001548 u8 *tag = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001549 app_namespace_t *app_ns;
Florin Corasc1a42652019-02-08 18:27:29 -08001550 int rv;
Florin Coras1c710452017-10-17 00:03:13 -07001551
Guanghua Zhangfcd5e122019-08-24 10:52:19 +08001552 session_cli_return_if_not_enabled ();
1553
Steven Luongc4b5d102024-07-30 13:44:01 -07001554 if (session_rule_table_is_enabled () == 0)
1555 return clib_error_return (0, "session rule table engine is not enabled");
1556
Dave Barachb7b92992018-10-17 10:38:51 -04001557 clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
1558 clib_memset (&rmt_ip, 0, sizeof (rmt_ip));
Florin Coras1c710452017-10-17 00:03:13 -07001559 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1560 {
1561 if (unformat (input, "del"))
1562 is_add = 0;
1563 else if (unformat (input, "add"))
1564 ;
1565 else if (unformat (input, "appns %_%v%_", &ns_id))
1566 ;
1567 else if (unformat (input, "scope global"))
1568 scope = SESSION_RULE_SCOPE_GLOBAL;
1569 else if (unformat (input, "scope local"))
1570 scope = SESSION_RULE_SCOPE_LOCAL;
1571 else if (unformat (input, "scope all"))
1572 scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1573 else if (unformat (input, "proto %U", unformat_transport_proto, &proto))
1574 ;
1575 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1576 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1577 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1578 &rmt_port))
1579 {
1580 is_ip4 = 1;
1581 conn_set = 1;
1582 }
1583 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1584 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1585 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1586 &rmt_port))
1587 {
1588 is_ip4 = 0;
1589 conn_set = 1;
1590 }
1591 else if (unformat (input, "action %d", &action))
1592 ;
Florin Corasc97a7392017-11-05 23:07:07 -08001593 else if (unformat (input, "tag %_%v%_", &tag))
1594 ;
Florin Coras1c710452017-10-17 00:03:13 -07001595 else
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001596 {
1597 error = clib_error_return (0, "unknown input `%U'",
1598 format_unformat_error, input);
1599 goto done;
1600 }
Florin Coras1c710452017-10-17 00:03:13 -07001601 }
1602
Florin Corasc97a7392017-11-05 23:07:07 -08001603 if (proto == ~0)
1604 {
1605 vlib_cli_output (vm, "proto must be set");
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001606 goto done;
Florin Corasc97a7392017-11-05 23:07:07 -08001607 }
1608 if (is_add && !conn_set && action == ~0)
1609 {
1610 vlib_cli_output (vm, "connection and action must be set for add");
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001611 goto done;
Florin Corasc97a7392017-11-05 23:07:07 -08001612 }
1613 if (!is_add && !tag && !conn_set)
1614 {
1615 vlib_cli_output (vm, "connection or tag must be set for delete");
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001616 goto done;
Florin Corasc97a7392017-11-05 23:07:07 -08001617 }
1618 if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN)
1619 {
1620 vlib_cli_output (vm, "tag too long (max u64)");
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001621 goto done;
Florin Corasc97a7392017-11-05 23:07:07 -08001622 }
Florin Coras1c710452017-10-17 00:03:13 -07001623
1624 if (ns_id)
1625 {
1626 app_ns = app_namespace_get_from_id (ns_id);
1627 if (!app_ns)
Florin Corasc97a7392017-11-05 23:07:07 -08001628 {
1629 vlib_cli_output (vm, "namespace %v does not exist", ns_id);
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001630 goto done;
Florin Corasc97a7392017-11-05 23:07:07 -08001631 }
Florin Coras1c710452017-10-17 00:03:13 -07001632 }
1633 else
1634 {
1635 app_ns = app_namespace_get_default ();
1636 }
1637 appns_index = app_namespace_index (app_ns);
1638
1639 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1640 session_rule_add_del_args_t args = {
zhanglimaoa04ebb82019-03-13 10:36:54 +08001641 .transport_proto = proto,
Florin Coras1c710452017-10-17 00:03:13 -07001642 .table_args.lcl.fp_addr = lcl_ip,
1643 .table_args.lcl.fp_len = lcl_plen,
1644 .table_args.lcl.fp_proto = fib_proto,
1645 .table_args.rmt.fp_addr = rmt_ip,
1646 .table_args.rmt.fp_len = rmt_plen,
1647 .table_args.rmt.fp_proto = fib_proto,
1648 .table_args.lcl_port = lcl_port,
1649 .table_args.rmt_port = rmt_port,
1650 .table_args.action_index = action,
1651 .table_args.is_add = is_add,
Florin Corasc97a7392017-11-05 23:07:07 -08001652 .table_args.tag = tag,
Florin Coras1c710452017-10-17 00:03:13 -07001653 .appns_index = appns_index,
1654 .scope = scope,
1655 };
Florin Corasc1a42652019-02-08 18:27:29 -08001656 if ((rv = vnet_session_rule_add_del (&args)))
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001657 error = clib_error_return (0, "rule add del returned %u", rv);
Florin Corasc1a42652019-02-08 18:27:29 -08001658
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001659done:
1660 vec_free (ns_id);
Florin Corasc97a7392017-11-05 23:07:07 -08001661 vec_free (tag);
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001662 return error;
Florin Coras1c710452017-10-17 00:03:13 -07001663}
1664
Florin Coras1c710452017-10-17 00:03:13 -07001665VLIB_CLI_COMMAND (session_rule_command, static) =
1666{
1667 .path = "session rule",
1668 .short_help = "session rule [add|del] appns <ns_id> proto <proto> "
1669 "<lcl-ip/plen> <lcl-port> <rmt-ip/plen> <rmt-port> action <action>",
1670 .function = session_rule_command_fn,
1671};
Florin Coras1c710452017-10-17 00:03:13 -07001672
Florin Coras7999e832017-10-31 01:51:04 -07001673void
1674session_lookup_dump_rules_table (u32 fib_index, u8 fib_proto,
1675 u8 transport_proto)
1676{
1677 vlib_main_t *vm = vlib_get_main ();
1678 session_table_t *st;
1679 st = session_table_get_for_fib_index (fib_index, fib_proto);
Steven Luongc4b5d102024-07-30 13:44:01 -07001680 if (st == 0)
1681 return;
1682 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1683 fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001684}
1685
1686void
1687session_lookup_dump_local_rules_table (u32 table_index, u8 fib_proto,
1688 u8 transport_proto)
1689{
1690 vlib_main_t *vm = vlib_get_main ();
1691 session_table_t *st;
1692 st = session_table_get (table_index);
Steven Luongc4b5d102024-07-30 13:44:01 -07001693 if (st == 0)
1694 return;
1695 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1696 fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001697}
1698
Florin Coras1c710452017-10-17 00:03:13 -07001699static clib_error_t *
1700show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input,
1701 vlib_cli_command_t * cmd)
1702{
1703 u32 transport_proto = ~0, lcl_port, rmt_port, lcl_plen, rmt_plen;
1704 u32 fib_index, scope = 0;
1705 ip46_address_t lcl_ip, rmt_ip;
1706 u8 is_ip4 = 1, show_one = 0;
1707 app_namespace_t *app_ns;
1708 session_table_t *st;
1709 u8 *ns_id = 0, fib_proto;
1710
Guanghua Zhangfcd5e122019-08-24 10:52:19 +08001711 session_cli_return_if_not_enabled ();
1712
Dave Barachb7b92992018-10-17 10:38:51 -04001713 clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
1714 clib_memset (&rmt_ip, 0, sizeof (rmt_ip));
Florin Coras1c710452017-10-17 00:03:13 -07001715 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1716 {
1717 if (unformat (input, "%U", unformat_transport_proto, &transport_proto))
1718 ;
1719 else if (unformat (input, "appns %_%v%_", &ns_id))
1720 ;
1721 else if (unformat (input, "scope global"))
Steven Luonge87a03f2024-07-18 09:10:48 -07001722 scope = SESSION_RULE_SCOPE_GLOBAL;
Florin Coras1c710452017-10-17 00:03:13 -07001723 else if (unformat (input, "scope local"))
Steven Luonge87a03f2024-07-18 09:10:48 -07001724 scope = SESSION_RULE_SCOPE_LOCAL;
Florin Coras1c710452017-10-17 00:03:13 -07001725 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1726 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1727 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1728 &rmt_port))
1729 {
1730 is_ip4 = 1;
1731 show_one = 1;
1732 }
1733 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1734 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1735 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1736 &rmt_port))
1737 {
1738 is_ip4 = 0;
1739 show_one = 1;
1740 }
1741 else
Steven Luong0a3b0b22024-08-06 13:28:09 -07001742 {
1743 vec_free (ns_id);
1744 return clib_error_return (0, "unknown input `%U'",
1745 format_unformat_error, input);
1746 }
Florin Coras1c710452017-10-17 00:03:13 -07001747 }
1748
1749 if (transport_proto == ~0)
1750 {
1751 vlib_cli_output (vm, "transport proto must be set");
Steven Luong0a3b0b22024-08-06 13:28:09 -07001752 goto done;
Florin Coras1c710452017-10-17 00:03:13 -07001753 }
1754
1755 if (ns_id)
1756 {
1757 app_ns = app_namespace_get_from_id (ns_id);
1758 if (!app_ns)
1759 {
1760 vlib_cli_output (vm, "appns %v doesn't exist", ns_id);
Steven Luong0a3b0b22024-08-06 13:28:09 -07001761 goto done;
Florin Coras1c710452017-10-17 00:03:13 -07001762 }
1763 }
1764 else
1765 {
1766 app_ns = app_namespace_get_default ();
1767 }
1768
Steven Luonge87a03f2024-07-18 09:10:48 -07001769 if (scope == SESSION_RULE_SCOPE_GLOBAL || scope == 0)
Florin Coras1c710452017-10-17 00:03:13 -07001770 {
1771 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1772 fib_index = is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
1773 st = session_table_get_for_fib_index (fib_proto, fib_index);
1774 }
1775 else
1776 {
1777 st = app_namespace_get_local_table (app_ns);
1778 }
1779
Steven Luongc4b5d102024-07-30 13:44:01 -07001780 if (session_rule_table_is_enabled () == 0)
1781 {
1782 vlib_cli_output (vm, "session rule table engine is not enabled");
1783 goto done;
1784 }
1785
Florin Coras1c710452017-10-17 00:03:13 -07001786 if (show_one)
1787 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001788 if (st)
1789 session_rules_table_show_rule (vm, st->srtg_handle, transport_proto,
1790 &lcl_ip, lcl_port, &rmt_ip, rmt_port,
1791 is_ip4);
Steven Luong0a3b0b22024-08-06 13:28:09 -07001792 goto done;
Florin Coras1c710452017-10-17 00:03:13 -07001793 }
1794
Florin Corasc97a7392017-11-05 23:07:07 -08001795 vlib_cli_output (vm, "%U rules table", format_transport_proto,
1796 transport_proto);
Steven Luonge87a03f2024-07-18 09:10:48 -07001797 if (scope == SESSION_RULE_SCOPE_LOCAL)
1798 {
1799 if (st)
1800 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001801 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1802 FIB_PROTOCOL_IP4);
1803 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1804 FIB_PROTOCOL_IP6);
Steven Luonge87a03f2024-07-18 09:10:48 -07001805 }
1806 }
1807 else
1808 {
1809 /*
1810 * 2 separate session tables for global entries, 1 for ip4 and 1 for ip6
1811 */
1812 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4,
1813 app_ns->ip4_fib_index);
1814 if (st)
Steven Luongc4b5d102024-07-30 13:44:01 -07001815 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1816 FIB_PROTOCOL_IP4);
Steven Luonge87a03f2024-07-18 09:10:48 -07001817
1818 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6,
1819 app_ns->ip6_fib_index);
1820 if (st)
Steven Luongc4b5d102024-07-30 13:44:01 -07001821 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1822 FIB_PROTOCOL_IP6);
Steven Luonge87a03f2024-07-18 09:10:48 -07001823 }
Steven Luong0a3b0b22024-08-06 13:28:09 -07001824done:
Florin Coras1c710452017-10-17 00:03:13 -07001825 vec_free (ns_id);
1826 return 0;
1827}
1828
Florin Coras1c710452017-10-17 00:03:13 -07001829VLIB_CLI_COMMAND (show_session_rules_command, static) =
1830{
1831 .path = "show session rules",
Florin Corasdff48db2017-11-19 18:06:58 -08001832 .short_help = "show session rules [<proto> appns <id> <lcl-ip/plen> "
1833 "<lcl-port> <rmt-ip/plen> <rmt-port> scope <scope>]",
Florin Coras1c710452017-10-17 00:03:13 -07001834 .function = show_session_rules_command_fn,
1835};
Florin Coras1c710452017-10-17 00:03:13 -07001836
Florin Coras894d0a62023-11-17 16:35:04 -08001837u8 *
1838format_session_lookup_tables (u8 *s, va_list *args)
1839{
1840 u32 fib_proto = va_arg (*args, u32);
1841 u32 *fibs, num_fibs = 0, fib_index, indent;
1842 session_table_t *st;
1843 u64 total_mem = 0;
1844
1845 fibs = fib_index_to_table_index[fib_proto];
1846
1847 for (fib_index = 0; fib_index < vec_len (fibs); fib_index++)
1848 {
1849 if (fibs[fib_index] == ~0)
1850 continue;
1851
1852 num_fibs += 1;
1853 st = session_table_get (fibs[fib_index]);
1854 total_mem += session_table_memory_size (st);
1855 }
1856
1857 indent = format_get_indent (s);
1858 s = format (s, "active fibs:\t%u\n", num_fibs);
1859 s = format (s, "%Umax fib-index:\t%u\n", format_white_space, indent,
1860 vec_len (fibs) - 1);
1861 s = format (s, "%Utable memory:\t%U\n", format_white_space, indent,
1862 format_memory_size, total_mem);
1863 s = format (s, "%Uvec memory:\t%U\n", format_white_space, indent,
1864 format_memory_size, vec_mem_size (fibs));
1865
1866 return s;
1867}
1868
1869static clib_error_t *
1870show_session_lookup_command_fn (vlib_main_t *vm, unformat_input_t *input,
1871 vlib_cli_command_t *cmd)
1872{
1873 session_table_t *st;
1874 u32 fib_index = ~0;
1875
1876 session_cli_return_if_not_enabled ();
1877 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1878 {
1879 if (unformat (input, "table %u", &fib_index))
1880 ;
1881 else
1882 return clib_error_return (0, "unknown input `%U'",
1883 format_unformat_error, input);
1884 }
1885
1886 if (fib_index != ~0)
1887 {
1888 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
1889 if (st)
1890 vlib_cli_output (vm, "%U", format_session_table, st);
1891 else
1892 vlib_cli_output (vm, "no ip4 table for fib-index %u", fib_index);
1893 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1894 if (st)
1895 vlib_cli_output (vm, "%U", format_session_table, st);
1896 else
1897 vlib_cli_output (vm, "no ip6 table for fib-index %u", fib_index);
1898 goto done;
1899 }
1900
1901 vlib_cli_output (vm, "ip4 fib lookup tables:\n %U",
1902 format_session_lookup_tables, FIB_PROTOCOL_IP4);
1903 vlib_cli_output (vm, "ip6 fib lookup tables:\n %U",
1904 format_session_lookup_tables, FIB_PROTOCOL_IP6);
1905
1906done:
1907 return 0;
1908}
1909
1910VLIB_CLI_COMMAND (show_session_lookup_command, static) = {
1911 .path = "show session lookup",
1912 .short_help = "show session lookup [table <fib-index>]",
1913 .function = show_session_lookup_command_fn,
1914};
1915
Florin Coras04e53442017-07-16 17:12:15 -07001916void
1917session_lookup_init (void)
1918{
Florin Corasf9bdc032024-02-02 13:01:07 -08001919 session_lookup_main_t *slm = &sl_main;
1920
1921 clib_spinlock_init (&slm->st_alloc_lock);
1922
Steven Luong5682ca82024-07-17 16:16:05 -07001923 /* We are not contributing any route to the fib. But we allocate a fib source
1924 * so that when we lock the fib table, we can view that we have a lock on the
1925 * particular fib table in case we wonder why the fib table is not free after
1926 * "ip table del"
1927 */
1928 slm->fib_src = fib_source_allocate (
1929 "session lookup", FIB_SOURCE_PRIORITY_LOW, FIB_SOURCE_BH_SIMPLE);
1930
Florin Corascea194d2017-10-02 00:18:51 -07001931 /*
1932 * Allocate default table and map it to fib_index 0
1933 */
1934 session_table_t *st = session_table_alloc ();
1935 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP4], 0);
1936 fib_index_to_table_index[FIB_PROTOCOL_IP4][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001937 st->active_fib_proto = FIB_PROTOCOL_IP4;
1938 session_table_init (st, FIB_PROTOCOL_IP4);
Florin Corascea194d2017-10-02 00:18:51 -07001939 st = session_table_alloc ();
1940 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP6], 0);
1941 fib_index_to_table_index[FIB_PROTOCOL_IP6][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001942 st->active_fib_proto = FIB_PROTOCOL_IP6;
1943 session_table_init (st, FIB_PROTOCOL_IP6);
Florin Coras04e53442017-07-16 17:12:15 -07001944}
1945
Steven Luong5682ca82024-07-17 16:16:05 -07001946void
1947session_lookup_table_cleanup (u32 fib_proto, u32 fib_index)
1948{
1949 session_table_t *st;
1950 u32 table_index;
1951
1952 session_lookup_fib_table_unlock (fib_index, fib_proto);
1953 if (fib_index_to_lock_count[fib_proto][fib_index] == 0)
1954 {
1955 table_index = session_lookup_get_index_for_fib (fib_proto, fib_index);
1956 st = session_table_get (table_index);
1957 if (st)
1958 {
1959 session_table_free (st, fib_proto);
1960 if (vec_len (fib_index_to_table_index[fib_proto]) > fib_index)
1961 fib_index_to_table_index[fib_proto][fib_index] = ~0;
1962 }
1963 }
1964}
1965
Florin Coras04e53442017-07-16 17:12:15 -07001966/*
1967 * fd.io coding-style-patch-verification: ON
1968 *
1969 * Local Variables:
1970 * eval: (c-set-style "gnu")
1971 * End:
1972 */