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