blob: abaad5019fabdac8aefa59b8df2d49d8ac3383a7 [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>
Florin Coras04e53442017-07-16 17:12:15 -070031
Florin Corascea194d2017-10-02 00:18:51 -070032/**
Florin Corascea194d2017-10-02 00:18:51 -070033 * Network namespace index (i.e., fib index) to session lookup table. We
34 * should have one per network protocol type but for now we only support IP4/6
35 */
36static u32 *fib_index_to_table_index[2];
37
Florin Coras04e53442017-07-16 17:12:15 -070038/* *INDENT-OFF* */
39/* 16 octets */
40typedef CLIB_PACKED (struct {
41 union
42 {
43 struct
44 {
45 ip4_address_t src;
46 ip4_address_t dst;
47 u16 src_port;
48 u16 dst_port;
49 /* align by making this 4 octets even though its a 1-bit field
50 * NOTE: avoid key overlap with other transports that use 5 tuples for
51 * session identification.
52 */
53 u32 proto;
54 };
55 u64 as_u64[2];
56 };
57}) v4_connection_key_t;
58
59typedef CLIB_PACKED (struct {
60 union
61 {
62 struct
63 {
64 /* 48 octets */
65 ip6_address_t src;
66 ip6_address_t dst;
67 u16 src_port;
68 u16 dst_port;
69 u32 proto;
70 u64 unused;
71 };
72 u64 as_u64[6];
73 };
74}) v6_connection_key_t;
75/* *INDENT-ON* */
76
77typedef clib_bihash_kv_16_8_t session_kv4_t;
78typedef clib_bihash_kv_48_8_t session_kv6_t;
79
80always_inline void
81make_v4_ss_kv (session_kv4_t * kv, ip4_address_t * lcl, ip4_address_t * rmt,
82 u16 lcl_port, u16 rmt_port, u8 proto)
83{
Florin Coras9679c812018-06-21 08:14:34 -070084 kv->key[0] = (u64) rmt->as_u32 << 32 | (u64) lcl->as_u32;
85 kv->key[1] = (u64) proto << 32 | (u64) rmt_port << 16 | (u64) lcl_port;
Florin Coras04e53442017-07-16 17:12:15 -070086 kv->value = ~0ULL;
87}
88
89always_inline void
90make_v4_listener_kv (session_kv4_t * kv, ip4_address_t * lcl, u16 lcl_port,
91 u8 proto)
92{
Florin Coras9679c812018-06-21 08:14:34 -070093 kv->key[0] = (u64) lcl->as_u32;
94 kv->key[1] = (u64) proto << 32 | (u64) lcl_port;
Florin Coras04e53442017-07-16 17:12:15 -070095 kv->value = ~0ULL;
96}
97
98always_inline void
Florin Corasdbd44562017-11-09 19:30:17 -080099make_v4_proxy_kv (session_kv4_t * kv, ip4_address_t * lcl, u8 proto)
100{
Florin Coras9679c812018-06-21 08:14:34 -0700101 kv->key[0] = (u64) lcl->as_u32;
102 kv->key[1] = (u64) proto << 32;
Florin Corasdbd44562017-11-09 19:30:17 -0800103 kv->value = ~0ULL;
104}
105
106always_inline void
Florin Coras561af9b2017-12-09 10:19:43 -0800107make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700108{
Florin Coras561af9b2017-12-09 10:19:43 -0800109 make_v4_ss_kv (kv, &tc->lcl_ip.ip4, &tc->rmt_ip.ip4, tc->lcl_port,
110 tc->rmt_port, tc->proto);
Florin Coras04e53442017-07-16 17:12:15 -0700111}
112
113always_inline void
114make_v6_ss_kv (session_kv6_t * kv, ip6_address_t * lcl, ip6_address_t * rmt,
115 u16 lcl_port, u16 rmt_port, u8 proto)
116{
Florin Coras9679c812018-06-21 08:14:34 -0700117 kv->key[0] = lcl->as_u64[0];
118 kv->key[1] = lcl->as_u64[1];
119 kv->key[2] = rmt->as_u64[0];
120 kv->key[3] = rmt->as_u64[1];
121 kv->key[4] = (u64) proto << 32 | (u64) rmt_port << 16 | (u64) lcl_port;
122 kv->key[5] = 0;
Florin Coras04e53442017-07-16 17:12:15 -0700123 kv->value = ~0ULL;
124}
125
126always_inline void
127make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port,
128 u8 proto)
129{
Florin Coras9679c812018-06-21 08:14:34 -0700130 kv->key[0] = lcl->as_u64[0];
131 kv->key[1] = lcl->as_u64[1];
132 kv->key[2] = 0;
133 kv->key[3] = 0;
134 kv->key[4] = (u64) proto << 32 | (u64) lcl_port;
135 kv->key[5] = 0;
Florin Coras04e53442017-07-16 17:12:15 -0700136 kv->value = ~0ULL;
137}
138
139always_inline void
Florin Corasdbd44562017-11-09 19:30:17 -0800140make_v6_proxy_kv (session_kv6_t * kv, ip6_address_t * lcl, u8 proto)
141{
Florin Coras9679c812018-06-21 08:14:34 -0700142 kv->key[0] = lcl->as_u64[0];
143 kv->key[1] = lcl->as_u64[1];
144 kv->key[2] = 0;
145 kv->key[3] = 0;
146 kv->key[4] = (u64) proto << 32;
147 kv->key[5] = 0;
Florin Corasdbd44562017-11-09 19:30:17 -0800148 kv->value = ~0ULL;
149}
150
151always_inline void
Florin Coras561af9b2017-12-09 10:19:43 -0800152make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700153{
Florin Coras561af9b2017-12-09 10:19:43 -0800154 make_v6_ss_kv (kv, &tc->lcl_ip.ip6, &tc->rmt_ip.ip6, tc->lcl_port,
155 tc->rmt_port, tc->proto);
Florin Coras04e53442017-07-16 17:12:15 -0700156}
157
Florin Corascea194d2017-10-02 00:18:51 -0700158static session_table_t *
Florin Coras6c36f532017-11-03 18:32:34 -0700159session_table_get_or_alloc (u8 fib_proto, u8 fib_index)
Florin Coras04e53442017-07-16 17:12:15 -0700160{
Florin Corascea194d2017-10-02 00:18:51 -0700161 session_table_t *st;
Florin Coras6c36f532017-11-03 18:32:34 -0700162 u32 table_index;
163 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
Florin Corascea194d2017-10-02 00:18:51 -0700164 {
165 st = session_table_alloc ();
166 table_index = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -0700167 vec_validate (fib_index_to_table_index[fib_proto], fib_index);
168 fib_index_to_table_index[fib_proto][fib_index] = table_index;
169 st->active_fib_proto = fib_proto;
Florin Corasb795bd02017-12-14 11:30:48 -0800170 session_table_init (st, fib_proto);
Florin Corascea194d2017-10-02 00:18:51 -0700171 return st;
172 }
173 else
174 {
Florin Coras6c36f532017-11-03 18:32:34 -0700175 table_index = fib_index_to_table_index[fib_proto][fib_index];
Florin Corascea194d2017-10-02 00:18:51 -0700176 return session_table_get (table_index);
177 }
178}
179
180static session_table_t *
Florin Coras6c36f532017-11-03 18:32:34 -0700181session_table_get_or_alloc_for_connection (transport_connection_t * tc)
182{
183 u32 fib_proto;
184 fib_proto = transport_connection_fib_proto (tc);
185 return session_table_get_or_alloc (fib_proto, tc->fib_index);
186}
187
188static session_table_t *
Florin Corascea194d2017-10-02 00:18:51 -0700189session_table_get_for_connection (transport_connection_t * tc)
190{
191 u32 fib_proto = transport_connection_fib_proto (tc);
192 if (vec_len (fib_index_to_table_index[fib_proto]) <= tc->fib_index)
193 return 0;
194 return
195 session_table_get (fib_index_to_table_index[fib_proto][tc->fib_index]);
196}
197
198static session_table_t *
199session_table_get_for_fib_index (u32 fib_proto, u32 fib_index)
200{
201 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
202 return 0;
203 return session_table_get (fib_index_to_table_index[fib_proto][fib_index]);
204}
205
206u32
207session_lookup_get_index_for_fib (u32 fib_proto, u32 fib_index)
208{
209 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
210 return SESSION_TABLE_INVALID_INDEX;
211 return fib_index_to_table_index[fib_proto][fib_index];
212}
213
214/**
215 * Add transport connection to a session table
216 *
217 * Session lookup 5-tuple (src-ip, dst-ip, src-port, dst-port, session-type)
218 * is added to requested session table.
219 *
220 * @param tc transport connection to be added
221 * @param value value to be stored
222 *
223 * @return non-zero if failure
224 */
225int
226session_lookup_add_connection (transport_connection_t * tc, u64 value)
227{
228 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700229 session_kv4_t kv4;
230 session_kv6_t kv6;
231
Florin Corascea194d2017-10-02 00:18:51 -0700232 st = session_table_get_or_alloc_for_connection (tc);
233 if (!st)
234 return -1;
Florin Coras68810622017-07-24 17:40:28 -0700235 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700236 {
Florin Coras04e53442017-07-16 17:12:15 -0700237 make_v4_ss_kv_from_tc (&kv4, tc);
238 kv4.value = value;
Florin Corascea194d2017-10-02 00:18:51 -0700239 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4,
240 1 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700241 }
242 else
243 {
Florin Coras04e53442017-07-16 17:12:15 -0700244 make_v6_ss_kv_from_tc (&kv6, tc);
245 kv6.value = value;
Florin Corascea194d2017-10-02 00:18:51 -0700246 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6,
247 1 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700248 }
249}
250
Florin Coras04e53442017-07-16 17:12:15 -0700251int
Florin Corascea194d2017-10-02 00:18:51 -0700252session_lookup_add_session_endpoint (u32 table_index,
253 session_endpoint_t * sep, u64 value)
Florin Coras04e53442017-07-16 17:12:15 -0700254{
Florin Corascea194d2017-10-02 00:18:51 -0700255 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700256 session_kv4_t kv4;
257 session_kv6_t kv6;
Florin Coras68810622017-07-24 17:40:28 -0700258
Florin Corascea194d2017-10-02 00:18:51 -0700259 st = session_table_get (table_index);
260 if (!st)
261 return -1;
262 if (sep->is_ip4)
263 {
264 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
265 sep->transport_proto);
266 kv4.value = value;
267 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 1);
268 }
269 else
270 {
271 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
272 sep->transport_proto);
273 kv6.value = value;
274 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 1);
275 }
276}
277
278int
279session_lookup_del_session_endpoint (u32 table_index,
280 session_endpoint_t * sep)
281{
282 session_table_t *st;
283 session_kv4_t kv4;
284 session_kv6_t kv6;
285
286 st = session_table_get (table_index);
287 if (!st)
288 return -1;
289 if (sep->is_ip4)
290 {
291 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
292 sep->transport_proto);
293 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 0);
294 }
295 else
296 {
297 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
298 sep->transport_proto);
299 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 0);
300 }
301}
302
303/**
304 * Delete transport connection from session table
305 *
306 * @param table_index session table index
307 * @param tc transport connection to be removed
308 *
309 * @return non-zero if failure
310 */
311int
312session_lookup_del_connection (transport_connection_t * tc)
313{
314 session_table_t *st;
315 session_kv4_t kv4;
316 session_kv6_t kv6;
317
318 st = session_table_get_for_connection (tc);
319 if (!st)
320 return -1;
Florin Coras68810622017-07-24 17:40:28 -0700321 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700322 {
Florin Coras04e53442017-07-16 17:12:15 -0700323 make_v4_ss_kv_from_tc (&kv4, tc);
Florin Corascea194d2017-10-02 00:18:51 -0700324 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4,
Florin Coras04e53442017-07-16 17:12:15 -0700325 0 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700326 }
327 else
328 {
Florin Coras04e53442017-07-16 17:12:15 -0700329 make_v6_ss_kv_from_tc (&kv6, tc);
Florin Corascea194d2017-10-02 00:18:51 -0700330 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6,
Florin Coras04e53442017-07-16 17:12:15 -0700331 0 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700332 }
Florin Coras04e53442017-07-16 17:12:15 -0700333}
334
335int
Florin Coras288eaab2019-02-03 15:26:14 -0800336session_lookup_del_session (session_t * s)
Florin Coras04e53442017-07-16 17:12:15 -0700337{
338 transport_connection_t *ts;
Florin Coras1ee78302019-02-05 15:51:15 -0800339 ts = transport_get_connection (session_get_transport_proto (s),
340 s->connection_index, s->thread_index);
Florin Corase1e7fb82019-09-25 07:28:34 -0700341 if (!ts || (ts->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
Nathan Skrzypczak2eed1a12019-07-04 14:26:21 +0200342 return 0;
Florin Corascea194d2017-10-02 00:18:51 -0700343 return session_lookup_del_connection (ts);
Florin Coras04e53442017-07-16 17:12:15 -0700344}
345
Florin Corasdff48db2017-11-19 18:06:58 -0800346static u8
347session_lookup_action_index_is_valid (u32 action_index)
Florin Corasf0c1c962017-11-02 21:31:46 -0700348{
Florin Corasdff48db2017-11-19 18:06:58 -0800349 if (action_index == SESSION_RULES_TABLE_ACTION_ALLOW
350 || action_index == SESSION_RULES_TABLE_INVALID_INDEX)
351 return 0;
352 return 1;
353}
354
Florin Corasf8f516a2018-02-08 15:10:09 -0800355static u64
356session_lookup_action_to_handle (u32 action_index)
Florin Corasdff48db2017-11-19 18:06:58 -0800357{
358 switch (action_index)
359 {
360 case SESSION_RULES_TABLE_ACTION_DROP:
Florin Corasf8f516a2018-02-08 15:10:09 -0800361 return SESSION_DROP_HANDLE;
Florin Corasdff48db2017-11-19 18:06:58 -0800362 case SESSION_RULES_TABLE_ACTION_ALLOW:
363 case SESSION_RULES_TABLE_INVALID_INDEX:
Florin Corasf8f516a2018-02-08 15:10:09 -0800364 return SESSION_INVALID_HANDLE;
Florin Corasdff48db2017-11-19 18:06:58 -0800365 default:
Florin Corasf8f516a2018-02-08 15:10:09 -0800366 /* application index */
Florin Corasdff48db2017-11-19 18:06:58 -0800367 return action_index;
368 }
Florin Corasf0c1c962017-11-02 21:31:46 -0700369}
370
Florin Coras288eaab2019-02-03 15:26:14 -0800371static session_t *
Florin Coras7999e832017-10-31 01:51:04 -0700372session_lookup_app_listen_session (u32 app_index, u8 fib_proto,
373 u8 transport_proto)
Florin Coras1c710452017-10-17 00:03:13 -0700374{
375 application_t *app;
Florin Corasdff48db2017-11-19 18:06:58 -0800376 app = application_get_if_valid (app_index);
Florin Coras1c710452017-10-17 00:03:13 -0700377 if (!app)
378 return 0;
379
Florin Coras15531972018-08-12 23:50:53 -0700380 return app_worker_first_listener (application_get_default_worker (app),
381 fib_proto, transport_proto);
Florin Coras1c710452017-10-17 00:03:13 -0700382}
383
Florin Coras288eaab2019-02-03 15:26:14 -0800384static session_t *
Florin Corasa2ff7b82017-11-08 17:55:03 -0800385session_lookup_action_to_session (u32 action_index, u8 fib_proto,
386 u8 transport_proto)
387{
Florin Corasdff48db2017-11-19 18:06:58 -0800388 u32 app_index;
Florin Corasf8f516a2018-02-08 15:10:09 -0800389 app_index = session_lookup_action_to_handle (action_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800390 /* Nothing sophisticated for now, action index is app index */
Florin Corasdff48db2017-11-19 18:06:58 -0800391 return session_lookup_app_listen_session (app_index, fib_proto,
Florin Corasa2ff7b82017-11-08 17:55:03 -0800392 transport_proto);
393}
394
Florin Corasf8f516a2018-02-08 15:10:09 -0800395/** UNUSED */
Florin Coras288eaab2019-02-03 15:26:14 -0800396session_t *
Florin Corasa2ff7b82017-11-08 17:55:03 -0800397session_lookup_rules_table_session4 (session_table_t * st, u8 proto,
398 ip4_address_t * lcl, u16 lcl_port,
399 ip4_address_t * rmt, u16 rmt_port)
Florin Coras1c710452017-10-17 00:03:13 -0700400{
Florin Corasc97a7392017-11-05 23:07:07 -0800401 session_rules_table_t *srt = &st->session_rules[proto];
Florin Corasdff48db2017-11-19 18:06:58 -0800402 u32 action_index, app_index;
Florin Corasc97a7392017-11-05 23:07:07 -0800403 action_index = session_rules_table_lookup4 (srt, lcl, rmt, lcl_port,
Florin Coras1c710452017-10-17 00:03:13 -0700404 rmt_port);
Florin Corasf8f516a2018-02-08 15:10:09 -0800405 app_index = session_lookup_action_to_handle (action_index);
Florin Coras1c710452017-10-17 00:03:13 -0700406 /* Nothing sophisticated for now, action index is app index */
Florin Corasdff48db2017-11-19 18:06:58 -0800407 return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP4,
Florin Coras7999e832017-10-31 01:51:04 -0700408 proto);
Florin Coras1c710452017-10-17 00:03:13 -0700409}
410
Florin Corasf8f516a2018-02-08 15:10:09 -0800411/** UNUSED */
Florin Coras288eaab2019-02-03 15:26:14 -0800412session_t *
Florin Corasdff48db2017-11-19 18:06:58 -0800413session_lookup_rules_table_session6 (session_table_t * st, u8 proto,
414 ip6_address_t * lcl, u16 lcl_port,
415 ip6_address_t * rmt, u16 rmt_port)
Florin Coras1c710452017-10-17 00:03:13 -0700416{
Florin Corasc97a7392017-11-05 23:07:07 -0800417 session_rules_table_t *srt = &st->session_rules[proto];
Florin Corasdff48db2017-11-19 18:06:58 -0800418 u32 action_index, app_index;
Florin Corasc97a7392017-11-05 23:07:07 -0800419 action_index = session_rules_table_lookup6 (srt, lcl, rmt, lcl_port,
Florin Coras1c710452017-10-17 00:03:13 -0700420 rmt_port);
Florin Corasf8f516a2018-02-08 15:10:09 -0800421 app_index = session_lookup_action_to_handle (action_index);
Florin Corasdff48db2017-11-19 18:06:58 -0800422 return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP6,
Florin Coras7999e832017-10-31 01:51:04 -0700423 proto);
Florin Coras1c710452017-10-17 00:03:13 -0700424}
425
Florin Corasa2ff7b82017-11-08 17:55:03 -0800426/**
427 * Lookup listener for session endpoint in table
428 *
429 * @param table_index table where the endpoint should be looked up
430 * @param sep session endpoint to be looked up
431 * @param use_rules flag that indicates if the session rules of the table
432 * should be used
433 * @return invalid handle if nothing is found, the handle of a valid listener
Florin Corasf8f516a2018-02-08 15:10:09 -0800434 * or an action derived handle if a rule is hit
Florin Corasa2ff7b82017-11-08 17:55:03 -0800435 */
Florin Coras3cbc04b2017-10-02 00:18:51 -0700436u64
Florin Corasa2ff7b82017-11-08 17:55:03 -0800437session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
438 u8 use_rules)
Florin Coras04e53442017-07-16 17:12:15 -0700439{
Florin Corasc97a7392017-11-05 23:07:07 -0800440 session_rules_table_t *srt;
Florin Corascea194d2017-10-02 00:18:51 -0700441 session_table_t *st;
Florin Corasf0c1c962017-11-02 21:31:46 -0700442 u32 ai;
Florin Corascea194d2017-10-02 00:18:51 -0700443 int rv;
Florin Coras04e53442017-07-16 17:12:15 -0700444
Florin Corascea194d2017-10-02 00:18:51 -0700445 st = session_table_get (table_index);
446 if (!st)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700447 return SESSION_INVALID_HANDLE;
Florin Corascea194d2017-10-02 00:18:51 -0700448 if (sep->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700449 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800450 session_kv4_t kv4;
451 ip4_address_t lcl4;
452
Florin Coras561af9b2017-12-09 10:19:43 -0800453 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
454 sep->transport_proto);
Florin Corascea194d2017-10-02 00:18:51 -0700455 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
456 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700457 return kv4.value;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800458 if (use_rules)
459 {
Dave Barachb7b92992018-10-17 10:38:51 -0400460 clib_memset (&lcl4, 0, sizeof (lcl4));
Florin Corasa2ff7b82017-11-08 17:55:03 -0800461 srt = &st->session_rules[sep->transport_proto];
462 ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0,
463 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800464 if (session_lookup_action_index_is_valid (ai))
Florin Corasf8f516a2018-02-08 15:10:09 -0800465 return session_lookup_action_to_handle (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800466 }
Florin Coras68810622017-07-24 17:40:28 -0700467 }
468 else
469 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800470 session_kv6_t kv6;
471 ip6_address_t lcl6;
472
Florin Coras561af9b2017-12-09 10:19:43 -0800473 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
474 sep->transport_proto);
Florin Corascea194d2017-10-02 00:18:51 -0700475 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
476 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700477 return kv6.value;
Florin Coras1c710452017-10-17 00:03:13 -0700478
Florin Corasa2ff7b82017-11-08 17:55:03 -0800479 if (use_rules)
480 {
Dave Barachb7b92992018-10-17 10:38:51 -0400481 clib_memset (&lcl6, 0, sizeof (lcl6));
Florin Corasa2ff7b82017-11-08 17:55:03 -0800482 srt = &st->session_rules[sep->transport_proto];
483 ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0,
484 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800485 if (session_lookup_action_index_is_valid (ai))
Florin Corasf8f516a2018-02-08 15:10:09 -0800486 return session_lookup_action_to_handle (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800487 }
Florin Coras68810622017-07-24 17:40:28 -0700488 }
Florin Coras3cbc04b2017-10-02 00:18:51 -0700489 return SESSION_INVALID_HANDLE;
490}
491
Florin Corasa2ff7b82017-11-08 17:55:03 -0800492/**
493 * Look up endpoint in local session table
494 *
495 * The result, for now, is an application index and it may in the future
496 * be extended to a more complicated "action object". The only action we
497 * emulate now is "drop" and for that we return a special app index.
498 *
499 * Lookup logic is to check in order:
500 * - the rules in the table (connect acls)
501 * - session sub-table for a listener
502 * - session sub-table for a local listener (zeroed addr)
503 *
504 * @param table_index table where the lookup should be done
505 * @param sep session endpoint to be looked up
Florin Corasf8f516a2018-02-08 15:10:09 -0800506 * @return session handle that can be interpreted as an adjacency
Florin Corasa2ff7b82017-11-08 17:55:03 -0800507 */
Florin Corasf8f516a2018-02-08 15:10:09 -0800508u64
Florin Corasa2ff7b82017-11-08 17:55:03 -0800509session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
Florin Coras68810622017-07-24 17:40:28 -0700510{
Florin Corasc97a7392017-11-05 23:07:07 -0800511 session_rules_table_t *srt;
Florin Corascea194d2017-10-02 00:18:51 -0700512 session_table_t *st;
Florin Corasf0c1c962017-11-02 21:31:46 -0700513 u32 ai;
Florin Corascea194d2017-10-02 00:18:51 -0700514 int rv;
Florin Coras68810622017-07-24 17:40:28 -0700515
Florin Corascea194d2017-10-02 00:18:51 -0700516 st = session_table_get (table_index);
517 if (!st)
518 return SESSION_INVALID_INDEX;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800519 ASSERT (st->is_local);
520
Florin Corascea194d2017-10-02 00:18:51 -0700521 if (sep->is_ip4)
Florin Coras68810622017-07-24 17:40:28 -0700522 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800523 session_kv4_t kv4;
524 ip4_address_t lcl4;
525
526 /*
527 * Check if endpoint has special rules associated
528 */
Dave Barachb7b92992018-10-17 10:38:51 -0400529 clib_memset (&lcl4, 0, sizeof (lcl4));
Florin Corasa2ff7b82017-11-08 17:55:03 -0800530 srt = &st->session_rules[sep->transport_proto];
531 ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0,
532 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800533 if (session_lookup_action_index_is_valid (ai))
Florin Corasf8f516a2018-02-08 15:10:09 -0800534 return session_lookup_action_to_handle (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800535
536 /*
537 * Check if session endpoint is a listener
538 */
Florin Corascea194d2017-10-02 00:18:51 -0700539 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
540 sep->transport_proto);
541 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
542 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800543 return kv4.value;
Florin Corascea194d2017-10-02 00:18:51 -0700544
545 /*
546 * Zero out the ip. Logic is that connect to local ips, say
547 * 127.0.0.1:port, can match 0.0.0.0:port
548 */
Florin Coras477e91a2018-02-27 10:05:57 -0800549 if (ip4_is_local_host (&sep->ip.ip4))
550 {
551 kv4.key[0] = 0;
552 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
553 if (rv == 0)
554 return kv4.value;
555 }
556 else
557 {
558 kv4.key[0] = 0;
559 }
Florin Corasdbd44562017-11-09 19:30:17 -0800560
561 /*
562 * Zero out the port and check if we have proxy
563 */
564 kv4.key[1] = 0;
565 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
566 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800567 return kv4.value;
Florin Coras68810622017-07-24 17:40:28 -0700568 }
569 else
570 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800571 session_kv6_t kv6;
572 ip6_address_t lcl6;
573
Dave Barachb7b92992018-10-17 10:38:51 -0400574 clib_memset (&lcl6, 0, sizeof (lcl6));
Florin Corasa2ff7b82017-11-08 17:55:03 -0800575 srt = &st->session_rules[sep->transport_proto];
576 ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0,
577 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800578 if (session_lookup_action_index_is_valid (ai))
Florin Corasf8f516a2018-02-08 15:10:09 -0800579 return session_lookup_action_to_handle (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800580
Florin Corascea194d2017-10-02 00:18:51 -0700581 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
582 sep->transport_proto);
583 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
584 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800585 return kv6.value;
Florin Corascea194d2017-10-02 00:18:51 -0700586
587 /*
588 * Zero out the ip. Same logic as above.
589 */
Florin Coras477e91a2018-02-27 10:05:57 -0800590
591 if (ip6_is_local_host (&sep->ip.ip6))
592 {
593 kv6.key[0] = kv6.key[1] = 0;
594 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
595 if (rv == 0)
596 return kv6.value;
597 }
598 else
599 {
600 kv6.key[0] = kv6.key[1] = 0;
601 }
Florin Corasdbd44562017-11-09 19:30:17 -0800602
603 /*
604 * Zero out the port. Same logic as above.
605 */
606 kv6.key[4] = kv6.key[5] = 0;
607 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
608 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800609 return kv6.value;
Florin Coras04e53442017-07-16 17:12:15 -0700610 }
Florin Corasf8f516a2018-02-08 15:10:09 -0800611 return SESSION_INVALID_HANDLE;
Florin Coras04e53442017-07-16 17:12:15 -0700612}
613
Florin Coras288eaab2019-02-03 15:26:14 -0800614static inline session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700615session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl,
Florin Coras477e91a2018-02-27 10:05:57 -0800616 u16 lcl_port, u8 proto, u8 use_wildcard)
Florin Coras04e53442017-07-16 17:12:15 -0700617{
Florin Coras04e53442017-07-16 17:12:15 -0700618 session_kv4_t kv4;
619 int rv;
620
Florin Corasdbd44562017-11-09 19:30:17 -0800621 /*
622 * First, try a fully formed listener
623 */
Florin Coras04e53442017-07-16 17:12:15 -0700624 make_v4_listener_kv (&kv4, lcl, lcl_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700625 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700626 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700627 return listen_session_get ((u32) kv4.value);
Florin Coras04e53442017-07-16 17:12:15 -0700628
Florin Corasdbd44562017-11-09 19:30:17 -0800629 /*
630 * Zero out the lcl ip and check if any 0/0 port binds have been done
631 */
Florin Coras477e91a2018-02-27 10:05:57 -0800632 if (use_wildcard)
633 {
634 kv4.key[0] = 0;
635 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
636 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700637 return listen_session_get ((u32) kv4.value);
Florin Coras477e91a2018-02-27 10:05:57 -0800638 }
639 else
640 {
641 kv4.key[0] = 0;
642 }
Florin Coras04e53442017-07-16 17:12:15 -0700643
Florin Corasdbd44562017-11-09 19:30:17 -0800644 /*
645 * Zero out port and check if we have a proxy set up for our ip
646 */
647 make_v4_proxy_kv (&kv4, lcl, proto);
648 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
649 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700650 return listen_session_get ((u32) kv4.value);
Florin Corasdbd44562017-11-09 19:30:17 -0800651
Florin Coras04e53442017-07-16 17:12:15 -0700652 return 0;
653}
654
Florin Coras288eaab2019-02-03 15:26:14 -0800655session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700656session_lookup_listener4 (u32 fib_index, ip4_address_t * lcl, u16 lcl_port,
Yu Pingb092b772019-12-27 04:04:33 +0800657 u8 proto, u8 use_wildcard)
Florin Coras04e53442017-07-16 17:12:15 -0700658{
Florin Corascea194d2017-10-02 00:18:51 -0700659 session_table_t *st;
660 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
661 if (!st)
662 return 0;
Yu Pingb092b772019-12-27 04:04:33 +0800663 return session_lookup_listener4_i (st, lcl, lcl_port, proto, use_wildcard);
Florin Coras04e53442017-07-16 17:12:15 -0700664}
665
Florin Coras288eaab2019-02-03 15:26:14 -0800666static session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700667session_lookup_listener6_i (session_table_t * st, ip6_address_t * lcl,
Florin Coras477e91a2018-02-27 10:05:57 -0800668 u16 lcl_port, u8 proto, u8 ip_wildcard)
Florin Coras04e53442017-07-16 17:12:15 -0700669{
Florin Coras04e53442017-07-16 17:12:15 -0700670 session_kv6_t kv6;
671 int rv;
672
673 make_v6_listener_kv (&kv6, lcl, lcl_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700674 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700675 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700676 return listen_session_get ((u32) kv6.value);
Florin Coras04e53442017-07-16 17:12:15 -0700677
678 /* Zero out the lcl ip */
Florin Coras477e91a2018-02-27 10:05:57 -0800679 if (ip_wildcard)
680 {
681 kv6.key[0] = kv6.key[1] = 0;
682 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
683 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700684 return listen_session_get ((u32) kv6.value);
Florin Coras477e91a2018-02-27 10:05:57 -0800685 }
686 else
687 {
688 kv6.key[0] = kv6.key[1] = 0;
689 }
Florin Coras04e53442017-07-16 17:12:15 -0700690
Florin Corasdbd44562017-11-09 19:30:17 -0800691 make_v6_proxy_kv (&kv6, lcl, proto);
692 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
693 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700694 return listen_session_get ((u32) kv6.value);
Florin Coras04e53442017-07-16 17:12:15 -0700695 return 0;
696}
697
Florin Coras288eaab2019-02-03 15:26:14 -0800698session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700699session_lookup_listener6 (u32 fib_index, ip6_address_t * lcl, u16 lcl_port,
Yu Pingb092b772019-12-27 04:04:33 +0800700 u8 proto, u8 use_wildcard)
Florin Coras04e53442017-07-16 17:12:15 -0700701{
Florin Corascea194d2017-10-02 00:18:51 -0700702 session_table_t *st;
703 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
704 if (!st)
705 return 0;
Yu Pingb092b772019-12-27 04:04:33 +0800706 return session_lookup_listener6_i (st, lcl, lcl_port, proto, use_wildcard);
Florin Coras04e53442017-07-16 17:12:15 -0700707}
708
Florin Coras477e91a2018-02-27 10:05:57 -0800709/**
710 * Lookup listener, exact or proxy (inaddr_any:0) match
711 */
Florin Coras288eaab2019-02-03 15:26:14 -0800712session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700713session_lookup_listener (u32 table_index, session_endpoint_t * sep)
Florin Coras04e53442017-07-16 17:12:15 -0700714{
Florin Corascea194d2017-10-02 00:18:51 -0700715 session_table_t *st;
716 st = session_table_get (table_index);
717 if (!st)
718 return 0;
719 if (sep->is_ip4)
720 return session_lookup_listener4_i (st, &sep->ip.ip4, sep->port,
Florin Coras477e91a2018-02-27 10:05:57 -0800721 sep->transport_proto, 0);
Florin Corascea194d2017-10-02 00:18:51 -0700722 else
723 return session_lookup_listener6_i (st, &sep->ip.ip6, sep->port,
Florin Coras477e91a2018-02-27 10:05:57 -0800724 sep->transport_proto, 0);
Florin Coras04e53442017-07-16 17:12:15 -0700725 return 0;
726}
727
Florin Coras9f1a5432019-03-10 21:03:20 -0700728/**
729 * Lookup listener wildcard match
730 */
731session_t *
732session_lookup_listener_wildcard (u32 table_index, session_endpoint_t * sep)
733{
734 session_table_t *st;
735 st = session_table_get (table_index);
736 if (!st)
737 return 0;
738 if (sep->is_ip4)
739 return session_lookup_listener4_i (st, &sep->ip.ip4, sep->port,
740 sep->transport_proto,
741 1 /* use_wildcard */ );
742 else
743 return session_lookup_listener6_i (st, &sep->ip.ip6, sep->port,
744 sep->transport_proto,
745 1 /* use_wildcard */ );
746 return 0;
747}
748
Florin Corascea194d2017-10-02 00:18:51 -0700749int
750session_lookup_add_half_open (transport_connection_t * tc, u64 value)
751{
752 session_table_t *st;
753 session_kv4_t kv4;
754 session_kv6_t kv6;
755
756 st = session_table_get_or_alloc_for_connection (tc);
757 if (!st)
758 return 0;
759 if (tc->is_ip4)
760 {
761 make_v4_ss_kv_from_tc (&kv4, tc);
762 kv4.value = value;
763 return clib_bihash_add_del_16_8 (&st->v4_half_open_hash, &kv4,
764 1 /* is_add */ );
765 }
766 else
767 {
768 make_v6_ss_kv_from_tc (&kv6, tc);
769 kv6.value = value;
770 return clib_bihash_add_del_48_8 (&st->v6_half_open_hash, &kv6,
771 1 /* is_add */ );
772 }
773}
774
775int
776session_lookup_del_half_open (transport_connection_t * tc)
777{
778 session_table_t *st;
779 session_kv4_t kv4;
780 session_kv6_t kv6;
781
782 st = session_table_get_for_connection (tc);
783 if (!st)
784 return -1;
785 if (tc->is_ip4)
786 {
787 make_v4_ss_kv_from_tc (&kv4, tc);
788 return clib_bihash_add_del_16_8 (&st->v4_half_open_hash, &kv4,
789 0 /* is_add */ );
790 }
791 else
792 {
793 make_v6_ss_kv_from_tc (&kv6, tc);
794 return clib_bihash_add_del_48_8 (&st->v6_half_open_hash, &kv6,
795 0 /* is_add */ );
796 }
797}
798
Florin Coras04e53442017-07-16 17:12:15 -0700799u64
Florin Corascea194d2017-10-02 00:18:51 -0700800session_lookup_half_open_handle (transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700801{
Florin Corascea194d2017-10-02 00:18:51 -0700802 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700803 session_kv4_t kv4;
804 session_kv6_t kv6;
805 int rv;
806
Florin Corascea194d2017-10-02 00:18:51 -0700807 st = session_table_get_for_fib_index (transport_connection_fib_proto (tc),
808 tc->fib_index);
809 if (!st)
810 return HALF_OPEN_LOOKUP_INVALID_VALUE;
811 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700812 {
Florin Corascea194d2017-10-02 00:18:51 -0700813 make_v4_ss_kv (&kv4, &tc->lcl_ip.ip4, &tc->rmt_ip.ip4, tc->lcl_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700814 tc->rmt_port, tc->proto);
Florin Corascea194d2017-10-02 00:18:51 -0700815 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700816 if (rv == 0)
817 return kv4.value;
Florin Corascea194d2017-10-02 00:18:51 -0700818 }
819 else
820 {
821 make_v6_ss_kv (&kv6, &tc->lcl_ip.ip6, &tc->rmt_ip.ip6, tc->lcl_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700822 tc->rmt_port, tc->proto);
Florin Corascea194d2017-10-02 00:18:51 -0700823 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700824 if (rv == 0)
825 return kv6.value;
Florin Coras04e53442017-07-16 17:12:15 -0700826 }
827 return HALF_OPEN_LOOKUP_INVALID_VALUE;
828}
829
830transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700831session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700832{
Florin Coras04e53442017-07-16 17:12:15 -0700833 if (handle != HALF_OPEN_LOOKUP_INVALID_VALUE)
Florin Corascea194d2017-10-02 00:18:51 -0700834 {
Florin Coras1ee78302019-02-05 15:51:15 -0800835 u32 sst = session_type_from_proto_and_ip (proto, is_ip4);
836 return transport_get_half_open (sst, handle & 0xFFFFFFFF);
Florin Corascea194d2017-10-02 00:18:51 -0700837 }
Florin Coras04e53442017-07-16 17:12:15 -0700838 return 0;
839}
840
Florin Corascea194d2017-10-02 00:18:51 -0700841/**
842 * Lookup connection with ip4 and transport layer information
843 *
844 * This is used on the fast path so it needs to be fast. Thereby,
845 * duplication of code and 'hacks' allowed.
846 *
847 * The lookup is incremental and returns whenever something is matched. The
848 * steps are:
849 * - Try to find an established session
Florin Corascea194d2017-10-02 00:18:51 -0700850 * - Try to find a half-open connection
Florin Coras1c710452017-10-17 00:03:13 -0700851 * - Try session rules table
Florin Corasa2ff7b82017-11-08 17:55:03 -0800852 * - Try to find a fully-formed or local source wildcarded (listener bound to
853 * all interfaces) listener session
Florin Corascea194d2017-10-02 00:18:51 -0700854 * - return 0
855 *
856 * @param fib_index index of fib wherein the connection was received
857 * @param lcl local ip4 address
858 * @param rmt remote ip4 address
859 * @param lcl_port local port
860 * @param rmt_port remote port
861 * @param proto transport protocol (e.g., tcp, udp)
862 * @param thread_index thread index for request
Florin Corasdff48db2017-11-19 18:06:58 -0800863 * @param is_filtered return flag that indicates if connection was filtered.
Florin Corascea194d2017-10-02 00:18:51 -0700864 *
865 * @return pointer to transport connection, if one is found, 0 otherwise
866 */
Florin Coras04e53442017-07-16 17:12:15 -0700867transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700868session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl,
869 ip4_address_t * rmt, u16 lcl_port,
Florin Corasdff48db2017-11-19 18:06:58 -0800870 u16 rmt_port, u8 proto, u32 thread_index,
Florin Corasb5e55a22019-01-10 12:42:47 -0800871 u8 * result)
Florin Coras04e53442017-07-16 17:12:15 -0700872{
Florin Corascea194d2017-10-02 00:18:51 -0700873 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700874 session_kv4_t kv4;
Florin Coras288eaab2019-02-03 15:26:14 -0800875 session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800876 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -0700877 int rv;
878
Florin Corascea194d2017-10-02 00:18:51 -0700879 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
880 if (PREDICT_FALSE (!st))
881 return 0;
882
Florin Corasa2ff7b82017-11-08 17:55:03 -0800883 /*
884 * Lookup session amongst established ones
885 */
Florin Coras04e53442017-07-16 17:12:15 -0700886 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700887 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700888 if (rv == 0)
889 {
Florin Corasb5e55a22019-01-10 12:42:47 -0800890 if (PREDICT_FALSE ((u32) (kv4.value >> 32) != thread_index))
891 {
892 *result = SESSION_LOOKUP_RESULT_WRONG_THREAD;
893 return 0;
894 }
Florin Corascea194d2017-10-02 00:18:51 -0700895 s = session_get (kv4.value & 0xFFFFFFFFULL, thread_index);
Florin Coras1ee78302019-02-05 15:51:15 -0800896 return transport_get_connection (proto, s->connection_index,
897 thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700898 }
899
Florin Corasa2ff7b82017-11-08 17:55:03 -0800900 /*
901 * Try half-open connections
902 */
Florin Corascea194d2017-10-02 00:18:51 -0700903 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700904 if (rv == 0)
Florin Coras1ee78302019-02-05 15:51:15 -0800905 return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF);
Florin Coras1c710452017-10-17 00:03:13 -0700906
Florin Corasa2ff7b82017-11-08 17:55:03 -0800907 /*
908 * Check the session rules table
909 */
910 action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl,
911 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -0800912 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -0800913 {
Florin Corasb5e55a22019-01-10 12:42:47 -0800914 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
915 {
916 *result = SESSION_LOOKUP_RESULT_FILTERED;
917 return 0;
918 }
Florin Corasdff48db2017-11-19 18:06:58 -0800919 if ((s = session_lookup_action_to_session (action_index,
920 FIB_PROTOCOL_IP4, proto)))
Florin Coras1ee78302019-02-05 15:51:15 -0800921 return transport_get_listener (proto, s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -0800922 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800923 }
924
925 /*
926 * If nothing is found, check if any listener is available
927 */
Florin Coras477e91a2018-02-27 10:05:57 -0800928 s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800929 if (s)
Florin Coras1ee78302019-02-05 15:51:15 -0800930 return transport_get_listener (proto, s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800931
932 return 0;
Florin Coras04e53442017-07-16 17:12:15 -0700933}
934
Florin Corascea194d2017-10-02 00:18:51 -0700935/**
936 * Lookup connection with ip4 and transport layer information
937 *
Florin Corasb5e55a22019-01-10 12:42:47 -0800938 * Not optimized. Lookup logic is identical to that of
939 * @ref session_lookup_connection_wt4
Florin Corascea194d2017-10-02 00:18:51 -0700940 *
941 * @param fib_index index of the fib wherein the connection was received
942 * @param lcl local ip4 address
943 * @param rmt remote ip4 address
944 * @param lcl_port local port
945 * @param rmt_port remote port
946 * @param proto transport protocol (e.g., tcp, udp)
947 *
948 * @return pointer to transport connection, if one is found, 0 otherwise
949 */
Florin Coras04e53442017-07-16 17:12:15 -0700950transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700951session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl,
952 ip4_address_t * rmt, u16 lcl_port, u16 rmt_port,
953 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700954{
Florin Corascea194d2017-10-02 00:18:51 -0700955 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700956 session_kv4_t kv4;
Florin Coras288eaab2019-02-03 15:26:14 -0800957 session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800958 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -0700959 int rv;
960
Florin Corascea194d2017-10-02 00:18:51 -0700961 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
962 if (PREDICT_FALSE (!st))
963 return 0;
964
Florin Corasa2ff7b82017-11-08 17:55:03 -0800965 /*
966 * Lookup session amongst established ones
967 */
Florin Coras04e53442017-07-16 17:12:15 -0700968 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700969 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700970 if (rv == 0)
971 {
Florin Corascea194d2017-10-02 00:18:51 -0700972 s = session_get_from_handle (kv4.value);
Florin Coras1ee78302019-02-05 15:51:15 -0800973 return transport_get_connection (proto, s->connection_index,
974 s->thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700975 }
976
Florin Corasa2ff7b82017-11-08 17:55:03 -0800977 /*
978 * Try half-open connections
979 */
Florin Corascea194d2017-10-02 00:18:51 -0700980 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700981 if (rv == 0)
Florin Coras1ee78302019-02-05 15:51:15 -0800982 return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800983
984 /*
985 * Check the session rules table
986 */
987 action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl,
988 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -0800989 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -0800990 {
Florin Corasdff48db2017-11-19 18:06:58 -0800991 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
992 return 0;
993 if ((s = session_lookup_action_to_session (action_index,
994 FIB_PROTOCOL_IP4, proto)))
Florin Coras1ee78302019-02-05 15:51:15 -0800995 return transport_get_listener (proto, s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -0800996 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800997 }
998
999 /*
1000 * If nothing is found, check if any listener is available
1001 */
Florin Coras477e91a2018-02-27 10:05:57 -08001002 s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001003 if (s)
Florin Coras1ee78302019-02-05 15:51:15 -08001004 return transport_get_listener (proto, s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001005
1006 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001007}
1008
Florin Corascea194d2017-10-02 00:18:51 -07001009/**
1010 * Lookup session with ip4 and transport layer information
1011 *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001012 * Important note: this may look into another thread's pool table and
1013 * register as 'peeker'. Caller should call @ref session_pool_remove_peeker as
1014 * if needed as soon as possible.
1015 *
1016 * Lookup logic is similar to that of @ref session_lookup_connection_wt4 but
1017 * this returns a session as opposed to a transport connection and it does not
1018 * try to lookup half-open sessions.
1019 *
1020 * Typically used by dgram connections
Florin Corascea194d2017-10-02 00:18:51 -07001021 */
Florin Coras288eaab2019-02-03 15:26:14 -08001022session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001023session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt,
1024 u16 lcl_port, u16 rmt_port, u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -07001025{
Florin Corascea194d2017-10-02 00:18:51 -07001026 session_table_t *st;
1027 session_kv4_t kv4;
Florin Coras288eaab2019-02-03 15:26:14 -08001028 session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001029 u32 action_index;
Florin Corascea194d2017-10-02 00:18:51 -07001030 int rv;
1031
1032 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
1033 if (PREDICT_FALSE (!st))
1034 return 0;
1035
Florin Corasa2ff7b82017-11-08 17:55:03 -08001036 /*
1037 * Lookup session amongst established ones
1038 */
Florin Corascea194d2017-10-02 00:18:51 -07001039 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
1040 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
1041 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001042 return session_get_from_handle_safe (kv4.value);
Florin Corascea194d2017-10-02 00:18:51 -07001043
Florin Corasa2ff7b82017-11-08 17:55:03 -08001044 /*
1045 * Check the session rules table
1046 */
1047 action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl,
1048 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001049 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001050 {
Florin Corasdff48db2017-11-19 18:06:58 -08001051 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1052 return 0;
1053 return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4,
1054 proto);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001055 }
1056
1057 /*
1058 * If nothing is found, check if any listener is available
1059 */
Florin Coras477e91a2018-02-27 10:05:57 -08001060 if ((s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1)))
Florin Corascea194d2017-10-02 00:18:51 -07001061 return s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001062
1063 return 0;
Florin Corascea194d2017-10-02 00:18:51 -07001064}
1065
1066/**
1067 * Lookup connection with ip6 and transport layer information
1068 *
1069 * This is used on the fast path so it needs to be fast. Thereby,
1070 * duplication of code and 'hacks' allowed.
1071 *
1072 * The lookup is incremental and returns whenever something is matched. The
1073 * steps are:
1074 * - Try to find an established session
Florin Corascea194d2017-10-02 00:18:51 -07001075 * - Try to find a half-open connection
Florin Coras1c710452017-10-17 00:03:13 -07001076 * - Try session rules table
Florin Corasa2ff7b82017-11-08 17:55:03 -08001077 * - Try to find a fully-formed or local source wildcarded (listener bound to
1078 * all interfaces) listener session
Florin Corascea194d2017-10-02 00:18:51 -07001079 * - return 0
1080 *
1081 * @param fib_index index of the fib wherein the connection was received
1082 * @param lcl local ip6 address
1083 * @param rmt remote ip6 address
1084 * @param lcl_port local port
1085 * @param rmt_port remote port
1086 * @param proto transport protocol (e.g., tcp, udp)
1087 * @param thread_index thread index for request
1088 *
1089 * @return pointer to transport connection, if one is found, 0 otherwise
1090 */
1091transport_connection_t *
1092session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl,
1093 ip6_address_t * rmt, u16 lcl_port,
Florin Corasdff48db2017-11-19 18:06:58 -08001094 u16 rmt_port, u8 proto, u32 thread_index,
Florin Corasb5e55a22019-01-10 12:42:47 -08001095 u8 * result)
Florin Corascea194d2017-10-02 00:18:51 -07001096{
1097 session_table_t *st;
Florin Coras288eaab2019-02-03 15:26:14 -08001098 session_t *s;
Florin Coras04e53442017-07-16 17:12:15 -07001099 session_kv6_t kv6;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001100 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -07001101 int rv;
1102
Florin Corascea194d2017-10-02 00:18:51 -07001103 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1104 if (PREDICT_FALSE (!st))
1105 return 0;
1106
Florin Coras04e53442017-07-16 17:12:15 -07001107 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -07001108 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001109 if (rv == 0)
1110 {
Florin Corascea194d2017-10-02 00:18:51 -07001111 ASSERT ((u32) (kv6.value >> 32) == thread_index);
Florin Corasb5e55a22019-01-10 12:42:47 -08001112 if (PREDICT_FALSE ((u32) (kv6.value >> 32) != thread_index))
1113 {
1114 *result = SESSION_LOOKUP_RESULT_WRONG_THREAD;
1115 return 0;
1116 }
Florin Corascea194d2017-10-02 00:18:51 -07001117 s = session_get (kv6.value & 0xFFFFFFFFULL, thread_index);
Florin Coras1ee78302019-02-05 15:51:15 -08001118 return transport_get_connection (proto, s->connection_index,
1119 thread_index);
Florin Coras04e53442017-07-16 17:12:15 -07001120 }
1121
Florin Corasa2ff7b82017-11-08 17:55:03 -08001122 /* Try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -07001123 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001124 if (rv == 0)
Florin Coras1ee78302019-02-05 15:51:15 -08001125 return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF);
Florin Coras04e53442017-07-16 17:12:15 -07001126
Florin Corasa2ff7b82017-11-08 17:55:03 -08001127 /* Check the session rules table */
1128 action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
1129 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001130 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001131 {
Florin Corasb5e55a22019-01-10 12:42:47 -08001132 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1133 {
1134 *result = SESSION_LOOKUP_RESULT_FILTERED;
1135 return 0;
1136 }
Florin Corasdff48db2017-11-19 18:06:58 -08001137 if ((s = session_lookup_action_to_session (action_index,
1138 FIB_PROTOCOL_IP6, proto)))
Florin Coras1ee78302019-02-05 15:51:15 -08001139 return transport_get_listener (proto, s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -08001140 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001141 }
1142
1143 /* If nothing is found, check if any listener is available */
Florin Coras477e91a2018-02-27 10:05:57 -08001144 s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001145 if (s)
Florin Coras1ee78302019-02-05 15:51:15 -08001146 return transport_get_listener (proto, s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001147
1148 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001149}
1150
Florin Corascea194d2017-10-02 00:18:51 -07001151/**
1152 * Lookup connection with ip6 and transport layer information
1153 *
1154 * Not optimized. This is used on the fast path so it needs to be fast.
1155 * Thereby, duplication of code and 'hacks' allowed. Lookup logic is identical
1156 * to that of @ref session_lookup_connection_wt4
1157 *
1158 * @param fib_index index of the fib wherein the connection was received
1159 * @param lcl local ip6 address
1160 * @param rmt remote ip6 address
1161 * @param lcl_port local port
1162 * @param rmt_port remote port
1163 * @param proto transport protocol (e.g., tcp, udp)
1164 *
1165 * @return pointer to transport connection, if one is found, 0 otherwise
1166 */
Florin Coras04e53442017-07-16 17:12:15 -07001167transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -07001168session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl,
1169 ip6_address_t * rmt, u16 lcl_port, u16 rmt_port,
1170 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -07001171{
Florin Corascea194d2017-10-02 00:18:51 -07001172 session_table_t *st;
Florin Coras288eaab2019-02-03 15:26:14 -08001173 session_t *s;
Florin Coras04e53442017-07-16 17:12:15 -07001174 session_kv6_t kv6;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001175 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -07001176 int rv;
1177
Florin Corascea194d2017-10-02 00:18:51 -07001178 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1179 if (PREDICT_FALSE (!st))
1180 return 0;
1181
Florin Coras04e53442017-07-16 17:12:15 -07001182 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -07001183 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001184 if (rv == 0)
1185 {
Florin Corascea194d2017-10-02 00:18:51 -07001186 s = session_get_from_handle (kv6.value);
Florin Coras1ee78302019-02-05 15:51:15 -08001187 return transport_get_connection (proto, s->connection_index,
1188 s->thread_index);
Florin Coras04e53442017-07-16 17:12:15 -07001189 }
1190
Florin Corasa2ff7b82017-11-08 17:55:03 -08001191 /* Try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -07001192 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001193 if (rv == 0)
Florin Coras1ee78302019-02-05 15:51:15 -08001194 return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF);
Florin Coras04e53442017-07-16 17:12:15 -07001195
Florin Corasa2ff7b82017-11-08 17:55:03 -08001196 /* Check the session rules table */
1197 action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
1198 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001199 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001200 {
Florin Corasdff48db2017-11-19 18:06:58 -08001201 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1202 return 0;
1203 if ((s = session_lookup_action_to_session (action_index,
1204 FIB_PROTOCOL_IP6, proto)))
Florin Coras1ee78302019-02-05 15:51:15 -08001205 return transport_get_listener (proto, s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -08001206 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001207 }
1208
1209 /* If nothing is found, check if any listener is available */
Florin Coras477e91a2018-02-27 10:05:57 -08001210 s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001211 if (s)
Florin Coras1ee78302019-02-05 15:51:15 -08001212 return transport_get_listener (proto, s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001213
1214 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001215}
1216
Florin Corascea194d2017-10-02 00:18:51 -07001217/**
1218 * Lookup session with ip6 and transport layer information
1219 *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001220 * Important note: this may look into another thread's pool table and
1221 * register as 'peeker'. Caller should call @ref session_pool_remove_peeker as
1222 * if needed as soon as possible.
1223 *
1224 * Lookup logic is similar to that of @ref session_lookup_connection_wt6 but
1225 * this returns a session as opposed to a transport connection and it does not
1226 * try to lookup half-open sessions.
1227 *
1228 * Typically used by dgram connections
Florin Corascea194d2017-10-02 00:18:51 -07001229 */
Florin Coras288eaab2019-02-03 15:26:14 -08001230session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001231session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt,
1232 u16 lcl_port, u16 rmt_port, u8 proto)
Florin Corascea194d2017-10-02 00:18:51 -07001233{
1234 session_table_t *st;
1235 session_kv6_t kv6;
Florin Coras288eaab2019-02-03 15:26:14 -08001236 session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001237 u32 action_index;
Florin Corascea194d2017-10-02 00:18:51 -07001238 int rv;
1239
1240 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1241 if (PREDICT_FALSE (!st))
1242 return 0;
1243
1244 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
1245 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
1246 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001247 return session_get_from_handle_safe (kv6.value);
Florin Corascea194d2017-10-02 00:18:51 -07001248
Florin Corasa2ff7b82017-11-08 17:55:03 -08001249 /* Check the session rules table */
1250 action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
1251 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001252 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001253 {
Florin Corasdff48db2017-11-19 18:06:58 -08001254 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1255 return 0;
1256 return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP6,
1257 proto);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001258 }
1259
Florin Corascea194d2017-10-02 00:18:51 -07001260 /* If nothing is found, check if any listener is available */
Florin Coras477e91a2018-02-27 10:05:57 -08001261 if ((s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1)))
Florin Corascea194d2017-10-02 00:18:51 -07001262 return s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001263 return 0;
Florin Corascea194d2017-10-02 00:18:51 -07001264}
1265
Florin Corasc1a42652019-02-08 18:27:29 -08001266int
Florin Coras1c710452017-10-17 00:03:13 -07001267vnet_session_rule_add_del (session_rule_add_del_args_t * args)
1268{
1269 app_namespace_t *app_ns = app_namespace_get (args->appns_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001270 session_rules_table_t *srt;
Florin Coras1c710452017-10-17 00:03:13 -07001271 session_table_t *st;
1272 u32 fib_index;
1273 u8 fib_proto;
Florin Corasc1a42652019-02-08 18:27:29 -08001274 int rv = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001275
1276 if (!app_ns)
Florin Corasc1a42652019-02-08 18:27:29 -08001277 return VNET_API_ERROR_APP_INVALID_NS;
1278
Florin Coras1c710452017-10-17 00:03:13 -07001279 if (args->scope > 3)
Florin Corasc1a42652019-02-08 18:27:29 -08001280 return VNET_API_ERROR_INVALID_VALUE;
1281
Florin Corasc97a7392017-11-05 23:07:07 -08001282 if (args->transport_proto != TRANSPORT_PROTO_TCP
1283 && args->transport_proto != TRANSPORT_PROTO_UDP)
Florin Corasc1a42652019-02-08 18:27:29 -08001284 return VNET_API_ERROR_INVALID_VALUE;
1285
Florin Coras1c710452017-10-17 00:03:13 -07001286 if ((args->scope & SESSION_RULE_SCOPE_GLOBAL) || args->scope == 0)
1287 {
1288 fib_proto = args->table_args.rmt.fp_proto;
1289 fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1290 st = session_table_get_for_fib_index (fib_proto, fib_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001291 srt = &st->session_rules[args->transport_proto];
Florin Corasc1a42652019-02-08 18:27:29 -08001292 if ((rv = session_rules_table_add_del (srt, &args->table_args)))
1293 return rv;
Florin Coras1c710452017-10-17 00:03:13 -07001294 }
1295 if (args->scope & SESSION_RULE_SCOPE_LOCAL)
1296 {
Dave Barachb7b92992018-10-17 10:38:51 -04001297 clib_memset (&args->table_args.lcl, 0, sizeof (args->table_args.lcl));
Florin Corasa2ff7b82017-11-08 17:55:03 -08001298 args->table_args.lcl.fp_proto = args->table_args.rmt.fp_proto;
1299 args->table_args.lcl_port = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001300 st = app_namespace_get_local_table (app_ns);
Florin Corasc97a7392017-11-05 23:07:07 -08001301 srt = &st->session_rules[args->transport_proto];
Florin Corasc1a42652019-02-08 18:27:29 -08001302 rv = session_rules_table_add_del (srt, &args->table_args);
Florin Coras1c710452017-10-17 00:03:13 -07001303 }
Florin Corasc1a42652019-02-08 18:27:29 -08001304 return rv;
Florin Coras1c710452017-10-17 00:03:13 -07001305}
1306
Florin Coras6c36f532017-11-03 18:32:34 -07001307/**
1308 * Mark (global) tables as pertaining to app ns
1309 */
1310void
1311session_lookup_set_tables_appns (app_namespace_t * app_ns)
1312{
1313 session_table_t *st;
1314 u32 fib_index;
1315 u8 fp;
1316
1317 for (fp = 0; fp < ARRAY_LEN (fib_index_to_table_index); fp++)
1318 {
1319 fib_index = app_namespace_get_fib_index (app_ns, fp);
Florin Coras95cd8642019-12-30 21:53:19 -08001320 st = session_table_get_or_alloc (fp, fib_index);
Florin Coras6c36f532017-11-03 18:32:34 -07001321 if (st)
1322 st->appns_index = app_namespace_index (app_ns);
1323 }
1324}
1325
Florin Corascea194d2017-10-02 00:18:51 -07001326u8 *
1327format_ip4_session_lookup_kvp (u8 * s, va_list * args)
1328{
1329 clib_bihash_kv_16_8_t *kvp = va_arg (*args, clib_bihash_kv_16_8_t *);
Florin Coras2b81e3c2019-02-27 07:55:46 -08001330 u32 is_local = va_arg (*args, u32);
Florin Coras15531972018-08-12 23:50:53 -07001331 v4_connection_key_t *key = (v4_connection_key_t *) kvp->key;
Florin Coras288eaab2019-02-03 15:26:14 -08001332 session_t *session;
Florin Coras15531972018-08-12 23:50:53 -07001333 app_worker_t *app_wrk;
Florin Coras053a0e42018-11-13 15:52:38 -08001334 const u8 *app_name;
1335 u8 *str = 0;
Florin Corascea194d2017-10-02 00:18:51 -07001336
Florin Corascea194d2017-10-02 00:18:51 -07001337 if (!is_local)
1338 {
1339 session = session_get_from_handle (kvp->value);
Florin Coras15531972018-08-12 23:50:53 -07001340 app_wrk = app_worker_get (session->app_wrk_index);
1341 app_name = application_name_from_index (app_wrk->app_index);
Florin Coras561af9b2017-12-09 10:19:43 -08001342 str = format (0, "[%U] %U:%d->%U:%d", format_transport_proto_short,
1343 key->proto, format_ip4_address, &key->src,
1344 clib_net_to_host_u16 (key->src_port), format_ip4_address,
1345 &key->dst, clib_net_to_host_u16 (key->dst_port));
Florin Corascea194d2017-10-02 00:18:51 -07001346 s = format (s, "%-40v%-30v", str, app_name);
1347 }
1348 else
1349 {
Florin Coras2b81e3c2019-02-27 07:55:46 -08001350 session = session_get_from_handle (kvp->value);
1351 app_wrk = app_worker_get (session->app_wrk_index);
Florin Coras15531972018-08-12 23:50:53 -07001352 app_name = application_name_from_index (app_wrk->app_index);
Florin Coras561af9b2017-12-09 10:19:43 -08001353 str = format (0, "[%U] %U:%d", format_transport_proto_short, key->proto,
1354 format_ip4_address, &key->src,
1355 clib_net_to_host_u16 (key->src_port));
Florin Corascea194d2017-10-02 00:18:51 -07001356 s = format (s, "%-30v%-30v", str, app_name);
1357 }
Florin Corascea194d2017-10-02 00:18:51 -07001358 return s;
1359}
1360
1361typedef struct _ip4_session_table_show_ctx_t
1362{
1363 vlib_main_t *vm;
1364 u8 is_local;
1365} ip4_session_table_show_ctx_t;
1366
1367static int
1368ip4_session_table_show (clib_bihash_kv_16_8_t * kvp, void *arg)
1369{
1370 ip4_session_table_show_ctx_t *ctx = arg;
1371 vlib_cli_output (ctx->vm, "%U", format_ip4_session_lookup_kvp, kvp,
1372 ctx->is_local);
1373 return 1;
1374}
1375
1376void
1377session_lookup_show_table_entries (vlib_main_t * vm, session_table_t * table,
1378 u8 type, u8 is_local)
1379{
1380 ip4_session_table_show_ctx_t ctx = {
1381 .vm = vm,
1382 .is_local = is_local,
1383 };
1384 if (!is_local)
1385 vlib_cli_output (vm, "%-40s%-30s", "Session", "Application");
1386 else
1387 vlib_cli_output (vm, "%-30s%-30s", "Listener", "Application");
1388 switch (type)
1389 {
1390 /* main table v4 */
1391 case 0:
1392 ip4_session_table_walk (&table->v4_session_hash, ip4_session_table_show,
1393 &ctx);
1394 break;
1395 default:
1396 clib_warning ("not supported");
1397 }
1398}
Florin Coras66b11312017-07-31 17:18:03 -07001399
Florin Coras1c710452017-10-17 00:03:13 -07001400static clib_error_t *
1401session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
1402 vlib_cli_command_t * cmd)
1403{
Florin Corasc97a7392017-11-05 23:07:07 -08001404 u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen = 0, rmt_plen = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001405 u32 appns_index, scope = 0;
1406 ip46_address_t lcl_ip, rmt_ip;
1407 u8 is_ip4 = 1, conn_set = 0;
1408 u8 fib_proto, is_add = 1, *ns_id = 0;
Florin Corasc97a7392017-11-05 23:07:07 -08001409 u8 *tag = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001410 app_namespace_t *app_ns;
Florin Corasc1a42652019-02-08 18:27:29 -08001411 int rv;
Florin Coras1c710452017-10-17 00:03:13 -07001412
Guanghua Zhangfcd5e122019-08-24 10:52:19 +08001413 session_cli_return_if_not_enabled ();
1414
Dave Barachb7b92992018-10-17 10:38:51 -04001415 clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
1416 clib_memset (&rmt_ip, 0, sizeof (rmt_ip));
Florin Coras1c710452017-10-17 00:03:13 -07001417 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1418 {
1419 if (unformat (input, "del"))
1420 is_add = 0;
1421 else if (unformat (input, "add"))
1422 ;
1423 else if (unformat (input, "appns %_%v%_", &ns_id))
1424 ;
1425 else if (unformat (input, "scope global"))
1426 scope = SESSION_RULE_SCOPE_GLOBAL;
1427 else if (unformat (input, "scope local"))
1428 scope = SESSION_RULE_SCOPE_LOCAL;
1429 else if (unformat (input, "scope all"))
1430 scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1431 else if (unformat (input, "proto %U", unformat_transport_proto, &proto))
1432 ;
1433 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1434 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1435 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1436 &rmt_port))
1437 {
1438 is_ip4 = 1;
1439 conn_set = 1;
1440 }
1441 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1442 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1443 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1444 &rmt_port))
1445 {
1446 is_ip4 = 0;
1447 conn_set = 1;
1448 }
1449 else if (unformat (input, "action %d", &action))
1450 ;
Florin Corasc97a7392017-11-05 23:07:07 -08001451 else if (unformat (input, "tag %_%v%_", &tag))
1452 ;
Florin Coras1c710452017-10-17 00:03:13 -07001453 else
1454 return clib_error_return (0, "unknown input `%U'",
1455 format_unformat_error, input);
1456 }
1457
Florin Corasc97a7392017-11-05 23:07:07 -08001458 if (proto == ~0)
1459 {
1460 vlib_cli_output (vm, "proto must be set");
1461 return 0;
1462 }
1463 if (is_add && !conn_set && action == ~0)
1464 {
1465 vlib_cli_output (vm, "connection and action must be set for add");
1466 return 0;
1467 }
1468 if (!is_add && !tag && !conn_set)
1469 {
1470 vlib_cli_output (vm, "connection or tag must be set for delete");
1471 return 0;
1472 }
1473 if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN)
1474 {
1475 vlib_cli_output (vm, "tag too long (max u64)");
1476 return 0;
1477 }
Florin Coras1c710452017-10-17 00:03:13 -07001478
1479 if (ns_id)
1480 {
1481 app_ns = app_namespace_get_from_id (ns_id);
1482 if (!app_ns)
Florin Corasc97a7392017-11-05 23:07:07 -08001483 {
1484 vlib_cli_output (vm, "namespace %v does not exist", ns_id);
1485 return 0;
1486 }
Florin Coras1c710452017-10-17 00:03:13 -07001487 }
1488 else
1489 {
1490 app_ns = app_namespace_get_default ();
1491 }
1492 appns_index = app_namespace_index (app_ns);
1493
1494 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1495 session_rule_add_del_args_t args = {
zhanglimaoa04ebb82019-03-13 10:36:54 +08001496 .transport_proto = proto,
Florin Coras1c710452017-10-17 00:03:13 -07001497 .table_args.lcl.fp_addr = lcl_ip,
1498 .table_args.lcl.fp_len = lcl_plen,
1499 .table_args.lcl.fp_proto = fib_proto,
1500 .table_args.rmt.fp_addr = rmt_ip,
1501 .table_args.rmt.fp_len = rmt_plen,
1502 .table_args.rmt.fp_proto = fib_proto,
1503 .table_args.lcl_port = lcl_port,
1504 .table_args.rmt_port = rmt_port,
1505 .table_args.action_index = action,
1506 .table_args.is_add = is_add,
Florin Corasc97a7392017-11-05 23:07:07 -08001507 .table_args.tag = tag,
Florin Coras1c710452017-10-17 00:03:13 -07001508 .appns_index = appns_index,
1509 .scope = scope,
1510 };
Florin Corasc1a42652019-02-08 18:27:29 -08001511 if ((rv = vnet_session_rule_add_del (&args)))
1512 return clib_error_return (0, "rule add del returned %u", rv);
1513
Florin Corasc97a7392017-11-05 23:07:07 -08001514 vec_free (tag);
Florin Corasc1a42652019-02-08 18:27:29 -08001515 return 0;
Florin Coras1c710452017-10-17 00:03:13 -07001516}
1517
1518/* *INDENT-OFF* */
1519VLIB_CLI_COMMAND (session_rule_command, static) =
1520{
1521 .path = "session rule",
1522 .short_help = "session rule [add|del] appns <ns_id> proto <proto> "
1523 "<lcl-ip/plen> <lcl-port> <rmt-ip/plen> <rmt-port> action <action>",
1524 .function = session_rule_command_fn,
1525};
1526/* *INDENT-ON* */
1527
Florin Coras7999e832017-10-31 01:51:04 -07001528void
1529session_lookup_dump_rules_table (u32 fib_index, u8 fib_proto,
1530 u8 transport_proto)
1531{
1532 vlib_main_t *vm = vlib_get_main ();
Florin Corasc97a7392017-11-05 23:07:07 -08001533 session_rules_table_t *srt;
Florin Coras7999e832017-10-31 01:51:04 -07001534 session_table_t *st;
1535 st = session_table_get_for_fib_index (fib_index, fib_proto);
Florin Corasc97a7392017-11-05 23:07:07 -08001536 srt = &st->session_rules[transport_proto];
1537 session_rules_table_cli_dump (vm, srt, fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001538}
1539
1540void
1541session_lookup_dump_local_rules_table (u32 table_index, u8 fib_proto,
1542 u8 transport_proto)
1543{
1544 vlib_main_t *vm = vlib_get_main ();
Florin Corasc97a7392017-11-05 23:07:07 -08001545 session_rules_table_t *srt;
Florin Coras7999e832017-10-31 01:51:04 -07001546 session_table_t *st;
1547 st = session_table_get (table_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001548 srt = &st->session_rules[transport_proto];
1549 session_rules_table_cli_dump (vm, srt, fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001550}
1551
Florin Coras1c710452017-10-17 00:03:13 -07001552static clib_error_t *
1553show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input,
1554 vlib_cli_command_t * cmd)
1555{
1556 u32 transport_proto = ~0, lcl_port, rmt_port, lcl_plen, rmt_plen;
1557 u32 fib_index, scope = 0;
1558 ip46_address_t lcl_ip, rmt_ip;
1559 u8 is_ip4 = 1, show_one = 0;
1560 app_namespace_t *app_ns;
Florin Corasc97a7392017-11-05 23:07:07 -08001561 session_rules_table_t *srt;
Florin Coras1c710452017-10-17 00:03:13 -07001562 session_table_t *st;
1563 u8 *ns_id = 0, fib_proto;
1564
Guanghua Zhangfcd5e122019-08-24 10:52:19 +08001565 session_cli_return_if_not_enabled ();
1566
Dave Barachb7b92992018-10-17 10:38:51 -04001567 clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
1568 clib_memset (&rmt_ip, 0, sizeof (rmt_ip));
Florin Coras1c710452017-10-17 00:03:13 -07001569 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1570 {
1571 if (unformat (input, "%U", unformat_transport_proto, &transport_proto))
1572 ;
1573 else if (unformat (input, "appns %_%v%_", &ns_id))
1574 ;
1575 else if (unformat (input, "scope global"))
1576 scope = 1;
1577 else if (unformat (input, "scope local"))
1578 scope = 2;
1579 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1580 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1581 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1582 &rmt_port))
1583 {
1584 is_ip4 = 1;
1585 show_one = 1;
1586 }
1587 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1588 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1589 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1590 &rmt_port))
1591 {
1592 is_ip4 = 0;
1593 show_one = 1;
1594 }
1595 else
1596 return clib_error_return (0, "unknown input `%U'",
1597 format_unformat_error, input);
1598 }
1599
1600 if (transport_proto == ~0)
1601 {
1602 vlib_cli_output (vm, "transport proto must be set");
1603 return 0;
1604 }
1605
1606 if (ns_id)
1607 {
1608 app_ns = app_namespace_get_from_id (ns_id);
1609 if (!app_ns)
1610 {
1611 vlib_cli_output (vm, "appns %v doesn't exist", ns_id);
1612 return 0;
1613 }
1614 }
1615 else
1616 {
1617 app_ns = app_namespace_get_default ();
1618 }
1619
1620 if (scope == 1 || scope == 0)
1621 {
1622 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1623 fib_index = is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
1624 st = session_table_get_for_fib_index (fib_proto, fib_index);
1625 }
1626 else
1627 {
1628 st = app_namespace_get_local_table (app_ns);
1629 }
1630
1631 if (show_one)
1632 {
Florin Corasc97a7392017-11-05 23:07:07 -08001633 srt = &st->session_rules[transport_proto];
1634 session_rules_table_show_rule (vm, srt, &lcl_ip, lcl_port, &rmt_ip,
1635 rmt_port, is_ip4);
Florin Coras1c710452017-10-17 00:03:13 -07001636 return 0;
1637 }
1638
Florin Corasc97a7392017-11-05 23:07:07 -08001639 vlib_cli_output (vm, "%U rules table", format_transport_proto,
1640 transport_proto);
1641 srt = &st->session_rules[transport_proto];
1642 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
1643 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP6);
Florin Coras1c710452017-10-17 00:03:13 -07001644
1645 vec_free (ns_id);
1646 return 0;
1647}
1648
1649/* *INDENT-OFF* */
1650VLIB_CLI_COMMAND (show_session_rules_command, static) =
1651{
1652 .path = "show session rules",
Florin Corasdff48db2017-11-19 18:06:58 -08001653 .short_help = "show session rules [<proto> appns <id> <lcl-ip/plen> "
1654 "<lcl-port> <rmt-ip/plen> <rmt-port> scope <scope>]",
Florin Coras1c710452017-10-17 00:03:13 -07001655 .function = show_session_rules_command_fn,
1656};
1657/* *INDENT-ON* */
1658
Florin Coras04e53442017-07-16 17:12:15 -07001659void
1660session_lookup_init (void)
1661{
Florin Corascea194d2017-10-02 00:18:51 -07001662 /*
1663 * Allocate default table and map it to fib_index 0
1664 */
1665 session_table_t *st = session_table_alloc ();
1666 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP4], 0);
1667 fib_index_to_table_index[FIB_PROTOCOL_IP4][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001668 st->active_fib_proto = FIB_PROTOCOL_IP4;
1669 session_table_init (st, FIB_PROTOCOL_IP4);
Florin Corascea194d2017-10-02 00:18:51 -07001670 st = session_table_alloc ();
1671 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP6], 0);
1672 fib_index_to_table_index[FIB_PROTOCOL_IP6][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001673 st->active_fib_proto = FIB_PROTOCOL_IP6;
1674 session_table_init (st, FIB_PROTOCOL_IP6);
Florin Coras04e53442017-07-16 17:12:15 -07001675}
1676
1677/*
1678 * fd.io coding-style-patch-verification: ON
1679 *
1680 * Local Variables:
1681 * eval: (c-set-style "gnu")
1682 * End:
1683 */