nat: cleanup & reorganization
[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 /* *INDENT-OFF* */
58 #define _(N, i, n, s) \
59   pool_free (db->bib._##n##_bib); \
60   pool_free (db->st._##n##_st);
61   foreach_nat_protocol
62 #undef _
63 /* *INDENT-ON* */
64
65   pool_free (db->bib._unk_proto_bib);
66   pool_free (db->st._unk_proto_st);
67
68   return 0;
69 }
70
71 nat64_db_bib_entry_t *
72 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   if (db->bib.bib_entries_num >= db->bib.limit)
83     {
84       db->free_addr_port_cb (db, out_addr, out_port, proto);
85       //nat_ipfix_logging_max_bibs (thread_index, db->bib.limit);
86       return 0;
87     }
88
89   /* create pool entry */
90   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       foreach_nat_protocol
99 #undef _
100 /* *INDENT-ON* */
101     default:
102       pool_get (db->bib._unk_proto_bib, bibe);
103       kv.value = bibe - db->bib._unk_proto_bib;
104       break;
105     }
106
107   db->bib.bib_entries_num++;
108
109   clib_memset (bibe, 0, sizeof (*bibe));
110   bibe->in_addr.as_u64[0] = in_addr->as_u64[0];
111   bibe->in_addr.as_u64[1] = in_addr->as_u64[1];
112   bibe->in_port = in_port;
113   bibe->out_addr.as_u32 = out_addr->as_u32;
114   bibe->out_port = out_port;
115   bibe->fib_index = fib_index;
116   bibe->proto = proto;
117   bibe->is_static = is_static;
118
119   /* create hash lookup */
120   bibe_key.addr.as_u64[0] = bibe->in_addr.as_u64[0];
121   bibe_key.addr.as_u64[1] = bibe->in_addr.as_u64[1];
122   bibe_key.fib_index = bibe->fib_index;
123   bibe_key.port = bibe->in_port;
124   bibe_key.proto = bibe->proto;
125   bibe_key.rsvd = 0;
126   kv.key[0] = bibe_key.as_u64[0];
127   kv.key[1] = bibe_key.as_u64[1];
128   kv.key[2] = bibe_key.as_u64[2];
129   clib_bihash_add_del_24_8 (&db->bib.in2out, &kv, 1);
130
131   clib_memset (&bibe_key.addr, 0, sizeof (bibe_key.addr));
132   bibe_key.addr.ip4.as_u32 = bibe->out_addr.as_u32;
133   bibe_key.fib_index = 0;
134   bibe_key.port = bibe->out_port;
135   kv.key[0] = bibe_key.as_u64[0];
136   kv.key[1] = bibe_key.as_u64[1];
137   kv.key[2] = bibe_key.as_u64[2];
138   clib_bihash_add_del_24_8 (&db->bib.out2in, &kv, 1);
139
140   fib_table_t *fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
141   nat_ipfix_logging_nat64_bib (thread_index, in_addr, out_addr, proto,
142                                in_port, out_port, fib->ft_table_id, 1);
143   return bibe;
144 }
145
146 void
147 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   u32 *ste_to_be_free = 0, *ste_index, bibe_index;
154   nat64_db_st_entry_t *st, *ste;
155
156   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       foreach_nat_protocol
165 #undef _
166 /* *INDENT-ON* */
167     default:
168       bib = db->bib._unk_proto_bib;
169       st = db->st._unk_proto_st;
170       break;
171     }
172
173   db->bib.bib_entries_num--;
174
175   bibe_index = bibe - bib;
176
177   /* delete ST entries for static BIB entry */
178   if (bibe->is_static)
179     {
180       pool_foreach (ste, st, (
181                                {
182                                if (ste->bibe_index == bibe_index)
183                                vec_add1 (ste_to_be_free, ste - st);}
184                     ));
185       vec_foreach (ste_index, ste_to_be_free)
186         nat64_db_st_entry_free (thread_index, db,
187                                 pool_elt_at_index (st, ste_index[0]));
188       vec_free (ste_to_be_free);
189     }
190
191   /* delete hash lookup */
192   bibe_key.addr.as_u64[0] = bibe->in_addr.as_u64[0];
193   bibe_key.addr.as_u64[1] = bibe->in_addr.as_u64[1];
194   bibe_key.fib_index = bibe->fib_index;
195   bibe_key.port = bibe->in_port;
196   bibe_key.proto = bibe->proto;
197   bibe_key.rsvd = 0;
198   kv.key[0] = bibe_key.as_u64[0];
199   kv.key[1] = bibe_key.as_u64[1];
200   kv.key[2] = bibe_key.as_u64[2];
201   clib_bihash_add_del_24_8 (&db->bib.in2out, &kv, 0);
202
203   clib_memset (&bibe_key.addr, 0, sizeof (bibe_key.addr));
204   bibe_key.addr.ip4.as_u32 = bibe->out_addr.as_u32;
205   bibe_key.fib_index = 0;
206   bibe_key.port = bibe->out_port;
207   kv.key[0] = bibe_key.as_u64[0];
208   kv.key[1] = bibe_key.as_u64[1];
209   kv.key[2] = bibe_key.as_u64[2];
210   clib_bihash_add_del_24_8 (&db->bib.out2in, &kv, 0);
211
212   if (!db->addr_free)
213     db->free_addr_port_cb (db, &bibe->out_addr, bibe->out_port, bibe->proto);
214
215   fib_table_t *fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
216   nat_ipfix_logging_nat64_bib (thread_index, &bibe->in_addr, &bibe->out_addr,
217                                bibe->proto, bibe->in_port, bibe->out_port,
218                                fib->ft_table_id, 0);
219
220   /* delete from pool */
221   pool_put (bib, bibe);
222 }
223
224 nat64_db_bib_entry_t *
225 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   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   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       foreach_nat_protocol
241 #undef _
242 /* *INDENT-ON* */
243     default:
244       bib = db->bib._unk_proto_bib;
245       break;
246     }
247
248   bibe_key.addr.as_u64[0] = addr->as_u64[0];
249   bibe_key.addr.as_u64[1] = addr->as_u64[1];
250   bibe_key.fib_index = fib_index;
251   bibe_key.port = port;
252   bibe_key.proto = proto;
253   bibe_key.rsvd = 0;
254
255   kv.key[0] = bibe_key.as_u64[0];
256   kv.key[1] = bibe_key.as_u64[1];
257   kv.key[2] = bibe_key.as_u64[2];
258
259   if (!clib_bihash_search_24_8
260       (is_ip6 ? &db->bib.in2out : &db->bib.out2in, &kv, &value))
261     bibe = pool_elt_at_index (bib, value.value);
262
263   return bibe;
264 }
265
266 void
267 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   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       foreach_nat_protocol
282     #undef _
283       bib = db->bib._unk_proto_bib;
284       pool_foreach (bibe, bib, ({
285         if (fn (bibe, ctx))
286           return;
287       }));
288     /* *INDENT-ON* */
289     }
290   else
291     {
292       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           foreach_nat_protocol
300     #undef _
301     /* *INDENT-ON* */
302         default:
303           bib = db->bib._unk_proto_bib;
304           break;
305         }
306
307       /* *INDENT-OFF* */
308       pool_foreach (bibe, bib,
309       ({
310         if (fn (bibe, ctx))
311           return;
312       }));
313       /* *INDENT-ON* */
314     }
315 }
316
317 nat64_db_bib_entry_t *
318 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   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       foreach_nat_protocol
330 #undef _
331 /* *INDENT-ON* */
332     default:
333       bib = db->bib._unk_proto_bib;
334       break;
335     }
336
337   return pool_elt_at_index (bib, bibe_index);
338 }
339
340 void
341 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   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       foreach_nat_protocol
356     #undef _
357       st = db->st._unk_proto_st;
358       pool_foreach (ste, st, ({
359         if (fn (ste, ctx))
360           return;
361       }));
362     /* *INDENT-ON* */
363     }
364   else
365     {
366       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           foreach_nat_protocol
374     #undef _
375     /* *INDENT-ON* */
376         default:
377           st = db->st._unk_proto_st;
378           break;
379         }
380
381       /* *INDENT-OFF* */
382       pool_foreach (ste, st,
383       ({
384         if (fn (ste, ctx))
385           return;
386       }));
387       /* *INDENT-ON* */
388     }
389 }
390
391 nat64_db_st_entry_t *
392 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   if (db->st.st_entries_num >= db->st.limit)
403     {
404       //nat_ipfix_logging_max_sessions (thread_index, db->st.limit);
405       return 0;
406     }
407
408   /* create pool entry */
409   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       foreach_nat_protocol
419 #undef _
420 /* *INDENT-ON* */
421     default:
422       pool_get (db->st._unk_proto_st, ste);
423       kv.value = ste - db->st._unk_proto_st;
424       bib = db->bib._unk_proto_bib;
425       break;
426     }
427
428   db->st.st_entries_num++;
429
430   clib_memset (ste, 0, sizeof (*ste));
431   ste->in_r_addr.as_u64[0] = in_r_addr->as_u64[0];
432   ste->in_r_addr.as_u64[1] = in_r_addr->as_u64[1];
433   ste->out_r_addr.as_u32 = out_r_addr->as_u32;
434   ste->r_port = r_port;
435   ste->bibe_index = bibe - bib;
436   ste->proto = bibe->proto;
437
438   /* increment session number for BIB entry */
439   bibe->ses_num++;
440
441   /* create hash lookup */
442   clib_memset (&ste_key, 0, sizeof (ste_key));
443   ste_key.l_addr.as_u64[0] = bibe->in_addr.as_u64[0];
444   ste_key.l_addr.as_u64[1] = bibe->in_addr.as_u64[1];
445   ste_key.r_addr.as_u64[0] = ste->in_r_addr.as_u64[0];
446   ste_key.r_addr.as_u64[1] = ste->in_r_addr.as_u64[1];
447   ste_key.fib_index = bibe->fib_index;
448   ste_key.l_port = bibe->in_port;
449   ste_key.r_port = ste->r_port;
450   ste_key.proto = ste->proto;
451   kv.key[0] = ste_key.as_u64[0];
452   kv.key[1] = ste_key.as_u64[1];
453   kv.key[2] = ste_key.as_u64[2];
454   kv.key[3] = ste_key.as_u64[3];
455   kv.key[4] = ste_key.as_u64[4];
456   kv.key[5] = ste_key.as_u64[5];
457   clib_bihash_add_del_48_8 (&db->st.in2out, &kv, 1);
458
459   clib_memset (&ste_key, 0, sizeof (ste_key));
460   ste_key.l_addr.ip4.as_u32 = bibe->out_addr.as_u32;
461   ste_key.r_addr.ip4.as_u32 = ste->out_r_addr.as_u32;
462   ste_key.l_port = bibe->out_port;
463   ste_key.r_port = ste->r_port;
464   ste_key.proto = ste->proto;
465   kv.key[0] = ste_key.as_u64[0];
466   kv.key[1] = ste_key.as_u64[1];
467   kv.key[2] = ste_key.as_u64[2];
468   kv.key[3] = ste_key.as_u64[3];
469   kv.key[4] = ste_key.as_u64[4];
470   kv.key[5] = ste_key.as_u64[5];
471   clib_bihash_add_del_48_8 (&db->st.out2in, &kv, 1);
472
473   fib_table_t *fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
474   nat_ipfix_logging_nat64_session (thread_index, &bibe->in_addr,
475                                    &bibe->out_addr, bibe->proto,
476                                    bibe->in_port, bibe->out_port,
477                                    &ste->in_r_addr, &ste->out_r_addr,
478                                    ste->r_port, ste->r_port, fib->ft_table_id,
479                                    1);
480   nat_syslog_nat64_sadd (bibe->fib_index, &bibe->in_addr, bibe->in_port,
481                          &bibe->out_addr, bibe->out_port, &ste->out_r_addr,
482                          ste->r_port, bibe->proto);
483   return ste;
484 }
485
486 void
487 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   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       foreach_nat_protocol
504 #undef _
505 /* *INDENT-ON* */
506     default:
507       st = db->st._unk_proto_st;
508       bib = db->bib._unk_proto_bib;
509       break;
510     }
511
512   bibe = pool_elt_at_index (bib, ste->bibe_index);
513
514   db->st.st_entries_num--;
515
516   /* delete hash lookup */
517   clib_memset (&ste_key, 0, sizeof (ste_key));
518   ste_key.l_addr.as_u64[0] = bibe->in_addr.as_u64[0];
519   ste_key.l_addr.as_u64[1] = bibe->in_addr.as_u64[1];
520   ste_key.r_addr.as_u64[0] = ste->in_r_addr.as_u64[0];
521   ste_key.r_addr.as_u64[1] = ste->in_r_addr.as_u64[1];
522   ste_key.fib_index = bibe->fib_index;
523   ste_key.l_port = bibe->in_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.in2out, &kv, 0);
533
534   clib_memset (&ste_key, 0, sizeof (ste_key));
535   ste_key.l_addr.ip4.as_u32 = bibe->out_addr.as_u32;
536   ste_key.r_addr.ip4.as_u32 = ste->out_r_addr.as_u32;
537   ste_key.l_port = bibe->out_port;
538   ste_key.r_port = ste->r_port;
539   ste_key.proto = ste->proto;
540   kv.key[0] = ste_key.as_u64[0];
541   kv.key[1] = ste_key.as_u64[1];
542   kv.key[2] = ste_key.as_u64[2];
543   kv.key[3] = ste_key.as_u64[3];
544   kv.key[4] = ste_key.as_u64[4];
545   kv.key[5] = ste_key.as_u64[5];
546   clib_bihash_add_del_48_8 (&db->st.out2in, &kv, 0);
547
548   fib_table_t *fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
549   nat_ipfix_logging_nat64_session (thread_index, &bibe->in_addr,
550                                    &bibe->out_addr, bibe->proto,
551                                    bibe->in_port, bibe->out_port,
552                                    &ste->in_r_addr, &ste->out_r_addr,
553                                    ste->r_port, ste->r_port, fib->ft_table_id,
554                                    0);
555   nat_syslog_nat64_sdel (bibe->fib_index, &bibe->in_addr, bibe->in_port,
556                          &bibe->out_addr, bibe->out_port, &ste->out_r_addr,
557                          ste->r_port, bibe->proto);
558
559   /* delete from pool */
560   pool_put (st, ste);
561
562   /* decrement session number for BIB entry */
563   bibe->ses_num--;
564
565   /* delete BIB entry if last session and dynamic */
566   if (!bibe->is_static && !bibe->ses_num)
567     nat64_db_bib_entry_free (thread_index, db, bibe);
568 }
569
570 nat64_db_st_entry_t *
571 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   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   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       foreach_nat_protocol
588 #undef _
589 /* *INDENT-ON* */
590     default:
591       st = db->st._unk_proto_st;
592       break;
593     }
594
595   clib_memset (&ste_key, 0, sizeof (ste_key));
596   ste_key.l_addr.as_u64[0] = l_addr->as_u64[0];
597   ste_key.l_addr.as_u64[1] = l_addr->as_u64[1];
598   ste_key.r_addr.as_u64[0] = r_addr->as_u64[0];
599   ste_key.r_addr.as_u64[1] = r_addr->as_u64[1];
600   ste_key.fib_index = fib_index;
601   ste_key.l_port = l_port;
602   ste_key.r_port = r_port;
603   ste_key.proto = proto;
604   kv.key[0] = ste_key.as_u64[0];
605   kv.key[1] = ste_key.as_u64[1];
606   kv.key[2] = ste_key.as_u64[2];
607   kv.key[3] = ste_key.as_u64[3];
608   kv.key[4] = ste_key.as_u64[4];
609   kv.key[5] = ste_key.as_u64[5];
610
611   if (!clib_bihash_search_48_8
612       (is_ip6 ? &db->st.in2out : &db->st.out2in, &kv, &value))
613     ste = pool_elt_at_index (st, value.value);
614
615   return ste;
616 }
617
618 u32
619 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   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       foreach_nat_protocol
631 #undef _
632 /* *INDENT-ON* */
633     default:
634       st = db->st._unk_proto_st;
635       return (u32) ~ 0;
636     }
637
638   return ste - st;
639 }
640
641 nat64_db_st_entry_t *
642 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   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       foreach_nat_protocol
654 #undef _
655 /* *INDENT-ON* */
656     default:
657       st = db->st._unk_proto_st;
658       break;
659     }
660
661   return pool_elt_at_index (st, ste_index);
662 }
663
664 void
665 nad64_db_st_free_expired (u32 thread_index, nat64_db_t * db, u32 now)
666 {
667   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   foreach_nat_protocol
685 #undef _
686   st = db->st._unk_proto_st;
687   pool_foreach (ste, st, ({
688     if (ste->expire < now)
689       vec_add1 (ste_to_be_free, ste - st);
690   }));
691   vec_foreach (ste_index, ste_to_be_free)
692     nat64_db_st_entry_free (thread_index, db,
693                             pool_elt_at_index(st, ste_index[0]));
694   vec_free (ste_to_be_free);
695 /* *INDENT-ON* */
696 }
697
698 void
699 nat64_db_free_out_addr (u32 thread_index,
700                         nat64_db_t * db, ip4_address_t * out_addr)
701 {
702   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   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   foreach_nat_protocol
721 #undef _
722   st = db->st._unk_proto_st;
723   pool_foreach (ste, st, ({
724     bibe = pool_elt_at_index (db->bib._unk_proto_bib, ste->bibe_index);
725     if (bibe->out_addr.as_u32 == out_addr->as_u32)
726       vec_add1 (ste_to_be_free, ste - st);
727   }));
728   vec_foreach (ste_index, ste_to_be_free)
729     nat64_db_st_entry_free (thread_index, db,
730                             pool_elt_at_index(st, ste_index[0]));
731   vec_free (ste_to_be_free);
732   db->addr_free = 0;
733 /* *INDENT-ON* */
734 }
735
736 /*
737  * fd.io coding-style-patch-verification: ON
738  *
739  * Local Variables:
740  * eval: (c-set-style "gnu")
741  * End:
742  */