blob: afbb8dada52a35a6d7390baa7fe8bad6e76146f8 [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
116make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * t)
117{
rootc9d1c5b2017-08-15 12:58:31 -0400118 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 -0700119 session_type_from_proto_and_ip (t->proto, 1));
Florin Coras04e53442017-07-16 17:12:15 -0700120}
121
122always_inline void
123make_v6_ss_kv (session_kv6_t * kv, ip6_address_t * lcl, ip6_address_t * rmt,
124 u16 lcl_port, u16 rmt_port, u8 proto)
125{
126 v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
127
128 key->src.as_u64[0] = lcl->as_u64[0];
129 key->src.as_u64[1] = lcl->as_u64[1];
130 key->dst.as_u64[0] = rmt->as_u64[0];
131 key->dst.as_u64[1] = rmt->as_u64[1];
132 key->src_port = lcl_port;
133 key->dst_port = rmt_port;
134 key->proto = proto;
135 key->unused = 0;
136
137 kv->value = ~0ULL;
138}
139
140always_inline void
141make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port,
142 u8 proto)
143{
144 v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
145
146 key->src.as_u64[0] = lcl->as_u64[0];
147 key->src.as_u64[1] = lcl->as_u64[1];
148 key->dst.as_u64[0] = 0;
149 key->dst.as_u64[1] = 0;
150 key->src_port = lcl_port;
151 key->dst_port = 0;
152 key->proto = proto;
153 key->unused = 0;
154
155 kv->value = ~0ULL;
156}
157
158always_inline void
159make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * t)
160{
rootc9d1c5b2017-08-15 12:58:31 -0400161 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 -0700162 session_type_from_proto_and_ip (t->proto, 0));
Florin Coras04e53442017-07-16 17:12:15 -0700163}
164
Florin Corascea194d2017-10-02 00:18:51 -0700165static session_table_t *
Florin Coras6c36f532017-11-03 18:32:34 -0700166session_table_get_or_alloc (u8 fib_proto, u8 fib_index)
Florin Coras04e53442017-07-16 17:12:15 -0700167{
Florin Corascea194d2017-10-02 00:18:51 -0700168 session_table_t *st;
Florin Coras6c36f532017-11-03 18:32:34 -0700169 u32 table_index;
170 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
Florin Corascea194d2017-10-02 00:18:51 -0700171 {
172 st = session_table_alloc ();
173 table_index = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -0700174 vec_validate (fib_index_to_table_index[fib_proto], fib_index);
175 fib_index_to_table_index[fib_proto][fib_index] = table_index;
176 st->active_fib_proto = fib_proto;
Florin Corascea194d2017-10-02 00:18:51 -0700177 return st;
178 }
179 else
180 {
Florin Coras6c36f532017-11-03 18:32:34 -0700181 table_index = fib_index_to_table_index[fib_proto][fib_index];
Florin Corascea194d2017-10-02 00:18:51 -0700182 return session_table_get (table_index);
183 }
184}
185
186static session_table_t *
Florin Coras6c36f532017-11-03 18:32:34 -0700187session_table_get_or_alloc_for_connection (transport_connection_t * tc)
188{
189 u32 fib_proto;
190 fib_proto = transport_connection_fib_proto (tc);
191 return session_table_get_or_alloc (fib_proto, tc->fib_index);
192}
193
194static session_table_t *
Florin Corascea194d2017-10-02 00:18:51 -0700195session_table_get_for_connection (transport_connection_t * tc)
196{
197 u32 fib_proto = transport_connection_fib_proto (tc);
198 if (vec_len (fib_index_to_table_index[fib_proto]) <= tc->fib_index)
199 return 0;
200 return
201 session_table_get (fib_index_to_table_index[fib_proto][tc->fib_index]);
202}
203
204static session_table_t *
205session_table_get_for_fib_index (u32 fib_proto, u32 fib_index)
206{
207 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
208 return 0;
209 return session_table_get (fib_index_to_table_index[fib_proto][fib_index]);
210}
211
212u32
213session_lookup_get_index_for_fib (u32 fib_proto, u32 fib_index)
214{
215 if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
216 return SESSION_TABLE_INVALID_INDEX;
217 return fib_index_to_table_index[fib_proto][fib_index];
218}
219
220/**
221 * Add transport connection to a session table
222 *
223 * Session lookup 5-tuple (src-ip, dst-ip, src-port, dst-port, session-type)
224 * is added to requested session table.
225 *
226 * @param tc transport connection to be added
227 * @param value value to be stored
228 *
229 * @return non-zero if failure
230 */
231int
232session_lookup_add_connection (transport_connection_t * tc, u64 value)
233{
234 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700235 session_kv4_t kv4;
236 session_kv6_t kv6;
237
Florin Corascea194d2017-10-02 00:18:51 -0700238 st = session_table_get_or_alloc_for_connection (tc);
239 if (!st)
240 return -1;
Florin Coras68810622017-07-24 17:40:28 -0700241 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700242 {
Florin Coras04e53442017-07-16 17:12:15 -0700243 make_v4_ss_kv_from_tc (&kv4, tc);
244 kv4.value = value;
Florin Corascea194d2017-10-02 00:18:51 -0700245 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4,
246 1 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700247 }
248 else
249 {
Florin Coras04e53442017-07-16 17:12:15 -0700250 make_v6_ss_kv_from_tc (&kv6, tc);
251 kv6.value = value;
Florin Corascea194d2017-10-02 00:18:51 -0700252 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6,
253 1 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700254 }
255}
256
Florin Coras04e53442017-07-16 17:12:15 -0700257int
Florin Corascea194d2017-10-02 00:18:51 -0700258session_lookup_add_session_endpoint (u32 table_index,
259 session_endpoint_t * sep, u64 value)
Florin Coras04e53442017-07-16 17:12:15 -0700260{
Florin Corascea194d2017-10-02 00:18:51 -0700261 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700262 session_kv4_t kv4;
263 session_kv6_t kv6;
Florin Coras68810622017-07-24 17:40:28 -0700264
Florin Corascea194d2017-10-02 00:18:51 -0700265 st = session_table_get (table_index);
266 if (!st)
267 return -1;
268 if (sep->is_ip4)
269 {
270 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
271 sep->transport_proto);
272 kv4.value = value;
273 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 1);
274 }
275 else
276 {
277 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
278 sep->transport_proto);
279 kv6.value = value;
280 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 1);
281 }
282}
283
284int
285session_lookup_del_session_endpoint (u32 table_index,
286 session_endpoint_t * sep)
287{
288 session_table_t *st;
289 session_kv4_t kv4;
290 session_kv6_t kv6;
291
292 st = session_table_get (table_index);
293 if (!st)
294 return -1;
295 if (sep->is_ip4)
296 {
297 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
298 sep->transport_proto);
299 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 0);
300 }
301 else
302 {
303 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
304 sep->transport_proto);
305 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 0);
306 }
307}
308
309/**
310 * Delete transport connection from session table
311 *
312 * @param table_index session table index
313 * @param tc transport connection to be removed
314 *
315 * @return non-zero if failure
316 */
317int
318session_lookup_del_connection (transport_connection_t * tc)
319{
320 session_table_t *st;
321 session_kv4_t kv4;
322 session_kv6_t kv6;
323
324 st = session_table_get_for_connection (tc);
325 if (!st)
326 return -1;
Florin Coras68810622017-07-24 17:40:28 -0700327 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700328 {
Florin Coras04e53442017-07-16 17:12:15 -0700329 make_v4_ss_kv_from_tc (&kv4, tc);
Florin Corascea194d2017-10-02 00:18:51 -0700330 return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4,
Florin Coras04e53442017-07-16 17:12:15 -0700331 0 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700332 }
333 else
334 {
Florin Coras04e53442017-07-16 17:12:15 -0700335 make_v6_ss_kv_from_tc (&kv6, tc);
Florin Corascea194d2017-10-02 00:18:51 -0700336 return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6,
Florin Coras04e53442017-07-16 17:12:15 -0700337 0 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700338 }
Florin Coras04e53442017-07-16 17:12:15 -0700339}
340
341int
Florin Corascea194d2017-10-02 00:18:51 -0700342session_lookup_del_session (stream_session_t * s)
Florin Coras04e53442017-07-16 17:12:15 -0700343{
344 transport_connection_t *ts;
345 ts = tp_vfts[s->session_type].get_connection (s->connection_index,
346 s->thread_index);
Florin Corascea194d2017-10-02 00:18:51 -0700347 return session_lookup_del_connection (ts);
Florin Coras04e53442017-07-16 17:12:15 -0700348}
349
Florin Corasf0c1c962017-11-02 21:31:46 -0700350static u32
351session_lookup_action_to_session (u32 action_index)
352{
353 if (action_index != SESSION_RULES_TABLE_ACTION_DROP)
354 return action_index;
355 return SESSION_INVALID_INDEX;
356}
357
Florin Coras1c710452017-10-17 00:03:13 -0700358static stream_session_t *
Florin Coras7999e832017-10-31 01:51:04 -0700359session_lookup_app_listen_session (u32 app_index, u8 fib_proto,
360 u8 transport_proto)
Florin Coras1c710452017-10-17 00:03:13 -0700361{
362 application_t *app;
363 app = application_get (app_index);
364 if (!app)
365 return 0;
366
Florin Coras7999e832017-10-31 01:51:04 -0700367 return application_first_listener (app, fib_proto, transport_proto);
Florin Coras1c710452017-10-17 00:03:13 -0700368}
369
370stream_session_t *
Florin Corasc97a7392017-11-05 23:07:07 -0800371session_lookup_rules_table4 (session_table_t * st, u8 proto,
Florin Coras1c710452017-10-17 00:03:13 -0700372 ip4_address_t * lcl, u16 lcl_port,
373 ip4_address_t * rmt, u16 rmt_port)
374{
Florin Corasc97a7392017-11-05 23:07:07 -0800375 session_rules_table_t *srt = &st->session_rules[proto];
Florin Corasf0c1c962017-11-02 21:31:46 -0700376 u32 action_index, session_index;
Florin Corasc97a7392017-11-05 23:07:07 -0800377 action_index = session_rules_table_lookup4 (srt, lcl, rmt, lcl_port,
Florin Coras1c710452017-10-17 00:03:13 -0700378 rmt_port);
Florin Corasf0c1c962017-11-02 21:31:46 -0700379 session_index = session_lookup_action_to_session (action_index);
Florin Coras1c710452017-10-17 00:03:13 -0700380 /* Nothing sophisticated for now, action index is app index */
Florin Corasf0c1c962017-11-02 21:31:46 -0700381 return session_lookup_app_listen_session (session_index, FIB_PROTOCOL_IP4,
Florin Coras7999e832017-10-31 01:51:04 -0700382 proto);
Florin Coras1c710452017-10-17 00:03:13 -0700383}
384
385stream_session_t *
Florin Corasc97a7392017-11-05 23:07:07 -0800386session_lookup_rules_table6 (session_table_t * st, u8 proto,
Florin Coras1c710452017-10-17 00:03:13 -0700387 ip6_address_t * lcl, u16 lcl_port,
388 ip6_address_t * rmt, u16 rmt_port)
389{
Florin Corasc97a7392017-11-05 23:07:07 -0800390 session_rules_table_t *srt = &st->session_rules[proto];
Florin Corasf0c1c962017-11-02 21:31:46 -0700391 u32 action_index, session_index;
Florin Corasc97a7392017-11-05 23:07:07 -0800392 action_index = session_rules_table_lookup6 (srt, lcl, rmt, lcl_port,
Florin Coras1c710452017-10-17 00:03:13 -0700393 rmt_port);
Florin Corasf0c1c962017-11-02 21:31:46 -0700394 session_index = session_lookup_action_to_session (action_index);
395 return session_lookup_app_listen_session (session_index, FIB_PROTOCOL_IP6,
Florin Coras7999e832017-10-31 01:51:04 -0700396 proto);
Florin Coras1c710452017-10-17 00:03:13 -0700397}
398
Florin Coras3cbc04b2017-10-02 00:18:51 -0700399u64
Florin Corascea194d2017-10-02 00:18:51 -0700400session_lookup_session_endpoint (u32 table_index, session_endpoint_t * sep)
Florin Coras04e53442017-07-16 17:12:15 -0700401{
Florin Corasc97a7392017-11-05 23:07:07 -0800402 session_rules_table_t *srt;
Florin Corascea194d2017-10-02 00:18:51 -0700403 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700404 session_kv4_t kv4;
405 session_kv6_t kv6;
Florin Coras1c710452017-10-17 00:03:13 -0700406 ip4_address_t lcl4;
407 ip6_address_t lcl6;
Florin Corasf0c1c962017-11-02 21:31:46 -0700408 u32 ai;
Florin Corascea194d2017-10-02 00:18:51 -0700409 int rv;
Florin Coras4e4531e2017-11-06 23:27:56 -0800410 u8 sst;
Florin Coras04e53442017-07-16 17:12:15 -0700411
Florin Coras4e4531e2017-11-06 23:27:56 -0800412 sst = session_type_from_proto_and_ip (sep->transport_proto, sep->is_ip4);
Florin Corascea194d2017-10-02 00:18:51 -0700413 st = session_table_get (table_index);
414 if (!st)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700415 return SESSION_INVALID_HANDLE;
Florin Corascea194d2017-10-02 00:18:51 -0700416 if (sep->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700417 {
Florin Coras4e4531e2017-11-06 23:27:56 -0800418 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port, sst);
Florin Corascea194d2017-10-02 00:18:51 -0700419 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
420 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700421 return kv4.value;
Florin Coras1c710452017-10-17 00:03:13 -0700422
423 memset (&lcl4, 0, sizeof (lcl4));
Florin Corasc97a7392017-11-05 23:07:07 -0800424 srt = &st->session_rules[sep->transport_proto];
425 ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0,
426 sep->port);
Florin Corasf0c1c962017-11-02 21:31:46 -0700427 if (ai != SESSION_RULES_TABLE_INVALID_INDEX)
428 return session_lookup_action_to_session (ai);
Florin Coras68810622017-07-24 17:40:28 -0700429 }
430 else
431 {
Florin Coras4e4531e2017-11-06 23:27:56 -0800432 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, sst);
Florin Corascea194d2017-10-02 00:18:51 -0700433 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
434 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700435 return kv6.value;
Florin Coras1c710452017-10-17 00:03:13 -0700436
437 memset (&lcl6, 0, sizeof (lcl6));
Florin Corasc97a7392017-11-05 23:07:07 -0800438 srt = &st->session_rules[sep->transport_proto];
439 ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0,
440 sep->port);
Florin Corasf0c1c962017-11-02 21:31:46 -0700441 if (ai != SESSION_RULES_TABLE_INVALID_INDEX)
442 return session_lookup_action_to_session (ai);
Florin Coras68810622017-07-24 17:40:28 -0700443 }
Florin Coras3cbc04b2017-10-02 00:18:51 -0700444 return SESSION_INVALID_HANDLE;
445}
446
447stream_session_t *
448session_lookup_global_session_endpoint (session_endpoint_t * sep)
449{
450 session_table_t *st;
451 session_kv4_t kv4;
452 session_kv6_t kv6;
Florin Coras1c710452017-10-17 00:03:13 -0700453 ip4_address_t lcl4;
454 ip6_address_t lcl6;
Florin Coras3cbc04b2017-10-02 00:18:51 -0700455 u8 fib_proto;
456 u32 table_index;
457 int rv;
458
459 fib_proto = session_endpoint_fib_proto (sep);
460 table_index = session_lookup_get_index_for_fib (fib_proto, sep->fib_index);
461 st = session_table_get (table_index);
462 if (!st)
463 return 0;
464 if (sep->is_ip4)
465 {
466 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
467 sep->transport_proto);
468 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
469 if (rv == 0)
470 return session_get_from_handle (kv4.value);
Florin Coras1c710452017-10-17 00:03:13 -0700471 memset (&lcl4, 0, sizeof (lcl4));
Florin Corasc97a7392017-11-05 23:07:07 -0800472 return session_lookup_rules_table4 (st, sep->transport_proto, &lcl4, 0,
Florin Coras1c710452017-10-17 00:03:13 -0700473 &sep->ip.ip4, sep->port);
Florin Coras3cbc04b2017-10-02 00:18:51 -0700474 }
475 else
476 {
477 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
478 sep->transport_proto);
479 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
480 if (rv == 0)
481 return session_get_from_handle (kv6.value);
Florin Coras1c710452017-10-17 00:03:13 -0700482 memset (&lcl6, 0, sizeof (lcl6));
Florin Corasc97a7392017-11-05 23:07:07 -0800483 return session_lookup_rules_table6 (st, sep->transport_proto, &lcl6, 0,
Florin Coras1c710452017-10-17 00:03:13 -0700484 &sep->ip.ip6, sep->port);
Florin Coras3cbc04b2017-10-02 00:18:51 -0700485 }
Florin Coras68810622017-07-24 17:40:28 -0700486}
487
Florin Corascea194d2017-10-02 00:18:51 -0700488u32
489session_lookup_local_session_endpoint (u32 table_index,
490 session_endpoint_t * sep)
Florin Coras68810622017-07-24 17:40:28 -0700491{
Florin Corasc97a7392017-11-05 23:07:07 -0800492 session_rules_table_t *srt;
Florin Corascea194d2017-10-02 00:18:51 -0700493 session_table_t *st;
Florin Coras68810622017-07-24 17:40:28 -0700494 session_kv4_t kv4;
495 session_kv6_t kv6;
Florin Coras1c710452017-10-17 00:03:13 -0700496 ip4_address_t lcl4;
497 ip6_address_t lcl6;
Florin Corasf0c1c962017-11-02 21:31:46 -0700498 u32 ai;
Florin Corascea194d2017-10-02 00:18:51 -0700499 int rv;
Florin Coras68810622017-07-24 17:40:28 -0700500
Florin Corascea194d2017-10-02 00:18:51 -0700501 st = session_table_get (table_index);
502 if (!st)
503 return SESSION_INVALID_INDEX;
504 if (sep->is_ip4)
Florin Coras68810622017-07-24 17:40:28 -0700505 {
Florin Corascea194d2017-10-02 00:18:51 -0700506 make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
507 sep->transport_proto);
508 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
509 if (rv == 0)
510 return (u32) kv4.value;
511
512 /*
513 * Zero out the ip. Logic is that connect to local ips, say
514 * 127.0.0.1:port, can match 0.0.0.0:port
515 */
516 kv4.key[0] = 0;
517 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
518 if (rv == 0)
519 return (u32) kv4.value;
Florin Coras1c710452017-10-17 00:03:13 -0700520
521 memset (&lcl4, 0, sizeof (lcl4));
Florin Corasc97a7392017-11-05 23:07:07 -0800522 srt = &st->session_rules[sep->transport_proto];
523 ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0,
524 sep->port);
Florin Corasf0c1c962017-11-02 21:31:46 -0700525 if (ai != SESSION_RULES_TABLE_INVALID_INDEX)
526 return session_lookup_action_to_session (ai);
Florin Coras68810622017-07-24 17:40:28 -0700527 }
528 else
529 {
Florin Corascea194d2017-10-02 00:18:51 -0700530 make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
531 sep->transport_proto);
532 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
533 if (rv == 0)
534 return (u32) kv6.value;
535
536 /*
537 * Zero out the ip. Same logic as above.
538 */
539 kv6.key[0] = kv6.key[1] = 0;
540 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
541 if (rv == 0)
542 return (u32) kv6.value;
Florin Coras1c710452017-10-17 00:03:13 -0700543
544 memset (&lcl6, 0, sizeof (lcl6));
Florin Corasc97a7392017-11-05 23:07:07 -0800545 srt = &st->session_rules[sep->transport_proto];
546 ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0,
547 sep->port);
Florin Corasf0c1c962017-11-02 21:31:46 -0700548 if (ai != SESSION_RULES_TABLE_INVALID_INDEX)
549 return session_lookup_action_to_session (ai);
Florin Coras04e53442017-07-16 17:12:15 -0700550 }
Florin Corascea194d2017-10-02 00:18:51 -0700551 return SESSION_INVALID_INDEX;
Florin Coras04e53442017-07-16 17:12:15 -0700552}
553
Florin Corascea194d2017-10-02 00:18:51 -0700554static stream_session_t *
555session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl,
556 u16 lcl_port, u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700557{
Florin Coras04e53442017-07-16 17:12:15 -0700558 session_kv4_t kv4;
559 int rv;
560
561 make_v4_listener_kv (&kv4, lcl, lcl_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700562 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700563 if (rv == 0)
564 return session_manager_get_listener (proto, (u32) kv4.value);
565
566 /* Zero out the lcl ip */
567 kv4.key[0] = 0;
Florin Corascea194d2017-10-02 00:18:51 -0700568 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700569 if (rv == 0)
570 return session_manager_get_listener (proto, (u32) kv4.value);
571
572 return 0;
573}
574
Florin Coras04e53442017-07-16 17:12:15 -0700575stream_session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700576session_lookup_listener4 (u32 fib_index, ip4_address_t * lcl, u16 lcl_port,
577 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700578{
Florin Corascea194d2017-10-02 00:18:51 -0700579 session_table_t *st;
580 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
581 if (!st)
582 return 0;
583 return session_lookup_listener4_i (st, lcl, lcl_port, proto);
Florin Coras04e53442017-07-16 17:12:15 -0700584}
585
Florin Corascea194d2017-10-02 00:18:51 -0700586static stream_session_t *
587session_lookup_listener6_i (session_table_t * st, ip6_address_t * lcl,
588 u16 lcl_port, u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700589{
Florin Coras04e53442017-07-16 17:12:15 -0700590 session_kv6_t kv6;
591 int rv;
592
593 make_v6_listener_kv (&kv6, lcl, lcl_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700594 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700595 if (rv == 0)
596 return session_manager_get_listener (proto, (u32) kv6.value);
597
598 /* Zero out the lcl ip */
599 kv6.key[0] = kv6.key[1] = 0;
Florin Corascea194d2017-10-02 00:18:51 -0700600 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700601 if (rv == 0)
602 return session_manager_get_listener (proto, (u32) kv6.value);
603
604 return 0;
605}
606
Florin Coras04e53442017-07-16 17:12:15 -0700607stream_session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700608session_lookup_listener6 (u32 fib_index, ip6_address_t * lcl, u16 lcl_port,
609 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700610{
Florin Corascea194d2017-10-02 00:18:51 -0700611 session_table_t *st;
612 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
613 if (!st)
614 return 0;
615 return session_lookup_listener6_i (st, lcl, lcl_port, proto);
Florin Coras04e53442017-07-16 17:12:15 -0700616}
617
618stream_session_t *
Florin Corascea194d2017-10-02 00:18:51 -0700619session_lookup_listener (u32 table_index, session_endpoint_t * sep)
Florin Coras04e53442017-07-16 17:12:15 -0700620{
Florin Corascea194d2017-10-02 00:18:51 -0700621 session_table_t *st;
622 st = session_table_get (table_index);
623 if (!st)
624 return 0;
625 if (sep->is_ip4)
626 return session_lookup_listener4_i (st, &sep->ip.ip4, sep->port,
627 sep->transport_proto);
628 else
629 return session_lookup_listener6_i (st, &sep->ip.ip6, sep->port,
630 sep->transport_proto);
Florin Coras04e53442017-07-16 17:12:15 -0700631 return 0;
632}
633
Florin Corascea194d2017-10-02 00:18:51 -0700634int
635session_lookup_add_half_open (transport_connection_t * tc, u64 value)
636{
637 session_table_t *st;
638 session_kv4_t kv4;
639 session_kv6_t kv6;
640
641 st = session_table_get_or_alloc_for_connection (tc);
642 if (!st)
643 return 0;
644 if (tc->is_ip4)
645 {
646 make_v4_ss_kv_from_tc (&kv4, tc);
647 kv4.value = value;
648 return clib_bihash_add_del_16_8 (&st->v4_half_open_hash, &kv4,
649 1 /* is_add */ );
650 }
651 else
652 {
653 make_v6_ss_kv_from_tc (&kv6, tc);
654 kv6.value = value;
655 return clib_bihash_add_del_48_8 (&st->v6_half_open_hash, &kv6,
656 1 /* is_add */ );
657 }
658}
659
660int
661session_lookup_del_half_open (transport_connection_t * tc)
662{
663 session_table_t *st;
664 session_kv4_t kv4;
665 session_kv6_t kv6;
666
667 st = session_table_get_for_connection (tc);
668 if (!st)
669 return -1;
670 if (tc->is_ip4)
671 {
672 make_v4_ss_kv_from_tc (&kv4, tc);
673 return clib_bihash_add_del_16_8 (&st->v4_half_open_hash, &kv4,
674 0 /* is_add */ );
675 }
676 else
677 {
678 make_v6_ss_kv_from_tc (&kv6, tc);
679 return clib_bihash_add_del_48_8 (&st->v6_half_open_hash, &kv6,
680 0 /* is_add */ );
681 }
682}
683
Florin Coras04e53442017-07-16 17:12:15 -0700684u64
Florin Corascea194d2017-10-02 00:18:51 -0700685session_lookup_half_open_handle (transport_connection_t * tc)
Florin Coras04e53442017-07-16 17:12:15 -0700686{
Florin Corascea194d2017-10-02 00:18:51 -0700687 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700688 session_kv4_t kv4;
689 session_kv6_t kv6;
690 int rv;
691
Florin Corascea194d2017-10-02 00:18:51 -0700692 st = session_table_get_for_fib_index (transport_connection_fib_proto (tc),
693 tc->fib_index);
694 if (!st)
695 return HALF_OPEN_LOOKUP_INVALID_VALUE;
696 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700697 {
Florin Corascea194d2017-10-02 00:18:51 -0700698 make_v4_ss_kv (&kv4, &tc->lcl_ip.ip4, &tc->rmt_ip.ip4, tc->lcl_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700699 tc->rmt_port, tc->proto);
Florin Corascea194d2017-10-02 00:18:51 -0700700 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700701 if (rv == 0)
702 return kv4.value;
Florin Corascea194d2017-10-02 00:18:51 -0700703 }
704 else
705 {
706 make_v6_ss_kv (&kv6, &tc->lcl_ip.ip6, &tc->rmt_ip.ip6, tc->lcl_port,
Florin Coras3cbc04b2017-10-02 00:18:51 -0700707 tc->rmt_port, tc->proto);
Florin Corascea194d2017-10-02 00:18:51 -0700708 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700709 if (rv == 0)
710 return kv6.value;
Florin Coras04e53442017-07-16 17:12:15 -0700711 }
712 return HALF_OPEN_LOOKUP_INVALID_VALUE;
713}
714
715transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700716session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700717{
Florin Corascea194d2017-10-02 00:18:51 -0700718 u32 sst;
719
Florin Coras04e53442017-07-16 17:12:15 -0700720 if (handle != HALF_OPEN_LOOKUP_INVALID_VALUE)
Florin Corascea194d2017-10-02 00:18:51 -0700721 {
722 sst = session_type_from_proto_and_ip (proto, is_ip4);
723 return tp_vfts[sst].get_half_open (handle & 0xFFFFFFFF);
724 }
Florin Coras04e53442017-07-16 17:12:15 -0700725 return 0;
726}
727
Florin Corasc97a7392017-11-05 23:07:07 -0800728static transport_connection_t *
729session_lookup_rules_table_connection4 (session_table_t * st, u8 proto,
Florin Coras1c710452017-10-17 00:03:13 -0700730 ip4_address_t * lcl, u16 lcl_port,
731 ip4_address_t * rmt, u16 rmt_port)
732{
733 stream_session_t *s;
Florin Corasc97a7392017-11-05 23:07:07 -0800734 s = session_lookup_rules_table4 (st, proto, lcl, lcl_port, rmt, rmt_port);
Florin Coras1c710452017-10-17 00:03:13 -0700735 if (s)
736 return tp_vfts[s->session_type].get_listener (s->connection_index);
737 return 0;
738}
739
Florin Corasc97a7392017-11-05 23:07:07 -0800740static transport_connection_t *
741session_lookup_rules_table_connection6 (session_table_t * srt, u8 proto,
Florin Coras1c710452017-10-17 00:03:13 -0700742 ip6_address_t * lcl, u16 lcl_port,
743 ip6_address_t * rmt, u16 rmt_port)
744{
745 stream_session_t *s;
746 s = session_lookup_rules_table6 (srt, proto, lcl, lcl_port, rmt, rmt_port);
747 if (s)
748 return tp_vfts[s->session_type].get_listener (s->connection_index);
749 return 0;
750}
751
Florin Corascea194d2017-10-02 00:18:51 -0700752/**
753 * Lookup connection with ip4 and transport layer information
754 *
755 * This is used on the fast path so it needs to be fast. Thereby,
756 * duplication of code and 'hacks' allowed.
757 *
758 * The lookup is incremental and returns whenever something is matched. The
759 * steps are:
760 * - Try to find an established session
761 * - Try to find a fully-formed or local source wildcarded (listener bound to
762 * all interfaces) listener session
763 * - Try to find a half-open connection
Florin Coras1c710452017-10-17 00:03:13 -0700764 * - Try session rules table
Florin Corascea194d2017-10-02 00:18:51 -0700765 * - return 0
766 *
767 * @param fib_index index of fib wherein the connection was received
768 * @param lcl local ip4 address
769 * @param rmt remote ip4 address
770 * @param lcl_port local port
771 * @param rmt_port remote port
772 * @param proto transport protocol (e.g., tcp, udp)
773 * @param thread_index thread index for request
774 *
775 * @return pointer to transport connection, if one is found, 0 otherwise
776 */
Florin Coras04e53442017-07-16 17:12:15 -0700777transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700778session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl,
779 ip4_address_t * rmt, u16 lcl_port,
780 u16 rmt_port, u8 proto, u32 thread_index)
Florin Coras04e53442017-07-16 17:12:15 -0700781{
Florin Corascea194d2017-10-02 00:18:51 -0700782 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700783 session_kv4_t kv4;
784 stream_session_t *s;
785 int rv;
786
Florin Corascea194d2017-10-02 00:18:51 -0700787 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
788 if (PREDICT_FALSE (!st))
789 return 0;
790
Florin Coras04e53442017-07-16 17:12:15 -0700791 /* Lookup session amongst established ones */
792 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700793 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700794 if (rv == 0)
795 {
Florin Corascea194d2017-10-02 00:18:51 -0700796 ASSERT ((u32) (kv4.value >> 32) == thread_index);
797 s = session_get (kv4.value & 0xFFFFFFFFULL, thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700798 return tp_vfts[s->session_type].get_connection (s->connection_index,
Florin Corascea194d2017-10-02 00:18:51 -0700799 thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700800 }
801
802 /* If nothing is found, check if any listener is available */
Florin Corascea194d2017-10-02 00:18:51 -0700803 s = session_lookup_listener4_i (st, lcl, lcl_port, proto);
Florin Coras04e53442017-07-16 17:12:15 -0700804 if (s)
805 return tp_vfts[s->session_type].get_listener (s->connection_index);
806
Florin Coras1c710452017-10-17 00:03:13 -0700807 /* Try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -0700808 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700809 if (rv == 0)
Florin Corascea194d2017-10-02 00:18:51 -0700810 {
811 u32 sst = session_type_from_proto_and_ip (proto, 1);
812 return tp_vfts[sst].get_half_open (kv4.value & 0xFFFFFFFF);
813 }
Florin Coras1c710452017-10-17 00:03:13 -0700814
815 /* Check the session rules table */
Florin Corasc97a7392017-11-05 23:07:07 -0800816 return session_lookup_rules_table_connection4 (st, proto, lcl, lcl_port,
817 rmt, rmt_port);
Florin Coras04e53442017-07-16 17:12:15 -0700818}
819
Florin Corascea194d2017-10-02 00:18:51 -0700820/**
821 * Lookup connection with ip4 and transport layer information
822 *
823 * Not optimized. This is used on the fast path so it needs to be fast.
824 * Thereby, duplication of code and 'hacks' allowed. Lookup logic is identical
825 * to that of @ref session_lookup_connection_wt4
826 *
827 * @param fib_index index of the fib wherein the connection was received
828 * @param lcl local ip4 address
829 * @param rmt remote ip4 address
830 * @param lcl_port local port
831 * @param rmt_port remote port
832 * @param proto transport protocol (e.g., tcp, udp)
833 *
834 * @return pointer to transport connection, if one is found, 0 otherwise
835 */
Florin Coras04e53442017-07-16 17:12:15 -0700836transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700837session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl,
838 ip4_address_t * rmt, u16 lcl_port, u16 rmt_port,
839 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700840{
Florin Corascea194d2017-10-02 00:18:51 -0700841 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700842 session_kv4_t kv4;
843 stream_session_t *s;
844 int rv;
845
Florin Corascea194d2017-10-02 00:18:51 -0700846 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
847 if (PREDICT_FALSE (!st))
848 return 0;
849
Florin Coras04e53442017-07-16 17:12:15 -0700850 /* Lookup session amongst established ones */
851 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700852 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700853 if (rv == 0)
854 {
Florin Corascea194d2017-10-02 00:18:51 -0700855 s = session_get_from_handle (kv4.value);
Florin Coras04e53442017-07-16 17:12:15 -0700856 return tp_vfts[s->session_type].get_connection (s->connection_index,
857 s->thread_index);
858 }
859
860 /* If nothing is found, check if any listener is available */
Florin Corascea194d2017-10-02 00:18:51 -0700861 s = session_lookup_listener4_i (st, lcl, lcl_port, proto);
Florin Coras04e53442017-07-16 17:12:15 -0700862 if (s)
863 return tp_vfts[s->session_type].get_listener (s->connection_index);
864
865 /* Finally, try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -0700866 rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
Florin Coras04e53442017-07-16 17:12:15 -0700867 if (rv == 0)
Florin Corascea194d2017-10-02 00:18:51 -0700868 {
869 u32 sst = session_type_from_proto_and_ip (proto, 1);
870 return tp_vfts[sst].get_half_open (kv4.value & 0xFFFFFFFF);
871 }
Florin Coras1c710452017-10-17 00:03:13 -0700872 /* Check the session rules table */
Florin Corasc97a7392017-11-05 23:07:07 -0800873 return session_lookup_rules_table_connection4 (st, proto, lcl, lcl_port,
874 rmt, rmt_port);
Florin Coras04e53442017-07-16 17:12:15 -0700875}
876
Florin Corascea194d2017-10-02 00:18:51 -0700877/**
878 * Lookup session with ip4 and transport layer information
879 *
Florin Coras3cbc04b2017-10-02 00:18:51 -0700880 * Important note: this may look into another thread's pool table and
881 * register as 'peeker'. Caller should call @ref session_pool_remove_peeker as
882 * if needed as soon as possible.
883 *
884 * Lookup logic is similar to that of @ref session_lookup_connection_wt4 but
885 * this returns a session as opposed to a transport connection and it does not
886 * try to lookup half-open sessions.
887 *
888 * Typically used by dgram connections
Florin Corascea194d2017-10-02 00:18:51 -0700889 */
890stream_session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -0700891session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt,
892 u16 lcl_port, u16 rmt_port, u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -0700893{
Florin Corascea194d2017-10-02 00:18:51 -0700894 session_table_t *st;
895 session_kv4_t kv4;
896 stream_session_t *s;
897 int rv;
898
899 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
900 if (PREDICT_FALSE (!st))
901 return 0;
902
903 /* Lookup session amongst established ones */
904 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
905 rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
906 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700907 return session_get_from_handle_safe (kv4.value);
Florin Corascea194d2017-10-02 00:18:51 -0700908
909 /* If nothing is found, check if any listener is available */
910 if ((s = session_lookup_listener4_i (st, lcl, lcl_port, proto)))
911 return s;
Florin Corasc97a7392017-11-05 23:07:07 -0800912 return session_lookup_rules_table4 (st, proto, lcl,
Florin Coras1c710452017-10-17 00:03:13 -0700913 lcl_port, rmt, rmt_port);
Florin Corascea194d2017-10-02 00:18:51 -0700914}
915
916/**
917 * Lookup connection with ip6 and transport layer information
918 *
919 * This is used on the fast path so it needs to be fast. Thereby,
920 * duplication of code and 'hacks' allowed.
921 *
922 * The lookup is incremental and returns whenever something is matched. The
923 * steps are:
924 * - Try to find an established session
925 * - Try to find a fully-formed or local source wildcarded (listener bound to
926 * all interfaces) listener session
927 * - Try to find a half-open connection
Florin Coras1c710452017-10-17 00:03:13 -0700928 * - Try session rules table
Florin Corascea194d2017-10-02 00:18:51 -0700929 * - return 0
930 *
931 * @param fib_index index of the fib wherein the connection was received
932 * @param lcl local ip6 address
933 * @param rmt remote ip6 address
934 * @param lcl_port local port
935 * @param rmt_port remote port
936 * @param proto transport protocol (e.g., tcp, udp)
937 * @param thread_index thread index for request
938 *
939 * @return pointer to transport connection, if one is found, 0 otherwise
940 */
941transport_connection_t *
942session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl,
943 ip6_address_t * rmt, u16 lcl_port,
944 u16 rmt_port, u8 proto, u32 thread_index)
945{
946 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -0700947 stream_session_t *s;
948 session_kv6_t kv6;
949 int rv;
950
Florin Corascea194d2017-10-02 00:18:51 -0700951 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
952 if (PREDICT_FALSE (!st))
953 return 0;
954
Florin Coras04e53442017-07-16 17:12:15 -0700955 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -0700956 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700957 if (rv == 0)
958 {
Florin Corascea194d2017-10-02 00:18:51 -0700959 ASSERT ((u32) (kv6.value >> 32) == thread_index);
960 s = session_get (kv6.value & 0xFFFFFFFFULL, thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700961 return tp_vfts[s->session_type].get_connection (s->connection_index,
Florin Corascea194d2017-10-02 00:18:51 -0700962 thread_index);
Florin Coras04e53442017-07-16 17:12:15 -0700963 }
964
965 /* If nothing is found, check if any listener is available */
Florin Corascea194d2017-10-02 00:18:51 -0700966 s = session_lookup_listener6_i (st, lcl, lcl_port, proto);
Florin Coras04e53442017-07-16 17:12:15 -0700967 if (s)
968 return tp_vfts[s->session_type].get_listener (s->connection_index);
969
970 /* Finally, try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -0700971 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -0700972 if (rv == 0)
Florin Corascea194d2017-10-02 00:18:51 -0700973 {
974 u32 sst = session_type_from_proto_and_ip (proto, 1);
975 return tp_vfts[sst].get_half_open (kv6.value & 0xFFFFFFFF);
976 }
Florin Coras04e53442017-07-16 17:12:15 -0700977
Florin Corasc97a7392017-11-05 23:07:07 -0800978 return session_lookup_rules_table_connection6 (st, proto, lcl, lcl_port,
979 rmt, rmt_port);
Florin Coras04e53442017-07-16 17:12:15 -0700980}
981
Florin Corascea194d2017-10-02 00:18:51 -0700982/**
983 * Lookup connection with ip6 and transport layer information
984 *
985 * Not optimized. This is used on the fast path so it needs to be fast.
986 * Thereby, duplication of code and 'hacks' allowed. Lookup logic is identical
987 * to that of @ref session_lookup_connection_wt4
988 *
989 * @param fib_index index of the fib wherein the connection was received
990 * @param lcl local ip6 address
991 * @param rmt remote ip6 address
992 * @param lcl_port local port
993 * @param rmt_port remote port
994 * @param proto transport protocol (e.g., tcp, udp)
995 *
996 * @return pointer to transport connection, if one is found, 0 otherwise
997 */
Florin Coras04e53442017-07-16 17:12:15 -0700998transport_connection_t *
Florin Corascea194d2017-10-02 00:18:51 -0700999session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl,
1000 ip6_address_t * rmt, u16 lcl_port, u16 rmt_port,
1001 u8 proto)
Florin Coras04e53442017-07-16 17:12:15 -07001002{
Florin Corascea194d2017-10-02 00:18:51 -07001003 session_table_t *st;
Florin Coras04e53442017-07-16 17:12:15 -07001004 stream_session_t *s;
1005 session_kv6_t kv6;
1006 int rv;
1007
Florin Corascea194d2017-10-02 00:18:51 -07001008 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1009 if (PREDICT_FALSE (!st))
1010 return 0;
1011
Florin Coras04e53442017-07-16 17:12:15 -07001012 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
Florin Corascea194d2017-10-02 00:18:51 -07001013 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001014 if (rv == 0)
1015 {
Florin Corascea194d2017-10-02 00:18:51 -07001016 s = session_get_from_handle (kv6.value);
Florin Coras04e53442017-07-16 17:12:15 -07001017 return tp_vfts[s->session_type].get_connection (s->connection_index,
1018 s->thread_index);
1019 }
1020
1021 /* If nothing is found, check if any listener is available */
Florin Corascea194d2017-10-02 00:18:51 -07001022 s = session_lookup_listener6 (fib_index, lcl, lcl_port, proto);
Florin Coras04e53442017-07-16 17:12:15 -07001023 if (s)
1024 return tp_vfts[s->session_type].get_listener (s->connection_index);
1025
1026 /* Finally, try half-open connections */
Florin Corascea194d2017-10-02 00:18:51 -07001027 rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
Florin Coras04e53442017-07-16 17:12:15 -07001028 if (rv == 0)
Florin Corascea194d2017-10-02 00:18:51 -07001029 {
1030 u32 sst = session_type_from_proto_and_ip (proto, 1);
1031 return tp_vfts[sst].get_half_open (kv6.value & 0xFFFFFFFF);
1032 }
Florin Coras04e53442017-07-16 17:12:15 -07001033
Florin Corasc97a7392017-11-05 23:07:07 -08001034 return session_lookup_rules_table_connection6 (st, proto, lcl, lcl_port,
1035 rmt, rmt_port);
Florin Coras04e53442017-07-16 17:12:15 -07001036}
1037
Florin Corascea194d2017-10-02 00:18:51 -07001038/**
1039 * Lookup session with ip6 and transport layer information
1040 *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001041 * Important note: this may look into another thread's pool table and
1042 * register as 'peeker'. Caller should call @ref session_pool_remove_peeker as
1043 * if needed as soon as possible.
1044 *
1045 * Lookup logic is similar to that of @ref session_lookup_connection_wt6 but
1046 * this returns a session as opposed to a transport connection and it does not
1047 * try to lookup half-open sessions.
1048 *
1049 * Typically used by dgram connections
Florin Corascea194d2017-10-02 00:18:51 -07001050 */
1051stream_session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -07001052session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt,
1053 u16 lcl_port, u16 rmt_port, u8 proto)
Florin Corascea194d2017-10-02 00:18:51 -07001054{
1055 session_table_t *st;
1056 session_kv6_t kv6;
1057 stream_session_t *s;
1058 int rv;
1059
1060 st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
1061 if (PREDICT_FALSE (!st))
1062 return 0;
1063
1064 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
1065 rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
1066 if (rv == 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001067 return session_get_from_handle_safe (kv6.value);
Florin Corascea194d2017-10-02 00:18:51 -07001068
1069 /* If nothing is found, check if any listener is available */
1070 if ((s = session_lookup_listener6_i (st, lcl, lcl_port, proto)))
1071 return s;
Florin Corasc97a7392017-11-05 23:07:07 -08001072 return session_lookup_rules_table6 (st, proto, lcl,
Florin Coras1c710452017-10-17 00:03:13 -07001073 lcl_port, rmt, rmt_port);
Florin Corascea194d2017-10-02 00:18:51 -07001074}
1075
1076u64
1077session_lookup_local_listener_make_handle (session_endpoint_t * sep)
1078{
1079 return ((u64) SESSION_LOCAL_TABLE_PREFIX << 32
1080 | (u32) sep->port << 16 | (u32) sep->transport_proto << 8
1081 | (u32) sep->is_ip4);
1082}
1083
1084u8
1085session_lookup_local_is_handle (u64 handle)
1086{
1087 if (handle >> 32 == SESSION_LOCAL_TABLE_PREFIX)
1088 return 1;
1089 return 0;
1090}
1091
1092int
1093session_lookup_local_listener_parse_handle (u64 handle,
1094 session_endpoint_t * sep)
1095{
1096 u32 local_table_handle;
1097 if (handle >> 32 != SESSION_LOCAL_TABLE_PREFIX)
1098 return -1;
1099 local_table_handle = handle & 0xFFFFFFFFULL;
1100 sep->is_ip4 = local_table_handle & 0xff;
1101 local_table_handle >>= 8;
1102 sep->transport_proto = local_table_handle & 0xff;
1103 sep->port = local_table_handle >> 8;
1104 return 0;
1105}
1106
Florin Coras1c710452017-10-17 00:03:13 -07001107clib_error_t *
1108vnet_session_rule_add_del (session_rule_add_del_args_t * args)
1109{
1110 app_namespace_t *app_ns = app_namespace_get (args->appns_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001111 session_rules_table_t *srt;
Florin Coras1c710452017-10-17 00:03:13 -07001112 session_table_t *st;
1113 u32 fib_index;
1114 u8 fib_proto;
1115 clib_error_t *error;
1116
1117 if (!app_ns)
1118 return clib_error_return_code (0, VNET_API_ERROR_APP_INVALID_NS, 0,
1119 "invalid app ns");
1120 if (args->scope > 3)
1121 return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
1122 "invalid scope");
Florin Corasc97a7392017-11-05 23:07:07 -08001123 if (args->transport_proto != TRANSPORT_PROTO_TCP
1124 && args->transport_proto != TRANSPORT_PROTO_UDP)
1125 return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
1126 "invalid transport proto");
Florin Coras1c710452017-10-17 00:03:13 -07001127 if ((args->scope & SESSION_RULE_SCOPE_GLOBAL) || args->scope == 0)
1128 {
1129 fib_proto = args->table_args.rmt.fp_proto;
1130 fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1131 st = session_table_get_for_fib_index (fib_proto, fib_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001132 srt = &st->session_rules[args->transport_proto];
1133 if ((error = session_rules_table_add_del (srt, &args->table_args)))
1134 {
1135 clib_error_report (error);
1136 return error;
1137 }
Florin Coras1c710452017-10-17 00:03:13 -07001138 }
1139 if (args->scope & SESSION_RULE_SCOPE_LOCAL)
1140 {
1141 st = app_namespace_get_local_table (app_ns);
Florin Corasc97a7392017-11-05 23:07:07 -08001142 srt = &st->session_rules[args->transport_proto];
1143 error = session_rules_table_add_del (srt, &args->table_args);
Florin Coras1c710452017-10-17 00:03:13 -07001144 }
1145 return error;
1146}
1147
Florin Coras6c36f532017-11-03 18:32:34 -07001148/**
1149 * Mark (global) tables as pertaining to app ns
1150 */
1151void
1152session_lookup_set_tables_appns (app_namespace_t * app_ns)
1153{
1154 session_table_t *st;
1155 u32 fib_index;
1156 u8 fp;
1157
1158 for (fp = 0; fp < ARRAY_LEN (fib_index_to_table_index); fp++)
1159 {
1160 fib_index = app_namespace_get_fib_index (app_ns, fp);
1161 st = session_table_get_for_fib_index (fp, fib_index);
1162 if (st)
1163 st->appns_index = app_namespace_index (app_ns);
1164 }
1165}
1166
Florin Corascea194d2017-10-02 00:18:51 -07001167u8 *
1168format_ip4_session_lookup_kvp (u8 * s, va_list * args)
1169{
1170 clib_bihash_kv_16_8_t *kvp = va_arg (*args, clib_bihash_kv_16_8_t *);
1171 u32 is_local = va_arg (*args, u32);
1172 u8 *app_name, *str = 0;
1173 stream_session_t *session;
1174 v4_connection_key_t *key = (v4_connection_key_t *) kvp->key;
1175
1176 char *proto = key->proto == TRANSPORT_PROTO_TCP ? "T" : "U";
1177 if (!is_local)
1178 {
1179 session = session_get_from_handle (kvp->value);
1180 app_name = application_name_from_index (session->app_index);
1181 str = format (0, "[%s] %U:%d->%U:%d", proto, format_ip4_address,
1182 &key->src, clib_net_to_host_u16 (key->src_port),
1183 format_ip4_address, &key->dst,
1184 clib_net_to_host_u16 (key->dst_port));
1185 s = format (s, "%-40v%-30v", str, app_name);
1186 }
1187 else
1188 {
1189 app_name = application_name_from_index (kvp->value);
1190 str = format (0, "[%s] %U:%d", proto, format_ip4_address,
1191 &key->src, clib_net_to_host_u16 (key->src_port));
1192 s = format (s, "%-30v%-30v", str, app_name);
1193 }
1194 vec_free (app_name);
1195 return s;
1196}
1197
1198typedef struct _ip4_session_table_show_ctx_t
1199{
1200 vlib_main_t *vm;
1201 u8 is_local;
1202} ip4_session_table_show_ctx_t;
1203
1204static int
1205ip4_session_table_show (clib_bihash_kv_16_8_t * kvp, void *arg)
1206{
1207 ip4_session_table_show_ctx_t *ctx = arg;
1208 vlib_cli_output (ctx->vm, "%U", format_ip4_session_lookup_kvp, kvp,
1209 ctx->is_local);
1210 return 1;
1211}
1212
1213void
1214session_lookup_show_table_entries (vlib_main_t * vm, session_table_t * table,
1215 u8 type, u8 is_local)
1216{
1217 ip4_session_table_show_ctx_t ctx = {
1218 .vm = vm,
1219 .is_local = is_local,
1220 };
1221 if (!is_local)
1222 vlib_cli_output (vm, "%-40s%-30s", "Session", "Application");
1223 else
1224 vlib_cli_output (vm, "%-30s%-30s", "Listener", "Application");
1225 switch (type)
1226 {
1227 /* main table v4 */
1228 case 0:
1229 ip4_session_table_walk (&table->v4_session_hash, ip4_session_table_show,
1230 &ctx);
1231 break;
1232 default:
1233 clib_warning ("not supported");
1234 }
1235}
Florin Coras66b11312017-07-31 17:18:03 -07001236
Florin Coras1c710452017-10-17 00:03:13 -07001237static clib_error_t *
1238session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
1239 vlib_cli_command_t * cmd)
1240{
Florin Corasc97a7392017-11-05 23:07:07 -08001241 u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen = 0, rmt_plen = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001242 u32 appns_index, scope = 0;
1243 ip46_address_t lcl_ip, rmt_ip;
1244 u8 is_ip4 = 1, conn_set = 0;
1245 u8 fib_proto, is_add = 1, *ns_id = 0;
Florin Corasc97a7392017-11-05 23:07:07 -08001246 u8 *tag = 0;
Florin Coras1c710452017-10-17 00:03:13 -07001247 app_namespace_t *app_ns;
Florin Corasc97a7392017-11-05 23:07:07 -08001248 clib_error_t *error;
Florin Coras1c710452017-10-17 00:03:13 -07001249
1250 memset (&lcl_ip, 0, sizeof (lcl_ip));
1251 memset (&rmt_ip, 0, sizeof (rmt_ip));
1252 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1253 {
1254 if (unformat (input, "del"))
1255 is_add = 0;
1256 else if (unformat (input, "add"))
1257 ;
1258 else if (unformat (input, "appns %_%v%_", &ns_id))
1259 ;
1260 else if (unformat (input, "scope global"))
1261 scope = SESSION_RULE_SCOPE_GLOBAL;
1262 else if (unformat (input, "scope local"))
1263 scope = SESSION_RULE_SCOPE_LOCAL;
1264 else if (unformat (input, "scope all"))
1265 scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL;
1266 else if (unformat (input, "proto %U", unformat_transport_proto, &proto))
1267 ;
1268 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1269 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1270 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1271 &rmt_port))
1272 {
1273 is_ip4 = 1;
1274 conn_set = 1;
1275 }
1276 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1277 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1278 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1279 &rmt_port))
1280 {
1281 is_ip4 = 0;
1282 conn_set = 1;
1283 }
1284 else if (unformat (input, "action %d", &action))
1285 ;
Florin Corasc97a7392017-11-05 23:07:07 -08001286 else if (unformat (input, "tag %_%v%_", &tag))
1287 ;
Florin Coras1c710452017-10-17 00:03:13 -07001288 else
1289 return clib_error_return (0, "unknown input `%U'",
1290 format_unformat_error, input);
1291 }
1292
Florin Corasc97a7392017-11-05 23:07:07 -08001293 if (proto == ~0)
1294 {
1295 vlib_cli_output (vm, "proto must be set");
1296 return 0;
1297 }
1298 if (is_add && !conn_set && action == ~0)
1299 {
1300 vlib_cli_output (vm, "connection and action must be set for add");
1301 return 0;
1302 }
1303 if (!is_add && !tag && !conn_set)
1304 {
1305 vlib_cli_output (vm, "connection or tag must be set for delete");
1306 return 0;
1307 }
1308 if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN)
1309 {
1310 vlib_cli_output (vm, "tag too long (max u64)");
1311 return 0;
1312 }
Florin Coras1c710452017-10-17 00:03:13 -07001313
1314 if (ns_id)
1315 {
1316 app_ns = app_namespace_get_from_id (ns_id);
1317 if (!app_ns)
Florin Corasc97a7392017-11-05 23:07:07 -08001318 {
1319 vlib_cli_output (vm, "namespace %v does not exist", ns_id);
1320 return 0;
1321 }
Florin Coras1c710452017-10-17 00:03:13 -07001322 }
1323 else
1324 {
1325 app_ns = app_namespace_get_default ();
1326 }
1327 appns_index = app_namespace_index (app_ns);
1328
1329 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1330 session_rule_add_del_args_t args = {
1331 .table_args.lcl.fp_addr = lcl_ip,
1332 .table_args.lcl.fp_len = lcl_plen,
1333 .table_args.lcl.fp_proto = fib_proto,
1334 .table_args.rmt.fp_addr = rmt_ip,
1335 .table_args.rmt.fp_len = rmt_plen,
1336 .table_args.rmt.fp_proto = fib_proto,
1337 .table_args.lcl_port = lcl_port,
1338 .table_args.rmt_port = rmt_port,
1339 .table_args.action_index = action,
1340 .table_args.is_add = is_add,
Florin Corasc97a7392017-11-05 23:07:07 -08001341 .table_args.tag = tag,
Florin Coras1c710452017-10-17 00:03:13 -07001342 .appns_index = appns_index,
1343 .scope = scope,
1344 };
Florin Corasc97a7392017-11-05 23:07:07 -08001345 error = vnet_session_rule_add_del (&args);
1346 vec_free (tag);
1347 return error;
Florin Coras1c710452017-10-17 00:03:13 -07001348}
1349
1350/* *INDENT-OFF* */
1351VLIB_CLI_COMMAND (session_rule_command, static) =
1352{
1353 .path = "session rule",
1354 .short_help = "session rule [add|del] appns <ns_id> proto <proto> "
1355 "<lcl-ip/plen> <lcl-port> <rmt-ip/plen> <rmt-port> action <action>",
1356 .function = session_rule_command_fn,
1357};
1358/* *INDENT-ON* */
1359
Florin Coras7999e832017-10-31 01:51:04 -07001360void
1361session_lookup_dump_rules_table (u32 fib_index, u8 fib_proto,
1362 u8 transport_proto)
1363{
1364 vlib_main_t *vm = vlib_get_main ();
Florin Corasc97a7392017-11-05 23:07:07 -08001365 session_rules_table_t *srt;
Florin Coras7999e832017-10-31 01:51:04 -07001366 session_table_t *st;
1367 st = session_table_get_for_fib_index (fib_index, fib_proto);
Florin Corasc97a7392017-11-05 23:07:07 -08001368 srt = &st->session_rules[transport_proto];
1369 session_rules_table_cli_dump (vm, srt, fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001370}
1371
1372void
1373session_lookup_dump_local_rules_table (u32 table_index, u8 fib_proto,
1374 u8 transport_proto)
1375{
1376 vlib_main_t *vm = vlib_get_main ();
Florin Corasc97a7392017-11-05 23:07:07 -08001377 session_rules_table_t *srt;
Florin Coras7999e832017-10-31 01:51:04 -07001378 session_table_t *st;
1379 st = session_table_get (table_index);
Florin Corasc97a7392017-11-05 23:07:07 -08001380 srt = &st->session_rules[transport_proto];
1381 session_rules_table_cli_dump (vm, srt, fib_proto);
Florin Coras7999e832017-10-31 01:51:04 -07001382}
1383
Florin Coras1c710452017-10-17 00:03:13 -07001384static clib_error_t *
1385show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input,
1386 vlib_cli_command_t * cmd)
1387{
1388 u32 transport_proto = ~0, lcl_port, rmt_port, lcl_plen, rmt_plen;
1389 u32 fib_index, scope = 0;
1390 ip46_address_t lcl_ip, rmt_ip;
1391 u8 is_ip4 = 1, show_one = 0;
1392 app_namespace_t *app_ns;
Florin Corasc97a7392017-11-05 23:07:07 -08001393 session_rules_table_t *srt;
Florin Coras1c710452017-10-17 00:03:13 -07001394 session_table_t *st;
1395 u8 *ns_id = 0, fib_proto;
1396
1397 memset (&lcl_ip, 0, sizeof (lcl_ip));
1398 memset (&rmt_ip, 0, sizeof (rmt_ip));
1399 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1400 {
1401 if (unformat (input, "%U", unformat_transport_proto, &transport_proto))
1402 ;
1403 else if (unformat (input, "appns %_%v%_", &ns_id))
1404 ;
1405 else if (unformat (input, "scope global"))
1406 scope = 1;
1407 else if (unformat (input, "scope local"))
1408 scope = 2;
1409 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip4_address,
1410 &lcl_ip.ip4, &lcl_plen, &lcl_port,
1411 unformat_ip4_address, &rmt_ip.ip4, &rmt_plen,
1412 &rmt_port))
1413 {
1414 is_ip4 = 1;
1415 show_one = 1;
1416 }
1417 else if (unformat (input, "%U/%d %d %U/%d %d", unformat_ip6_address,
1418 &lcl_ip.ip6, &lcl_plen, &lcl_port,
1419 unformat_ip6_address, &rmt_ip.ip6, &rmt_plen,
1420 &rmt_port))
1421 {
1422 is_ip4 = 0;
1423 show_one = 1;
1424 }
1425 else
1426 return clib_error_return (0, "unknown input `%U'",
1427 format_unformat_error, input);
1428 }
1429
1430 if (transport_proto == ~0)
1431 {
1432 vlib_cli_output (vm, "transport proto must be set");
1433 return 0;
1434 }
1435
1436 if (ns_id)
1437 {
1438 app_ns = app_namespace_get_from_id (ns_id);
1439 if (!app_ns)
1440 {
1441 vlib_cli_output (vm, "appns %v doesn't exist", ns_id);
1442 return 0;
1443 }
1444 }
1445 else
1446 {
1447 app_ns = app_namespace_get_default ();
1448 }
1449
1450 if (scope == 1 || scope == 0)
1451 {
1452 fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
1453 fib_index = is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
1454 st = session_table_get_for_fib_index (fib_proto, fib_index);
1455 }
1456 else
1457 {
1458 st = app_namespace_get_local_table (app_ns);
1459 }
1460
1461 if (show_one)
1462 {
Florin Corasc97a7392017-11-05 23:07:07 -08001463 srt = &st->session_rules[transport_proto];
1464 session_rules_table_show_rule (vm, srt, &lcl_ip, lcl_port, &rmt_ip,
1465 rmt_port, is_ip4);
Florin Coras1c710452017-10-17 00:03:13 -07001466 return 0;
1467 }
1468
Florin Corasc97a7392017-11-05 23:07:07 -08001469 vlib_cli_output (vm, "%U rules table", format_transport_proto,
1470 transport_proto);
1471 srt = &st->session_rules[transport_proto];
1472 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4);
1473 session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP6);
Florin Coras1c710452017-10-17 00:03:13 -07001474
1475 vec_free (ns_id);
1476 return 0;
1477}
1478
1479/* *INDENT-OFF* */
1480VLIB_CLI_COMMAND (show_session_rules_command, static) =
1481{
1482 .path = "show session rules",
1483 .short_help = "show session rules [appns <id> proto <proto> <lcl-ip/plen>"
1484 " <lcl-port> <rmt-ip/plen> <rmt-port>]",
1485 .function = show_session_rules_command_fn,
1486};
1487/* *INDENT-ON* */
1488
Florin Coras04e53442017-07-16 17:12:15 -07001489void
1490session_lookup_init (void)
1491{
Florin Corascea194d2017-10-02 00:18:51 -07001492 /*
1493 * Allocate default table and map it to fib_index 0
1494 */
1495 session_table_t *st = session_table_alloc ();
1496 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP4], 0);
1497 fib_index_to_table_index[FIB_PROTOCOL_IP4][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001498 st->active_fib_proto = FIB_PROTOCOL_IP4;
1499 session_table_init (st, FIB_PROTOCOL_IP4);
Florin Corascea194d2017-10-02 00:18:51 -07001500 st = session_table_alloc ();
1501 vec_validate (fib_index_to_table_index[FIB_PROTOCOL_IP6], 0);
1502 fib_index_to_table_index[FIB_PROTOCOL_IP6][0] = session_table_index (st);
Florin Coras6c36f532017-11-03 18:32:34 -07001503 st->active_fib_proto = FIB_PROTOCOL_IP6;
1504 session_table_init (st, FIB_PROTOCOL_IP6);
Florin Coras04e53442017-07-16 17:12:15 -07001505}
1506
1507/*
1508 * fd.io coding-style-patch-verification: ON
1509 *
1510 * Local Variables:
1511 * eval: (c-set-style "gnu")
1512 * End:
1513 */