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