blob: 41f9dbf0c1e6054bef3ba21f526b5b2b81cf6fc8 [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>
30
31static session_lookup_t session_lookup;
32extern transport_proto_vft_t *tp_vfts;
33
34/* *INDENT-OFF* */
35/* 16 octets */
36typedef CLIB_PACKED (struct {
37 union
38 {
39 struct
40 {
41 ip4_address_t src;
42 ip4_address_t dst;
43 u16 src_port;
44 u16 dst_port;
45 /* align by making this 4 octets even though its a 1-bit field
46 * NOTE: avoid key overlap with other transports that use 5 tuples for
47 * session identification.
48 */
49 u32 proto;
50 };
51 u64 as_u64[2];
52 };
53}) v4_connection_key_t;
54
55typedef CLIB_PACKED (struct {
56 union
57 {
58 struct
59 {
60 /* 48 octets */
61 ip6_address_t src;
62 ip6_address_t dst;
63 u16 src_port;
64 u16 dst_port;
65 u32 proto;
66 u64 unused;
67 };
68 u64 as_u64[6];
69 };
70}) v6_connection_key_t;
71/* *INDENT-ON* */
72
73typedef clib_bihash_kv_16_8_t session_kv4_t;
74typedef clib_bihash_kv_48_8_t session_kv6_t;
75
76always_inline void
77make_v4_ss_kv (session_kv4_t * kv, ip4_address_t * lcl, ip4_address_t * rmt,
78 u16 lcl_port, u16 rmt_port, u8 proto)
79{
80 v4_connection_key_t *key = (v4_connection_key_t *) kv->key;
81
82 key->src.as_u32 = lcl->as_u32;
83 key->dst.as_u32 = rmt->as_u32;
84 key->src_port = lcl_port;
85 key->dst_port = rmt_port;
86 key->proto = proto;
87
88 kv->value = ~0ULL;
89}
90
91always_inline void
92make_v4_listener_kv (session_kv4_t * kv, ip4_address_t * lcl, u16 lcl_port,
93 u8 proto)
94{
95 v4_connection_key_t *key = (v4_connection_key_t *) kv->key;
96
97 key->src.as_u32 = lcl->as_u32;
98 key->dst.as_u32 = 0;
99 key->src_port = lcl_port;
100 key->dst_port = 0;
101 key->proto = proto;
102
103 kv->value = ~0ULL;
104}
105
106always_inline void
107make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * t)
108{
109 return make_v4_ss_kv (kv, &t->lcl_ip.ip4, &t->rmt_ip.ip4, t->lcl_port,
Florin Coras68810622017-07-24 17:40:28 -0700110 t->rmt_port, t->transport_proto);
Florin Coras04e53442017-07-16 17:12:15 -0700111}
112
113always_inline void
114make_v6_ss_kv (session_kv6_t * kv, ip6_address_t * lcl, ip6_address_t * rmt,
115 u16 lcl_port, u16 rmt_port, u8 proto)
116{
117 v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
118
119 key->src.as_u64[0] = lcl->as_u64[0];
120 key->src.as_u64[1] = lcl->as_u64[1];
121 key->dst.as_u64[0] = rmt->as_u64[0];
122 key->dst.as_u64[1] = rmt->as_u64[1];
123 key->src_port = lcl_port;
124 key->dst_port = rmt_port;
125 key->proto = proto;
126 key->unused = 0;
127
128 kv->value = ~0ULL;
129}
130
131always_inline void
132make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port,
133 u8 proto)
134{
135 v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
136
137 key->src.as_u64[0] = lcl->as_u64[0];
138 key->src.as_u64[1] = lcl->as_u64[1];
139 key->dst.as_u64[0] = 0;
140 key->dst.as_u64[1] = 0;
141 key->src_port = lcl_port;
142 key->dst_port = 0;
143 key->proto = proto;
144 key->unused = 0;
145
146 kv->value = ~0ULL;
147}
148
149always_inline void
150make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * t)
151{
152 make_v6_ss_kv (kv, &t->lcl_ip.ip6, &t->rmt_ip.ip6, t->lcl_port,
Florin Coras68810622017-07-24 17:40:28 -0700153 t->rmt_port, t->transport_proto);
Florin Coras04e53442017-07-16 17:12:15 -0700154}
155
156/*
157 * Session lookup key; (src-ip, dst-ip, src-port, dst-port, session-type)
158 * Value: (owner thread index << 32 | session_index);
159 */
160void
161stream_session_table_add_for_tc (transport_connection_t * tc, u64 value)
162{
163 session_lookup_t *sl = &session_lookup;
164 session_kv4_t kv4;
165 session_kv6_t kv6;
166
Florin Coras68810622017-07-24 17:40:28 -0700167 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700168 {
Florin Coras04e53442017-07-16 17:12:15 -0700169 make_v4_ss_kv_from_tc (&kv4, tc);
170 kv4.value = value;
171 clib_bihash_add_del_16_8 (&sl->v4_session_hash, &kv4, 1 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700172 }
173 else
174 {
Florin Coras04e53442017-07-16 17:12:15 -0700175 make_v6_ss_kv_from_tc (&kv6, tc);
176 kv6.value = value;
177 clib_bihash_add_del_48_8 (&sl->v6_session_hash, &kv6, 1 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700178 }
179}
180
181void
182stream_session_table_add (session_manager_main_t * smm, stream_session_t * s,
183 u64 value)
184{
185 transport_connection_t *tc;
186
187 tc = tp_vfts[s->session_type].get_connection (s->connection_index,
188 s->thread_index);
189 stream_session_table_add_for_tc (tc, value);
190}
191
Florin Coras04e53442017-07-16 17:12:15 -0700192int
193stream_session_table_del_for_tc (transport_connection_t * tc)
194{
195 session_lookup_t *sl = &session_lookup;
196 session_kv4_t kv4;
197 session_kv6_t kv6;
Florin Coras68810622017-07-24 17:40:28 -0700198
199 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700200 {
Florin Coras04e53442017-07-16 17:12:15 -0700201 make_v4_ss_kv_from_tc (&kv4, tc);
202 return clib_bihash_add_del_16_8 (&sl->v4_session_hash, &kv4,
203 0 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700204 }
205 else
206 {
Florin Coras04e53442017-07-16 17:12:15 -0700207 make_v6_ss_kv_from_tc (&kv6, tc);
208 return clib_bihash_add_del_48_8 (&sl->v6_session_hash, &kv6,
209 0 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700210 }
211
212 return 0;
213}
214
215int
216stream_session_table_del (stream_session_t * s)
217{
218 transport_connection_t *ts;
219 ts = tp_vfts[s->session_type].get_connection (s->connection_index,
220 s->thread_index);
221 return stream_session_table_del_for_tc (ts);
222}
223
Florin Coras68810622017-07-24 17:40:28 -0700224
Florin Coras04e53442017-07-16 17:12:15 -0700225void
Florin Coras68810622017-07-24 17:40:28 -0700226stream_session_half_open_table_add (transport_connection_t * tc, u64 value)
Florin Coras04e53442017-07-16 17:12:15 -0700227{
228 session_lookup_t *sl = &session_lookup;
229 session_kv4_t kv4;
230 session_kv6_t kv6;
231
Florin Coras68810622017-07-24 17:40:28 -0700232 if (tc->is_ip4)
Florin Coras04e53442017-07-16 17:12:15 -0700233 {
Florin Coras68810622017-07-24 17:40:28 -0700234 make_v4_ss_kv_from_tc (&kv4, tc);
235 kv4.value = value;
236 clib_bihash_add_del_16_8 (&sl->v4_half_open_hash, &kv4,
237 1 /* is_add */ );
238 }
239 else
240 {
241 make_v6_ss_kv_from_tc (&kv6, tc);
242 kv6.value = value;
243 clib_bihash_add_del_48_8 (&sl->v6_half_open_hash, &kv6,
244 1 /* is_add */ );
245 }
246}
247
248void
249stream_session_half_open_table_del (transport_connection_t * tc)
250{
251 session_lookup_t *sl = &session_lookup;
252 session_kv4_t kv4;
253 session_kv6_t kv6;
254
255 if (tc->is_ip4)
256 {
Florin Coras04e53442017-07-16 17:12:15 -0700257 make_v4_ss_kv_from_tc (&kv4, tc);
258 clib_bihash_add_del_16_8 (&sl->v4_half_open_hash, &kv4,
259 0 /* is_add */ );
Florin Coras68810622017-07-24 17:40:28 -0700260 }
261 else
262 {
Florin Coras04e53442017-07-16 17:12:15 -0700263 make_v6_ss_kv_from_tc (&kv6, tc);
264 clib_bihash_add_del_48_8 (&sl->v6_half_open_hash, &kv6,
265 0 /* is_add */ );
Florin Coras04e53442017-07-16 17:12:15 -0700266 }
267}
268
269stream_session_t *
270stream_session_lookup_listener4 (ip4_address_t * lcl, u16 lcl_port, u8 proto)
271{
272 session_lookup_t *sl = &session_lookup;
273 session_kv4_t kv4;
274 int rv;
275
276 make_v4_listener_kv (&kv4, lcl, lcl_port, proto);
277 rv = clib_bihash_search_inline_16_8 (&sl->v4_session_hash, &kv4);
278 if (rv == 0)
279 return session_manager_get_listener (proto, (u32) kv4.value);
280
281 /* Zero out the lcl ip */
282 kv4.key[0] = 0;
283 rv = clib_bihash_search_inline_16_8 (&sl->v4_session_hash, &kv4);
284 if (rv == 0)
285 return session_manager_get_listener (proto, (u32) kv4.value);
286
287 return 0;
288}
289
290/** Looks up a session based on the 5-tuple passed as argument.
291 *
292 * First it tries to find an established session, if this fails, it tries
293 * finding a listener session if this fails, it tries a lookup with a
294 * wildcarded local source (listener bound to all interfaces)
295 */
296stream_session_t *
297stream_session_lookup4 (ip4_address_t * lcl, ip4_address_t * rmt,
298 u16 lcl_port, u16 rmt_port, u8 proto)
299{
300 session_lookup_t *sl = &session_lookup;
301 session_kv4_t kv4;
302 stream_session_t *s;
303 int rv;
304
305 /* Lookup session amongst established ones */
306 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
307 rv = clib_bihash_search_inline_16_8 (&sl->v4_session_hash, &kv4);
308 if (rv == 0)
309 return stream_session_get_from_handle (kv4.value);
310
311 /* If nothing is found, check if any listener is available */
312 if ((s = stream_session_lookup_listener4 (lcl, lcl_port, proto)))
313 return s;
314
315 /* Finally, try half-open connections */
316 rv = clib_bihash_search_inline_16_8 (&sl->v4_half_open_hash, &kv4);
317 if (rv == 0)
318 return stream_session_get_from_handle (kv4.value);
319 return 0;
320}
321
322stream_session_t *
323stream_session_lookup_listener6 (ip6_address_t * lcl, u16 lcl_port, u8 proto)
324{
325 session_lookup_t *sl = &session_lookup;
326 session_kv6_t kv6;
327 int rv;
328
329 make_v6_listener_kv (&kv6, lcl, lcl_port, proto);
330 rv = clib_bihash_search_inline_48_8 (&sl->v6_session_hash, &kv6);
331 if (rv == 0)
332 return session_manager_get_listener (proto, (u32) kv6.value);
333
334 /* Zero out the lcl ip */
335 kv6.key[0] = kv6.key[1] = 0;
336 rv = clib_bihash_search_inline_48_8 (&sl->v6_session_hash, &kv6);
337 if (rv == 0)
338 return session_manager_get_listener (proto, (u32) kv6.value);
339
340 return 0;
341}
342
343/* Looks up a session based on the 5-tuple passed as argument.
344 * First it tries to find an established session, if this fails, it tries
345 * finding a listener session if this fails, it tries a lookup with a
346 * wildcarded local source (listener bound to all interfaces) */
347stream_session_t *
348stream_session_lookup6 (ip6_address_t * lcl, ip6_address_t * rmt,
349 u16 lcl_port, u16 rmt_port, u8 proto)
350{
351 session_lookup_t *sl = &session_lookup;
352 session_kv6_t kv6;
353 stream_session_t *s;
354 int rv;
355
356 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
357 rv = clib_bihash_search_inline_48_8 (&sl->v6_session_hash, &kv6);
358 if (rv == 0)
359 return stream_session_get_from_handle (kv6.value);
360
361 /* If nothing is found, check if any listener is available */
362 if ((s = stream_session_lookup_listener6 (lcl, lcl_port, proto)))
363 return s;
364
365 /* Finally, try half-open connections */
366 rv = clib_bihash_search_inline_48_8 (&sl->v6_half_open_hash, &kv6);
367 if (rv == 0)
368 return stream_session_get_from_handle (kv6.value);
369 return 0;
370}
371
372stream_session_t *
373stream_session_lookup_listener (ip46_address_t * lcl, u16 lcl_port, u8 proto)
374{
375 switch (proto)
376 {
377 case SESSION_TYPE_IP4_UDP:
378 case SESSION_TYPE_IP4_TCP:
379 return stream_session_lookup_listener4 (&lcl->ip4, lcl_port, proto);
380 break;
381 case SESSION_TYPE_IP6_UDP:
382 case SESSION_TYPE_IP6_TCP:
383 return stream_session_lookup_listener6 (&lcl->ip6, lcl_port, proto);
384 break;
385 }
386 return 0;
387}
388
389u64
390stream_session_half_open_lookup_handle (ip46_address_t * lcl,
391 ip46_address_t * rmt, u16 lcl_port,
392 u16 rmt_port, u8 proto)
393{
394 session_lookup_t *sl = &session_lookup;
395 session_kv4_t kv4;
396 session_kv6_t kv6;
397 int rv;
398
399 switch (proto)
400 {
401 case SESSION_TYPE_IP4_UDP:
402 case SESSION_TYPE_IP4_TCP:
403 make_v4_ss_kv (&kv4, &lcl->ip4, &rmt->ip4, lcl_port, rmt_port, proto);
404 rv = clib_bihash_search_inline_16_8 (&sl->v4_half_open_hash, &kv4);
405
406 if (rv == 0)
407 return kv4.value;
408
409 return HALF_OPEN_LOOKUP_INVALID_VALUE;
410 break;
411 case SESSION_TYPE_IP6_UDP:
412 case SESSION_TYPE_IP6_TCP:
413 make_v6_ss_kv (&kv6, &lcl->ip6, &rmt->ip6, lcl_port, rmt_port, proto);
414 rv = clib_bihash_search_inline_48_8 (&sl->v6_half_open_hash, &kv6);
415
416 if (rv == 0)
417 return kv6.value;
418
419 return HALF_OPEN_LOOKUP_INVALID_VALUE;
420 break;
421 }
422 return HALF_OPEN_LOOKUP_INVALID_VALUE;
423}
424
425transport_connection_t *
426stream_session_half_open_lookup (ip46_address_t * lcl, ip46_address_t * rmt,
427 u16 lcl_port, u16 rmt_port, u8 proto)
428{
429 u64 handle;
430 handle =
431 stream_session_half_open_lookup_handle (lcl, rmt, lcl_port, rmt_port,
432 proto);
433 if (handle != HALF_OPEN_LOOKUP_INVALID_VALUE)
434 return tp_vfts[proto].get_half_open (handle & 0xFFFFFFFF);
435 return 0;
436}
437
438always_inline stream_session_t *
439stream_session_get_tsi (u64 ti_and_si, u32 thread_index)
440{
441 ASSERT ((u32) (ti_and_si >> 32) == thread_index);
442 return pool_elt_at_index (session_manager_main.sessions[thread_index],
443 ti_and_si & 0xFFFFFFFFULL);
444}
445
446transport_connection_t *
447stream_session_lookup_transport_wt4 (ip4_address_t * lcl, ip4_address_t * rmt,
448 u16 lcl_port, u16 rmt_port, u8 proto,
449 u32 my_thread_index)
450{
451 session_lookup_t *sl = &session_lookup;
452 session_kv4_t kv4;
453 stream_session_t *s;
454 int rv;
455
456 /* Lookup session amongst established ones */
457 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
458 rv = clib_bihash_search_inline_16_8 (&sl->v4_session_hash, &kv4);
459 if (rv == 0)
460 {
461 s = stream_session_get_tsi (kv4.value, my_thread_index);
462 return tp_vfts[s->session_type].get_connection (s->connection_index,
463 my_thread_index);
464 }
465
466 /* If nothing is found, check if any listener is available */
467 s = stream_session_lookup_listener4 (lcl, lcl_port, proto);
468 if (s)
469 return tp_vfts[s->session_type].get_listener (s->connection_index);
470
471 /* Finally, try half-open connections */
472 rv = clib_bihash_search_inline_16_8 (&sl->v4_half_open_hash, &kv4);
473 if (rv == 0)
474 return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
475 return 0;
476}
477
478transport_connection_t *
479stream_session_lookup_transport4 (ip4_address_t * lcl, ip4_address_t * rmt,
480 u16 lcl_port, u16 rmt_port, u8 proto)
481{
482 session_lookup_t *sl = &session_lookup;
483 session_kv4_t kv4;
484 stream_session_t *s;
485 int rv;
486
487 /* Lookup session amongst established ones */
488 make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
489 rv = clib_bihash_search_inline_16_8 (&sl->v4_session_hash, &kv4);
490 if (rv == 0)
491 {
492 s = stream_session_get_from_handle (kv4.value);
493 return tp_vfts[s->session_type].get_connection (s->connection_index,
494 s->thread_index);
495 }
496
497 /* If nothing is found, check if any listener is available */
498 s = stream_session_lookup_listener4 (lcl, lcl_port, proto);
499 if (s)
500 return tp_vfts[s->session_type].get_listener (s->connection_index);
501
502 /* Finally, try half-open connections */
503 rv = clib_bihash_search_inline_16_8 (&sl->v4_half_open_hash, &kv4);
504 if (rv == 0)
505 return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
506 return 0;
507}
508
509transport_connection_t *
510stream_session_lookup_transport_wt6 (ip6_address_t * lcl, ip6_address_t * rmt,
511 u16 lcl_port, u16 rmt_port, u8 proto,
512 u32 my_thread_index)
513{
514 session_lookup_t *sl = &session_lookup;
515 stream_session_t *s;
516 session_kv6_t kv6;
517 int rv;
518
519 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
520 rv = clib_bihash_search_inline_48_8 (&sl->v6_session_hash, &kv6);
521 if (rv == 0)
522 {
523 s = stream_session_get_tsi (kv6.value, my_thread_index);
524 return tp_vfts[s->session_type].get_connection (s->connection_index,
525 my_thread_index);
526 }
527
528 /* If nothing is found, check if any listener is available */
529 s = stream_session_lookup_listener6 (lcl, lcl_port, proto);
530 if (s)
531 return tp_vfts[s->session_type].get_listener (s->connection_index);
532
533 /* Finally, try half-open connections */
534 rv = clib_bihash_search_inline_48_8 (&sl->v6_half_open_hash, &kv6);
535 if (rv == 0)
536 return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
537
538 return 0;
539}
540
541transport_connection_t *
542stream_session_lookup_transport6 (ip6_address_t * lcl, ip6_address_t * rmt,
543 u16 lcl_port, u16 rmt_port, u8 proto)
544{
545 session_lookup_t *sl = &session_lookup;
546 stream_session_t *s;
547 session_kv6_t kv6;
548 int rv;
549
550 make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
551 rv = clib_bihash_search_inline_48_8 (&sl->v6_session_hash, &kv6);
552 if (rv == 0)
553 {
554 s = stream_session_get_from_handle (kv6.value);
555 return tp_vfts[s->session_type].get_connection (s->connection_index,
556 s->thread_index);
557 }
558
559 /* If nothing is found, check if any listener is available */
560 s = stream_session_lookup_listener6 (lcl, lcl_port, proto);
561 if (s)
562 return tp_vfts[s->session_type].get_listener (s->connection_index);
563
564 /* Finally, try half-open connections */
565 rv = clib_bihash_search_inline_48_8 (&sl->v6_half_open_hash, &kv6);
566 if (rv == 0)
567 return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
568
569 return 0;
570}
571
Florin Coras66b11312017-07-31 17:18:03 -0700572#define foreach_hash_table_parameter \
573 _(v4,session,buckets,20000) \
574 _(v4,session,memory,(64<<20)) \
575 _(v6,session,buckets,20000) \
576 _(v6,session,memory,(64<<20)) \
577 _(v4,halfopen,buckets,20000) \
578 _(v4,halfopen,memory,(64<<20)) \
579 _(v6,halfopen,buckets,20000) \
580 _(v6,halfopen,memory,(64<<20))
581
Florin Coras04e53442017-07-16 17:12:15 -0700582void
583session_lookup_init (void)
584{
585 session_lookup_t *sl = &session_lookup;
Florin Coras04e53442017-07-16 17:12:15 -0700586
Florin Coras66b11312017-07-31 17:18:03 -0700587#define _(af,table,parm,value) \
588 u32 configured_##af##_##table##_table_##parm = value;
589 foreach_hash_table_parameter;
590#undef _
591
592#define _(af,table,parm,value) \
593 if (session_manager_main.configured_##af##_##table##_table_##parm) \
594 configured_##af##_##table##_table_##parm = \
595 session_manager_main.configured_##af##_##table##_table_##parm;
596 foreach_hash_table_parameter;
597#undef _
598
599 clib_bihash_init_16_8 (&sl->v4_session_hash, "v4 session table",
600 configured_v4_session_table_buckets,
601 configured_v4_session_table_memory);
602 clib_bihash_init_48_8 (&sl->v6_session_hash, "v6 session table",
603 configured_v6_session_table_buckets,
604 configured_v6_session_table_memory);
Florin Coras04e53442017-07-16 17:12:15 -0700605 clib_bihash_init_16_8 (&sl->v4_half_open_hash, "v4 half-open table",
Florin Coras66b11312017-07-31 17:18:03 -0700606 configured_v4_halfopen_table_buckets,
607 configured_v4_halfopen_table_memory);
Florin Coras04e53442017-07-16 17:12:15 -0700608 clib_bihash_init_48_8 (&sl->v6_half_open_hash, "v6 half-open table",
Florin Coras66b11312017-07-31 17:18:03 -0700609 configured_v6_halfopen_table_buckets,
610 configured_v6_halfopen_table_memory);
Florin Coras04e53442017-07-16 17:12:15 -0700611}
612
613/*
614 * fd.io coding-style-patch-verification: ON
615 *
616 * Local Variables:
617 * eval: (c-set-style "gnu")
618 * End:
619 */