Line data Source code
1 : /*
2 : * Copyright (c) 2020 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 : #include <vnet/fib/fib_table.h>
17 : #include <nat/lib/ipfix_logging.h>
18 : #include <nat/lib/nat_syslog.h>
19 : #include <nat/lib/inlines.h>
20 : #include <nat/nat64/nat64_db.h>
21 :
22 : int
23 20 : nat64_db_init (nat64_db_t * db, nat64_config_t c,
24 : nat64_db_free_addr_port_function_t free_addr_port_cb)
25 : {
26 20 : clib_bihash_init_24_8 (&db->bib.in2out, "bib-in2out", c.bib_buckets,
27 20 : c.bib_memory_size);
28 :
29 20 : clib_bihash_init_24_8 (&db->bib.out2in, "bib-out2in", c.bib_buckets,
30 20 : c.bib_memory_size);
31 :
32 20 : clib_bihash_init_48_8 (&db->st.in2out, "st-in2out", c.st_buckets,
33 20 : c.st_memory_size);
34 :
35 20 : clib_bihash_init_48_8 (&db->st.out2in, "st-out2in", c.st_buckets,
36 20 : c.st_memory_size);
37 :
38 20 : db->free_addr_port_cb = free_addr_port_cb;
39 20 : db->bib.limit = 10 * c.bib_buckets;
40 20 : db->bib.bib_entries_num = 0;
41 20 : db->st.limit = 10 * c.st_buckets;
42 20 : db->st.st_entries_num = 0;
43 20 : db->addr_free = 0;
44 :
45 20 : return 0;
46 : }
47 :
48 : int
49 20 : nat64_db_free (nat64_db_t * db)
50 : {
51 20 : clib_bihash_free_24_8 (&db->bib.in2out);
52 20 : clib_bihash_free_24_8 (&db->bib.out2in);
53 :
54 20 : clib_bihash_free_48_8 (&db->st.in2out);
55 20 : clib_bihash_free_48_8 (&db->st.out2in);
56 :
57 : /* *INDENT-OFF* */
58 : #define _(N, i, n, s) \
59 : pool_free (db->bib._##n##_bib); \
60 : pool_free (db->st._##n##_st);
61 20 : foreach_nat_protocol
62 : #undef _
63 : /* *INDENT-ON* */
64 :
65 20 : pool_free (db->bib._unk_proto_bib);
66 20 : pool_free (db->st._unk_proto_st);
67 :
68 20 : return 0;
69 : }
70 :
71 : nat64_db_bib_entry_t *
72 39 : nat64_db_bib_entry_create (u32 thread_index, nat64_db_t * db,
73 : ip6_address_t * in_addr,
74 : ip4_address_t * out_addr, u16 in_port,
75 : u16 out_port, u32 fib_index, u8 proto,
76 : u8 is_static)
77 : {
78 : nat64_db_bib_entry_t *bibe;
79 : nat64_db_bib_entry_key_t bibe_key;
80 : clib_bihash_kv_24_8_t kv;
81 :
82 39 : if (db->bib.bib_entries_num >= db->bib.limit)
83 : {
84 0 : db->free_addr_port_cb (db, out_addr, out_port, proto);
85 0 : nat_ipfix_logging_max_bibs (thread_index, db->bib.limit);
86 0 : return 0;
87 : }
88 :
89 : /* create pool entry */
90 39 : switch (ip_proto_to_nat_proto (proto))
91 : {
92 : /* *INDENT-OFF* */
93 : #define _(N, i, n, s) \
94 : case NAT_PROTOCOL_##N: \
95 : pool_get (db->bib._##n##_bib, bibe); \
96 : kv.value = bibe - db->bib._##n##_bib; \
97 : break;
98 39 : foreach_nat_protocol
99 : #undef _
100 : /* *INDENT-ON* */
101 0 : default:
102 0 : pool_get (db->bib._unk_proto_bib, bibe);
103 0 : kv.value = bibe - db->bib._unk_proto_bib;
104 0 : break;
105 : }
106 :
107 39 : db->bib.bib_entries_num++;
108 :
109 39 : clib_memset (bibe, 0, sizeof (*bibe));
110 39 : bibe->in_addr.as_u64[0] = in_addr->as_u64[0];
111 39 : bibe->in_addr.as_u64[1] = in_addr->as_u64[1];
112 39 : bibe->in_port = in_port;
113 39 : bibe->out_addr.as_u32 = out_addr->as_u32;
114 39 : bibe->out_port = out_port;
115 39 : bibe->fib_index = fib_index;
116 39 : bibe->proto = proto;
117 39 : bibe->is_static = is_static;
118 :
119 : /* create hash lookup */
120 39 : bibe_key.addr.as_u64[0] = bibe->in_addr.as_u64[0];
121 39 : bibe_key.addr.as_u64[1] = bibe->in_addr.as_u64[1];
122 39 : bibe_key.fib_index = bibe->fib_index;
123 39 : bibe_key.port = bibe->in_port;
124 39 : bibe_key.proto = bibe->proto;
125 39 : bibe_key.rsvd = 0;
126 39 : kv.key[0] = bibe_key.as_u64[0];
127 39 : kv.key[1] = bibe_key.as_u64[1];
128 39 : kv.key[2] = bibe_key.as_u64[2];
129 39 : clib_bihash_add_del_24_8 (&db->bib.in2out, &kv, 1);
130 :
131 39 : clib_memset (&bibe_key.addr, 0, sizeof (bibe_key.addr));
132 39 : bibe_key.addr.ip4.as_u32 = bibe->out_addr.as_u32;
133 39 : bibe_key.fib_index = 0;
134 39 : bibe_key.port = bibe->out_port;
135 39 : kv.key[0] = bibe_key.as_u64[0];
136 39 : kv.key[1] = bibe_key.as_u64[1];
137 39 : kv.key[2] = bibe_key.as_u64[2];
138 39 : clib_bihash_add_del_24_8 (&db->bib.out2in, &kv, 1);
139 :
140 39 : fib_table_t *fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
141 39 : nat_ipfix_logging_nat64_bib (thread_index, in_addr, out_addr, proto,
142 : in_port, out_port, fib->ft_table_id, 1);
143 39 : return bibe;
144 : }
145 :
146 : void
147 5 : nat64_db_bib_entry_free (u32 thread_index, nat64_db_t * db,
148 : nat64_db_bib_entry_t * bibe)
149 : {
150 : nat64_db_bib_entry_key_t bibe_key;
151 : clib_bihash_kv_24_8_t kv;
152 : nat64_db_bib_entry_t *bib;
153 5 : u32 *ste_to_be_free = 0, *ste_index, bibe_index;
154 : nat64_db_st_entry_t *st, *ste;
155 :
156 5 : switch (ip_proto_to_nat_proto (bibe->proto))
157 : {
158 : /* *INDENT-OFF* */
159 : #define _(N, i, n, s) \
160 : case NAT_PROTOCOL_##N: \
161 : bib = db->bib._##n##_bib; \
162 : st = db->st._##n##_st; \
163 : break;
164 5 : foreach_nat_protocol
165 : #undef _
166 : /* *INDENT-ON* */
167 0 : default:
168 0 : bib = db->bib._unk_proto_bib;
169 0 : st = db->st._unk_proto_st;
170 0 : break;
171 : }
172 :
173 5 : db->bib.bib_entries_num--;
174 :
175 5 : bibe_index = bibe - bib;
176 :
177 : /* delete ST entries for static BIB entry */
178 5 : if (bibe->is_static)
179 : {
180 1 : pool_foreach (ste, st)
181 : {
182 0 : if (ste->bibe_index == bibe_index)
183 0 : vec_add1 (ste_to_be_free, ste - st);
184 : }
185 1 : vec_foreach (ste_index, ste_to_be_free)
186 0 : nat64_db_st_entry_free (thread_index, db,
187 0 : pool_elt_at_index (st, ste_index[0]));
188 1 : vec_free (ste_to_be_free);
189 : }
190 :
191 : /* delete hash lookup */
192 5 : bibe_key.addr.as_u64[0] = bibe->in_addr.as_u64[0];
193 5 : bibe_key.addr.as_u64[1] = bibe->in_addr.as_u64[1];
194 5 : bibe_key.fib_index = bibe->fib_index;
195 5 : bibe_key.port = bibe->in_port;
196 5 : bibe_key.proto = bibe->proto;
197 5 : bibe_key.rsvd = 0;
198 5 : kv.key[0] = bibe_key.as_u64[0];
199 5 : kv.key[1] = bibe_key.as_u64[1];
200 5 : kv.key[2] = bibe_key.as_u64[2];
201 5 : clib_bihash_add_del_24_8 (&db->bib.in2out, &kv, 0);
202 :
203 5 : clib_memset (&bibe_key.addr, 0, sizeof (bibe_key.addr));
204 5 : bibe_key.addr.ip4.as_u32 = bibe->out_addr.as_u32;
205 5 : bibe_key.fib_index = 0;
206 5 : bibe_key.port = bibe->out_port;
207 5 : kv.key[0] = bibe_key.as_u64[0];
208 5 : kv.key[1] = bibe_key.as_u64[1];
209 5 : kv.key[2] = bibe_key.as_u64[2];
210 5 : clib_bihash_add_del_24_8 (&db->bib.out2in, &kv, 0);
211 :
212 5 : if (!db->addr_free)
213 3 : db->free_addr_port_cb (db, &bibe->out_addr, bibe->out_port, bibe->proto);
214 :
215 5 : fib_table_t *fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
216 5 : nat_ipfix_logging_nat64_bib (thread_index, &bibe->in_addr, &bibe->out_addr,
217 5 : bibe->proto, bibe->in_port, bibe->out_port,
218 : fib->ft_table_id, 0);
219 :
220 : /* delete from pool */
221 5 : pool_put (bib, bibe);
222 5 : }
223 :
224 : nat64_db_bib_entry_t *
225 60 : nat64_db_bib_entry_find (nat64_db_t * db, ip46_address_t * addr, u16 port,
226 : u8 proto, u32 fib_index, u8 is_ip6)
227 : {
228 60 : nat64_db_bib_entry_t *bibe = 0;
229 : nat64_db_bib_entry_key_t bibe_key;
230 : clib_bihash_kv_24_8_t kv, value;
231 : nat64_db_bib_entry_t *bib;
232 :
233 60 : switch (ip_proto_to_nat_proto (proto))
234 : {
235 : /* *INDENT-OFF* */
236 : #define _(N, i, n, s) \
237 : case NAT_PROTOCOL_##N: \
238 : bib = db->bib._##n##_bib; \
239 : break;
240 60 : foreach_nat_protocol
241 : #undef _
242 : /* *INDENT-ON* */
243 0 : default:
244 0 : bib = db->bib._unk_proto_bib;
245 0 : break;
246 : }
247 :
248 60 : bibe_key.addr.as_u64[0] = addr->as_u64[0];
249 60 : bibe_key.addr.as_u64[1] = addr->as_u64[1];
250 60 : bibe_key.fib_index = fib_index;
251 60 : bibe_key.port = port;
252 60 : bibe_key.proto = proto;
253 60 : bibe_key.rsvd = 0;
254 :
255 60 : kv.key[0] = bibe_key.as_u64[0];
256 60 : kv.key[1] = bibe_key.as_u64[1];
257 60 : kv.key[2] = bibe_key.as_u64[2];
258 :
259 60 : if (!clib_bihash_search_24_8
260 : (is_ip6 ? &db->bib.in2out : &db->bib.out2in, &kv, &value))
261 19 : bibe = pool_elt_at_index (bib, value.value);
262 :
263 60 : return bibe;
264 : }
265 :
266 : void
267 22 : nat64_db_bib_walk (nat64_db_t * db, u8 proto,
268 : nat64_db_bib_walk_fn_t fn, void *ctx)
269 : {
270 : nat64_db_bib_entry_t *bib, *bibe;
271 :
272 22 : if (proto == 255)
273 : {
274 : /* *INDENT-OFF* */
275 : #define _(N, i, n, s) \
276 : bib = db->bib._##n##_bib; \
277 : pool_foreach (bibe, bib) { \
278 : if (fn (bibe, ctx)) \
279 : return; \
280 : }
281 54 : foreach_nat_protocol
282 : #undef _
283 20 : bib = db->bib._unk_proto_bib;
284 20 : pool_foreach (bibe, bib) {
285 0 : if (fn (bibe, ctx))
286 0 : return;
287 : }
288 : /* *INDENT-ON* */
289 : }
290 : else
291 : {
292 2 : switch (ip_proto_to_nat_proto (proto))
293 : {
294 : /* *INDENT-OFF* */
295 : #define _(N, i, n, s) \
296 : case NAT_PROTOCOL_##N: \
297 : bib = db->bib._##n##_bib; \
298 : break;
299 2 : foreach_nat_protocol
300 : #undef _
301 : /* *INDENT-ON* */
302 0 : default:
303 0 : bib = db->bib._unk_proto_bib;
304 0 : break;
305 : }
306 :
307 : /* *INDENT-OFF* */
308 3 : pool_foreach (bibe, bib)
309 : {
310 1 : if (fn (bibe, ctx))
311 0 : return;
312 : }
313 : /* *INDENT-ON* */
314 : }
315 : }
316 :
317 : nat64_db_bib_entry_t *
318 103 : nat64_db_bib_entry_by_index (nat64_db_t * db, u8 proto, u32 bibe_index)
319 : {
320 : nat64_db_bib_entry_t *bib;
321 :
322 103 : switch (ip_proto_to_nat_proto (proto))
323 : {
324 : /* *INDENT-OFF* */
325 : #define _(N, i, n, s) \
326 : case NAT_PROTOCOL_##N: \
327 : bib = db->bib._##n##_bib; \
328 : break;
329 103 : foreach_nat_protocol
330 : #undef _
331 : /* *INDENT-ON* */
332 0 : default:
333 0 : bib = db->bib._unk_proto_bib;
334 0 : break;
335 : }
336 :
337 103 : return pool_elt_at_index (bib, bibe_index);
338 : }
339 :
340 : void
341 28 : nat64_db_st_walk (nat64_db_t * db, u8 proto,
342 : nat64_db_st_walk_fn_t fn, void *ctx)
343 : {
344 : nat64_db_st_entry_t *st, *ste;
345 :
346 28 : if (proto == 255)
347 : {
348 : /* *INDENT-OFF* */
349 : #define _(N, i, n, s) \
350 : st = db->st._##n##_st; \
351 : pool_foreach (ste, st) { \
352 : if (fn (ste, ctx)) \
353 : return; \
354 : }
355 68 : foreach_nat_protocol
356 : #undef _
357 26 : st = db->st._unk_proto_st;
358 26 : pool_foreach (ste, st) {
359 0 : if (fn (ste, ctx))
360 0 : return;
361 : }
362 : /* *INDENT-ON* */
363 : }
364 : else
365 : {
366 2 : switch (ip_proto_to_nat_proto (proto))
367 : {
368 : /* *INDENT-OFF* */
369 : #define _(N, i, n, s) \
370 : case NAT_PROTOCOL_##N: \
371 : st = db->st._##n##_st; \
372 : break;
373 2 : foreach_nat_protocol
374 : #undef _
375 : /* *INDENT-ON* */
376 0 : default:
377 0 : st = db->st._unk_proto_st;
378 0 : break;
379 : }
380 :
381 : /* *INDENT-OFF* */
382 2 : pool_foreach (ste, st)
383 : {
384 2 : if (fn (ste, ctx))
385 2 : return;
386 : }
387 : /* *INDENT-ON* */
388 : }
389 : }
390 :
391 : nat64_db_st_entry_t *
392 36 : nat64_db_st_entry_create (u32 thread_index, nat64_db_t * db,
393 : nat64_db_bib_entry_t * bibe,
394 : ip6_address_t * in_r_addr,
395 : ip4_address_t * out_r_addr, u16 r_port)
396 : {
397 : nat64_db_st_entry_t *ste;
398 : nat64_db_bib_entry_t *bib;
399 : nat64_db_st_entry_key_t ste_key;
400 : clib_bihash_kv_48_8_t kv;
401 :
402 36 : if (db->st.st_entries_num >= db->st.limit)
403 : {
404 0 : nat_ipfix_logging_max_sessions (thread_index, db->st.limit);
405 0 : return 0;
406 : }
407 :
408 : /* create pool entry */
409 36 : switch (ip_proto_to_nat_proto (bibe->proto))
410 : {
411 : /* *INDENT-OFF* */
412 : #define _(N, i, n, s) \
413 : case NAT_PROTOCOL_##N: \
414 : pool_get (db->st._##n##_st, ste); \
415 : kv.value = ste - db->st._##n##_st; \
416 : bib = db->bib._##n##_bib; \
417 : break;
418 36 : foreach_nat_protocol
419 : #undef _
420 : /* *INDENT-ON* */
421 0 : default:
422 0 : pool_get (db->st._unk_proto_st, ste);
423 0 : kv.value = ste - db->st._unk_proto_st;
424 0 : bib = db->bib._unk_proto_bib;
425 0 : break;
426 : }
427 :
428 36 : db->st.st_entries_num++;
429 :
430 36 : clib_memset (ste, 0, sizeof (*ste));
431 36 : ste->in_r_addr.as_u64[0] = in_r_addr->as_u64[0];
432 36 : ste->in_r_addr.as_u64[1] = in_r_addr->as_u64[1];
433 36 : ste->out_r_addr.as_u32 = out_r_addr->as_u32;
434 36 : ste->r_port = r_port;
435 36 : ste->bibe_index = bibe - bib;
436 36 : ste->proto = bibe->proto;
437 :
438 : /* increment session number for BIB entry */
439 36 : bibe->ses_num++;
440 :
441 : /* create hash lookup */
442 36 : clib_memset (&ste_key, 0, sizeof (ste_key));
443 36 : ste_key.l_addr.as_u64[0] = bibe->in_addr.as_u64[0];
444 36 : ste_key.l_addr.as_u64[1] = bibe->in_addr.as_u64[1];
445 36 : ste_key.r_addr.as_u64[0] = ste->in_r_addr.as_u64[0];
446 36 : ste_key.r_addr.as_u64[1] = ste->in_r_addr.as_u64[1];
447 36 : ste_key.fib_index = bibe->fib_index;
448 36 : ste_key.l_port = bibe->in_port;
449 36 : ste_key.r_port = ste->r_port;
450 36 : ste_key.proto = ste->proto;
451 36 : kv.key[0] = ste_key.as_u64[0];
452 36 : kv.key[1] = ste_key.as_u64[1];
453 36 : kv.key[2] = ste_key.as_u64[2];
454 36 : kv.key[3] = ste_key.as_u64[3];
455 36 : kv.key[4] = ste_key.as_u64[4];
456 36 : kv.key[5] = ste_key.as_u64[5];
457 36 : clib_bihash_add_del_48_8 (&db->st.in2out, &kv, 1);
458 :
459 36 : clib_memset (&ste_key, 0, sizeof (ste_key));
460 36 : ste_key.l_addr.ip4.as_u32 = bibe->out_addr.as_u32;
461 36 : ste_key.r_addr.ip4.as_u32 = ste->out_r_addr.as_u32;
462 36 : ste_key.l_port = bibe->out_port;
463 36 : ste_key.r_port = ste->r_port;
464 36 : ste_key.proto = ste->proto;
465 36 : kv.key[0] = ste_key.as_u64[0];
466 36 : kv.key[1] = ste_key.as_u64[1];
467 36 : kv.key[2] = ste_key.as_u64[2];
468 36 : kv.key[3] = ste_key.as_u64[3];
469 36 : kv.key[4] = ste_key.as_u64[4];
470 36 : kv.key[5] = ste_key.as_u64[5];
471 36 : clib_bihash_add_del_48_8 (&db->st.out2in, &kv, 1);
472 :
473 36 : fib_table_t *fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
474 36 : nat_ipfix_logging_nat64_session (thread_index, &bibe->in_addr,
475 36 : &bibe->out_addr, bibe->proto,
476 36 : bibe->in_port, bibe->out_port,
477 36 : &ste->in_r_addr, &ste->out_r_addr,
478 36 : ste->r_port, ste->r_port, fib->ft_table_id,
479 : 1);
480 36 : nat_syslog_nat64_sadd (bibe->fib_index, &bibe->in_addr, bibe->in_port,
481 36 : &bibe->out_addr, bibe->out_port, &ste->out_r_addr,
482 36 : ste->r_port, bibe->proto);
483 36 : return ste;
484 : }
485 :
486 : void
487 4 : nat64_db_st_entry_free (u32 thread_index,
488 : nat64_db_t * db, nat64_db_st_entry_t * ste)
489 : {
490 : nat64_db_st_entry_t *st;
491 : nat64_db_bib_entry_t *bib, *bibe;
492 : nat64_db_st_entry_key_t ste_key;
493 : clib_bihash_kv_48_8_t kv;
494 :
495 4 : switch (ip_proto_to_nat_proto (ste->proto))
496 : {
497 : /* *INDENT-OFF* */
498 : #define _(N, i, n, s) \
499 : case NAT_PROTOCOL_##N: \
500 : st = db->st._##n##_st; \
501 : bib = db->bib._##n##_bib; \
502 : break;
503 4 : foreach_nat_protocol
504 : #undef _
505 : /* *INDENT-ON* */
506 0 : default:
507 0 : st = db->st._unk_proto_st;
508 0 : bib = db->bib._unk_proto_bib;
509 0 : break;
510 : }
511 :
512 4 : bibe = pool_elt_at_index (bib, ste->bibe_index);
513 :
514 4 : db->st.st_entries_num--;
515 :
516 : /* delete hash lookup */
517 4 : clib_memset (&ste_key, 0, sizeof (ste_key));
518 4 : ste_key.l_addr.as_u64[0] = bibe->in_addr.as_u64[0];
519 4 : ste_key.l_addr.as_u64[1] = bibe->in_addr.as_u64[1];
520 4 : ste_key.r_addr.as_u64[0] = ste->in_r_addr.as_u64[0];
521 4 : ste_key.r_addr.as_u64[1] = ste->in_r_addr.as_u64[1];
522 4 : ste_key.fib_index = bibe->fib_index;
523 4 : ste_key.l_port = bibe->in_port;
524 4 : ste_key.r_port = ste->r_port;
525 4 : ste_key.proto = ste->proto;
526 4 : kv.key[0] = ste_key.as_u64[0];
527 4 : kv.key[1] = ste_key.as_u64[1];
528 4 : kv.key[2] = ste_key.as_u64[2];
529 4 : kv.key[3] = ste_key.as_u64[3];
530 4 : kv.key[4] = ste_key.as_u64[4];
531 4 : kv.key[5] = ste_key.as_u64[5];
532 4 : clib_bihash_add_del_48_8 (&db->st.in2out, &kv, 0);
533 :
534 4 : clib_memset (&ste_key, 0, sizeof (ste_key));
535 4 : ste_key.l_addr.ip4.as_u32 = bibe->out_addr.as_u32;
536 4 : ste_key.r_addr.ip4.as_u32 = ste->out_r_addr.as_u32;
537 4 : ste_key.l_port = bibe->out_port;
538 4 : ste_key.r_port = ste->r_port;
539 4 : ste_key.proto = ste->proto;
540 4 : kv.key[0] = ste_key.as_u64[0];
541 4 : kv.key[1] = ste_key.as_u64[1];
542 4 : kv.key[2] = ste_key.as_u64[2];
543 4 : kv.key[3] = ste_key.as_u64[3];
544 4 : kv.key[4] = ste_key.as_u64[4];
545 4 : kv.key[5] = ste_key.as_u64[5];
546 4 : clib_bihash_add_del_48_8 (&db->st.out2in, &kv, 0);
547 :
548 4 : fib_table_t *fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
549 4 : nat_ipfix_logging_nat64_session (thread_index, &bibe->in_addr,
550 4 : &bibe->out_addr, bibe->proto,
551 4 : bibe->in_port, bibe->out_port,
552 : &ste->in_r_addr, &ste->out_r_addr,
553 4 : ste->r_port, ste->r_port, fib->ft_table_id,
554 : 0);
555 4 : nat_syslog_nat64_sdel (bibe->fib_index, &bibe->in_addr, bibe->in_port,
556 4 : &bibe->out_addr, bibe->out_port, &ste->out_r_addr,
557 4 : ste->r_port, bibe->proto);
558 :
559 : /* delete from pool */
560 4 : pool_put (st, ste);
561 :
562 : /* decrement session number for BIB entry */
563 4 : bibe->ses_num--;
564 :
565 : /* delete BIB entry if last session and dynamic */
566 4 : if (!bibe->is_static && !bibe->ses_num)
567 4 : nat64_db_bib_entry_free (thread_index, db, bibe);
568 4 : }
569 :
570 : nat64_db_st_entry_t *
571 97 : nat64_db_st_entry_find (nat64_db_t * db, ip46_address_t * l_addr,
572 : ip46_address_t * r_addr, u16 l_port, u16 r_port,
573 : u8 proto, u32 fib_index, u8 is_ip6)
574 : {
575 97 : nat64_db_st_entry_t *ste = 0;
576 : nat64_db_st_entry_t *st;
577 : nat64_db_st_entry_key_t ste_key;
578 : clib_bihash_kv_48_8_t kv, value;
579 :
580 97 : switch (ip_proto_to_nat_proto (proto))
581 : {
582 : /* *INDENT-OFF* */
583 : #define _(N, i, n, s) \
584 : case NAT_PROTOCOL_##N: \
585 : st = db->st._##n##_st; \
586 : break;
587 97 : foreach_nat_protocol
588 : #undef _
589 : /* *INDENT-ON* */
590 0 : default:
591 0 : st = db->st._unk_proto_st;
592 0 : break;
593 : }
594 :
595 97 : clib_memset (&ste_key, 0, sizeof (ste_key));
596 97 : ste_key.l_addr.as_u64[0] = l_addr->as_u64[0];
597 97 : ste_key.l_addr.as_u64[1] = l_addr->as_u64[1];
598 97 : ste_key.r_addr.as_u64[0] = r_addr->as_u64[0];
599 97 : ste_key.r_addr.as_u64[1] = r_addr->as_u64[1];
600 97 : ste_key.fib_index = fib_index;
601 97 : ste_key.l_port = l_port;
602 97 : ste_key.r_port = r_port;
603 97 : ste_key.proto = proto;
604 97 : kv.key[0] = ste_key.as_u64[0];
605 97 : kv.key[1] = ste_key.as_u64[1];
606 97 : kv.key[2] = ste_key.as_u64[2];
607 97 : kv.key[3] = ste_key.as_u64[3];
608 97 : kv.key[4] = ste_key.as_u64[4];
609 97 : kv.key[5] = ste_key.as_u64[5];
610 :
611 97 : if (!clib_bihash_search_48_8
612 : (is_ip6 ? &db->st.in2out : &db->st.out2in, &kv, &value))
613 59 : ste = pool_elt_at_index (st, value.value);
614 :
615 97 : return ste;
616 : }
617 :
618 : u32
619 0 : nat64_db_st_entry_get_index (nat64_db_t * db, nat64_db_st_entry_t * ste)
620 : {
621 : nat64_db_st_entry_t *st;
622 :
623 0 : switch (ip_proto_to_nat_proto (ste->proto))
624 : {
625 : /* *INDENT-OFF* */
626 : #define _(N, i, n, s) \
627 : case NAT_PROTOCOL_##N: \
628 : st = db->st._##n##_st; \
629 : break;
630 0 : foreach_nat_protocol
631 : #undef _
632 : /* *INDENT-ON* */
633 0 : default:
634 0 : st = db->st._unk_proto_st;
635 0 : return (u32) ~ 0;
636 : }
637 :
638 0 : return ste - st;
639 : }
640 :
641 : nat64_db_st_entry_t *
642 0 : nat64_db_st_entry_by_index (nat64_db_t * db, u8 proto, u32 ste_index)
643 : {
644 : nat64_db_st_entry_t *st;
645 :
646 0 : switch (ip_proto_to_nat_proto (proto))
647 : {
648 : /* *INDENT-OFF* */
649 : #define _(N, i, n, s) \
650 : case NAT_PROTOCOL_##N: \
651 : st = db->st._##n##_st; \
652 : break;
653 0 : foreach_nat_protocol
654 : #undef _
655 : /* *INDENT-ON* */
656 0 : default:
657 0 : st = db->st._unk_proto_st;
658 0 : break;
659 : }
660 :
661 0 : return pool_elt_at_index (st, ste_index);
662 : }
663 :
664 : void
665 34 : nad64_db_st_free_expired (u32 thread_index, nat64_db_t * db, u32 now)
666 : {
667 34 : u32 *ste_to_be_free = 0, *ste_index;
668 : nat64_db_st_entry_t *st, *ste;
669 :
670 : /* *INDENT-OFF* */
671 : #define _(N, i, n, s) \
672 : st = db->st._##n##_st; \
673 : pool_foreach (ste, st) {\
674 : if (i == NAT_PROTOCOL_TCP && !ste->tcp_state) \
675 : continue; \
676 : if (ste->expire < now) \
677 : vec_add1 (ste_to_be_free, ste - st); \
678 : } \
679 : vec_foreach (ste_index, ste_to_be_free) \
680 : nat64_db_st_entry_free (thread_index, db, \
681 : pool_elt_at_index(st, ste_index[0])); \
682 : vec_free (ste_to_be_free); \
683 : ste_to_be_free = 0;
684 42 : foreach_nat_protocol
685 : #undef _
686 34 : st = db->st._unk_proto_st;
687 34 : pool_foreach (ste, st) {
688 0 : if (ste->expire < now)
689 0 : vec_add1 (ste_to_be_free, ste - st);
690 : }
691 34 : vec_foreach (ste_index, ste_to_be_free)
692 0 : nat64_db_st_entry_free (thread_index, db,
693 0 : pool_elt_at_index(st, ste_index[0]));
694 34 : vec_free (ste_to_be_free);
695 : /* *INDENT-ON* */
696 34 : }
697 :
698 : void
699 4 : nat64_db_free_out_addr (u32 thread_index,
700 : nat64_db_t * db, ip4_address_t * out_addr)
701 : {
702 4 : u32 *ste_to_be_free = 0, *ste_index;
703 : nat64_db_st_entry_t *st, *ste;
704 : nat64_db_bib_entry_t *bibe;
705 :
706 4 : db->addr_free = 1;
707 : /* *INDENT-OFF* */
708 : #define _(N, i, n, s) \
709 : st = db->st._##n##_st; \
710 : pool_foreach (ste, st) { \
711 : bibe = pool_elt_at_index (db->bib._##n##_bib, ste->bibe_index); \
712 : if (bibe->out_addr.as_u32 == out_addr->as_u32) \
713 : vec_add1 (ste_to_be_free, ste - st); \
714 : } \
715 : vec_foreach (ste_index, ste_to_be_free) \
716 : nat64_db_st_entry_free (thread_index, db, \
717 : pool_elt_at_index(st, ste_index[0])); \
718 : vec_free (ste_to_be_free); \
719 : ste_to_be_free = 0;
720 8 : foreach_nat_protocol
721 : #undef _
722 4 : st = db->st._unk_proto_st;
723 4 : pool_foreach (ste, st) {
724 0 : bibe = pool_elt_at_index (db->bib._unk_proto_bib, ste->bibe_index);
725 0 : if (bibe->out_addr.as_u32 == out_addr->as_u32)
726 0 : vec_add1 (ste_to_be_free, ste - st);
727 : }
728 4 : vec_foreach (ste_index, ste_to_be_free)
729 0 : nat64_db_st_entry_free (thread_index, db,
730 0 : pool_elt_at_index(st, ste_index[0]));
731 4 : vec_free (ste_to_be_free);
732 4 : db->addr_free = 0;
733 : /* *INDENT-ON* */
734 4 : }
735 :
736 : /*
737 : * fd.io coding-style-patch-verification: ON
738 : *
739 : * Local Variables:
740 : * eval: (c-set-style "gnu")
741 : * End:
742 : */
|