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