blob: 28a1feb1ed8924ce7af339ab37f0e6a670e8236a [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{
Steven Luonge38d9472024-11-06 13:47:26 -08001386 app_namespace_t *app_ns = app_namespace_get_if_valid (args->appns_index);
Florin Coras1c710452017-10-17 00:03:13 -07001387 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 Luonge38d9472024-11-06 13:47:26 -08001407 if (!st)
1408 return SESSION_E_INVALID;
Steven Luongc4b5d102024-07-30 13:44:01 -07001409 session_rules_table_init (st, fib_proto);
1410 if ((rv = session_rules_table_add_del (
1411 st->srtg_handle, args->transport_proto, &args->table_args)))
Florin Corasc1a42652019-02-08 18:27:29 -08001412 return rv;
Florin Coras1c710452017-10-17 00:03:13 -07001413 }
1414 if (args->scope & SESSION_RULE_SCOPE_LOCAL)
1415 {
Dave Barachb7b92992018-10-17 10:38:51 -04001416 clib_memset (&args->table_args.lcl, 0, sizeof (args->table_args.lcl));
Florin Corasa2ff7b82017-11-08 17:55:03 -08001417 args->table_args.lcl.fp_proto = args->table_args.rmt.fp_proto;
1418 args->table_args.lcl_port = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001419 st = app_namespace_get_local_table (app_ns);
Steven Luongc4b5d102024-07-30 13:44:01 -07001420 session_rules_table_init (st, args->table_args.rmt.fp_proto);
1421 rv = session_rules_table_add_del (st->srtg_handle, args->transport_proto,
1422 &args->table_args);
Florin Coras1c710452017-10-17 00:03:13 -07001423 }
Florin Corasc1a42652019-02-08 18:27:29 -08001424 return rv;
Florin Coras1c710452017-10-17 00:03:13 -07001425}
1426
Steven Luong5682ca82024-07-17 16:16:05 -07001427static void
1428session_lookup_fib_table_lock (u32 fib_index, u32 protocol)
1429{
1430 fib_table_lock (fib_index, protocol, sl_main.fib_src);
1431 vec_validate (fib_index_to_lock_count[protocol], fib_index);
1432 fib_index_to_lock_count[protocol][fib_index]++;
1433 ASSERT (fib_index_to_lock_count[protocol][fib_index] > 0);
1434}
1435
1436static void
1437session_lookup_fib_table_unlock (u32 fib_index, u32 protocol)
1438{
1439 fib_table_unlock (fib_index, protocol, sl_main.fib_src);
1440 ASSERT (fib_index_to_lock_count[protocol][fib_index] > 0);
1441 fib_index_to_lock_count[protocol][fib_index]--;
1442}
1443
Florin Coras6c36f532017-11-03 18:32:34 -07001444/**
1445 * Mark (global) tables as pertaining to app ns
1446 */
1447void
1448session_lookup_set_tables_appns (app_namespace_t * app_ns)
1449{
1450 session_table_t *st;
1451 u32 fib_index;
1452 u8 fp;
1453
1454 for (fp = 0; fp < ARRAY_LEN (fib_index_to_table_index); fp++)
1455 {
1456 fib_index = app_namespace_get_fib_index (app_ns, fp);
Steven Luong2e67a3f2024-11-08 08:35:14 -08001457 if (fib_index == ~0)
1458 continue;
Florin Coras95cd8642019-12-30 21:53:19 -08001459 st = session_table_get_or_alloc (fp, fib_index);
Florin Coras6c36f532017-11-03 18:32:34 -07001460 if (st)
Steven Luong5682ca82024-07-17 16:16:05 -07001461 {
Steven Luonge0c4e6e2024-10-22 10:44:07 -07001462 vec_add1 (st->appns_index, app_namespace_index (app_ns));
Steven Luong5682ca82024-07-17 16:16:05 -07001463 session_lookup_fib_table_lock (fib_index, fp);
1464 }
Florin Coras6c36f532017-11-03 18:32:34 -07001465 }
1466}
1467
Florin Corascea194d2017-10-02 00:18:51 -07001468u8 *
1469format_ip4_session_lookup_kvp (u8 * s, va_list * args)
1470{
1471 clib_bihash_kv_16_8_t *kvp = va_arg (*args, clib_bihash_kv_16_8_t *);
Florin Coras2b81e3c2019-02-27 07:55:46 -08001472 u32 is_local = va_arg (*args, u32);
Florin Coras15531972018-08-12 23:50:53 -07001473 v4_connection_key_t *key = (v4_connection_key_t *) kvp->key;
Florin Coras288eaab2019-02-03 15:26:14 -08001474 session_t *session;
Florin Coras15531972018-08-12 23:50:53 -07001475 app_worker_t *app_wrk;
Florin Coras053a0e42018-11-13 15:52:38 -08001476 const u8 *app_name;
1477 u8 *str = 0;
Florin Corascea194d2017-10-02 00:18:51 -07001478
Florin Corascea194d2017-10-02 00:18:51 -07001479 if (!is_local)
1480 {
1481 session = session_get_from_handle (kvp->value);
Florin Coras15531972018-08-12 23:50:53 -07001482 app_wrk = app_worker_get (session->app_wrk_index);
1483 app_name = application_name_from_index (app_wrk->app_index);
Florin Coras561af9b2017-12-09 10:19:43 -08001484 str = format (0, "[%U] %U:%d->%U:%d", format_transport_proto_short,
1485 key->proto, format_ip4_address, &key->src,
1486 clib_net_to_host_u16 (key->src_port), format_ip4_address,
1487 &key->dst, clib_net_to_host_u16 (key->dst_port));
Florin Corascea194d2017-10-02 00:18:51 -07001488 s = format (s, "%-40v%-30v", str, app_name);
1489 }
1490 else
1491 {
Florin Coras2b81e3c2019-02-27 07:55:46 -08001492 session = session_get_from_handle (kvp->value);
1493 app_wrk = app_worker_get (session->app_wrk_index);
Florin Coras15531972018-08-12 23:50:53 -07001494 app_name = application_name_from_index (app_wrk->app_index);
Florin Coras561af9b2017-12-09 10:19:43 -08001495 str = format (0, "[%U] %U:%d", format_transport_proto_short, key->proto,
1496 format_ip4_address, &key->src,
1497 clib_net_to_host_u16 (key->src_port));
Florin Corascea194d2017-10-02 00:18:51 -07001498 s = format (s, "%-30v%-30v", str, app_name);
1499 }
Florin Corascea194d2017-10-02 00:18:51 -07001500 return s;
1501}
1502
1503typedef struct _ip4_session_table_show_ctx_t
1504{
1505 vlib_main_t *vm;
1506 u8 is_local;
1507} ip4_session_table_show_ctx_t;
1508
1509static int
1510ip4_session_table_show (clib_bihash_kv_16_8_t * kvp, void *arg)
1511{
1512 ip4_session_table_show_ctx_t *ctx = arg;
1513 vlib_cli_output (ctx->vm, "%U", format_ip4_session_lookup_kvp, kvp,
1514 ctx->is_local);
1515 return 1;
1516}
1517
1518void
1519session_lookup_show_table_entries (vlib_main_t * vm, session_table_t * table,
1520 u8 type, u8 is_local)
1521{
1522 ip4_session_table_show_ctx_t ctx = {
1523 .vm = vm,
1524 .is_local = is_local,
1525 };
1526 if (!is_local)
1527 vlib_cli_output (vm, "%-40s%-30s", "Session", "Application");
1528 else
1529 vlib_cli_output (vm, "%-30s%-30s", "Listener", "Application");
1530 switch (type)
1531 {
1532 /* main table v4 */
1533 case 0:
1534 ip4_session_table_walk (&table->v4_session_hash, ip4_session_table_show,
1535 &ctx);
1536 break;
1537 default:
1538 clib_warning ("not supported");
1539 }
1540}
Florin Coras66b11312017-07-31 17:18:03 -07001541
Florin Coras1c710452017-10-17 00:03:13 -07001542static clib_error_t *
1543session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
1544 vlib_cli_command_t * cmd)
1545{
Florin Corasc97a7392017-11-05 23:07:07 -08001546 u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen = 0, rmt_plen = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001547 u32 appns_index, scope = 0;
1548 ip46_address_t lcl_ip, rmt_ip;
1549 u8 is_ip4 = 1, conn_set = 0;
1550 u8 fib_proto, is_add = 1, *ns_id = 0;
Florin Corasc97a7392017-11-05 23:07:07 -08001551 u8 *tag = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001552 app_namespace_t *app_ns;
Florin Corasc1a42652019-02-08 18:27:29 -08001553 int rv;
Florin Coras1c710452017-10-17 00:03:13 -07001554
Steven Luongc4b5d102024-07-30 13:44:01 -07001555 if (session_rule_table_is_enabled () == 0)
Steven Luong2c52f5e2024-10-02 09:35:33 -07001556 {
1557 vlib_cli_output (vm, "session rule table engine is not enabled");
1558 unformat_skip_line (input);
1559 goto done;
1560 }
Steven Luongc4b5d102024-07-30 13:44:01 -07001561
Dave Barachb7b92992018-10-17 10:38:51 -04001562 clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
1563 clib_memset (&rmt_ip, 0, sizeof (rmt_ip));
Florin Coras1c710452017-10-17 00:03:13 -07001564 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1565 {
1566 if (unformat (input, "del"))
1567 is_add = 0;
1568 else if (unformat (input, "add"))
1569 ;
1570 else if (unformat (input, "appns %_%v%_", &ns_id))
1571 ;
1572 else if (unformat (input, "scope global"))
1573 scope = SESSION_RULE_SCOPE_GLOBAL;
1574 else if (unformat (input, "scope local"))
1575 scope = SESSION_RULE_SCOPE_LOCAL;
1576 else if (unformat (input, "scope all"))
1577 scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1578 else if (unformat (input, "proto %U", unformat_transport_proto, &proto))
1579 ;
1580 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1581 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1582 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1583 &rmt_port))
1584 {
1585 is_ip4 = 1;
1586 conn_set = 1;
1587 }
1588 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1589 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1590 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1591 &rmt_port))
1592 {
1593 is_ip4 = 0;
1594 conn_set = 1;
1595 }
1596 else if (unformat (input, "action %d", &action))
1597 ;
Florin Corasc97a7392017-11-05 23:07:07 -08001598 else if (unformat (input, "tag %_%v%_", &tag))
1599 ;
Florin Coras1c710452017-10-17 00:03:13 -07001600 else
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001601 {
Steven Luong2c52f5e2024-10-02 09:35:33 -07001602 vlib_cli_output (vm, "unknown input `%U'", format_unformat_error,
1603 input);
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001604 goto done;
1605 }
Florin Coras1c710452017-10-17 00:03:13 -07001606 }
1607
Florin Corasc97a7392017-11-05 23:07:07 -08001608 if (proto == ~0)
1609 {
1610 vlib_cli_output (vm, "proto must be set");
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001611 goto done;
Florin Corasc97a7392017-11-05 23:07:07 -08001612 }
1613 if (is_add && !conn_set && action == ~0)
1614 {
1615 vlib_cli_output (vm, "connection and action must be set for add");
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001616 goto done;
Florin Corasc97a7392017-11-05 23:07:07 -08001617 }
1618 if (!is_add && !tag && !conn_set)
1619 {
1620 vlib_cli_output (vm, "connection or tag must be set for delete");
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001621 goto done;
Florin Corasc97a7392017-11-05 23:07:07 -08001622 }
1623 if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN)
1624 {
1625 vlib_cli_output (vm, "tag too long (max u64)");
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001626 goto done;
Florin Corasc97a7392017-11-05 23:07:07 -08001627 }
Florin Coras1c710452017-10-17 00:03:13 -07001628
1629 if (ns_id)
1630 {
1631 app_ns = app_namespace_get_from_id (ns_id);
1632 if (!app_ns)
Florin Corasc97a7392017-11-05 23:07:07 -08001633 {
1634 vlib_cli_output (vm, "namespace %v does not exist", ns_id);
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001635 goto done;
Florin Corasc97a7392017-11-05 23:07:07 -08001636 }
Florin Coras1c710452017-10-17 00:03:13 -07001637 }
1638 else
1639 {
1640 app_ns = app_namespace_get_default ();
1641 }
1642 appns_index = app_namespace_index (app_ns);
1643
1644 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1645 session_rule_add_del_args_t args = {
zhanglimaoa04ebb82019-03-13 10:36:54 +08001646 .transport_proto = proto,
Florin Coras1c710452017-10-17 00:03:13 -07001647 .table_args.lcl.fp_addr = lcl_ip,
1648 .table_args.lcl.fp_len = lcl_plen,
1649 .table_args.lcl.fp_proto = fib_proto,
1650 .table_args.rmt.fp_addr = rmt_ip,
1651 .table_args.rmt.fp_len = rmt_plen,
1652 .table_args.rmt.fp_proto = fib_proto,
1653 .table_args.lcl_port = lcl_port,
1654 .table_args.rmt_port = rmt_port,
1655 .table_args.action_index = action,
1656 .table_args.is_add = is_add,
Florin Corasc97a7392017-11-05 23:07:07 -08001657 .table_args.tag = tag,
Florin Coras1c710452017-10-17 00:03:13 -07001658 .appns_index = appns_index,
1659 .scope = scope,
1660 };
Florin Corasc1a42652019-02-08 18:27:29 -08001661 if ((rv = vnet_session_rule_add_del (&args)))
Steven Luong2c52f5e2024-10-02 09:35:33 -07001662 vlib_cli_output (vm, "rule add del returned %d", rv);
Florin Corasc1a42652019-02-08 18:27:29 -08001663
Nathan Skrzypczak1a9e2f92021-07-28 19:35:08 +02001664done:
1665 vec_free (ns_id);
Florin Corasc97a7392017-11-05 23:07:07 -08001666 vec_free (tag);
Steven Luong2c52f5e2024-10-02 09:35:33 -07001667 return 0;
Florin Coras1c710452017-10-17 00:03:13 -07001668}
1669
Florin Coras1c710452017-10-17 00:03:13 -07001670VLIB_CLI_COMMAND (session_rule_command, static) =
1671{
1672 .path = "session rule",
1673 .short_help = "session rule [add|del] appns <ns_id> proto <proto> "
1674 "<lcl-ip/plen> <lcl-port> <rmt-ip/plen> <rmt-port> action <action>",
1675 .function = session_rule_command_fn,
1676};
Florin Coras1c710452017-10-17 00:03:13 -07001677
Florin Coras7999e832017-10-31 01:51:04 -07001678void
1679session_lookup_dump_rules_table (u32 fib_index, u8 fib_proto,
1680 u8 transport_proto)
1681{
1682 vlib_main_t *vm = vlib_get_main ();
1683 session_table_t *st;
1684 st = session_table_get_for_fib_index (fib_index, fib_proto);
Steven Luongc4b5d102024-07-30 13:44:01 -07001685 if (st == 0)
1686 return;
1687 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1688 fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001689}
1690
1691void
1692session_lookup_dump_local_rules_table (u32 table_index, u8 fib_proto,
1693 u8 transport_proto)
1694{
1695 vlib_main_t *vm = vlib_get_main ();
1696 session_table_t *st;
1697 st = session_table_get (table_index);
Steven Luongc4b5d102024-07-30 13:44:01 -07001698 if (st == 0)
1699 return;
1700 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1701 fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001702}
1703
Florin Coras1c710452017-10-17 00:03:13 -07001704static clib_error_t *
1705show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input,
1706 vlib_cli_command_t * cmd)
1707{
1708 u32 transport_proto = ~0, lcl_port, rmt_port, lcl_plen, rmt_plen;
1709 u32 fib_index, scope = 0;
1710 ip46_address_t lcl_ip, rmt_ip;
1711 u8 is_ip4 = 1, show_one = 0;
1712 app_namespace_t *app_ns;
1713 session_table_t *st;
1714 u8 *ns_id = 0, fib_proto;
1715
Guanghua Zhangfcd5e122019-08-24 10:52:19 +08001716 session_cli_return_if_not_enabled ();
1717
Dave Barachb7b92992018-10-17 10:38:51 -04001718 clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
1719 clib_memset (&rmt_ip, 0, sizeof (rmt_ip));
Florin Coras1c710452017-10-17 00:03:13 -07001720 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1721 {
1722 if (unformat (input, "%U", unformat_transport_proto, &transport_proto))
1723 ;
1724 else if (unformat (input, "appns %_%v%_", &ns_id))
1725 ;
1726 else if (unformat (input, "scope global"))
Steven Luonge87a03f2024-07-18 09:10:48 -07001727 scope = SESSION_RULE_SCOPE_GLOBAL;
Florin Coras1c710452017-10-17 00:03:13 -07001728 else if (unformat (input, "scope local"))
Steven Luonge87a03f2024-07-18 09:10:48 -07001729 scope = SESSION_RULE_SCOPE_LOCAL;
Florin Coras1c710452017-10-17 00:03:13 -07001730 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1731 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1732 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1733 &rmt_port))
1734 {
1735 is_ip4 = 1;
1736 show_one = 1;
1737 }
1738 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1739 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1740 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1741 &rmt_port))
1742 {
1743 is_ip4 = 0;
1744 show_one = 1;
1745 }
1746 else
Steven Luong0a3b0b22024-08-06 13:28:09 -07001747 {
1748 vec_free (ns_id);
1749 return clib_error_return (0, "unknown input `%U'",
1750 format_unformat_error, input);
1751 }
Florin Coras1c710452017-10-17 00:03:13 -07001752 }
1753
1754 if (transport_proto == ~0)
1755 {
1756 vlib_cli_output (vm, "transport proto must be set");
Steven Luong0a3b0b22024-08-06 13:28:09 -07001757 goto done;
Florin Coras1c710452017-10-17 00:03:13 -07001758 }
1759
1760 if (ns_id)
1761 {
1762 app_ns = app_namespace_get_from_id (ns_id);
1763 if (!app_ns)
1764 {
1765 vlib_cli_output (vm, "appns %v doesn't exist", ns_id);
Steven Luong0a3b0b22024-08-06 13:28:09 -07001766 goto done;
Florin Coras1c710452017-10-17 00:03:13 -07001767 }
1768 }
1769 else
1770 {
1771 app_ns = app_namespace_get_default ();
1772 }
1773
Steven Luonge87a03f2024-07-18 09:10:48 -07001774 if (scope == SESSION_RULE_SCOPE_GLOBAL || scope == 0)
Florin Coras1c710452017-10-17 00:03:13 -07001775 {
1776 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1777 fib_index = is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
1778 st = session_table_get_for_fib_index (fib_proto, fib_index);
1779 }
1780 else
1781 {
1782 st = app_namespace_get_local_table (app_ns);
1783 }
1784
Steven Luongc4b5d102024-07-30 13:44:01 -07001785 if (session_rule_table_is_enabled () == 0)
1786 {
1787 vlib_cli_output (vm, "session rule table engine is not enabled");
1788 goto done;
1789 }
1790
Florin Coras1c710452017-10-17 00:03:13 -07001791 if (show_one)
1792 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001793 if (st)
1794 session_rules_table_show_rule (vm, st->srtg_handle, transport_proto,
1795 &lcl_ip, lcl_port, &rmt_ip, rmt_port,
1796 is_ip4);
Steven Luong0a3b0b22024-08-06 13:28:09 -07001797 goto done;
Florin Coras1c710452017-10-17 00:03:13 -07001798 }
1799
Florin Corasc97a7392017-11-05 23:07:07 -08001800 vlib_cli_output (vm, "%U rules table", format_transport_proto,
1801 transport_proto);
Steven Luonge87a03f2024-07-18 09:10:48 -07001802 if (scope == SESSION_RULE_SCOPE_LOCAL)
1803 {
1804 if (st)
1805 {
Steven Luongc4b5d102024-07-30 13:44:01 -07001806 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1807 FIB_PROTOCOL_IP4);
1808 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1809 FIB_PROTOCOL_IP6);
Steven Luonge87a03f2024-07-18 09:10:48 -07001810 }
1811 }
1812 else
1813 {
1814 /*
1815 * 2 separate session tables for global entries, 1 for ip4 and 1 for ip6
1816 */
1817 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4,
1818 app_ns->ip4_fib_index);
1819 if (st)
Steven Luongc4b5d102024-07-30 13:44:01 -07001820 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1821 FIB_PROTOCOL_IP4);
Steven Luonge87a03f2024-07-18 09:10:48 -07001822
1823 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6,
1824 app_ns->ip6_fib_index);
1825 if (st)
Steven Luongc4b5d102024-07-30 13:44:01 -07001826 session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto,
1827 FIB_PROTOCOL_IP6);
Steven Luonge87a03f2024-07-18 09:10:48 -07001828 }
Steven Luong0a3b0b22024-08-06 13:28:09 -07001829done:
Florin Coras1c710452017-10-17 00:03:13 -07001830 vec_free (ns_id);
1831 return 0;
1832}
1833
Florin Coras1c710452017-10-17 00:03:13 -07001834VLIB_CLI_COMMAND (show_session_rules_command, static) =
1835{
1836 .path = "show session rules",
Florin Corasdff48db2017-11-19 18:06:58 -08001837 .short_help = "show session rules [<proto> appns <id> <lcl-ip/plen> "
1838 "<lcl-port> <rmt-ip/plen> <rmt-port> scope <scope>]",
Florin Coras1c710452017-10-17 00:03:13 -07001839 .function = show_session_rules_command_fn,
1840};
Florin Coras1c710452017-10-17 00:03:13 -07001841
Florin Coras894d0a62023-11-17 16:35:04 -08001842u8 *
1843format_session_lookup_tables (u8 *s, va_list *args)
1844{
1845 u32 fib_proto = va_arg (*args, u32);
1846 u32 *fibs, num_fibs = 0, fib_index, indent;
1847 session_table_t *st;
1848 u64 total_mem = 0;
1849
1850 fibs = fib_index_to_table_index[fib_proto];
1851
1852 for (fib_index = 0; fib_index < vec_len (fibs); fib_index++)
1853 {
1854 if (fibs[fib_index] == ~0)
1855 continue;
1856
1857 num_fibs += 1;
1858 st = session_table_get (fibs[fib_index]);
1859 total_mem += session_table_memory_size (st);
1860 }
1861
1862 indent = format_get_indent (s);
1863 s = format (s, "active fibs:\t%u\n", num_fibs);
1864 s = format (s, "%Umax fib-index:\t%u\n", format_white_space, indent,
1865 vec_len (fibs) - 1);
1866 s = format (s, "%Utable memory:\t%U\n", format_white_space, indent,
1867 format_memory_size, total_mem);
1868 s = format (s, "%Uvec memory:\t%U\n", format_white_space, indent,
1869 format_memory_size, vec_mem_size (fibs));
1870
1871 return s;
1872}
1873
1874static clib_error_t *
1875show_session_lookup_command_fn (vlib_main_t *vm, unformat_input_t *input,
1876 vlib_cli_command_t *cmd)
1877{
1878 session_table_t *st;
1879 u32 fib_index = ~0;
1880
1881 session_cli_return_if_not_enabled ();
1882 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1883 {
1884 if (unformat (input, "table %u", &fib_index))
1885 ;
1886 else
1887 return clib_error_return (0, "unknown input `%U'",
1888 format_unformat_error, input);
1889 }
1890
1891 if (fib_index != ~0)
1892 {
1893 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
1894 if (st)
1895 vlib_cli_output (vm, "%U", format_session_table, st);
1896 else
1897 vlib_cli_output (vm, "no ip4 table for fib-index %u", fib_index);
1898 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1899 if (st)
1900 vlib_cli_output (vm, "%U", format_session_table, st);
1901 else
1902 vlib_cli_output (vm, "no ip6 table for fib-index %u", fib_index);
1903 goto done;
1904 }
1905
1906 vlib_cli_output (vm, "ip4 fib lookup tables:\n %U",
1907 format_session_lookup_tables, FIB_PROTOCOL_IP4);
1908 vlib_cli_output (vm, "ip6 fib lookup tables:\n %U",
1909 format_session_lookup_tables, FIB_PROTOCOL_IP6);
1910
1911done:
1912 return 0;
1913}
1914
1915VLIB_CLI_COMMAND (show_session_lookup_command, static) = {
1916 .path = "show session lookup",
1917 .short_help = "show session lookup [table <fib-index>]",
1918 .function = show_session_lookup_command_fn,
1919};
1920
Florin Coras04e53442017-07-16 17:12:15 -07001921void
1922session_lookup_init (void)
1923{
Florin Corasf9bdc032024-02-02 13:01:07 -08001924 session_lookup_main_t *slm = &sl_main;
1925
1926 clib_spinlock_init (&slm->st_alloc_lock);
1927
Steven Luong5682ca82024-07-17 16:16:05 -07001928 /* We are not contributing any route to the fib. But we allocate a fib source
1929 * so that when we lock the fib table, we can view that we have a lock on the
1930 * particular fib table in case we wonder why the fib table is not free after
1931 * "ip table del"
1932 */
1933 slm->fib_src = fib_source_allocate (
1934 "session lookup", FIB_SOURCE_PRIORITY_LOW, FIB_SOURCE_BH_SIMPLE);
1935
Florin Corascea194d2017-10-02 00:18:51 -07001936 /*
1937 * Allocate default table and map it to fib_index 0
1938 */
1939 session_table_t *st = session_table_alloc ();
1940 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP4], 0);
1941 fib_index_to_table_index[FIB_PROTOCOL_IP4][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001942 st->active_fib_proto = FIB_PROTOCOL_IP4;
1943 session_table_init (st, FIB_PROTOCOL_IP4);
Florin Corascea194d2017-10-02 00:18:51 -07001944 st = session_table_alloc ();
1945 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP6], 0);
1946 fib_index_to_table_index[FIB_PROTOCOL_IP6][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001947 st->active_fib_proto = FIB_PROTOCOL_IP6;
1948 session_table_init (st, FIB_PROTOCOL_IP6);
Florin Coras04e53442017-07-16 17:12:15 -07001949}
1950
Steven Luong5682ca82024-07-17 16:16:05 -07001951void
Steven Luonge0c4e6e2024-10-22 10:44:07 -07001952session_lookup_table_cleanup (u32 fib_proto, u32 fib_index, u32 ns_index)
Steven Luong5682ca82024-07-17 16:16:05 -07001953{
1954 session_table_t *st;
Steven Luonge0c4e6e2024-10-22 10:44:07 -07001955 u32 table_index, appns_index;
1956 int i;
Steven Luong5682ca82024-07-17 16:16:05 -07001957
Steven Luong2e67a3f2024-11-08 08:35:14 -08001958 if (fib_index == ~0)
1959 return;
Steven Luong5682ca82024-07-17 16:16:05 -07001960 session_lookup_fib_table_unlock (fib_index, fib_proto);
Steven Luonge0c4e6e2024-10-22 10:44:07 -07001961 table_index = session_lookup_get_index_for_fib (fib_proto, fib_index);
1962 st = session_table_get (table_index);
1963 if (st == 0)
1964 return;
Steven Luong5682ca82024-07-17 16:16:05 -07001965 if (fib_index_to_lock_count[fib_proto][fib_index] == 0)
1966 {
Steven Luonge0c4e6e2024-10-22 10:44:07 -07001967 session_table_free (st, fib_proto);
1968 if (vec_len (fib_index_to_table_index[fib_proto]) > fib_index)
1969 fib_index_to_table_index[fib_proto][fib_index] = ~0;
Steven Luong5682ca82024-07-17 16:16:05 -07001970 }
Steven Luonge0c4e6e2024-10-22 10:44:07 -07001971 else
1972 vec_foreach_index (i, st->appns_index)
1973 {
1974 appns_index = *vec_elt_at_index (st->appns_index, i);
1975 if (ns_index == appns_index)
1976 vec_del1 (st->appns_index, i);
1977 }
Steven Luong5682ca82024-07-17 16:16:05 -07001978}
1979
Florin Coras04e53442017-07-16 17:12:15 -07001980/*
1981 * fd.io coding-style-patch-verification: ON
1982 *
1983 * Local Variables:
1984 * eval: (c-set-style "gnu")
1985 * End:
1986 */