blob: 37fccd9d7b7195fde52f69426595273b2dbfdeb5 [file] [log] [blame]
Florin Coras04e53442017-07-16 17:12:15 -07001/*
2 * Copyright (c) 2017 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16/** 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/**
33 * External vector of per transport virtual functions table
34 */
Florin Coras04e53442017-07-16 17:12:15 -070035extern transport_proto_vft_t *tp_vfts;
36
Florin Corascea194d2017-10-02 00:18:51 -070037/**
38 * Network namespace index (i.e., fib index) to session lookup table. We
39 * should have one per network protocol type but for now we only support IP4/6
40 */
41static u32 *fib_index_to_table_index[2];
42
Florin Coras04e53442017-07-16 17:12:15 -070043/* *INDENT-OFF* */
44/* 16 octets */
45typedef CLIB_PACKED (struct {
46 union
47 {
48 struct
49 {
50 ip4_address_t src;
51 ip4_address_t dst;
52 u16 src_port;
53 u16 dst_port;
54 /* align by making this 4 octets even though its a 1-bit field
55 * NOTE: avoid key overlap with other transports that use 5 tuples for
56 * session identification.
57 */
58 u32 proto;
59 };
60 u64 as_u64[2];
61 };
62}) v4_connection_key_t;
63
64typedef CLIB_PACKED (struct {
65 union
66 {
67 struct
68 {
69 /* 48 octets */
70 ip6_address_t src;
71 ip6_address_t dst;
72 u16 src_port;
73 u16 dst_port;
74 u32 proto;
75 u64 unused;
76 };
77 u64 as_u64[6];
78 };
79}) v6_connection_key_t;
80/* *INDENT-ON* */
81
82typedef clib_bihash_kv_16_8_t session_kv4_t;
83typedef clib_bihash_kv_48_8_t session_kv6_t;
84
85always_inline void
86make_v4_ss_kv (session_kv4_t * kv, ip4_address_t * lcl, ip4_address_t * rmt,
87 u16 lcl_port, u16 rmt_port, u8 proto)
88{
Florin Coras9679c812018-06-21 08:14:34 -070089 kv->key[0] = (u64) rmt->as_u32 << 32 | (u64) lcl->as_u32;
90 kv->key[1] = (u64) proto << 32 | (u64) rmt_port << 16 | (u64) lcl_port;
Florin Coras04e53442017-07-16 17:12:15 -070091 kv->value = ~0ULL;
92}
93
94always_inline void
95make_v4_listener_kv (session_kv4_t * kv, ip4_address_t * lcl, u16 lcl_port,
96 u8 proto)
97{
Florin Coras9679c812018-06-21 08:14:34 -070098 kv->key[0] = (u64) lcl->as_u32;
99 kv->key[1] = (u64) proto << 32 | (u64) lcl_port;
Florin Coras04e53442017-07-16 17:12:15 -0700100 kv->value = ~0ULL;
101}
102
103always_inline void
Florin Corasdbd44562017-11-09 19:30:17 -0800104make_v4_proxy_kv (session_kv4_t * kv, ip4_address_t * lcl, u8 proto)
105{
Florin Coras9679c812018-06-21 08:14:34 -0700106 kv->key[0] = (u64) lcl->as_u32;
107 kv->key[1] = (u64) proto << 32;
Florin Corasdbd44562017-11-09 19:30:17 -0800108 kv->value = ~0ULL;
109}
110
111always_inline void
Florin Coras561af9b2017-12-09 10:19:43 -0800112make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700113{
Florin Coras561af9b2017-12-09 10:19:43 -0800114 make_v4_ss_kv (kv, &tc->lcl_ip.ip4, &tc->rmt_ip.ip4, tc->lcl_port,
115 tc->rmt_port, tc->proto);
Florin Coras04e53442017-07-16 17:12:15 -0700116}
117
118always_inline void
119make_v6_ss_kv (session_kv6_t * kv, ip6_address_t * lcl, ip6_address_t * rmt,
120 u16 lcl_port, u16 rmt_port, u8 proto)
121{
Florin Coras9679c812018-06-21 08:14:34 -0700122 kv->key[0] = lcl->as_u64[0];
123 kv->key[1] = lcl->as_u64[1];
124 kv->key[2] = rmt->as_u64[0];
125 kv->key[3] = rmt->as_u64[1];
126 kv->key[4] = (u64) proto << 32 | (u64) rmt_port << 16 | (u64) lcl_port;
127 kv->key[5] = 0;
Florin Coras04e53442017-07-16 17:12:15 -0700128 kv->value = ~0ULL;
129}
130
131always_inline void
132make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port,
133 u8 proto)
134{
Florin Coras9679c812018-06-21 08:14:34 -0700135 kv->key[0] = lcl->as_u64[0];
136 kv->key[1] = lcl->as_u64[1];
137 kv->key[2] = 0;
138 kv->key[3] = 0;
139 kv->key[4] = (u64) proto << 32 | (u64) lcl_port;
140 kv->key[5] = 0;
Florin Coras04e53442017-07-16 17:12:15 -0700141 kv->value = ~0ULL;
142}
143
144always_inline void
Florin Corasdbd44562017-11-09 19:30:17 -0800145make_v6_proxy_kv (session_kv6_t * kv, ip6_address_t * lcl, u8 proto)
146{
Florin Coras9679c812018-06-21 08:14:34 -0700147 kv->key[0] = lcl->as_u64[0];
148 kv->key[1] = lcl->as_u64[1];
149 kv->key[2] = 0;
150 kv->key[3] = 0;
151 kv->key[4] = (u64) proto << 32;
152 kv->key[5] = 0;
Florin Corasdbd44562017-11-09 19:30:17 -0800153 kv->value = ~0ULL;
154}
155
156always_inline void
Florin Coras561af9b2017-12-09 10:19:43 -0800157make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700158{
Florin Coras561af9b2017-12-09 10:19:43 -0800159 make_v6_ss_kv (kv, &tc->lcl_ip.ip6, &tc->rmt_ip.ip6, tc->lcl_port,
160 tc->rmt_port, tc->proto);
Florin Coras04e53442017-07-16 17:12:15 -0700161}
162
Florin Corascea194d2017-10-02 00:18:51 -0700163static session_table_t *
Florin Coras6c36f532017-11-03 18:32:34 -0700164session_table_get_or_alloc (u8 fib_proto, u8 fib_index)
Florin Coras04e53442017-07-16 17:12:15 -0700165{
Florin Corascea194d2017-10-02 00:18:51 -0700166 session_table_t *st;
Florin Coras6c36f532017-11-03 18:32:34 -0700167 u32 table_index;
168 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
Florin Corascea194d2017-10-02 00:18:51 -0700169 {
170 st = session_table_alloc ();
171 table_index = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -0700172 vec_validate (fib_index_to_table_index[fib_proto], fib_index);
173 fib_index_to_table_index[fib_proto][fib_index] = table_index;
174 st->active_fib_proto = fib_proto;
Florin Corasb795bd02017-12-14 11:30:48 -0800175 session_table_init (st, fib_proto);
Florin Corascea194d2017-10-02 00:18:51 -0700176 return st;
177 }
178 else
179 {
Florin Coras6c36f532017-11-03 18:32:34 -0700180 table_index = fib_index_to_table_index[fib_proto][fib_index];
Florin Corascea194d2017-10-02 00:18:51 -0700181 return session_table_get (table_index);
182 }
183}
184
185static session_table_t *
Florin Coras6c36f532017-11-03 18:32:34 -0700186session_table_get_or_alloc_for_connection (transport_connection_t * tc)
187{
188 u32 fib_proto;
189 fib_proto = transport_connection_fib_proto (tc);
190 return session_table_get_or_alloc (fib_proto, tc->fib_index);
191}
192
193static session_table_t *
Florin Corascea194d2017-10-02 00:18:51 -0700194session_table_get_for_connection (transport_connection_t * tc)
195{
196 u32 fib_proto = transport_connection_fib_proto (tc);
197 if (vec_len (fib_index_to_table_index[fib_proto]) <= tc->fib_index)
198 return 0;
199 return
200 session_table_get (fib_index_to_table_index[fib_proto][tc->fib_index]);
201}
202
203static session_table_t *
204session_table_get_for_fib_index (u32 fib_proto, u32 fib_index)
205{
206 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
207 return 0;
208 return session_table_get (fib_index_to_table_index[fib_proto][fib_index]);
209}
210
211u32
212session_lookup_get_index_for_fib (u32 fib_proto, u32 fib_index)
213{
214 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
215 return SESSION_TABLE_INVALID_INDEX;
216 return fib_index_to_table_index[fib_proto][fib_index];
217}
218
219/**
220 * Add transport connection to a session table
221 *
222 * Session lookup 5-tuple (src-ip, dst-ip, src-port, dst-port, session-type)
223 * is added to requested session table.
224 *
225 * @param tc transport connection to be added
226 * @param value value to be stored
227 *
228 * @return non-zero if failure
229 */
230int
231session_lookup_add_connection (transport_connection_t * tc, u64 value)
232{
233 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700234 session_kv4_t kv4;
235 session_kv6_t kv6;
236
Florin Corascea194d2017-10-02 00:18:51 -0700237 st = session_table_get_or_alloc_for_connection (tc);
238 if (!st)
239 return -1;
Florin Coras68810622017-07-24 17:40:28 -0700240 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700241 {
Florin Coras04e53442017-07-16 17:12:15 -0700242 make_v4_ss_kv_from_tc (&kv4, tc);
243 kv4.value = value;
Florin Corascea194d2017-10-02 00:18:51 -0700244 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4,
245 1 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700246 }
247 else
248 {
Florin Coras04e53442017-07-16 17:12:15 -0700249 make_v6_ss_kv_from_tc (&kv6, tc);
250 kv6.value = value;
Florin Corascea194d2017-10-02 00:18:51 -0700251 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6,
252 1 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700253 }
254}
255
Florin Coras04e53442017-07-16 17:12:15 -0700256int
Florin Corascea194d2017-10-02 00:18:51 -0700257session_lookup_add_session_endpoint (u32 table_index,
258 session_endpoint_t * sep, u64 value)
Florin Coras04e53442017-07-16 17:12:15 -0700259{
Florin Corascea194d2017-10-02 00:18:51 -0700260 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700261 session_kv4_t kv4;
262 session_kv6_t kv6;
Florin Coras68810622017-07-24 17:40:28 -0700263
Florin Corascea194d2017-10-02 00:18:51 -0700264 st = session_table_get (table_index);
265 if (!st)
266 return -1;
267 if (sep->is_ip4)
268 {
269 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
270 sep->transport_proto);
271 kv4.value = value;
272 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 1);
273 }
274 else
275 {
276 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
277 sep->transport_proto);
278 kv6.value = value;
279 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 1);
280 }
281}
282
283int
284session_lookup_del_session_endpoint (u32 table_index,
285 session_endpoint_t * sep)
286{
287 session_table_t *st;
288 session_kv4_t kv4;
289 session_kv6_t kv6;
290
291 st = session_table_get (table_index);
292 if (!st)
293 return -1;
294 if (sep->is_ip4)
295 {
296 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
297 sep->transport_proto);
298 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 0);
299 }
300 else
301 {
302 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
303 sep->transport_proto);
304 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 0);
305 }
306}
307
308/**
309 * Delete transport connection from session table
310 *
311 * @param table_index session table index
312 * @param tc transport connection to be removed
313 *
314 * @return non-zero if failure
315 */
316int
317session_lookup_del_connection (transport_connection_t * tc)
318{
319 session_table_t *st;
320 session_kv4_t kv4;
321 session_kv6_t kv6;
322
323 st = session_table_get_for_connection (tc);
324 if (!st)
325 return -1;
Florin Coras68810622017-07-24 17:40:28 -0700326 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700327 {
Florin Coras04e53442017-07-16 17:12:15 -0700328 make_v4_ss_kv_from_tc (&kv4, tc);
Florin Corascea194d2017-10-02 00:18:51 -0700329 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4,
Florin Coras04e53442017-07-16 17:12:15 -0700330 0 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700331 }
332 else
333 {
Florin Coras04e53442017-07-16 17:12:15 -0700334 make_v6_ss_kv_from_tc (&kv6, tc);
Florin Corascea194d2017-10-02 00:18:51 -0700335 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6,
Florin Coras04e53442017-07-16 17:12:15 -0700336 0 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700337 }
Florin Coras04e53442017-07-16 17:12:15 -0700338}
339
340int
Florin Corascea194d2017-10-02 00:18:51 -0700341session_lookup_del_session (stream_session_t * s)
Florin Coras04e53442017-07-16 17:12:15 -0700342{
Florin Coras561af9b2017-12-09 10:19:43 -0800343 transport_proto_t tp = session_get_transport_proto (s);
Florin Coras04e53442017-07-16 17:12:15 -0700344 transport_connection_t *ts;
Florin Coras561af9b2017-12-09 10:19:43 -0800345 ts = tp_vfts[tp].get_connection (s->connection_index, s->thread_index);
Florin Corascea194d2017-10-02 00:18:51 -0700346 return session_lookup_del_connection (ts);
Florin Coras04e53442017-07-16 17:12:15 -0700347}
348
Florin Corasdff48db2017-11-19 18:06:58 -0800349static u8
350session_lookup_action_index_is_valid (u32 action_index)
Florin Corasf0c1c962017-11-02 21:31:46 -0700351{
Florin Corasdff48db2017-11-19 18:06:58 -0800352 if (action_index == SESSION_RULES_TABLE_ACTION_ALLOW
353 || action_index == SESSION_RULES_TABLE_INVALID_INDEX)
354 return 0;
355 return 1;
356}
357
Florin Corasf8f516a2018-02-08 15:10:09 -0800358static u64
359session_lookup_action_to_handle (u32 action_index)
Florin Corasdff48db2017-11-19 18:06:58 -0800360{
361 switch (action_index)
362 {
363 case SESSION_RULES_TABLE_ACTION_DROP:
Florin Corasf8f516a2018-02-08 15:10:09 -0800364 return SESSION_DROP_HANDLE;
Florin Corasdff48db2017-11-19 18:06:58 -0800365 case SESSION_RULES_TABLE_ACTION_ALLOW:
366 case SESSION_RULES_TABLE_INVALID_INDEX:
Florin Corasf8f516a2018-02-08 15:10:09 -0800367 return SESSION_INVALID_HANDLE;
Florin Corasdff48db2017-11-19 18:06:58 -0800368 default:
Florin Corasf8f516a2018-02-08 15:10:09 -0800369 /* application index */
Florin Corasdff48db2017-11-19 18:06:58 -0800370 return action_index;
371 }
Florin Corasf0c1c962017-11-02 21:31:46 -0700372}
373
Florin Coras1c710452017-10-17 00:03:13 -0700374static stream_session_t *
Florin Coras7999e832017-10-31 01:51:04 -0700375session_lookup_app_listen_session (u32 app_index, u8 fib_proto,
376 u8 transport_proto)
Florin Coras1c710452017-10-17 00:03:13 -0700377{
378 application_t *app;
Florin Corasdff48db2017-11-19 18:06:58 -0800379 app = application_get_if_valid (app_index);
Florin Coras1c710452017-10-17 00:03:13 -0700380 if (!app)
381 return 0;
382
Florin Coras7999e832017-10-31 01:51:04 -0700383 return application_first_listener (app, fib_proto, transport_proto);
Florin Coras1c710452017-10-17 00:03:13 -0700384}
385
Florin Corasa2ff7b82017-11-08 17:55:03 -0800386static stream_session_t *
387session_lookup_action_to_session (u32 action_index, u8 fib_proto,
388 u8 transport_proto)
389{
Florin Corasdff48db2017-11-19 18:06:58 -0800390 u32 app_index;
Florin Corasf8f516a2018-02-08 15:10:09 -0800391 app_index = session_lookup_action_to_handle (action_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800392 /* Nothing sophisticated for now, action index is app index */
Florin Corasdff48db2017-11-19 18:06:58 -0800393 return session_lookup_app_listen_session (app_index, fib_proto,
Florin Corasa2ff7b82017-11-08 17:55:03 -0800394 transport_proto);
395}
396
Florin Corasf8f516a2018-02-08 15:10:09 -0800397/** UNUSED */
Florin Coras1c710452017-10-17 00:03:13 -0700398stream_session_t *
Florin Corasa2ff7b82017-11-08 17:55:03 -0800399session_lookup_rules_table_session4 (session_table_t * st, u8 proto,
400 ip4_address_t * lcl, u16 lcl_port,
401 ip4_address_t * rmt, u16 rmt_port)
Florin Coras1c710452017-10-17 00:03:13 -0700402{
Florin Corasc97a7392017-11-05 23:07:07 -0800403 session_rules_table_t *srt = &st->session_rules[proto];
Florin Corasdff48db2017-11-19 18:06:58 -0800404 u32 action_index, app_index;
Florin Corasc97a7392017-11-05 23:07:07 -0800405 action_index = session_rules_table_lookup4 (srt, lcl, rmt, lcl_port,
Florin Coras1c710452017-10-17 00:03:13 -0700406 rmt_port);
Florin Corasf8f516a2018-02-08 15:10:09 -0800407 app_index = session_lookup_action_to_handle (action_index);
Florin Coras1c710452017-10-17 00:03:13 -0700408 /* Nothing sophisticated for now, action index is app index */
Florin Corasdff48db2017-11-19 18:06:58 -0800409 return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP4,
Florin Coras7999e832017-10-31 01:51:04 -0700410 proto);
Florin Coras1c710452017-10-17 00:03:13 -0700411}
412
Florin Corasf8f516a2018-02-08 15:10:09 -0800413/** UNUSED */
Florin Coras1c710452017-10-17 00:03:13 -0700414stream_session_t *
Florin Corasdff48db2017-11-19 18:06:58 -0800415session_lookup_rules_table_session6 (session_table_t * st, u8 proto,
416 ip6_address_t * lcl, u16 lcl_port,
417 ip6_address_t * rmt, u16 rmt_port)
Florin Coras1c710452017-10-17 00:03:13 -0700418{
Florin Corasc97a7392017-11-05 23:07:07 -0800419 session_rules_table_t *srt = &st->session_rules[proto];
Florin Corasdff48db2017-11-19 18:06:58 -0800420 u32 action_index, app_index;
Florin Corasc97a7392017-11-05 23:07:07 -0800421 action_index = session_rules_table_lookup6 (srt, lcl, rmt, lcl_port,
Florin Coras1c710452017-10-17 00:03:13 -0700422 rmt_port);
Florin Corasf8f516a2018-02-08 15:10:09 -0800423 app_index = session_lookup_action_to_handle (action_index);
Florin Corasdff48db2017-11-19 18:06:58 -0800424 return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP6,
Florin Coras7999e832017-10-31 01:51:04 -0700425 proto);
Florin Coras1c710452017-10-17 00:03:13 -0700426}
427
Florin Corasa2ff7b82017-11-08 17:55:03 -0800428/**
429 * Lookup listener for session endpoint in table
430 *
431 * @param table_index table where the endpoint should be looked up
432 * @param sep session endpoint to be looked up
433 * @param use_rules flag that indicates if the session rules of the table
434 * should be used
435 * @return invalid handle if nothing is found, the handle of a valid listener
Florin Corasf8f516a2018-02-08 15:10:09 -0800436 * or an action derived handle if a rule is hit
Florin Corasa2ff7b82017-11-08 17:55:03 -0800437 */
Florin Coras3cbc04b2017-10-02 00:18:51 -0700438u64
Florin Corasa2ff7b82017-11-08 17:55:03 -0800439session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
440 u8 use_rules)
Florin Coras04e53442017-07-16 17:12:15 -0700441{
Florin Corasc97a7392017-11-05 23:07:07 -0800442 session_rules_table_t *srt;
Florin Corascea194d2017-10-02 00:18:51 -0700443 session_table_t *st;
Florin Corasf0c1c962017-11-02 21:31:46 -0700444 u32 ai;
Florin Corascea194d2017-10-02 00:18:51 -0700445 int rv;
Florin Coras04e53442017-07-16 17:12:15 -0700446
Florin Corascea194d2017-10-02 00:18:51 -0700447 st = session_table_get (table_index);
448 if (!st)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700449 return SESSION_INVALID_HANDLE;
Florin Corascea194d2017-10-02 00:18:51 -0700450 if (sep->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700451 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800452 session_kv4_t kv4;
453 ip4_address_t lcl4;
454
Florin Coras561af9b2017-12-09 10:19:43 -0800455 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
456 sep->transport_proto);
Florin Corascea194d2017-10-02 00:18:51 -0700457 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
458 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700459 return kv4.value;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800460 if (use_rules)
461 {
462 memset (&lcl4, 0, sizeof (lcl4));
463 srt = &st->session_rules[sep->transport_proto];
464 ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0,
465 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800466 if (session_lookup_action_index_is_valid (ai))
Florin Corasf8f516a2018-02-08 15:10:09 -0800467 return session_lookup_action_to_handle (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800468 }
Florin Coras68810622017-07-24 17:40:28 -0700469 }
470 else
471 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800472 session_kv6_t kv6;
473 ip6_address_t lcl6;
474
Florin Coras561af9b2017-12-09 10:19:43 -0800475 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
476 sep->transport_proto);
Florin Corascea194d2017-10-02 00:18:51 -0700477 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
478 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700479 return kv6.value;
Florin Coras1c710452017-10-17 00:03:13 -0700480
Florin Corasa2ff7b82017-11-08 17:55:03 -0800481 if (use_rules)
482 {
483 memset (&lcl6, 0, sizeof (lcl6));
484 srt = &st->session_rules[sep->transport_proto];
485 ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0,
486 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800487 if (session_lookup_action_index_is_valid (ai))
Florin Corasf8f516a2018-02-08 15:10:09 -0800488 return session_lookup_action_to_handle (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800489 }
Florin Coras68810622017-07-24 17:40:28 -0700490 }
Florin Coras3cbc04b2017-10-02 00:18:51 -0700491 return SESSION_INVALID_HANDLE;
492}
493
Florin Corasa2ff7b82017-11-08 17:55:03 -0800494/**
495 * Look up endpoint in local session table
496 *
497 * The result, for now, is an application index and it may in the future
498 * be extended to a more complicated "action object". The only action we
499 * emulate now is "drop" and for that we return a special app index.
500 *
501 * Lookup logic is to check in order:
502 * - the rules in the table (connect acls)
503 * - session sub-table for a listener
504 * - session sub-table for a local listener (zeroed addr)
505 *
506 * @param table_index table where the lookup should be done
507 * @param sep session endpoint to be looked up
Florin Corasf8f516a2018-02-08 15:10:09 -0800508 * @return session handle that can be interpreted as an adjacency
Florin Corasa2ff7b82017-11-08 17:55:03 -0800509 */
Florin Corasf8f516a2018-02-08 15:10:09 -0800510u64
Florin Corasa2ff7b82017-11-08 17:55:03 -0800511session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
Florin Coras68810622017-07-24 17:40:28 -0700512{
Florin Corasc97a7392017-11-05 23:07:07 -0800513 session_rules_table_t *srt;
Florin Corascea194d2017-10-02 00:18:51 -0700514 session_table_t *st;
Florin Corasf0c1c962017-11-02 21:31:46 -0700515 u32 ai;
Florin Corascea194d2017-10-02 00:18:51 -0700516 int rv;
Florin Coras68810622017-07-24 17:40:28 -0700517
Florin Corascea194d2017-10-02 00:18:51 -0700518 st = session_table_get (table_index);
519 if (!st)
520 return SESSION_INVALID_INDEX;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800521 ASSERT (st->is_local);
522
Florin Corascea194d2017-10-02 00:18:51 -0700523 if (sep->is_ip4)
Florin Coras68810622017-07-24 17:40:28 -0700524 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800525 session_kv4_t kv4;
526 ip4_address_t lcl4;
527
528 /*
529 * Check if endpoint has special rules associated
530 */
531 memset (&lcl4, 0, sizeof (lcl4));
532 srt = &st->session_rules[sep->transport_proto];
533 ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0,
534 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800535 if (session_lookup_action_index_is_valid (ai))
Florin Corasf8f516a2018-02-08 15:10:09 -0800536 return session_lookup_action_to_handle (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800537
538 /*
539 * Check if session endpoint is a listener
540 */
Florin Corascea194d2017-10-02 00:18:51 -0700541 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
542 sep->transport_proto);
543 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
544 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800545 return kv4.value;
Florin Corascea194d2017-10-02 00:18:51 -0700546
547 /*
548 * Zero out the ip. Logic is that connect to local ips, say
549 * 127.0.0.1:port, can match 0.0.0.0:port
550 */
Florin Coras477e91a2018-02-27 10:05:57 -0800551 if (ip4_is_local_host (&sep->ip.ip4))
552 {
553 kv4.key[0] = 0;
554 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
555 if (rv == 0)
556 return kv4.value;
557 }
558 else
559 {
560 kv4.key[0] = 0;
561 }
Florin Corasdbd44562017-11-09 19:30:17 -0800562
563 /*
564 * Zero out the port and check if we have proxy
565 */
566 kv4.key[1] = 0;
567 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
568 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800569 return kv4.value;
Florin Coras68810622017-07-24 17:40:28 -0700570 }
571 else
572 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800573 session_kv6_t kv6;
574 ip6_address_t lcl6;
575
576 memset (&lcl6, 0, sizeof (lcl6));
577 srt = &st->session_rules[sep->transport_proto];
578 ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0,
579 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800580 if (session_lookup_action_index_is_valid (ai))
Florin Corasf8f516a2018-02-08 15:10:09 -0800581 return session_lookup_action_to_handle (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800582
Florin Corascea194d2017-10-02 00:18:51 -0700583 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
584 sep->transport_proto);
585 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
586 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800587 return kv6.value;
Florin Corascea194d2017-10-02 00:18:51 -0700588
589 /*
590 * Zero out the ip. Same logic as above.
591 */
Florin Coras477e91a2018-02-27 10:05:57 -0800592
593 if (ip6_is_local_host (&sep->ip.ip6))
594 {
595 kv6.key[0] = kv6.key[1] = 0;
596 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
597 if (rv == 0)
598 return kv6.value;
599 }
600 else
601 {
602 kv6.key[0] = kv6.key[1] = 0;
603 }
Florin Corasdbd44562017-11-09 19:30:17 -0800604
605 /*
606 * Zero out the port. Same logic as above.
607 */
608 kv6.key[4] = kv6.key[5] = 0;
609 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
610 if (rv == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -0800611 return kv6.value;
Florin Coras04e53442017-07-16 17:12:15 -0700612 }
Florin Corasf8f516a2018-02-08 15:10:09 -0800613 return SESSION_INVALID_HANDLE;
Florin Coras04e53442017-07-16 17:12:15 -0700614}
615
Florin Coras477e91a2018-02-27 10:05:57 -0800616static inline stream_session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700617session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl,
Florin Coras477e91a2018-02-27 10:05:57 -0800618 u16 lcl_port, u8 proto, u8 use_wildcard)
Florin Coras04e53442017-07-16 17:12:15 -0700619{
Florin Coras04e53442017-07-16 17:12:15 -0700620 session_kv4_t kv4;
621 int rv;
622
Florin Corasdbd44562017-11-09 19:30:17 -0800623 /*
624 * First, try a fully formed listener
625 */
Florin Coras04e53442017-07-16 17:12:15 -0700626 make_v4_listener_kv (&kv4, lcl, lcl_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700627 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700628 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700629 return listen_session_get ((u32) kv4.value);
Florin Coras04e53442017-07-16 17:12:15 -0700630
Florin Corasdbd44562017-11-09 19:30:17 -0800631 /*
632 * Zero out the lcl ip and check if any 0/0 port binds have been done
633 */
Florin Coras477e91a2018-02-27 10:05:57 -0800634 if (use_wildcard)
635 {
636 kv4.key[0] = 0;
637 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
638 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700639 return listen_session_get ((u32) kv4.value);
Florin Coras477e91a2018-02-27 10:05:57 -0800640 }
641 else
642 {
643 kv4.key[0] = 0;
644 }
Florin Coras04e53442017-07-16 17:12:15 -0700645
Florin Corasdbd44562017-11-09 19:30:17 -0800646 /*
647 * Zero out port and check if we have a proxy set up for our ip
648 */
649 make_v4_proxy_kv (&kv4, lcl, proto);
650 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
651 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700652 return listen_session_get ((u32) kv4.value);
Florin Corasdbd44562017-11-09 19:30:17 -0800653
Florin Coras04e53442017-07-16 17:12:15 -0700654 return 0;
655}
656
Florin Coras04e53442017-07-16 17:12:15 -0700657stream_session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700658session_lookup_listener4 (u32 fib_index, ip4_address_t * lcl, u16 lcl_port,
659 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700660{
Florin Corascea194d2017-10-02 00:18:51 -0700661 session_table_t *st;
662 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
663 if (!st)
664 return 0;
Florin Coras477e91a2018-02-27 10:05:57 -0800665 return session_lookup_listener4_i (st, lcl, lcl_port, proto, 0);
Florin Coras04e53442017-07-16 17:12:15 -0700666}
667
Florin Corascea194d2017-10-02 00:18:51 -0700668static stream_session_t *
669session_lookup_listener6_i (session_table_t * st, ip6_address_t * lcl,
Florin Coras477e91a2018-02-27 10:05:57 -0800670 u16 lcl_port, u8 proto, u8 ip_wildcard)
Florin Coras04e53442017-07-16 17:12:15 -0700671{
Florin Coras04e53442017-07-16 17:12:15 -0700672 session_kv6_t kv6;
673 int rv;
674
675 make_v6_listener_kv (&kv6, lcl, lcl_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700676 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700677 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700678 return listen_session_get ((u32) kv6.value);
Florin Coras04e53442017-07-16 17:12:15 -0700679
680 /* Zero out the lcl ip */
Florin Coras477e91a2018-02-27 10:05:57 -0800681 if (ip_wildcard)
682 {
683 kv6.key[0] = kv6.key[1] = 0;
684 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
685 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700686 return listen_session_get ((u32) kv6.value);
Florin Coras477e91a2018-02-27 10:05:57 -0800687 }
688 else
689 {
690 kv6.key[0] = kv6.key[1] = 0;
691 }
Florin Coras04e53442017-07-16 17:12:15 -0700692
Florin Corasdbd44562017-11-09 19:30:17 -0800693 make_v6_proxy_kv (&kv6, lcl, proto);
694 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
695 if (rv == 0)
Florin Coras5c9083d2018-04-13 06:39:07 -0700696 return listen_session_get ((u32) kv6.value);
Florin Coras04e53442017-07-16 17:12:15 -0700697 return 0;
698}
699
Florin Coras04e53442017-07-16 17:12:15 -0700700stream_session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700701session_lookup_listener6 (u32 fib_index, ip6_address_t * lcl, u16 lcl_port,
702 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700703{
Florin Corascea194d2017-10-02 00:18:51 -0700704 session_table_t *st;
705 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
706 if (!st)
707 return 0;
Florin Coras477e91a2018-02-27 10:05:57 -0800708 return session_lookup_listener6_i (st, lcl, lcl_port, proto, 1);
Florin Coras04e53442017-07-16 17:12:15 -0700709}
710
Florin Coras477e91a2018-02-27 10:05:57 -0800711/**
712 * Lookup listener, exact or proxy (inaddr_any:0) match
713 */
Florin Coras04e53442017-07-16 17:12:15 -0700714stream_session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700715session_lookup_listener (u32 table_index, session_endpoint_t * sep)
Florin Coras04e53442017-07-16 17:12:15 -0700716{
Florin Corascea194d2017-10-02 00:18:51 -0700717 session_table_t *st;
718 st = session_table_get (table_index);
719 if (!st)
720 return 0;
721 if (sep->is_ip4)
722 return session_lookup_listener4_i (st, &sep->ip.ip4, sep->port,
Florin Coras477e91a2018-02-27 10:05:57 -0800723 sep->transport_proto, 0);
Florin Corascea194d2017-10-02 00:18:51 -0700724 else
725 return session_lookup_listener6_i (st, &sep->ip.ip6, sep->port,
Florin Coras477e91a2018-02-27 10:05:57 -0800726 sep->transport_proto, 0);
Florin Coras04e53442017-07-16 17:12:15 -0700727 return 0;
728}
729
Florin Corascea194d2017-10-02 00:18:51 -0700730int
731session_lookup_add_half_open (transport_connection_t * tc, u64 value)
732{
733 session_table_t *st;
734 session_kv4_t kv4;
735 session_kv6_t kv6;
736
737 st = session_table_get_or_alloc_for_connection (tc);
738 if (!st)
739 return 0;
740 if (tc->is_ip4)
741 {
742 make_v4_ss_kv_from_tc (&kv4, tc);
743 kv4.value = value;
744 return clib_bihash_add_del_16_8 (&st->v4_half_open_hash, &kv4,
745 1 /* is_add */ );
746 }
747 else
748 {
749 make_v6_ss_kv_from_tc (&kv6, tc);
750 kv6.value = value;
751 return clib_bihash_add_del_48_8 (&st->v6_half_open_hash, &kv6,
752 1 /* is_add */ );
753 }
754}
755
756int
757session_lookup_del_half_open (transport_connection_t * tc)
758{
759 session_table_t *st;
760 session_kv4_t kv4;
761 session_kv6_t kv6;
762
763 st = session_table_get_for_connection (tc);
764 if (!st)
765 return -1;
766 if (tc->is_ip4)
767 {
768 make_v4_ss_kv_from_tc (&kv4, tc);
769 return clib_bihash_add_del_16_8 (&st->v4_half_open_hash, &kv4,
770 0 /* is_add */ );
771 }
772 else
773 {
774 make_v6_ss_kv_from_tc (&kv6, tc);
775 return clib_bihash_add_del_48_8 (&st->v6_half_open_hash, &kv6,
776 0 /* is_add */ );
777 }
778}
779
Florin Coras04e53442017-07-16 17:12:15 -0700780u64
Florin Corascea194d2017-10-02 00:18:51 -0700781session_lookup_half_open_handle (transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700782{
Florin Corascea194d2017-10-02 00:18:51 -0700783 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700784 session_kv4_t kv4;
785 session_kv6_t kv6;
786 int rv;
787
Florin Corascea194d2017-10-02 00:18:51 -0700788 st = session_table_get_for_fib_index (transport_connection_fib_proto (tc),
789 tc->fib_index);
790 if (!st)
791 return HALF_OPEN_LOOKUP_INVALID_VALUE;
792 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700793 {
Florin Corascea194d2017-10-02 00:18:51 -0700794 make_v4_ss_kv (&kv4, &tc->lcl_ip.ip4, &tc->rmt_ip.ip4, tc->lcl_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700795 tc->rmt_port, tc->proto);
Florin Corascea194d2017-10-02 00:18:51 -0700796 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700797 if (rv == 0)
798 return kv4.value;
Florin Corascea194d2017-10-02 00:18:51 -0700799 }
800 else
801 {
802 make_v6_ss_kv (&kv6, &tc->lcl_ip.ip6, &tc->rmt_ip.ip6, tc->lcl_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700803 tc->rmt_port, tc->proto);
Florin Corascea194d2017-10-02 00:18:51 -0700804 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700805 if (rv == 0)
806 return kv6.value;
Florin Coras04e53442017-07-16 17:12:15 -0700807 }
808 return HALF_OPEN_LOOKUP_INVALID_VALUE;
809}
810
811transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700812session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700813{
Florin Corascea194d2017-10-02 00:18:51 -0700814 u32 sst;
815
Florin Coras04e53442017-07-16 17:12:15 -0700816 if (handle != HALF_OPEN_LOOKUP_INVALID_VALUE)
Florin Corascea194d2017-10-02 00:18:51 -0700817 {
818 sst = session_type_from_proto_and_ip (proto, is_ip4);
819 return tp_vfts[sst].get_half_open (handle & 0xFFFFFFFF);
820 }
Florin Coras04e53442017-07-16 17:12:15 -0700821 return 0;
822}
823
Florin Corascea194d2017-10-02 00:18:51 -0700824/**
825 * Lookup connection with ip4 and transport layer information
826 *
827 * This is used on the fast path so it needs to be fast. Thereby,
828 * duplication of code and 'hacks' allowed.
829 *
830 * The lookup is incremental and returns whenever something is matched. The
831 * steps are:
832 * - Try to find an established session
Florin Corascea194d2017-10-02 00:18:51 -0700833 * - Try to find a half-open connection
Florin Coras1c710452017-10-17 00:03:13 -0700834 * - Try session rules table
Florin Corasa2ff7b82017-11-08 17:55:03 -0800835 * - Try to find a fully-formed or local source wildcarded (listener bound to
836 * all interfaces) listener session
Florin Corascea194d2017-10-02 00:18:51 -0700837 * - return 0
838 *
839 * @param fib_index index of fib wherein the connection was received
840 * @param lcl local ip4 address
841 * @param rmt remote ip4 address
842 * @param lcl_port local port
843 * @param rmt_port remote port
844 * @param proto transport protocol (e.g., tcp, udp)
845 * @param thread_index thread index for request
Florin Corasdff48db2017-11-19 18:06:58 -0800846 * @param is_filtered return flag that indicates if connection was filtered.
Florin Corascea194d2017-10-02 00:18:51 -0700847 *
848 * @return pointer to transport connection, if one is found, 0 otherwise
849 */
Florin Coras04e53442017-07-16 17:12:15 -0700850transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700851session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl,
852 ip4_address_t * rmt, u16 lcl_port,
Florin Corasdff48db2017-11-19 18:06:58 -0800853 u16 rmt_port, u8 proto, u32 thread_index,
854 u8 * is_filtered)
Florin Coras04e53442017-07-16 17:12:15 -0700855{
Florin Corascea194d2017-10-02 00:18:51 -0700856 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700857 session_kv4_t kv4;
858 stream_session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800859 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -0700860 int rv;
861
Florin Corascea194d2017-10-02 00:18:51 -0700862 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
863 if (PREDICT_FALSE (!st))
864 return 0;
865
Florin Corasa2ff7b82017-11-08 17:55:03 -0800866 /*
867 * Lookup session amongst established ones
868 */
Florin Coras04e53442017-07-16 17:12:15 -0700869 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700870 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700871 if (rv == 0)
872 {
Florin Corascea194d2017-10-02 00:18:51 -0700873 ASSERT ((u32) (kv4.value >> 32) == thread_index);
874 s = session_get (kv4.value & 0xFFFFFFFFULL, thread_index);
Florin Coras561af9b2017-12-09 10:19:43 -0800875 return tp_vfts[proto].get_connection (s->connection_index,
876 thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700877 }
878
Florin Corasa2ff7b82017-11-08 17:55:03 -0800879 /*
880 * Try half-open connections
881 */
Florin Corascea194d2017-10-02 00:18:51 -0700882 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700883 if (rv == 0)
Florin Coras561af9b2017-12-09 10:19:43 -0800884 return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
Florin Coras1c710452017-10-17 00:03:13 -0700885
Florin Corasa2ff7b82017-11-08 17:55:03 -0800886 /*
887 * Check the session rules table
888 */
889 action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl,
890 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -0800891 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -0800892 {
Florin Corasdff48db2017-11-19 18:06:58 -0800893 if ((*is_filtered = (action_index == SESSION_RULES_TABLE_ACTION_DROP)))
894 return 0;
895 if ((s = session_lookup_action_to_session (action_index,
896 FIB_PROTOCOL_IP4, proto)))
Florin Coras561af9b2017-12-09 10:19:43 -0800897 return tp_vfts[proto].get_listener (s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -0800898 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800899 }
900
901 /*
902 * If nothing is found, check if any listener is available
903 */
Florin Coras477e91a2018-02-27 10:05:57 -0800904 s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800905 if (s)
Florin Coras561af9b2017-12-09 10:19:43 -0800906 return tp_vfts[proto].get_listener (s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800907
908 return 0;
Florin Coras04e53442017-07-16 17:12:15 -0700909}
910
Florin Corascea194d2017-10-02 00:18:51 -0700911/**
912 * Lookup connection with ip4 and transport layer information
913 *
914 * Not optimized. This is used on the fast path so it needs to be fast.
915 * Thereby, duplication of code and 'hacks' allowed. Lookup logic is identical
916 * to that of @ref session_lookup_connection_wt4
917 *
918 * @param fib_index index of the fib wherein the connection was received
919 * @param lcl local ip4 address
920 * @param rmt remote ip4 address
921 * @param lcl_port local port
922 * @param rmt_port remote port
923 * @param proto transport protocol (e.g., tcp, udp)
924 *
925 * @return pointer to transport connection, if one is found, 0 otherwise
926 */
Florin Coras04e53442017-07-16 17:12:15 -0700927transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700928session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl,
929 ip4_address_t * rmt, u16 lcl_port, u16 rmt_port,
930 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700931{
Florin Corascea194d2017-10-02 00:18:51 -0700932 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700933 session_kv4_t kv4;
934 stream_session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800935 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -0700936 int rv;
937
Florin Corascea194d2017-10-02 00:18:51 -0700938 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
939 if (PREDICT_FALSE (!st))
940 return 0;
941
Florin Corasa2ff7b82017-11-08 17:55:03 -0800942 /*
943 * Lookup session amongst established ones
944 */
Florin Coras04e53442017-07-16 17:12:15 -0700945 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700946 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700947 if (rv == 0)
948 {
Florin Corascea194d2017-10-02 00:18:51 -0700949 s = session_get_from_handle (kv4.value);
Florin Coras561af9b2017-12-09 10:19:43 -0800950 return tp_vfts[proto].get_connection (s->connection_index,
951 s->thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700952 }
953
Florin Corasa2ff7b82017-11-08 17:55:03 -0800954 /*
955 * Try half-open connections
956 */
Florin Corascea194d2017-10-02 00:18:51 -0700957 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700958 if (rv == 0)
Florin Coras561af9b2017-12-09 10:19:43 -0800959 return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800960
961 /*
962 * Check the session rules table
963 */
964 action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl,
965 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -0800966 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -0800967 {
Florin Corasdff48db2017-11-19 18:06:58 -0800968 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
969 return 0;
970 if ((s = session_lookup_action_to_session (action_index,
971 FIB_PROTOCOL_IP4, proto)))
Florin Coras561af9b2017-12-09 10:19:43 -0800972 return tp_vfts[proto].get_listener (s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -0800973 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800974 }
975
976 /*
977 * If nothing is found, check if any listener is available
978 */
Florin Coras477e91a2018-02-27 10:05:57 -0800979 s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800980 if (s)
Florin Coras561af9b2017-12-09 10:19:43 -0800981 return tp_vfts[proto].get_listener (s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800982
983 return 0;
Florin Coras04e53442017-07-16 17:12:15 -0700984}
985
Florin Corascea194d2017-10-02 00:18:51 -0700986/**
987 * Lookup session with ip4 and transport layer information
988 *
Florin Coras3cbc04b2017-10-02 00:18:51 -0700989 * Important note: this may look into another thread's pool table and
990 * register as 'peeker'. Caller should call @ref session_pool_remove_peeker as
991 * if needed as soon as possible.
992 *
993 * Lookup logic is similar to that of @ref session_lookup_connection_wt4 but
994 * this returns a session as opposed to a transport connection and it does not
995 * try to lookup half-open sessions.
996 *
997 * Typically used by dgram connections
Florin Corascea194d2017-10-02 00:18:51 -0700998 */
999stream_session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001000session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt,
1001 u16 lcl_port, u16 rmt_port, u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -07001002{
Florin Corascea194d2017-10-02 00:18:51 -07001003 session_table_t *st;
1004 session_kv4_t kv4;
1005 stream_session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001006 u32 action_index;
Florin Corascea194d2017-10-02 00:18:51 -07001007 int rv;
1008
1009 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
1010 if (PREDICT_FALSE (!st))
1011 return 0;
1012
Florin Corasa2ff7b82017-11-08 17:55:03 -08001013 /*
1014 * Lookup session amongst established ones
1015 */
Florin Corascea194d2017-10-02 00:18:51 -07001016 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
1017 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
1018 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001019 return session_get_from_handle_safe (kv4.value);
Florin Corascea194d2017-10-02 00:18:51 -07001020
Florin Corasa2ff7b82017-11-08 17:55:03 -08001021 /*
1022 * Check the session rules table
1023 */
1024 action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl,
1025 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001026 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001027 {
Florin Corasdff48db2017-11-19 18:06:58 -08001028 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1029 return 0;
1030 return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4,
1031 proto);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001032 }
1033
1034 /*
1035 * If nothing is found, check if any listener is available
1036 */
Florin Coras477e91a2018-02-27 10:05:57 -08001037 if ((s = session_lookup_listener4_i (st, lcl, lcl_port, proto, 1)))
Florin Corascea194d2017-10-02 00:18:51 -07001038 return s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001039
1040 return 0;
Florin Corascea194d2017-10-02 00:18:51 -07001041}
1042
1043/**
1044 * Lookup connection with ip6 and transport layer information
1045 *
1046 * This is used on the fast path so it needs to be fast. Thereby,
1047 * duplication of code and 'hacks' allowed.
1048 *
1049 * The lookup is incremental and returns whenever something is matched. The
1050 * steps are:
1051 * - Try to find an established session
Florin Corascea194d2017-10-02 00:18:51 -07001052 * - Try to find a half-open connection
Florin Coras1c710452017-10-17 00:03:13 -07001053 * - Try session rules table
Florin Corasa2ff7b82017-11-08 17:55:03 -08001054 * - Try to find a fully-formed or local source wildcarded (listener bound to
1055 * all interfaces) listener session
Florin Corascea194d2017-10-02 00:18:51 -07001056 * - return 0
1057 *
1058 * @param fib_index index of the fib wherein the connection was received
1059 * @param lcl local ip6 address
1060 * @param rmt remote ip6 address
1061 * @param lcl_port local port
1062 * @param rmt_port remote port
1063 * @param proto transport protocol (e.g., tcp, udp)
1064 * @param thread_index thread index for request
1065 *
1066 * @return pointer to transport connection, if one is found, 0 otherwise
1067 */
1068transport_connection_t *
1069session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl,
1070 ip6_address_t * rmt, u16 lcl_port,
Florin Corasdff48db2017-11-19 18:06:58 -08001071 u16 rmt_port, u8 proto, u32 thread_index,
1072 u8 * is_filtered)
Florin Corascea194d2017-10-02 00:18:51 -07001073{
1074 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -07001075 stream_session_t *s;
1076 session_kv6_t kv6;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001077 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -07001078 int rv;
1079
Florin Corascea194d2017-10-02 00:18:51 -07001080 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1081 if (PREDICT_FALSE (!st))
1082 return 0;
1083
Florin Coras04e53442017-07-16 17:12:15 -07001084 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -07001085 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001086 if (rv == 0)
1087 {
Florin Corascea194d2017-10-02 00:18:51 -07001088 ASSERT ((u32) (kv6.value >> 32) == thread_index);
1089 s = session_get (kv6.value & 0xFFFFFFFFULL, thread_index);
Florin Coras561af9b2017-12-09 10:19:43 -08001090 return tp_vfts[proto].get_connection (s->connection_index,
1091 thread_index);
Florin Coras04e53442017-07-16 17:12:15 -07001092 }
1093
Florin Corasa2ff7b82017-11-08 17:55:03 -08001094 /* Try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -07001095 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001096 if (rv == 0)
Florin Coras561af9b2017-12-09 10:19:43 -08001097 return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
Florin Coras04e53442017-07-16 17:12:15 -07001098
Florin Corasa2ff7b82017-11-08 17:55:03 -08001099 /* Check the session rules table */
1100 action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
1101 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001102 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001103 {
Florin Corasdff48db2017-11-19 18:06:58 -08001104 if ((*is_filtered = (action_index == SESSION_RULES_TABLE_ACTION_DROP)))
1105 return 0;
1106 if ((s = session_lookup_action_to_session (action_index,
1107 FIB_PROTOCOL_IP6, proto)))
Florin Coras561af9b2017-12-09 10:19:43 -08001108 return tp_vfts[proto].get_listener (s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -08001109 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001110 }
1111
1112 /* If nothing is found, check if any listener is available */
Florin Coras477e91a2018-02-27 10:05:57 -08001113 s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001114 if (s)
Florin Coras561af9b2017-12-09 10:19:43 -08001115 return tp_vfts[proto].get_listener (s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001116
1117 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001118}
1119
Florin Corascea194d2017-10-02 00:18:51 -07001120/**
1121 * Lookup connection with ip6 and transport layer information
1122 *
1123 * Not optimized. This is used on the fast path so it needs to be fast.
1124 * Thereby, duplication of code and 'hacks' allowed. Lookup logic is identical
1125 * to that of @ref session_lookup_connection_wt4
1126 *
1127 * @param fib_index index of the fib wherein the connection was received
1128 * @param lcl local ip6 address
1129 * @param rmt remote ip6 address
1130 * @param lcl_port local port
1131 * @param rmt_port remote port
1132 * @param proto transport protocol (e.g., tcp, udp)
1133 *
1134 * @return pointer to transport connection, if one is found, 0 otherwise
1135 */
Florin Coras04e53442017-07-16 17:12:15 -07001136transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -07001137session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl,
1138 ip6_address_t * rmt, u16 lcl_port, u16 rmt_port,
1139 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -07001140{
Florin Corascea194d2017-10-02 00:18:51 -07001141 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -07001142 stream_session_t *s;
1143 session_kv6_t kv6;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001144 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -07001145 int rv;
1146
Florin Corascea194d2017-10-02 00:18:51 -07001147 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1148 if (PREDICT_FALSE (!st))
1149 return 0;
1150
Florin Coras04e53442017-07-16 17:12:15 -07001151 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -07001152 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001153 if (rv == 0)
1154 {
Florin Corascea194d2017-10-02 00:18:51 -07001155 s = session_get_from_handle (kv6.value);
Florin Coras561af9b2017-12-09 10:19:43 -08001156 return tp_vfts[proto].get_connection (s->connection_index,
1157 s->thread_index);
Florin Coras04e53442017-07-16 17:12:15 -07001158 }
1159
Florin Corasa2ff7b82017-11-08 17:55:03 -08001160 /* Try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -07001161 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001162 if (rv == 0)
Florin Coras561af9b2017-12-09 10:19:43 -08001163 return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
Florin Coras04e53442017-07-16 17:12:15 -07001164
Florin Corasa2ff7b82017-11-08 17:55:03 -08001165 /* Check the session rules table */
1166 action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
1167 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001168 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001169 {
Florin Corasdff48db2017-11-19 18:06:58 -08001170 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1171 return 0;
1172 if ((s = session_lookup_action_to_session (action_index,
1173 FIB_PROTOCOL_IP6, proto)))
Florin Coras561af9b2017-12-09 10:19:43 -08001174 return tp_vfts[proto].get_listener (s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -08001175 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001176 }
1177
1178 /* If nothing is found, check if any listener is available */
Florin Coras477e91a2018-02-27 10:05:57 -08001179 s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001180 if (s)
Florin Coras561af9b2017-12-09 10:19:43 -08001181 return tp_vfts[proto].get_listener (s->connection_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001182
1183 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001184}
1185
Florin Corascea194d2017-10-02 00:18:51 -07001186/**
1187 * Lookup session with ip6 and transport layer information
1188 *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001189 * Important note: this may look into another thread's pool table and
1190 * register as 'peeker'. Caller should call @ref session_pool_remove_peeker as
1191 * if needed as soon as possible.
1192 *
1193 * Lookup logic is similar to that of @ref session_lookup_connection_wt6 but
1194 * this returns a session as opposed to a transport connection and it does not
1195 * try to lookup half-open sessions.
1196 *
1197 * Typically used by dgram connections
Florin Corascea194d2017-10-02 00:18:51 -07001198 */
1199stream_session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001200session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt,
1201 u16 lcl_port, u16 rmt_port, u8 proto)
Florin Corascea194d2017-10-02 00:18:51 -07001202{
1203 session_table_t *st;
1204 session_kv6_t kv6;
1205 stream_session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001206 u32 action_index;
Florin Corascea194d2017-10-02 00:18:51 -07001207 int rv;
1208
1209 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1210 if (PREDICT_FALSE (!st))
1211 return 0;
1212
1213 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
1214 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
1215 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001216 return session_get_from_handle_safe (kv6.value);
Florin Corascea194d2017-10-02 00:18:51 -07001217
Florin Corasa2ff7b82017-11-08 17:55:03 -08001218 /* Check the session rules table */
1219 action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
1220 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001221 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001222 {
Florin Corasdff48db2017-11-19 18:06:58 -08001223 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1224 return 0;
1225 return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP6,
1226 proto);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001227 }
1228
Florin Corascea194d2017-10-02 00:18:51 -07001229 /* If nothing is found, check if any listener is available */
Florin Coras477e91a2018-02-27 10:05:57 -08001230 if ((s = session_lookup_listener6_i (st, lcl, lcl_port, proto, 1)))
Florin Corascea194d2017-10-02 00:18:51 -07001231 return s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001232 return 0;
Florin Corascea194d2017-10-02 00:18:51 -07001233}
1234
Florin Coras1c710452017-10-17 00:03:13 -07001235clib_error_t *
1236vnet_session_rule_add_del (session_rule_add_del_args_t * args)
1237{
1238 app_namespace_t *app_ns = app_namespace_get (args->appns_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001239 session_rules_table_t *srt;
Florin Coras1c710452017-10-17 00:03:13 -07001240 session_table_t *st;
1241 u32 fib_index;
1242 u8 fib_proto;
1243 clib_error_t *error;
1244
1245 if (!app_ns)
1246 return clib_error_return_code (0, VNET_API_ERROR_APP_INVALID_NS, 0,
1247 "invalid app ns");
1248 if (args->scope > 3)
1249 return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
1250 "invalid scope");
Florin Corasc97a7392017-11-05 23:07:07 -08001251 if (args->transport_proto != TRANSPORT_PROTO_TCP
1252 && args->transport_proto != TRANSPORT_PROTO_UDP)
1253 return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
1254 "invalid transport proto");
Florin Coras1c710452017-10-17 00:03:13 -07001255 if ((args->scope & SESSION_RULE_SCOPE_GLOBAL) || args->scope == 0)
1256 {
1257 fib_proto = args->table_args.rmt.fp_proto;
1258 fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1259 st = session_table_get_for_fib_index (fib_proto, fib_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001260 srt = &st->session_rules[args->transport_proto];
1261 if ((error = session_rules_table_add_del (srt, &args->table_args)))
1262 {
1263 clib_error_report (error);
1264 return error;
1265 }
Florin Coras1c710452017-10-17 00:03:13 -07001266 }
1267 if (args->scope & SESSION_RULE_SCOPE_LOCAL)
1268 {
Florin Corasa2ff7b82017-11-08 17:55:03 -08001269 memset (&args->table_args.lcl, 0, sizeof (args->table_args.lcl));
1270 args->table_args.lcl.fp_proto = args->table_args.rmt.fp_proto;
1271 args->table_args.lcl_port = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001272 st = app_namespace_get_local_table (app_ns);
Florin Corasc97a7392017-11-05 23:07:07 -08001273 srt = &st->session_rules[args->transport_proto];
1274 error = session_rules_table_add_del (srt, &args->table_args);
Florin Coras1c710452017-10-17 00:03:13 -07001275 }
1276 return error;
1277}
1278
Florin Coras6c36f532017-11-03 18:32:34 -07001279/**
1280 * Mark (global) tables as pertaining to app ns
1281 */
1282void
1283session_lookup_set_tables_appns (app_namespace_t * app_ns)
1284{
1285 session_table_t *st;
1286 u32 fib_index;
1287 u8 fp;
1288
1289 for (fp = 0; fp < ARRAY_LEN (fib_index_to_table_index); fp++)
1290 {
1291 fib_index = app_namespace_get_fib_index (app_ns, fp);
1292 st = session_table_get_for_fib_index (fp, fib_index);
1293 if (st)
1294 st->appns_index = app_namespace_index (app_ns);
1295 }
1296}
1297
Florin Corascea194d2017-10-02 00:18:51 -07001298u8 *
1299format_ip4_session_lookup_kvp (u8 * s, va_list * args)
1300{
1301 clib_bihash_kv_16_8_t *kvp = va_arg (*args, clib_bihash_kv_16_8_t *);
Florin Coras54693d22018-07-17 10:46:29 -07001302 u32 is_local = va_arg (*args, u32), app_index, session_index;
Florin Corascea194d2017-10-02 00:18:51 -07001303 u8 *app_name, *str = 0;
1304 stream_session_t *session;
1305 v4_connection_key_t *key = (v4_connection_key_t *) kvp->key;
1306
Florin Corascea194d2017-10-02 00:18:51 -07001307 if (!is_local)
1308 {
1309 session = session_get_from_handle (kvp->value);
1310 app_name = application_name_from_index (session->app_index);
Florin Coras561af9b2017-12-09 10:19:43 -08001311 str = format (0, "[%U] %U:%d->%U:%d", format_transport_proto_short,
1312 key->proto, format_ip4_address, &key->src,
1313 clib_net_to_host_u16 (key->src_port), format_ip4_address,
1314 &key->dst, clib_net_to_host_u16 (key->dst_port));
Florin Corascea194d2017-10-02 00:18:51 -07001315 s = format (s, "%-40v%-30v", str, app_name);
1316 }
1317 else
1318 {
Florin Coras54693d22018-07-17 10:46:29 -07001319 local_session_parse_handle (kvp->value, &app_index, &session_index);
1320 app_name = application_name_from_index (app_index);
Florin Coras561af9b2017-12-09 10:19:43 -08001321 str = format (0, "[%U] %U:%d", format_transport_proto_short, key->proto,
1322 format_ip4_address, &key->src,
1323 clib_net_to_host_u16 (key->src_port));
Florin Corascea194d2017-10-02 00:18:51 -07001324 s = format (s, "%-30v%-30v", str, app_name);
1325 }
1326 vec_free (app_name);
1327 return s;
1328}
1329
1330typedef struct _ip4_session_table_show_ctx_t
1331{
1332 vlib_main_t *vm;
1333 u8 is_local;
1334} ip4_session_table_show_ctx_t;
1335
1336static int
1337ip4_session_table_show (clib_bihash_kv_16_8_t * kvp, void *arg)
1338{
1339 ip4_session_table_show_ctx_t *ctx = arg;
1340 vlib_cli_output (ctx->vm, "%U", format_ip4_session_lookup_kvp, kvp,
1341 ctx->is_local);
1342 return 1;
1343}
1344
1345void
1346session_lookup_show_table_entries (vlib_main_t * vm, session_table_t * table,
1347 u8 type, u8 is_local)
1348{
1349 ip4_session_table_show_ctx_t ctx = {
1350 .vm = vm,
1351 .is_local = is_local,
1352 };
1353 if (!is_local)
1354 vlib_cli_output (vm, "%-40s%-30s", "Session", "Application");
1355 else
1356 vlib_cli_output (vm, "%-30s%-30s", "Listener", "Application");
1357 switch (type)
1358 {
1359 /* main table v4 */
1360 case 0:
1361 ip4_session_table_walk (&table->v4_session_hash, ip4_session_table_show,
1362 &ctx);
1363 break;
1364 default:
1365 clib_warning ("not supported");
1366 }
1367}
Florin Coras66b11312017-07-31 17:18:03 -07001368
Florin Coras1c710452017-10-17 00:03:13 -07001369static clib_error_t *
1370session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
1371 vlib_cli_command_t * cmd)
1372{
Florin Corasc97a7392017-11-05 23:07:07 -08001373 u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen = 0, rmt_plen = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001374 u32 appns_index, scope = 0;
1375 ip46_address_t lcl_ip, rmt_ip;
1376 u8 is_ip4 = 1, conn_set = 0;
1377 u8 fib_proto, is_add = 1, *ns_id = 0;
Florin Corasc97a7392017-11-05 23:07:07 -08001378 u8 *tag = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001379 app_namespace_t *app_ns;
Florin Corasc97a7392017-11-05 23:07:07 -08001380 clib_error_t *error;
Florin Coras1c710452017-10-17 00:03:13 -07001381
1382 memset (&lcl_ip, 0, sizeof (lcl_ip));
1383 memset (&rmt_ip, 0, sizeof (rmt_ip));
1384 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1385 {
1386 if (unformat (input, "del"))
1387 is_add = 0;
1388 else if (unformat (input, "add"))
1389 ;
1390 else if (unformat (input, "appns %_%v%_", &ns_id))
1391 ;
1392 else if (unformat (input, "scope global"))
1393 scope = SESSION_RULE_SCOPE_GLOBAL;
1394 else if (unformat (input, "scope local"))
1395 scope = SESSION_RULE_SCOPE_LOCAL;
1396 else if (unformat (input, "scope all"))
1397 scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1398 else if (unformat (input, "proto %U", unformat_transport_proto, &proto))
1399 ;
1400 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1401 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1402 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1403 &rmt_port))
1404 {
1405 is_ip4 = 1;
1406 conn_set = 1;
1407 }
1408 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1409 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1410 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1411 &rmt_port))
1412 {
1413 is_ip4 = 0;
1414 conn_set = 1;
1415 }
1416 else if (unformat (input, "action %d", &action))
1417 ;
Florin Corasc97a7392017-11-05 23:07:07 -08001418 else if (unformat (input, "tag %_%v%_", &tag))
1419 ;
Florin Coras1c710452017-10-17 00:03:13 -07001420 else
1421 return clib_error_return (0, "unknown input `%U'",
1422 format_unformat_error, input);
1423 }
1424
Florin Corasc97a7392017-11-05 23:07:07 -08001425 if (proto == ~0)
1426 {
1427 vlib_cli_output (vm, "proto must be set");
1428 return 0;
1429 }
1430 if (is_add && !conn_set && action == ~0)
1431 {
1432 vlib_cli_output (vm, "connection and action must be set for add");
1433 return 0;
1434 }
1435 if (!is_add && !tag && !conn_set)
1436 {
1437 vlib_cli_output (vm, "connection or tag must be set for delete");
1438 return 0;
1439 }
1440 if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN)
1441 {
1442 vlib_cli_output (vm, "tag too long (max u64)");
1443 return 0;
1444 }
Florin Coras1c710452017-10-17 00:03:13 -07001445
1446 if (ns_id)
1447 {
1448 app_ns = app_namespace_get_from_id (ns_id);
1449 if (!app_ns)
Florin Corasc97a7392017-11-05 23:07:07 -08001450 {
1451 vlib_cli_output (vm, "namespace %v does not exist", ns_id);
1452 return 0;
1453 }
Florin Coras1c710452017-10-17 00:03:13 -07001454 }
1455 else
1456 {
1457 app_ns = app_namespace_get_default ();
1458 }
1459 appns_index = app_namespace_index (app_ns);
1460
1461 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1462 session_rule_add_del_args_t args = {
1463 .table_args.lcl.fp_addr = lcl_ip,
1464 .table_args.lcl.fp_len = lcl_plen,
1465 .table_args.lcl.fp_proto = fib_proto,
1466 .table_args.rmt.fp_addr = rmt_ip,
1467 .table_args.rmt.fp_len = rmt_plen,
1468 .table_args.rmt.fp_proto = fib_proto,
1469 .table_args.lcl_port = lcl_port,
1470 .table_args.rmt_port = rmt_port,
1471 .table_args.action_index = action,
1472 .table_args.is_add = is_add,
Florin Corasc97a7392017-11-05 23:07:07 -08001473 .table_args.tag = tag,
Florin Coras1c710452017-10-17 00:03:13 -07001474 .appns_index = appns_index,
1475 .scope = scope,
1476 };
Florin Corasc97a7392017-11-05 23:07:07 -08001477 error = vnet_session_rule_add_del (&args);
1478 vec_free (tag);
1479 return error;
Florin Coras1c710452017-10-17 00:03:13 -07001480}
1481
1482/* *INDENT-OFF* */
1483VLIB_CLI_COMMAND (session_rule_command, static) =
1484{
1485 .path = "session rule",
1486 .short_help = "session rule [add|del] appns <ns_id> proto <proto> "
1487 "<lcl-ip/plen> <lcl-port> <rmt-ip/plen> <rmt-port> action <action>",
1488 .function = session_rule_command_fn,
1489};
1490/* *INDENT-ON* */
1491
Florin Coras7999e832017-10-31 01:51:04 -07001492void
1493session_lookup_dump_rules_table (u32 fib_index, u8 fib_proto,
1494 u8 transport_proto)
1495{
1496 vlib_main_t *vm = vlib_get_main ();
Florin Corasc97a7392017-11-05 23:07:07 -08001497 session_rules_table_t *srt;
Florin Coras7999e832017-10-31 01:51:04 -07001498 session_table_t *st;
1499 st = session_table_get_for_fib_index (fib_index, fib_proto);
Florin Corasc97a7392017-11-05 23:07:07 -08001500 srt = &st->session_rules[transport_proto];
1501 session_rules_table_cli_dump (vm, srt, fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001502}
1503
1504void
1505session_lookup_dump_local_rules_table (u32 table_index, u8 fib_proto,
1506 u8 transport_proto)
1507{
1508 vlib_main_t *vm = vlib_get_main ();
Florin Corasc97a7392017-11-05 23:07:07 -08001509 session_rules_table_t *srt;
Florin Coras7999e832017-10-31 01:51:04 -07001510 session_table_t *st;
1511 st = session_table_get (table_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001512 srt = &st->session_rules[transport_proto];
1513 session_rules_table_cli_dump (vm, srt, fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001514}
1515
Florin Coras1c710452017-10-17 00:03:13 -07001516static clib_error_t *
1517show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input,
1518 vlib_cli_command_t * cmd)
1519{
1520 u32 transport_proto = ~0, lcl_port, rmt_port, lcl_plen, rmt_plen;
1521 u32 fib_index, scope = 0;
1522 ip46_address_t lcl_ip, rmt_ip;
1523 u8 is_ip4 = 1, show_one = 0;
1524 app_namespace_t *app_ns;
Florin Corasc97a7392017-11-05 23:07:07 -08001525 session_rules_table_t *srt;
Florin Coras1c710452017-10-17 00:03:13 -07001526 session_table_t *st;
1527 u8 *ns_id = 0, fib_proto;
1528
1529 memset (&lcl_ip, 0, sizeof (lcl_ip));
1530 memset (&rmt_ip, 0, sizeof (rmt_ip));
1531 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1532 {
1533 if (unformat (input, "%U", unformat_transport_proto, &transport_proto))
1534 ;
1535 else if (unformat (input, "appns %_%v%_", &ns_id))
1536 ;
1537 else if (unformat (input, "scope global"))
1538 scope = 1;
1539 else if (unformat (input, "scope local"))
1540 scope = 2;
1541 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1542 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1543 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1544 &rmt_port))
1545 {
1546 is_ip4 = 1;
1547 show_one = 1;
1548 }
1549 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1550 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1551 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1552 &rmt_port))
1553 {
1554 is_ip4 = 0;
1555 show_one = 1;
1556 }
1557 else
1558 return clib_error_return (0, "unknown input `%U'",
1559 format_unformat_error, input);
1560 }
1561
1562 if (transport_proto == ~0)
1563 {
1564 vlib_cli_output (vm, "transport proto must be set");
1565 return 0;
1566 }
1567
1568 if (ns_id)
1569 {
1570 app_ns = app_namespace_get_from_id (ns_id);
1571 if (!app_ns)
1572 {
1573 vlib_cli_output (vm, "appns %v doesn't exist", ns_id);
1574 return 0;
1575 }
1576 }
1577 else
1578 {
1579 app_ns = app_namespace_get_default ();
1580 }
1581
1582 if (scope == 1 || scope == 0)
1583 {
1584 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1585 fib_index = is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
1586 st = session_table_get_for_fib_index (fib_proto, fib_index);
1587 }
1588 else
1589 {
1590 st = app_namespace_get_local_table (app_ns);
1591 }
1592
1593 if (show_one)
1594 {
Florin Corasc97a7392017-11-05 23:07:07 -08001595 srt = &st->session_rules[transport_proto];
1596 session_rules_table_show_rule (vm, srt, &lcl_ip, lcl_port, &rmt_ip,
1597 rmt_port, is_ip4);
Florin Coras1c710452017-10-17 00:03:13 -07001598 return 0;
1599 }
1600
Florin Corasc97a7392017-11-05 23:07:07 -08001601 vlib_cli_output (vm, "%U rules table", format_transport_proto,
1602 transport_proto);
1603 srt = &st->session_rules[transport_proto];
1604 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
1605 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP6);
Florin Coras1c710452017-10-17 00:03:13 -07001606
1607 vec_free (ns_id);
1608 return 0;
1609}
1610
1611/* *INDENT-OFF* */
1612VLIB_CLI_COMMAND (show_session_rules_command, static) =
1613{
1614 .path = "show session rules",
Florin Corasdff48db2017-11-19 18:06:58 -08001615 .short_help = "show session rules [<proto> appns <id> <lcl-ip/plen> "
1616 "<lcl-port> <rmt-ip/plen> <rmt-port> scope <scope>]",
Florin Coras1c710452017-10-17 00:03:13 -07001617 .function = show_session_rules_command_fn,
1618};
1619/* *INDENT-ON* */
1620
Florin Coras04e53442017-07-16 17:12:15 -07001621void
1622session_lookup_init (void)
1623{
Florin Corascea194d2017-10-02 00:18:51 -07001624 /*
1625 * Allocate default table and map it to fib_index 0
1626 */
1627 session_table_t *st = session_table_alloc ();
1628 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP4], 0);
1629 fib_index_to_table_index[FIB_PROTOCOL_IP4][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001630 st->active_fib_proto = FIB_PROTOCOL_IP4;
1631 session_table_init (st, FIB_PROTOCOL_IP4);
Florin Corascea194d2017-10-02 00:18:51 -07001632 st = session_table_alloc ();
1633 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP6], 0);
1634 fib_index_to_table_index[FIB_PROTOCOL_IP6][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001635 st->active_fib_proto = FIB_PROTOCOL_IP6;
1636 session_table_init (st, FIB_PROTOCOL_IP6);
Florin Coras04e53442017-07-16 17:12:15 -07001637}
1638
1639/*
1640 * fd.io coding-style-patch-verification: ON
1641 *
1642 * Local Variables:
1643 * eval: (c-set-style "gnu")
1644 * End:
1645 */