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