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