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