blob: 2e4e96a4dea0c36f9d065fda6053b524e0e50a31 [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{
89 v4_connection_key_t *key = (v4_connection_key_t *) kv->key;
90
91 key->src.as_u32 = lcl->as_u32;
92 key->dst.as_u32 = rmt->as_u32;
93 key->src_port = lcl_port;
94 key->dst_port = rmt_port;
95 key->proto = proto;
96
97 kv->value = ~0ULL;
98}
99
100always_inline void
101make_v4_listener_kv (session_kv4_t * kv, ip4_address_t * lcl, u16 lcl_port,
102 u8 proto)
103{
104 v4_connection_key_t *key = (v4_connection_key_t *) kv->key;
105
106 key->src.as_u32 = lcl->as_u32;
107 key->dst.as_u32 = 0;
108 key->src_port = lcl_port;
109 key->dst_port = 0;
110 key->proto = proto;
111
112 kv->value = ~0ULL;
113}
114
115always_inline void
Florin Corasdbd44562017-11-09 19:30:17 -0800116make_v4_proxy_kv (session_kv4_t * kv, ip4_address_t * lcl, u8 proto)
117{
118 v4_connection_key_t *key = (v4_connection_key_t *) kv->key;
119
120 key->src.as_u32 = lcl->as_u32;
121 key->dst.as_u32 = 0;
122 key->src_port = 0;
123 key->dst_port = 0;
124 key->proto = proto;
125
126 kv->value = ~0ULL;
127}
128
129always_inline void
Florin Coras04e53442017-07-16 17:12:15 -0700130make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * t)
131{
rootc9d1c5b2017-08-15 12:58:31 -0400132 make_v4_ss_kv (kv, &t->lcl_ip.ip4, &t->rmt_ip.ip4, t->lcl_port, t->rmt_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700133 session_type_from_proto_and_ip (t->proto, 1));
Florin Coras04e53442017-07-16 17:12:15 -0700134}
135
136always_inline void
137make_v6_ss_kv (session_kv6_t * kv, ip6_address_t * lcl, ip6_address_t * rmt,
138 u16 lcl_port, u16 rmt_port, u8 proto)
139{
140 v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
141
142 key->src.as_u64[0] = lcl->as_u64[0];
143 key->src.as_u64[1] = lcl->as_u64[1];
144 key->dst.as_u64[0] = rmt->as_u64[0];
145 key->dst.as_u64[1] = rmt->as_u64[1];
146 key->src_port = lcl_port;
147 key->dst_port = rmt_port;
148 key->proto = proto;
149 key->unused = 0;
150
151 kv->value = ~0ULL;
152}
153
154always_inline void
155make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port,
156 u8 proto)
157{
158 v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
159
160 key->src.as_u64[0] = lcl->as_u64[0];
161 key->src.as_u64[1] = lcl->as_u64[1];
162 key->dst.as_u64[0] = 0;
163 key->dst.as_u64[1] = 0;
164 key->src_port = lcl_port;
165 key->dst_port = 0;
166 key->proto = proto;
167 key->unused = 0;
168
169 kv->value = ~0ULL;
170}
171
172always_inline void
Florin Corasdbd44562017-11-09 19:30:17 -0800173make_v6_proxy_kv (session_kv6_t * kv, ip6_address_t * lcl, u8 proto)
174{
175 v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
176
177 key->src.as_u64[0] = lcl->as_u64[0];
178 key->src.as_u64[1] = lcl->as_u64[1];
179 key->dst.as_u64[0] = 0;
180 key->dst.as_u64[1] = 0;
181 key->src_port = 0;
182 key->dst_port = 0;
183 key->proto = proto;
184 key->unused = 0;
185
186 kv->value = ~0ULL;
187}
188
189always_inline void
Florin Coras04e53442017-07-16 17:12:15 -0700190make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * t)
191{
rootc9d1c5b2017-08-15 12:58:31 -0400192 make_v6_ss_kv (kv, &t->lcl_ip.ip6, &t->rmt_ip.ip6, t->lcl_port, t->rmt_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700193 session_type_from_proto_and_ip (t->proto, 0));
Florin Coras04e53442017-07-16 17:12:15 -0700194}
195
Florin Corascea194d2017-10-02 00:18:51 -0700196static session_table_t *
Florin Coras6c36f532017-11-03 18:32:34 -0700197session_table_get_or_alloc (u8 fib_proto, u8 fib_index)
Florin Coras04e53442017-07-16 17:12:15 -0700198{
Florin Corascea194d2017-10-02 00:18:51 -0700199 session_table_t *st;
Florin Coras6c36f532017-11-03 18:32:34 -0700200 u32 table_index;
201 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
Florin Corascea194d2017-10-02 00:18:51 -0700202 {
203 st = session_table_alloc ();
204 table_index = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -0700205 vec_validate (fib_index_to_table_index[fib_proto], fib_index);
206 fib_index_to_table_index[fib_proto][fib_index] = table_index;
207 st->active_fib_proto = fib_proto;
Florin Corascea194d2017-10-02 00:18:51 -0700208 return st;
209 }
210 else
211 {
Florin Coras6c36f532017-11-03 18:32:34 -0700212 table_index = fib_index_to_table_index[fib_proto][fib_index];
Florin Corascea194d2017-10-02 00:18:51 -0700213 return session_table_get (table_index);
214 }
215}
216
217static session_table_t *
Florin Coras6c36f532017-11-03 18:32:34 -0700218session_table_get_or_alloc_for_connection (transport_connection_t * tc)
219{
220 u32 fib_proto;
221 fib_proto = transport_connection_fib_proto (tc);
222 return session_table_get_or_alloc (fib_proto, tc->fib_index);
223}
224
225static session_table_t *
Florin Corascea194d2017-10-02 00:18:51 -0700226session_table_get_for_connection (transport_connection_t * tc)
227{
228 u32 fib_proto = transport_connection_fib_proto (tc);
229 if (vec_len (fib_index_to_table_index[fib_proto]) <= tc->fib_index)
230 return 0;
231 return
232 session_table_get (fib_index_to_table_index[fib_proto][tc->fib_index]);
233}
234
235static session_table_t *
236session_table_get_for_fib_index (u32 fib_proto, u32 fib_index)
237{
238 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
239 return 0;
240 return session_table_get (fib_index_to_table_index[fib_proto][fib_index]);
241}
242
243u32
244session_lookup_get_index_for_fib (u32 fib_proto, u32 fib_index)
245{
246 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
247 return SESSION_TABLE_INVALID_INDEX;
248 return fib_index_to_table_index[fib_proto][fib_index];
249}
250
251/**
252 * Add transport connection to a session table
253 *
254 * Session lookup 5-tuple (src-ip, dst-ip, src-port, dst-port, session-type)
255 * is added to requested session table.
256 *
257 * @param tc transport connection to be added
258 * @param value value to be stored
259 *
260 * @return non-zero if failure
261 */
262int
263session_lookup_add_connection (transport_connection_t * tc, u64 value)
264{
265 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700266 session_kv4_t kv4;
267 session_kv6_t kv6;
268
Florin Corascea194d2017-10-02 00:18:51 -0700269 st = session_table_get_or_alloc_for_connection (tc);
270 if (!st)
271 return -1;
Florin Coras68810622017-07-24 17:40:28 -0700272 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700273 {
Florin Coras04e53442017-07-16 17:12:15 -0700274 make_v4_ss_kv_from_tc (&kv4, tc);
275 kv4.value = value;
Florin Corascea194d2017-10-02 00:18:51 -0700276 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4,
277 1 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700278 }
279 else
280 {
Florin Coras04e53442017-07-16 17:12:15 -0700281 make_v6_ss_kv_from_tc (&kv6, tc);
282 kv6.value = value;
Florin Corascea194d2017-10-02 00:18:51 -0700283 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6,
284 1 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700285 }
286}
287
Florin Coras04e53442017-07-16 17:12:15 -0700288int
Florin Corascea194d2017-10-02 00:18:51 -0700289session_lookup_add_session_endpoint (u32 table_index,
290 session_endpoint_t * sep, u64 value)
Florin Coras04e53442017-07-16 17:12:15 -0700291{
Florin Corascea194d2017-10-02 00:18:51 -0700292 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700293 session_kv4_t kv4;
294 session_kv6_t kv6;
Florin Coras68810622017-07-24 17:40:28 -0700295
Florin Corascea194d2017-10-02 00:18:51 -0700296 st = session_table_get (table_index);
297 if (!st)
298 return -1;
299 if (sep->is_ip4)
300 {
301 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
302 sep->transport_proto);
303 kv4.value = value;
304 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 1);
305 }
306 else
307 {
308 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
309 sep->transport_proto);
310 kv6.value = value;
311 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 1);
312 }
313}
314
315int
316session_lookup_del_session_endpoint (u32 table_index,
317 session_endpoint_t * sep)
318{
319 session_table_t *st;
320 session_kv4_t kv4;
321 session_kv6_t kv6;
322
323 st = session_table_get (table_index);
324 if (!st)
325 return -1;
326 if (sep->is_ip4)
327 {
328 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
329 sep->transport_proto);
330 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 0);
331 }
332 else
333 {
334 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
335 sep->transport_proto);
336 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 0);
337 }
338}
339
340/**
341 * Delete transport connection from session table
342 *
343 * @param table_index session table index
344 * @param tc transport connection to be removed
345 *
346 * @return non-zero if failure
347 */
348int
349session_lookup_del_connection (transport_connection_t * tc)
350{
351 session_table_t *st;
352 session_kv4_t kv4;
353 session_kv6_t kv6;
354
355 st = session_table_get_for_connection (tc);
356 if (!st)
357 return -1;
Florin Coras68810622017-07-24 17:40:28 -0700358 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700359 {
Florin Coras04e53442017-07-16 17:12:15 -0700360 make_v4_ss_kv_from_tc (&kv4, tc);
Florin Corascea194d2017-10-02 00:18:51 -0700361 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4,
Florin Coras04e53442017-07-16 17:12:15 -0700362 0 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700363 }
364 else
365 {
Florin Coras04e53442017-07-16 17:12:15 -0700366 make_v6_ss_kv_from_tc (&kv6, tc);
Florin Corascea194d2017-10-02 00:18:51 -0700367 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6,
Florin Coras04e53442017-07-16 17:12:15 -0700368 0 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700369 }
Florin Coras04e53442017-07-16 17:12:15 -0700370}
371
372int
Florin Corascea194d2017-10-02 00:18:51 -0700373session_lookup_del_session (stream_session_t * s)
Florin Coras04e53442017-07-16 17:12:15 -0700374{
375 transport_connection_t *ts;
376 ts = tp_vfts[s->session_type].get_connection (s->connection_index,
377 s->thread_index);
Florin Corascea194d2017-10-02 00:18:51 -0700378 return session_lookup_del_connection (ts);
Florin Coras04e53442017-07-16 17:12:15 -0700379}
380
Florin Corasdff48db2017-11-19 18:06:58 -0800381static u8
382session_lookup_action_index_is_valid (u32 action_index)
Florin Corasf0c1c962017-11-02 21:31:46 -0700383{
Florin Corasdff48db2017-11-19 18:06:58 -0800384 if (action_index == SESSION_RULES_TABLE_ACTION_ALLOW
385 || action_index == SESSION_RULES_TABLE_INVALID_INDEX)
386 return 0;
387 return 1;
388}
389
390static u32
391session_lookup_action_to_app_index (u32 action_index)
392{
393 switch (action_index)
394 {
395 case SESSION_RULES_TABLE_ACTION_DROP:
396 return APP_DROP_INDEX;
397 case SESSION_RULES_TABLE_ACTION_ALLOW:
398 case SESSION_RULES_TABLE_INVALID_INDEX:
399 return APP_INVALID_INDEX;
400 default:
401 return action_index;
402 }
Florin Corasf0c1c962017-11-02 21:31:46 -0700403}
404
Florin Coras1c710452017-10-17 00:03:13 -0700405static stream_session_t *
Florin Coras7999e832017-10-31 01:51:04 -0700406session_lookup_app_listen_session (u32 app_index, u8 fib_proto,
407 u8 transport_proto)
Florin Coras1c710452017-10-17 00:03:13 -0700408{
409 application_t *app;
Florin Corasdff48db2017-11-19 18:06:58 -0800410 app = application_get_if_valid (app_index);
Florin Coras1c710452017-10-17 00:03:13 -0700411 if (!app)
412 return 0;
413
Florin Coras7999e832017-10-31 01:51:04 -0700414 return application_first_listener (app, fib_proto, transport_proto);
Florin Coras1c710452017-10-17 00:03:13 -0700415}
416
Florin Corasa2ff7b82017-11-08 17:55:03 -0800417static stream_session_t *
418session_lookup_action_to_session (u32 action_index, u8 fib_proto,
419 u8 transport_proto)
420{
Florin Corasdff48db2017-11-19 18:06:58 -0800421 u32 app_index;
422 app_index = session_lookup_action_to_app_index (action_index);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800423 /* Nothing sophisticated for now, action index is app index */
Florin Corasdff48db2017-11-19 18:06:58 -0800424 return session_lookup_app_listen_session (app_index, fib_proto,
Florin Corasa2ff7b82017-11-08 17:55:03 -0800425 transport_proto);
426}
427
Florin Coras1c710452017-10-17 00:03:13 -0700428stream_session_t *
Florin Corasa2ff7b82017-11-08 17:55:03 -0800429session_lookup_rules_table_session4 (session_table_t * st, u8 proto,
430 ip4_address_t * lcl, u16 lcl_port,
431 ip4_address_t * rmt, u16 rmt_port)
Florin Coras1c710452017-10-17 00:03:13 -0700432{
Florin Corasc97a7392017-11-05 23:07:07 -0800433 session_rules_table_t *srt = &st->session_rules[proto];
Florin Corasdff48db2017-11-19 18:06:58 -0800434 u32 action_index, app_index;
Florin Corasc97a7392017-11-05 23:07:07 -0800435 action_index = session_rules_table_lookup4 (srt, lcl, rmt, lcl_port,
Florin Coras1c710452017-10-17 00:03:13 -0700436 rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -0800437 app_index = session_lookup_action_to_app_index (action_index);
Florin Coras1c710452017-10-17 00:03:13 -0700438 /* Nothing sophisticated for now, action index is app index */
Florin Corasdff48db2017-11-19 18:06:58 -0800439 return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP4,
Florin Coras7999e832017-10-31 01:51:04 -0700440 proto);
Florin Coras1c710452017-10-17 00:03:13 -0700441}
442
443stream_session_t *
Florin Corasdff48db2017-11-19 18:06:58 -0800444session_lookup_rules_table_session6 (session_table_t * st, u8 proto,
445 ip6_address_t * lcl, u16 lcl_port,
446 ip6_address_t * rmt, u16 rmt_port)
Florin Coras1c710452017-10-17 00:03:13 -0700447{
Florin Corasc97a7392017-11-05 23:07:07 -0800448 session_rules_table_t *srt = &st->session_rules[proto];
Florin Corasdff48db2017-11-19 18:06:58 -0800449 u32 action_index, app_index;
Florin Corasc97a7392017-11-05 23:07:07 -0800450 action_index = session_rules_table_lookup6 (srt, lcl, rmt, lcl_port,
Florin Coras1c710452017-10-17 00:03:13 -0700451 rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -0800452 app_index = session_lookup_action_to_app_index (action_index);
453 return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP6,
Florin Coras7999e832017-10-31 01:51:04 -0700454 proto);
Florin Coras1c710452017-10-17 00:03:13 -0700455}
456
Florin Corasa2ff7b82017-11-08 17:55:03 -0800457/**
458 * Lookup listener for session endpoint in table
459 *
460 * @param table_index table where the endpoint should be looked up
461 * @param sep session endpoint to be looked up
462 * @param use_rules flag that indicates if the session rules of the table
463 * should be used
464 * @return invalid handle if nothing is found, the handle of a valid listener
465 * or an action_index if a rule is hit
466 */
Florin Coras3cbc04b2017-10-02 00:18:51 -0700467u64
Florin Corasa2ff7b82017-11-08 17:55:03 -0800468session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
469 u8 use_rules)
Florin Coras04e53442017-07-16 17:12:15 -0700470{
Florin Corasc97a7392017-11-05 23:07:07 -0800471 session_rules_table_t *srt;
Florin Corascea194d2017-10-02 00:18:51 -0700472 session_table_t *st;
Florin Corasf0c1c962017-11-02 21:31:46 -0700473 u32 ai;
Florin Corascea194d2017-10-02 00:18:51 -0700474 int rv;
Florin Coras4e4531e2017-11-06 23:27:56 -0800475 u8 sst;
Florin Coras04e53442017-07-16 17:12:15 -0700476
Florin Coras4e4531e2017-11-06 23:27:56 -0800477 sst = session_type_from_proto_and_ip (sep->transport_proto, sep->is_ip4);
Florin Corascea194d2017-10-02 00:18:51 -0700478 st = session_table_get (table_index);
479 if (!st)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700480 return SESSION_INVALID_HANDLE;
Florin Corascea194d2017-10-02 00:18:51 -0700481 if (sep->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700482 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800483 session_kv4_t kv4;
484 ip4_address_t lcl4;
485
Florin Coras4e4531e2017-11-06 23:27:56 -0800486 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port, sst);
Florin Corascea194d2017-10-02 00:18:51 -0700487 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
488 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700489 return kv4.value;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800490 if (use_rules)
491 {
492 memset (&lcl4, 0, sizeof (lcl4));
493 srt = &st->session_rules[sep->transport_proto];
494 ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0,
495 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800496 if (session_lookup_action_index_is_valid (ai))
497 return session_lookup_action_to_app_index (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800498 }
Florin Coras68810622017-07-24 17:40:28 -0700499 }
500 else
501 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800502 session_kv6_t kv6;
503 ip6_address_t lcl6;
504
Florin Coras4e4531e2017-11-06 23:27:56 -0800505 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, sst);
Florin Corascea194d2017-10-02 00:18:51 -0700506 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
507 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700508 return kv6.value;
Florin Coras1c710452017-10-17 00:03:13 -0700509
Florin Corasa2ff7b82017-11-08 17:55:03 -0800510 if (use_rules)
511 {
512 memset (&lcl6, 0, sizeof (lcl6));
513 srt = &st->session_rules[sep->transport_proto];
514 ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0,
515 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800516 if (session_lookup_action_index_is_valid (ai))
517 return session_lookup_action_to_app_index (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800518 }
Florin Coras68810622017-07-24 17:40:28 -0700519 }
Florin Coras3cbc04b2017-10-02 00:18:51 -0700520 return SESSION_INVALID_HANDLE;
521}
522
Florin Corasa2ff7b82017-11-08 17:55:03 -0800523/**
524 * Look up endpoint in local session table
525 *
526 * The result, for now, is an application index and it may in the future
527 * be extended to a more complicated "action object". The only action we
528 * emulate now is "drop" and for that we return a special app index.
529 *
530 * Lookup logic is to check in order:
531 * - the rules in the table (connect acls)
532 * - session sub-table for a listener
533 * - session sub-table for a local listener (zeroed addr)
534 *
535 * @param table_index table where the lookup should be done
536 * @param sep session endpoint to be looked up
537 * @return index that can be interpreted as an app index or drop action.
538 */
Florin Corascea194d2017-10-02 00:18:51 -0700539u32
Florin Corasa2ff7b82017-11-08 17:55:03 -0800540session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep)
Florin Coras68810622017-07-24 17:40:28 -0700541{
Florin Corasc97a7392017-11-05 23:07:07 -0800542 session_rules_table_t *srt;
Florin Corascea194d2017-10-02 00:18:51 -0700543 session_table_t *st;
Florin Corasf0c1c962017-11-02 21:31:46 -0700544 u32 ai;
Florin Corascea194d2017-10-02 00:18:51 -0700545 int rv;
Florin Coras68810622017-07-24 17:40:28 -0700546
Florin Corascea194d2017-10-02 00:18:51 -0700547 st = session_table_get (table_index);
548 if (!st)
549 return SESSION_INVALID_INDEX;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800550 ASSERT (st->is_local);
551
Florin Corascea194d2017-10-02 00:18:51 -0700552 if (sep->is_ip4)
Florin Coras68810622017-07-24 17:40:28 -0700553 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800554 session_kv4_t kv4;
555 ip4_address_t lcl4;
556
557 /*
558 * Check if endpoint has special rules associated
559 */
560 memset (&lcl4, 0, sizeof (lcl4));
561 srt = &st->session_rules[sep->transport_proto];
562 ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0,
563 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800564 if (session_lookup_action_index_is_valid (ai))
565 return session_lookup_action_to_app_index (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800566
567 /*
568 * Check if session endpoint is a listener
569 */
Florin Corascea194d2017-10-02 00:18:51 -0700570 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
571 sep->transport_proto);
572 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
573 if (rv == 0)
574 return (u32) kv4.value;
575
576 /*
577 * Zero out the ip. Logic is that connect to local ips, say
578 * 127.0.0.1:port, can match 0.0.0.0:port
579 */
580 kv4.key[0] = 0;
581 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
582 if (rv == 0)
583 return (u32) kv4.value;
Florin Corasdbd44562017-11-09 19:30:17 -0800584
585 /*
586 * Zero out the port and check if we have proxy
587 */
588 kv4.key[1] = 0;
589 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
590 if (rv == 0)
591 return (u32) kv4.value;
Florin Coras68810622017-07-24 17:40:28 -0700592 }
593 else
594 {
Florin Corasa2ff7b82017-11-08 17:55:03 -0800595 session_kv6_t kv6;
596 ip6_address_t lcl6;
597
598 memset (&lcl6, 0, sizeof (lcl6));
599 srt = &st->session_rules[sep->transport_proto];
600 ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0,
601 sep->port);
Florin Corasdff48db2017-11-19 18:06:58 -0800602 if (session_lookup_action_index_is_valid (ai))
603 return session_lookup_action_to_app_index (ai);
Florin Corasa2ff7b82017-11-08 17:55:03 -0800604
Florin Corascea194d2017-10-02 00:18:51 -0700605 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
606 sep->transport_proto);
607 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
608 if (rv == 0)
609 return (u32) kv6.value;
610
611 /*
612 * Zero out the ip. Same logic as above.
613 */
614 kv6.key[0] = kv6.key[1] = 0;
615 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
616 if (rv == 0)
617 return (u32) kv6.value;
Florin Corasdbd44562017-11-09 19:30:17 -0800618
619 /*
620 * Zero out the port. Same logic as above.
621 */
622 kv6.key[4] = kv6.key[5] = 0;
623 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
624 if (rv == 0)
625 return (u32) kv6.value;
Florin Coras04e53442017-07-16 17:12:15 -0700626 }
Florin Corasa2ff7b82017-11-08 17:55:03 -0800627 return APP_INVALID_INDEX;
Florin Coras04e53442017-07-16 17:12:15 -0700628}
629
Florin Corascea194d2017-10-02 00:18:51 -0700630static stream_session_t *
631session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl,
632 u16 lcl_port, u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700633{
Florin Coras04e53442017-07-16 17:12:15 -0700634 session_kv4_t kv4;
635 int rv;
636
Florin Corasdbd44562017-11-09 19:30:17 -0800637 /*
638 * First, try a fully formed listener
639 */
Florin Coras04e53442017-07-16 17:12:15 -0700640 make_v4_listener_kv (&kv4, lcl, lcl_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700641 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700642 if (rv == 0)
643 return session_manager_get_listener (proto, (u32) kv4.value);
644
Florin Corasdbd44562017-11-09 19:30:17 -0800645 /*
646 * Zero out the lcl ip and check if any 0/0 port binds have been done
647 */
Florin Coras04e53442017-07-16 17:12:15 -0700648 kv4.key[0] = 0;
Florin Corascea194d2017-10-02 00:18:51 -0700649 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700650 if (rv == 0)
651 return session_manager_get_listener (proto, (u32) kv4.value);
652
Florin Corasdbd44562017-11-09 19:30:17 -0800653 /*
654 * Zero out port and check if we have a proxy set up for our ip
655 */
656 make_v4_proxy_kv (&kv4, lcl, proto);
657 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
658 if (rv == 0)
659 return session_manager_get_listener (proto, (u32) kv4.value);
660
Florin Coras04e53442017-07-16 17:12:15 -0700661 return 0;
662}
663
Florin Coras04e53442017-07-16 17:12:15 -0700664stream_session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700665session_lookup_listener4 (u32 fib_index, ip4_address_t * lcl, u16 lcl_port,
666 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700667{
Florin Corascea194d2017-10-02 00:18:51 -0700668 session_table_t *st;
669 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
670 if (!st)
671 return 0;
672 return session_lookup_listener4_i (st, lcl, lcl_port, proto);
Florin Coras04e53442017-07-16 17:12:15 -0700673}
674
Florin Corascea194d2017-10-02 00:18:51 -0700675static stream_session_t *
676session_lookup_listener6_i (session_table_t * st, ip6_address_t * lcl,
677 u16 lcl_port, u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700678{
Florin Coras04e53442017-07-16 17:12:15 -0700679 session_kv6_t kv6;
680 int rv;
681
682 make_v6_listener_kv (&kv6, lcl, lcl_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700683 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700684 if (rv == 0)
685 return session_manager_get_listener (proto, (u32) kv6.value);
686
687 /* Zero out the lcl ip */
688 kv6.key[0] = kv6.key[1] = 0;
Florin Corascea194d2017-10-02 00:18:51 -0700689 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700690 if (rv == 0)
691 return session_manager_get_listener (proto, (u32) kv6.value);
692
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)
696 return session_manager_get_listener (proto, (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;
708 return session_lookup_listener6_i (st, lcl, lcl_port, proto);
Florin Coras04e53442017-07-16 17:12:15 -0700709}
710
711stream_session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700712session_lookup_listener (u32 table_index, session_endpoint_t * sep)
Florin Coras04e53442017-07-16 17:12:15 -0700713{
Florin Corascea194d2017-10-02 00:18:51 -0700714 session_table_t *st;
715 st = session_table_get (table_index);
716 if (!st)
717 return 0;
718 if (sep->is_ip4)
719 return session_lookup_listener4_i (st, &sep->ip.ip4, sep->port,
720 sep->transport_proto);
721 else
722 return session_lookup_listener6_i (st, &sep->ip.ip6, sep->port,
723 sep->transport_proto);
Florin Coras04e53442017-07-16 17:12:15 -0700724 return 0;
725}
726
Florin Corascea194d2017-10-02 00:18:51 -0700727int
728session_lookup_add_half_open (transport_connection_t * tc, u64 value)
729{
730 session_table_t *st;
731 session_kv4_t kv4;
732 session_kv6_t kv6;
733
734 st = session_table_get_or_alloc_for_connection (tc);
735 if (!st)
736 return 0;
737 if (tc->is_ip4)
738 {
739 make_v4_ss_kv_from_tc (&kv4, tc);
740 kv4.value = value;
741 return clib_bihash_add_del_16_8 (&st->v4_half_open_hash, &kv4,
742 1 /* is_add */ );
743 }
744 else
745 {
746 make_v6_ss_kv_from_tc (&kv6, tc);
747 kv6.value = value;
748 return clib_bihash_add_del_48_8 (&st->v6_half_open_hash, &kv6,
749 1 /* is_add */ );
750 }
751}
752
753int
754session_lookup_del_half_open (transport_connection_t * tc)
755{
756 session_table_t *st;
757 session_kv4_t kv4;
758 session_kv6_t kv6;
759
760 st = session_table_get_for_connection (tc);
761 if (!st)
762 return -1;
763 if (tc->is_ip4)
764 {
765 make_v4_ss_kv_from_tc (&kv4, tc);
766 return clib_bihash_add_del_16_8 (&st->v4_half_open_hash, &kv4,
767 0 /* is_add */ );
768 }
769 else
770 {
771 make_v6_ss_kv_from_tc (&kv6, tc);
772 return clib_bihash_add_del_48_8 (&st->v6_half_open_hash, &kv6,
773 0 /* is_add */ );
774 }
775}
776
Florin Coras04e53442017-07-16 17:12:15 -0700777u64
Florin Corascea194d2017-10-02 00:18:51 -0700778session_lookup_half_open_handle (transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700779{
Florin Corascea194d2017-10-02 00:18:51 -0700780 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700781 session_kv4_t kv4;
782 session_kv6_t kv6;
783 int rv;
784
Florin Corascea194d2017-10-02 00:18:51 -0700785 st = session_table_get_for_fib_index (transport_connection_fib_proto (tc),
786 tc->fib_index);
787 if (!st)
788 return HALF_OPEN_LOOKUP_INVALID_VALUE;
789 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700790 {
Florin Corascea194d2017-10-02 00:18:51 -0700791 make_v4_ss_kv (&kv4, &tc->lcl_ip.ip4, &tc->rmt_ip.ip4, tc->lcl_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700792 tc->rmt_port, tc->proto);
Florin Corascea194d2017-10-02 00:18:51 -0700793 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700794 if (rv == 0)
795 return kv4.value;
Florin Corascea194d2017-10-02 00:18:51 -0700796 }
797 else
798 {
799 make_v6_ss_kv (&kv6, &tc->lcl_ip.ip6, &tc->rmt_ip.ip6, tc->lcl_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700800 tc->rmt_port, tc->proto);
Florin Corascea194d2017-10-02 00:18:51 -0700801 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700802 if (rv == 0)
803 return kv6.value;
Florin Coras04e53442017-07-16 17:12:15 -0700804 }
805 return HALF_OPEN_LOOKUP_INVALID_VALUE;
806}
807
808transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700809session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700810{
Florin Corascea194d2017-10-02 00:18:51 -0700811 u32 sst;
812
Florin Coras04e53442017-07-16 17:12:15 -0700813 if (handle != HALF_OPEN_LOOKUP_INVALID_VALUE)
Florin Corascea194d2017-10-02 00:18:51 -0700814 {
815 sst = session_type_from_proto_and_ip (proto, is_ip4);
816 return tp_vfts[sst].get_half_open (handle & 0xFFFFFFFF);
817 }
Florin Coras04e53442017-07-16 17:12:15 -0700818 return 0;
819}
820
Florin Corascea194d2017-10-02 00:18:51 -0700821/**
822 * Lookup connection with ip4 and transport layer information
823 *
824 * This is used on the fast path so it needs to be fast. Thereby,
825 * duplication of code and 'hacks' allowed.
826 *
827 * The lookup is incremental and returns whenever something is matched. The
828 * steps are:
829 * - Try to find an established session
Florin Corascea194d2017-10-02 00:18:51 -0700830 * - Try to find a half-open connection
Florin Coras1c710452017-10-17 00:03:13 -0700831 * - Try session rules table
Florin Corasa2ff7b82017-11-08 17:55:03 -0800832 * - Try to find a fully-formed or local source wildcarded (listener bound to
833 * all interfaces) listener session
Florin Corascea194d2017-10-02 00:18:51 -0700834 * - return 0
835 *
836 * @param fib_index index of fib wherein the connection was received
837 * @param lcl local ip4 address
838 * @param rmt remote ip4 address
839 * @param lcl_port local port
840 * @param rmt_port remote port
841 * @param proto transport protocol (e.g., tcp, udp)
842 * @param thread_index thread index for request
Florin Corasdff48db2017-11-19 18:06:58 -0800843 * @param is_filtered return flag that indicates if connection was filtered.
Florin Corascea194d2017-10-02 00:18:51 -0700844 *
845 * @return pointer to transport connection, if one is found, 0 otherwise
846 */
Florin Coras04e53442017-07-16 17:12:15 -0700847transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700848session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl,
849 ip4_address_t * rmt, u16 lcl_port,
Florin Corasdff48db2017-11-19 18:06:58 -0800850 u16 rmt_port, u8 proto, u32 thread_index,
851 u8 * is_filtered)
Florin Coras04e53442017-07-16 17:12:15 -0700852{
Florin Corascea194d2017-10-02 00:18:51 -0700853 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700854 session_kv4_t kv4;
855 stream_session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800856 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -0700857 int rv;
858
Florin Corascea194d2017-10-02 00:18:51 -0700859 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
860 if (PREDICT_FALSE (!st))
861 return 0;
862
Florin Corasa2ff7b82017-11-08 17:55:03 -0800863 /*
864 * Lookup session amongst established ones
865 */
Florin Coras04e53442017-07-16 17:12:15 -0700866 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700867 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700868 if (rv == 0)
869 {
Florin Corascea194d2017-10-02 00:18:51 -0700870 ASSERT ((u32) (kv4.value >> 32) == thread_index);
871 s = session_get (kv4.value & 0xFFFFFFFFULL, thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700872 return tp_vfts[s->session_type].get_connection (s->connection_index,
Florin Corascea194d2017-10-02 00:18:51 -0700873 thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700874 }
875
Florin Corasa2ff7b82017-11-08 17:55:03 -0800876 /*
877 * Try half-open connections
878 */
Florin Corascea194d2017-10-02 00:18:51 -0700879 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700880 if (rv == 0)
Florin Corascea194d2017-10-02 00:18:51 -0700881 {
882 u32 sst = session_type_from_proto_and_ip (proto, 1);
883 return tp_vfts[sst].get_half_open (kv4.value & 0xFFFFFFFF);
884 }
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 Corasa2ff7b82017-11-08 17:55:03 -0800897 return tp_vfts[s->session_type].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 */
904 s = session_lookup_listener4_i (st, lcl, lcl_port, proto);
905 if (s)
906 return tp_vfts[s->session_type].get_listener (s->connection_index);
907
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 Coras04e53442017-07-16 17:12:15 -0700950 return tp_vfts[s->session_type].get_connection (s->connection_index,
951 s->thread_index);
952 }
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 Corascea194d2017-10-02 00:18:51 -0700959 {
960 u32 sst = session_type_from_proto_and_ip (proto, 1);
961 return tp_vfts[sst].get_half_open (kv4.value & 0xFFFFFFFF);
962 }
Florin Corasa2ff7b82017-11-08 17:55:03 -0800963
964 /*
965 * Check the session rules table
966 */
967 action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl,
968 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -0800969 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -0800970 {
Florin Corasdff48db2017-11-19 18:06:58 -0800971 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
972 return 0;
973 if ((s = session_lookup_action_to_session (action_index,
974 FIB_PROTOCOL_IP4, proto)))
Florin Corasa2ff7b82017-11-08 17:55:03 -0800975 return tp_vfts[s->session_type].get_listener (s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -0800976 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -0800977 }
978
979 /*
980 * If nothing is found, check if any listener is available
981 */
982 s = session_lookup_listener4_i (st, lcl, lcl_port, proto);
983 if (s)
984 return tp_vfts[s->session_type].get_listener (s->connection_index);
985
986 return 0;
Florin Coras04e53442017-07-16 17:12:15 -0700987}
988
Florin Corascea194d2017-10-02 00:18:51 -0700989/**
990 * Lookup session with ip4 and transport layer information
991 *
Florin Coras3cbc04b2017-10-02 00:18:51 -0700992 * Important note: this may look into another thread's pool table and
993 * register as 'peeker'. Caller should call @ref session_pool_remove_peeker as
994 * if needed as soon as possible.
995 *
996 * Lookup logic is similar to that of @ref session_lookup_connection_wt4 but
997 * this returns a session as opposed to a transport connection and it does not
998 * try to lookup half-open sessions.
999 *
1000 * Typically used by dgram connections
Florin Corascea194d2017-10-02 00:18:51 -07001001 */
1002stream_session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001003session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt,
1004 u16 lcl_port, u16 rmt_port, u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -07001005{
Florin Corascea194d2017-10-02 00:18:51 -07001006 session_table_t *st;
1007 session_kv4_t kv4;
1008 stream_session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001009 u32 action_index;
Florin Corascea194d2017-10-02 00:18:51 -07001010 int rv;
1011
1012 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
1013 if (PREDICT_FALSE (!st))
1014 return 0;
1015
Florin Corasa2ff7b82017-11-08 17:55:03 -08001016 /*
1017 * Lookup session amongst established ones
1018 */
Florin Corascea194d2017-10-02 00:18:51 -07001019 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
1020 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
1021 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001022 return session_get_from_handle_safe (kv4.value);
Florin Corascea194d2017-10-02 00:18:51 -07001023
Florin Corasa2ff7b82017-11-08 17:55:03 -08001024 /*
1025 * Check the session rules table
1026 */
1027 action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl,
1028 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001029 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001030 {
Florin Corasdff48db2017-11-19 18:06:58 -08001031 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1032 return 0;
1033 return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4,
1034 proto);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001035 }
1036
1037 /*
1038 * If nothing is found, check if any listener is available
1039 */
Florin Corascea194d2017-10-02 00:18:51 -07001040 if ((s = session_lookup_listener4_i (st, lcl, lcl_port, proto)))
1041 return s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001042
1043 return 0;
Florin Corascea194d2017-10-02 00:18:51 -07001044}
1045
1046/**
1047 * Lookup connection with ip6 and transport layer information
1048 *
1049 * This is used on the fast path so it needs to be fast. Thereby,
1050 * duplication of code and 'hacks' allowed.
1051 *
1052 * The lookup is incremental and returns whenever something is matched. The
1053 * steps are:
1054 * - Try to find an established session
Florin Corascea194d2017-10-02 00:18:51 -07001055 * - Try to find a half-open connection
Florin Coras1c710452017-10-17 00:03:13 -07001056 * - Try session rules table
Florin Corasa2ff7b82017-11-08 17:55:03 -08001057 * - Try to find a fully-formed or local source wildcarded (listener bound to
1058 * all interfaces) listener session
Florin Corascea194d2017-10-02 00:18:51 -07001059 * - return 0
1060 *
1061 * @param fib_index index of the fib wherein the connection was received
1062 * @param lcl local ip6 address
1063 * @param rmt remote ip6 address
1064 * @param lcl_port local port
1065 * @param rmt_port remote port
1066 * @param proto transport protocol (e.g., tcp, udp)
1067 * @param thread_index thread index for request
1068 *
1069 * @return pointer to transport connection, if one is found, 0 otherwise
1070 */
1071transport_connection_t *
1072session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl,
1073 ip6_address_t * rmt, u16 lcl_port,
Florin Corasdff48db2017-11-19 18:06:58 -08001074 u16 rmt_port, u8 proto, u32 thread_index,
1075 u8 * is_filtered)
Florin Corascea194d2017-10-02 00:18:51 -07001076{
1077 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -07001078 stream_session_t *s;
1079 session_kv6_t kv6;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001080 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -07001081 int rv;
1082
Florin Corascea194d2017-10-02 00:18:51 -07001083 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1084 if (PREDICT_FALSE (!st))
1085 return 0;
1086
Florin Coras04e53442017-07-16 17:12:15 -07001087 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -07001088 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001089 if (rv == 0)
1090 {
Florin Corascea194d2017-10-02 00:18:51 -07001091 ASSERT ((u32) (kv6.value >> 32) == thread_index);
1092 s = session_get (kv6.value & 0xFFFFFFFFULL, thread_index);
Florin Coras04e53442017-07-16 17:12:15 -07001093 return tp_vfts[s->session_type].get_connection (s->connection_index,
Florin Corascea194d2017-10-02 00:18:51 -07001094 thread_index);
Florin Coras04e53442017-07-16 17:12:15 -07001095 }
1096
Florin Corasa2ff7b82017-11-08 17:55:03 -08001097 /* Try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -07001098 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001099 if (rv == 0)
Florin Corascea194d2017-10-02 00:18:51 -07001100 {
1101 u32 sst = session_type_from_proto_and_ip (proto, 1);
1102 return tp_vfts[sst].get_half_open (kv6.value & 0xFFFFFFFF);
1103 }
Florin Coras04e53442017-07-16 17:12:15 -07001104
Florin Corasa2ff7b82017-11-08 17:55:03 -08001105 /* Check the session rules table */
1106 action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
1107 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001108 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001109 {
Florin Corasdff48db2017-11-19 18:06:58 -08001110 if ((*is_filtered = (action_index == SESSION_RULES_TABLE_ACTION_DROP)))
1111 return 0;
1112 if ((s = session_lookup_action_to_session (action_index,
1113 FIB_PROTOCOL_IP6, proto)))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001114 return tp_vfts[s->session_type].get_listener (s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -08001115 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001116 }
1117
1118 /* If nothing is found, check if any listener is available */
1119 s = session_lookup_listener6_i (st, lcl, lcl_port, proto);
1120 if (s)
1121 return tp_vfts[s->session_type].get_listener (s->connection_index);
1122
1123 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001124}
1125
Florin Corascea194d2017-10-02 00:18:51 -07001126/**
1127 * Lookup connection with ip6 and transport layer information
1128 *
1129 * Not optimized. This is used on the fast path so it needs to be fast.
1130 * Thereby, duplication of code and 'hacks' allowed. Lookup logic is identical
1131 * to that of @ref session_lookup_connection_wt4
1132 *
1133 * @param fib_index index of the fib wherein the connection was received
1134 * @param lcl local ip6 address
1135 * @param rmt remote ip6 address
1136 * @param lcl_port local port
1137 * @param rmt_port remote port
1138 * @param proto transport protocol (e.g., tcp, udp)
1139 *
1140 * @return pointer to transport connection, if one is found, 0 otherwise
1141 */
Florin Coras04e53442017-07-16 17:12:15 -07001142transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -07001143session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl,
1144 ip6_address_t * rmt, u16 lcl_port, u16 rmt_port,
1145 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -07001146{
Florin Corascea194d2017-10-02 00:18:51 -07001147 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -07001148 stream_session_t *s;
1149 session_kv6_t kv6;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001150 u32 action_index;
Florin Coras04e53442017-07-16 17:12:15 -07001151 int rv;
1152
Florin Corascea194d2017-10-02 00:18:51 -07001153 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1154 if (PREDICT_FALSE (!st))
1155 return 0;
1156
Florin Coras04e53442017-07-16 17:12:15 -07001157 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -07001158 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001159 if (rv == 0)
1160 {
Florin Corascea194d2017-10-02 00:18:51 -07001161 s = session_get_from_handle (kv6.value);
Florin Coras04e53442017-07-16 17:12:15 -07001162 return tp_vfts[s->session_type].get_connection (s->connection_index,
1163 s->thread_index);
1164 }
1165
Florin Corasa2ff7b82017-11-08 17:55:03 -08001166 /* Try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -07001167 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001168 if (rv == 0)
Florin Corascea194d2017-10-02 00:18:51 -07001169 {
1170 u32 sst = session_type_from_proto_and_ip (proto, 1);
1171 return tp_vfts[sst].get_half_open (kv6.value & 0xFFFFFFFF);
1172 }
Florin Coras04e53442017-07-16 17:12:15 -07001173
Florin Corasa2ff7b82017-11-08 17:55:03 -08001174 /* Check the session rules table */
1175 action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
1176 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001177 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001178 {
Florin Corasdff48db2017-11-19 18:06:58 -08001179 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1180 return 0;
1181 if ((s = session_lookup_action_to_session (action_index,
1182 FIB_PROTOCOL_IP6, proto)))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001183 return tp_vfts[s->session_type].get_listener (s->connection_index);
Florin Corasdff48db2017-11-19 18:06:58 -08001184 return 0;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001185 }
1186
1187 /* If nothing is found, check if any listener is available */
1188 s = session_lookup_listener6 (fib_index, lcl, lcl_port, proto);
1189 if (s)
1190 return tp_vfts[s->session_type].get_listener (s->connection_index);
1191
1192 return 0;
Florin Coras04e53442017-07-16 17:12:15 -07001193}
1194
Florin Corascea194d2017-10-02 00:18:51 -07001195/**
1196 * Lookup session with ip6 and transport layer information
1197 *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001198 * Important note: this may look into another thread's pool table and
1199 * register as 'peeker'. Caller should call @ref session_pool_remove_peeker as
1200 * if needed as soon as possible.
1201 *
1202 * Lookup logic is similar to that of @ref session_lookup_connection_wt6 but
1203 * this returns a session as opposed to a transport connection and it does not
1204 * try to lookup half-open sessions.
1205 *
1206 * Typically used by dgram connections
Florin Corascea194d2017-10-02 00:18:51 -07001207 */
1208stream_session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001209session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt,
1210 u16 lcl_port, u16 rmt_port, u8 proto)
Florin Corascea194d2017-10-02 00:18:51 -07001211{
1212 session_table_t *st;
1213 session_kv6_t kv6;
1214 stream_session_t *s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001215 u32 action_index;
Florin Corascea194d2017-10-02 00:18:51 -07001216 int rv;
1217
1218 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1219 if (PREDICT_FALSE (!st))
1220 return 0;
1221
1222 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
1223 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
1224 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001225 return session_get_from_handle_safe (kv6.value);
Florin Corascea194d2017-10-02 00:18:51 -07001226
Florin Corasa2ff7b82017-11-08 17:55:03 -08001227 /* Check the session rules table */
1228 action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
1229 rmt, lcl_port, rmt_port);
Florin Corasdff48db2017-11-19 18:06:58 -08001230 if (session_lookup_action_index_is_valid (action_index))
Florin Corasa2ff7b82017-11-08 17:55:03 -08001231 {
Florin Corasdff48db2017-11-19 18:06:58 -08001232 if (action_index == SESSION_RULES_TABLE_ACTION_DROP)
1233 return 0;
1234 return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP6,
1235 proto);
Florin Corasa2ff7b82017-11-08 17:55:03 -08001236 }
1237
Florin Corascea194d2017-10-02 00:18:51 -07001238 /* If nothing is found, check if any listener is available */
1239 if ((s = session_lookup_listener6_i (st, lcl, lcl_port, proto)))
1240 return s;
Florin Corasa2ff7b82017-11-08 17:55:03 -08001241 return 0;
Florin Corascea194d2017-10-02 00:18:51 -07001242}
1243
1244u64
1245session_lookup_local_listener_make_handle (session_endpoint_t * sep)
1246{
1247 return ((u64) SESSION_LOCAL_TABLE_PREFIX << 32
1248 | (u32) sep->port << 16 | (u32) sep->transport_proto << 8
1249 | (u32) sep->is_ip4);
1250}
1251
1252u8
1253session_lookup_local_is_handle (u64 handle)
1254{
1255 if (handle >> 32 == SESSION_LOCAL_TABLE_PREFIX)
1256 return 1;
1257 return 0;
1258}
1259
1260int
1261session_lookup_local_listener_parse_handle (u64 handle,
1262 session_endpoint_t * sep)
1263{
1264 u32 local_table_handle;
1265 if (handle >> 32 != SESSION_LOCAL_TABLE_PREFIX)
1266 return -1;
1267 local_table_handle = handle & 0xFFFFFFFFULL;
1268 sep->is_ip4 = local_table_handle & 0xff;
1269 local_table_handle >>= 8;
1270 sep->transport_proto = local_table_handle & 0xff;
1271 sep->port = local_table_handle >> 8;
1272 return 0;
1273}
1274
Florin Coras1c710452017-10-17 00:03:13 -07001275clib_error_t *
1276vnet_session_rule_add_del (session_rule_add_del_args_t * args)
1277{
1278 app_namespace_t *app_ns = app_namespace_get (args->appns_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001279 session_rules_table_t *srt;
Florin Coras1c710452017-10-17 00:03:13 -07001280 session_table_t *st;
1281 u32 fib_index;
1282 u8 fib_proto;
1283 clib_error_t *error;
1284
1285 if (!app_ns)
1286 return clib_error_return_code (0, VNET_API_ERROR_APP_INVALID_NS, 0,
1287 "invalid app ns");
1288 if (args->scope > 3)
1289 return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
1290 "invalid scope");
Florin Corasc97a7392017-11-05 23:07:07 -08001291 if (args->transport_proto != TRANSPORT_PROTO_TCP
1292 && args->transport_proto != TRANSPORT_PROTO_UDP)
1293 return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
1294 "invalid transport proto");
Florin Coras1c710452017-10-17 00:03:13 -07001295 if ((args->scope & SESSION_RULE_SCOPE_GLOBAL) || args->scope == 0)
1296 {
1297 fib_proto = args->table_args.rmt.fp_proto;
1298 fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1299 st = session_table_get_for_fib_index (fib_proto, fib_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001300 srt = &st->session_rules[args->transport_proto];
1301 if ((error = session_rules_table_add_del (srt, &args->table_args)))
1302 {
1303 clib_error_report (error);
1304 return error;
1305 }
Florin Coras1c710452017-10-17 00:03:13 -07001306 }
1307 if (args->scope & SESSION_RULE_SCOPE_LOCAL)
1308 {
Florin Corasa2ff7b82017-11-08 17:55:03 -08001309 memset (&args->table_args.lcl, 0, sizeof (args->table_args.lcl));
1310 args->table_args.lcl.fp_proto = args->table_args.rmt.fp_proto;
1311 args->table_args.lcl_port = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001312 st = app_namespace_get_local_table (app_ns);
Florin Corasc97a7392017-11-05 23:07:07 -08001313 srt = &st->session_rules[args->transport_proto];
1314 error = session_rules_table_add_del (srt, &args->table_args);
Florin Coras1c710452017-10-17 00:03:13 -07001315 }
1316 return error;
1317}
1318
Florin Coras6c36f532017-11-03 18:32:34 -07001319/**
1320 * Mark (global) tables as pertaining to app ns
1321 */
1322void
1323session_lookup_set_tables_appns (app_namespace_t * app_ns)
1324{
1325 session_table_t *st;
1326 u32 fib_index;
1327 u8 fp;
1328
1329 for (fp = 0; fp < ARRAY_LEN (fib_index_to_table_index); fp++)
1330 {
1331 fib_index = app_namespace_get_fib_index (app_ns, fp);
1332 st = session_table_get_for_fib_index (fp, fib_index);
1333 if (st)
1334 st->appns_index = app_namespace_index (app_ns);
1335 }
1336}
1337
Florin Corascea194d2017-10-02 00:18:51 -07001338u8 *
1339format_ip4_session_lookup_kvp (u8 * s, va_list * args)
1340{
1341 clib_bihash_kv_16_8_t *kvp = va_arg (*args, clib_bihash_kv_16_8_t *);
1342 u32 is_local = va_arg (*args, u32);
1343 u8 *app_name, *str = 0;
1344 stream_session_t *session;
1345 v4_connection_key_t *key = (v4_connection_key_t *) kvp->key;
1346
1347 char *proto = key->proto == TRANSPORT_PROTO_TCP ? "T" : "U";
1348 if (!is_local)
1349 {
1350 session = session_get_from_handle (kvp->value);
1351 app_name = application_name_from_index (session->app_index);
1352 str = format (0, "[%s] %U:%d->%U:%d", proto, format_ip4_address,
1353 &key->src, clib_net_to_host_u16 (key->src_port),
1354 format_ip4_address, &key->dst,
1355 clib_net_to_host_u16 (key->dst_port));
1356 s = format (s, "%-40v%-30v", str, app_name);
1357 }
1358 else
1359 {
1360 app_name = application_name_from_index (kvp->value);
1361 str = format (0, "[%s] %U:%d", proto, format_ip4_address,
1362 &key->src, clib_net_to_host_u16 (key->src_port));
1363 s = format (s, "%-30v%-30v", str, app_name);
1364 }
1365 vec_free (app_name);
1366 return s;
1367}
1368
1369typedef struct _ip4_session_table_show_ctx_t
1370{
1371 vlib_main_t *vm;
1372 u8 is_local;
1373} ip4_session_table_show_ctx_t;
1374
1375static int
1376ip4_session_table_show (clib_bihash_kv_16_8_t * kvp, void *arg)
1377{
1378 ip4_session_table_show_ctx_t *ctx = arg;
1379 vlib_cli_output (ctx->vm, "%U", format_ip4_session_lookup_kvp, kvp,
1380 ctx->is_local);
1381 return 1;
1382}
1383
1384void
1385session_lookup_show_table_entries (vlib_main_t * vm, session_table_t * table,
1386 u8 type, u8 is_local)
1387{
1388 ip4_session_table_show_ctx_t ctx = {
1389 .vm = vm,
1390 .is_local = is_local,
1391 };
1392 if (!is_local)
1393 vlib_cli_output (vm, "%-40s%-30s", "Session", "Application");
1394 else
1395 vlib_cli_output (vm, "%-30s%-30s", "Listener", "Application");
1396 switch (type)
1397 {
1398 /* main table v4 */
1399 case 0:
1400 ip4_session_table_walk (&table->v4_session_hash, ip4_session_table_show,
1401 &ctx);
1402 break;
1403 default:
1404 clib_warning ("not supported");
1405 }
1406}
Florin Coras66b11312017-07-31 17:18:03 -07001407
Florin Coras1c710452017-10-17 00:03:13 -07001408static clib_error_t *
1409session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
1410 vlib_cli_command_t * cmd)
1411{
Florin Corasc97a7392017-11-05 23:07:07 -08001412 u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen = 0, rmt_plen = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001413 u32 appns_index, scope = 0;
1414 ip46_address_t lcl_ip, rmt_ip;
1415 u8 is_ip4 = 1, conn_set = 0;
1416 u8 fib_proto, is_add = 1, *ns_id = 0;
Florin Corasc97a7392017-11-05 23:07:07 -08001417 u8 *tag = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001418 app_namespace_t *app_ns;
Florin Corasc97a7392017-11-05 23:07:07 -08001419 clib_error_t *error;
Florin Coras1c710452017-10-17 00:03:13 -07001420
1421 memset (&lcl_ip, 0, sizeof (lcl_ip));
1422 memset (&rmt_ip, 0, sizeof (rmt_ip));
1423 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1424 {
1425 if (unformat (input, "del"))
1426 is_add = 0;
1427 else if (unformat (input, "add"))
1428 ;
1429 else if (unformat (input, "appns %_%v%_", &ns_id))
1430 ;
1431 else if (unformat (input, "scope global"))
1432 scope = SESSION_RULE_SCOPE_GLOBAL;
1433 else if (unformat (input, "scope local"))
1434 scope = SESSION_RULE_SCOPE_LOCAL;
1435 else if (unformat (input, "scope all"))
1436 scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1437 else if (unformat (input, "proto %U", unformat_transport_proto, &proto))
1438 ;
1439 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1440 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1441 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1442 &rmt_port))
1443 {
1444 is_ip4 = 1;
1445 conn_set = 1;
1446 }
1447 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1448 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1449 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1450 &rmt_port))
1451 {
1452 is_ip4 = 0;
1453 conn_set = 1;
1454 }
1455 else if (unformat (input, "action %d", &action))
1456 ;
Florin Corasc97a7392017-11-05 23:07:07 -08001457 else if (unformat (input, "tag %_%v%_", &tag))
1458 ;
Florin Coras1c710452017-10-17 00:03:13 -07001459 else
1460 return clib_error_return (0, "unknown input `%U'",
1461 format_unformat_error, input);
1462 }
1463
Florin Corasc97a7392017-11-05 23:07:07 -08001464 if (proto == ~0)
1465 {
1466 vlib_cli_output (vm, "proto must be set");
1467 return 0;
1468 }
1469 if (is_add && !conn_set && action == ~0)
1470 {
1471 vlib_cli_output (vm, "connection and action must be set for add");
1472 return 0;
1473 }
1474 if (!is_add && !tag && !conn_set)
1475 {
1476 vlib_cli_output (vm, "connection or tag must be set for delete");
1477 return 0;
1478 }
1479 if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN)
1480 {
1481 vlib_cli_output (vm, "tag too long (max u64)");
1482 return 0;
1483 }
Florin Coras1c710452017-10-17 00:03:13 -07001484
1485 if (ns_id)
1486 {
1487 app_ns = app_namespace_get_from_id (ns_id);
1488 if (!app_ns)
Florin Corasc97a7392017-11-05 23:07:07 -08001489 {
1490 vlib_cli_output (vm, "namespace %v does not exist", ns_id);
1491 return 0;
1492 }
Florin Coras1c710452017-10-17 00:03:13 -07001493 }
1494 else
1495 {
1496 app_ns = app_namespace_get_default ();
1497 }
1498 appns_index = app_namespace_index (app_ns);
1499
1500 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1501 session_rule_add_del_args_t args = {
1502 .table_args.lcl.fp_addr = lcl_ip,
1503 .table_args.lcl.fp_len = lcl_plen,
1504 .table_args.lcl.fp_proto = fib_proto,
1505 .table_args.rmt.fp_addr = rmt_ip,
1506 .table_args.rmt.fp_len = rmt_plen,
1507 .table_args.rmt.fp_proto = fib_proto,
1508 .table_args.lcl_port = lcl_port,
1509 .table_args.rmt_port = rmt_port,
1510 .table_args.action_index = action,
1511 .table_args.is_add = is_add,
Florin Corasc97a7392017-11-05 23:07:07 -08001512 .table_args.tag = tag,
Florin Coras1c710452017-10-17 00:03:13 -07001513 .appns_index = appns_index,
1514 .scope = scope,
1515 };
Florin Corasc97a7392017-11-05 23:07:07 -08001516 error = vnet_session_rule_add_del (&args);
1517 vec_free (tag);
1518 return error;
Florin Coras1c710452017-10-17 00:03:13 -07001519}
1520
1521/* *INDENT-OFF* */
1522VLIB_CLI_COMMAND (session_rule_command, static) =
1523{
1524 .path = "session rule",
1525 .short_help = "session rule [add|del] appns <ns_id> proto <proto> "
1526 "<lcl-ip/plen> <lcl-port> <rmt-ip/plen> <rmt-port> action <action>",
1527 .function = session_rule_command_fn,
1528};
1529/* *INDENT-ON* */
1530
Florin Coras7999e832017-10-31 01:51:04 -07001531void
1532session_lookup_dump_rules_table (u32 fib_index, u8 fib_proto,
1533 u8 transport_proto)
1534{
1535 vlib_main_t *vm = vlib_get_main ();
Florin Corasc97a7392017-11-05 23:07:07 -08001536 session_rules_table_t *srt;
Florin Coras7999e832017-10-31 01:51:04 -07001537 session_table_t *st;
1538 st = session_table_get_for_fib_index (fib_index, fib_proto);
Florin Corasc97a7392017-11-05 23:07:07 -08001539 srt = &st->session_rules[transport_proto];
1540 session_rules_table_cli_dump (vm, srt, fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001541}
1542
1543void
1544session_lookup_dump_local_rules_table (u32 table_index, u8 fib_proto,
1545 u8 transport_proto)
1546{
1547 vlib_main_t *vm = vlib_get_main ();
Florin Corasc97a7392017-11-05 23:07:07 -08001548 session_rules_table_t *srt;
Florin Coras7999e832017-10-31 01:51:04 -07001549 session_table_t *st;
1550 st = session_table_get (table_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001551 srt = &st->session_rules[transport_proto];
1552 session_rules_table_cli_dump (vm, srt, fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001553}
1554
Florin Coras1c710452017-10-17 00:03:13 -07001555static clib_error_t *
1556show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input,
1557 vlib_cli_command_t * cmd)
1558{
1559 u32 transport_proto = ~0, lcl_port, rmt_port, lcl_plen, rmt_plen;
1560 u32 fib_index, scope = 0;
1561 ip46_address_t lcl_ip, rmt_ip;
1562 u8 is_ip4 = 1, show_one = 0;
1563 app_namespace_t *app_ns;
Florin Corasc97a7392017-11-05 23:07:07 -08001564 session_rules_table_t *srt;
Florin Coras1c710452017-10-17 00:03:13 -07001565 session_table_t *st;
1566 u8 *ns_id = 0, fib_proto;
1567
1568 memset (&lcl_ip, 0, sizeof (lcl_ip));
1569 memset (&rmt_ip, 0, sizeof (rmt_ip));
1570 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1571 {
1572 if (unformat (input, "%U", unformat_transport_proto, &transport_proto))
1573 ;
1574 else if (unformat (input, "appns %_%v%_", &ns_id))
1575 ;
1576 else if (unformat (input, "scope global"))
1577 scope = 1;
1578 else if (unformat (input, "scope local"))
1579 scope = 2;
1580 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1581 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1582 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1583 &rmt_port))
1584 {
1585 is_ip4 = 1;
1586 show_one = 1;
1587 }
1588 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1589 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1590 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1591 &rmt_port))
1592 {
1593 is_ip4 = 0;
1594 show_one = 1;
1595 }
1596 else
1597 return clib_error_return (0, "unknown input `%U'",
1598 format_unformat_error, input);
1599 }
1600
1601 if (transport_proto == ~0)
1602 {
1603 vlib_cli_output (vm, "transport proto must be set");
1604 return 0;
1605 }
1606
1607 if (ns_id)
1608 {
1609 app_ns = app_namespace_get_from_id (ns_id);
1610 if (!app_ns)
1611 {
1612 vlib_cli_output (vm, "appns %v doesn't exist", ns_id);
1613 return 0;
1614 }
1615 }
1616 else
1617 {
1618 app_ns = app_namespace_get_default ();
1619 }
1620
1621 if (scope == 1 || scope == 0)
1622 {
1623 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1624 fib_index = is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
1625 st = session_table_get_for_fib_index (fib_proto, fib_index);
1626 }
1627 else
1628 {
1629 st = app_namespace_get_local_table (app_ns);
1630 }
1631
1632 if (show_one)
1633 {
Florin Corasc97a7392017-11-05 23:07:07 -08001634 srt = &st->session_rules[transport_proto];
1635 session_rules_table_show_rule (vm, srt, &lcl_ip, lcl_port, &rmt_ip,
1636 rmt_port, is_ip4);
Florin Coras1c710452017-10-17 00:03:13 -07001637 return 0;
1638 }
1639
Florin Corasc97a7392017-11-05 23:07:07 -08001640 vlib_cli_output (vm, "%U rules table", format_transport_proto,
1641 transport_proto);
1642 srt = &st->session_rules[transport_proto];
1643 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
1644 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP6);
Florin Coras1c710452017-10-17 00:03:13 -07001645
1646 vec_free (ns_id);
1647 return 0;
1648}
1649
1650/* *INDENT-OFF* */
1651VLIB_CLI_COMMAND (show_session_rules_command, static) =
1652{
1653 .path = "show session rules",
Florin Corasdff48db2017-11-19 18:06:58 -08001654 .short_help = "show session rules [<proto> appns <id> <lcl-ip/plen> "
1655 "<lcl-port> <rmt-ip/plen> <rmt-port> scope <scope>]",
Florin Coras1c710452017-10-17 00:03:13 -07001656 .function = show_session_rules_command_fn,
1657};
1658/* *INDENT-ON* */
1659
Florin Coras04e53442017-07-16 17:12:15 -07001660void
1661session_lookup_init (void)
1662{
Florin Corascea194d2017-10-02 00:18:51 -07001663 /*
1664 * Allocate default table and map it to fib_index 0
1665 */
1666 session_table_t *st = session_table_alloc ();
1667 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP4], 0);
1668 fib_index_to_table_index[FIB_PROTOCOL_IP4][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001669 st->active_fib_proto = FIB_PROTOCOL_IP4;
1670 session_table_init (st, FIB_PROTOCOL_IP4);
Florin Corascea194d2017-10-02 00:18:51 -07001671 st = session_table_alloc ();
1672 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP6], 0);
1673 fib_index_to_table_index[FIB_PROTOCOL_IP6][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001674 st->active_fib_proto = FIB_PROTOCOL_IP6;
1675 session_table_init (st, FIB_PROTOCOL_IP6);
Florin Coras04e53442017-07-16 17:12:15 -07001676}
1677
1678/*
1679 * fd.io coding-style-patch-verification: ON
1680 *
1681 * Local Variables:
1682 * eval: (c-set-style "gnu")
1683 * End:
1684 */