FD.io VPP  v16.09
Vector Packet Processing
ip4_mtrie.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  * ip/ip4_fib.h: ip4 mtrie fib
17  *
18  * Copyright (c) 2012 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vnet/ip/ip.h>
41 
42 static void
44 {
46  memset (p->dst_address_bits_of_leaves, prefix_len, sizeof (p->dst_address_bits_of_leaves));
47 
48  /* Initialize leaves. */
49 #ifdef CLIB_HAVE_VEC128
50  {
51  u32x4 * l, init_x4;
52 
53 #ifndef __ALTIVEC__
54  init_x4 = u32x4_splat (init);
55 #else
56  {
57  u32x4_union_t y;
58  y.as_u32[0] = init;
59  y.as_u32[1] = init;
60  y.as_u32[2] = init;
61  y.as_u32[3] = init;
62  init_x4 = y.as_u32x4;
63  }
64 #endif
65 
66  for (l = p->leaves_as_u32x4; l < p->leaves_as_u32x4 + ARRAY_LEN (p->leaves_as_u32x4); l += 4)
67  {
68  l[0] = init_x4;
69  l[1] = init_x4;
70  l[2] = init_x4;
71  l[3] = init_x4;
72  }
73  }
74 #else
75  {
76  u32 * l;
77 
78  for (l = p->leaves; l < p->leaves + ARRAY_LEN (p->leaves); l += 4)
79  {
80  l[0] = init;
81  l[1] = init;
82  l[2] = init;
83  l[3] = init;
84  }
85  }
86 #endif
87 }
88 
91 {
93 
94  /* Get cache aligned ply. */
95  pool_get_aligned (m->ply_pool, p, sizeof (p[0]));
96 
97  ply_init (p, init_leaf, prefix_len);
99 }
100 
103 {
105  /* It better not be the root ply. */
106  ASSERT (n != 0);
107  return pool_elt_at_index (m->ply_pool, n);
108 }
109 
110 static void
112 {
113  uword i, is_root;
114 
115  is_root = p - m->ply_pool == 0;
116 
117  for (i = 0 ; i < ARRAY_LEN (p->leaves); i++)
118  {
119  ip4_fib_mtrie_leaf_t l = p->leaves[i];
121  ply_free (m, get_next_ply_for_leaf (m, l));
122  }
123 
124  if (is_root)
125  ply_init (p, IP4_FIB_MTRIE_LEAF_EMPTY, /* prefix_len */ 0);
126  else
127  pool_put (m->ply_pool, p);
128 }
129 
131 {
132  ip4_fib_mtrie_ply_t * root_ply = pool_elt_at_index (m->ply_pool, 0);
133  ply_free (m, root_ply);
134 }
135 
137 {
140 
141  l = p->leaves[dst.as_u8[0]];
144 
145  p = get_next_ply_for_leaf (m, l);
146  l = p->leaves[dst.as_u8[1]];
149 
150  p = get_next_ply_for_leaf (m, l);
151  l = p->leaves[dst.as_u8[2]];
154 
155  p = get_next_ply_for_leaf (m, l);
156  l = p->leaves[dst.as_u8[3]];
157 
160 }
161 
162 typedef struct {
167 
168 static void
170  ip4_fib_mtrie_ply_t * ply,
171  ip4_fib_mtrie_leaf_t new_leaf,
172  uword new_leaf_dst_address_bits)
173 {
174  ip4_fib_mtrie_leaf_t old_leaf;
175  uword i;
176 
178  ASSERT (! ip4_fib_mtrie_leaf_is_empty (new_leaf));
179 
180  for (i = 0; i < ARRAY_LEN (ply->leaves); i++)
181  {
182  old_leaf = ply->leaves[i];
183 
184  /* Recurse into sub plies. */
185  if (! ip4_fib_mtrie_leaf_is_terminal (old_leaf))
186  {
187  ip4_fib_mtrie_ply_t * sub_ply = get_next_ply_for_leaf (m, old_leaf);
188  set_ply_with_more_specific_leaf (m, sub_ply, new_leaf, new_leaf_dst_address_bits);
189  }
190 
191  /* Replace less specific terminal leaves with new leaf. */
192  else if (new_leaf_dst_address_bits >= ply->dst_address_bits_of_leaves[i])
193  {
194  __sync_val_compare_and_swap (&ply->leaves[i], old_leaf, new_leaf);
195  ASSERT(ply->leaves[i] == new_leaf);
196  ply->dst_address_bits_of_leaves[i] = new_leaf_dst_address_bits;
198  }
199  }
200 }
201 
202 static void
205  u32 old_ply_index,
206  u32 dst_address_byte_index)
207 {
208  ip4_fib_mtrie_leaf_t old_leaf, new_leaf;
209  i32 n_dst_bits_next_plies;
210  u8 dst_byte;
211 
212  ASSERT (a->dst_address_length > 0 && a->dst_address_length <= 32);
213  ASSERT (dst_address_byte_index < ARRAY_LEN (a->dst_address.as_u8));
214 
215  n_dst_bits_next_plies = a->dst_address_length - BITS (u8) * (dst_address_byte_index + 1);
216 
217  dst_byte = a->dst_address.as_u8[dst_address_byte_index];
218 
219  /* Number of bits next plies <= 0 => insert leaves this ply. */
220  if (n_dst_bits_next_plies <= 0)
221  {
222  uword i, n_dst_bits_this_ply, old_leaf_is_terminal;
223 
224  n_dst_bits_this_ply = -n_dst_bits_next_plies;
225  ASSERT ((a->dst_address.as_u8[dst_address_byte_index] & pow2_mask (n_dst_bits_this_ply)) == 0);
226 
227  for (i = dst_byte; i < dst_byte + (1 << n_dst_bits_this_ply); i++)
228  {
229  ip4_fib_mtrie_ply_t * old_ply, * new_ply;
230 
231  old_ply = pool_elt_at_index (m->ply_pool, old_ply_index);
232 
233  old_leaf = old_ply->leaves[i];
234  old_leaf_is_terminal = ip4_fib_mtrie_leaf_is_terminal (old_leaf);
235 
236  /* Is leaf to be inserted more specific? */
237  if (a->dst_address_length >= old_ply->dst_address_bits_of_leaves[i])
238  {
240 
241  if (old_leaf_is_terminal)
242  {
244  __sync_val_compare_and_swap (&old_ply->leaves[i], old_leaf,
245  new_leaf);
246  ASSERT(old_ply->leaves[i] == new_leaf);
247  old_ply->n_non_empty_leafs += ip4_fib_mtrie_leaf_is_empty (old_leaf);
248  ASSERT (old_ply->n_non_empty_leafs <= ARRAY_LEN (old_ply->leaves));
249  }
250  else
251  {
252  /* Existing leaf points to another ply. We need to place new_leaf into all
253  more specific slots. */
254  new_ply = get_next_ply_for_leaf (m, old_leaf);
255  set_ply_with_more_specific_leaf (m, new_ply, new_leaf, a->dst_address_length);
256  }
257  }
258 
259  else if (! old_leaf_is_terminal)
260  {
261  new_ply = get_next_ply_for_leaf (m, old_leaf);
262  set_leaf (m, a, new_ply - m->ply_pool, dst_address_byte_index + 1);
263  }
264  }
265  }
266  else
267  {
268  ip4_fib_mtrie_ply_t * old_ply, * new_ply;
269 
270  old_ply = pool_elt_at_index (m->ply_pool, old_ply_index);
271  old_leaf = old_ply->leaves[dst_byte];
272  if (ip4_fib_mtrie_leaf_is_terminal (old_leaf))
273  {
274  new_leaf = ply_create (m, old_leaf, old_ply->dst_address_bits_of_leaves[dst_byte]);
275  new_ply = get_next_ply_for_leaf (m, new_leaf);
276 
277  /* Refetch since ply_create may move pool. */
278  old_ply = pool_elt_at_index (m->ply_pool, old_ply_index);
279 
280  __sync_val_compare_and_swap (&old_ply->leaves[dst_byte], old_leaf,
281  new_leaf);
282  ASSERT(old_ply->leaves[dst_byte] == new_leaf);
283  old_ply->dst_address_bits_of_leaves[dst_byte] = 0;
284 
285  old_ply->n_non_empty_leafs -= ip4_fib_mtrie_leaf_is_non_empty (old_leaf);
286  ASSERT (old_ply->n_non_empty_leafs >= 0);
287 
288  /* Account for the ply we just created. */
289  old_ply->n_non_empty_leafs += 1;
290  }
291  else
292  new_ply = get_next_ply_for_leaf (m, old_leaf);
293 
294  set_leaf (m, a, new_ply - m->ply_pool, dst_address_byte_index + 1);
295  }
296 }
297 
298 static uword
301  ip4_fib_mtrie_ply_t * old_ply,
302  u32 dst_address_byte_index)
303 {
304  ip4_fib_mtrie_leaf_t old_leaf, del_leaf;
305  i32 n_dst_bits_next_plies;
306  i32 i, n_dst_bits_this_ply, old_leaf_is_terminal;
307  u8 dst_byte;
308 
309  ASSERT (a->dst_address_length > 0 && a->dst_address_length <= 32);
310  ASSERT (dst_address_byte_index < ARRAY_LEN (a->dst_address.as_u8));
311 
312  n_dst_bits_next_plies = a->dst_address_length - BITS (u8) * (dst_address_byte_index + 1);
313 
314  dst_byte = a->dst_address.as_u8[dst_address_byte_index];
315  if (n_dst_bits_next_plies < 0)
316  dst_byte &= ~pow2_mask (-n_dst_bits_next_plies);
317 
318  n_dst_bits_this_ply = n_dst_bits_next_plies <= 0 ? -n_dst_bits_next_plies : 0;
319  n_dst_bits_this_ply = clib_min (8, n_dst_bits_this_ply);
320 
322 
323  for (i = dst_byte; i < dst_byte + (1 << n_dst_bits_this_ply); i++)
324  {
325  old_leaf = old_ply->leaves[i];
326  old_leaf_is_terminal = ip4_fib_mtrie_leaf_is_terminal (old_leaf);
327 
328  if (old_leaf == del_leaf
329  || (! old_leaf_is_terminal
330  && unset_leaf (m, a, get_next_ply_for_leaf (m, old_leaf), dst_address_byte_index + 1)))
331  {
332  old_ply->leaves[i] = IP4_FIB_MTRIE_LEAF_EMPTY;
333  old_ply->dst_address_bits_of_leaves[i] = 0;
334 
335  /* No matter what we just deleted a non-empty leaf. */
336  ASSERT (! ip4_fib_mtrie_leaf_is_empty (old_leaf));
337  old_ply->n_non_empty_leafs -= 1;
338 
339  ASSERT (old_ply->n_non_empty_leafs >= 0);
340  if (old_ply->n_non_empty_leafs == 0 && dst_address_byte_index > 0)
341  {
342  pool_put (m->ply_pool, old_ply);
343  /* Old ply was deleted. */
344  return 1;
345  }
346  }
347  }
348 
349  /* Old ply was not deleted. */
350  return 0;
351 }
352 
354 {
356  memset (m, 0, sizeof (m[0]));
358  root = ply_create (m, IP4_FIB_MTRIE_LEAF_EMPTY, /* dst_address_bits_of_leaves */ 0);
360 }
361 
362 void
364  ip4_address_t dst_address,
365  u32 dst_address_length,
366  u32 adj_index,
367  u32 is_del)
368 {
369  ip4_fib_mtrie_t * m = &fib->mtrie;
370  ip4_fib_mtrie_ply_t * root_ply;
372  ip4_main_t * im = &ip4_main;
373 
374  ASSERT(m->ply_pool != 0);
375 
376  root_ply = pool_elt_at_index (m->ply_pool, 0);
377 
378  /* Honor dst_address_length. Fib masks are in network byte order */
379  dst_address.as_u32 &= im->fib_masks[dst_address_length];
380  a.dst_address = dst_address;
381  a.dst_address_length = dst_address_length;
382  a.adj_index = adj_index;
383 
384  if (! is_del)
385  {
386  if (dst_address_length == 0)
388  else
389  set_leaf (m, &a, /* ply_index */ 0, /* dst_address_byte_index */ 0);
390  }
391  else
392  {
393  if (dst_address_length == 0)
395 
396  else
397  {
398  ip4_main_t * im = &ip4_main;
399  uword i;
400 
401  unset_leaf (m, &a, root_ply, 0);
402 
403  /* Find next less specific route and insert into mtrie. */
404  for (i = ARRAY_LEN (fib->adj_index_by_dst_address) - 1; i >= 1; i--)
405  {
406  uword * p;
407  ip4_address_t key;
408 
409  if (! fib->adj_index_by_dst_address[i])
410  continue;
411 
412  key.as_u32 = dst_address.as_u32 & im->fib_masks[i];
413  p = hash_get (fib->adj_index_by_dst_address[i], key.as_u32);
414  if (p)
415  {
416  a.dst_address = key;
417  a.dst_address_length = i;
418  a.adj_index = p[0];
419  set_leaf (m, &a, /* ply_index */ 0, /* dst_address_byte_index */ 0);
420  break;
421  }
422  }
423  }
424  }
425 }
426 
429 {
430  ip4_fib_mtrie_leaf_t l = p[0];
431  uword was_remapped_to_empty_leaf = 0;
433  {
434  u32 adj_index = ip4_fib_mtrie_leaf_get_adj_index (l);
435  u32 m = vec_elt (lm->adjacency_remap_table, adj_index);
436  if (m)
437  {
438  was_remapped_to_empty_leaf = m == ~0;
439 
440  /*
441  * The intent of the original form - which dates to 2013 or
442  * earlier - is not obvious. Here's the original:
443  *
444  * if (was_remapped_to_empty_leaf)
445  * p[0] = (was_remapped_to_empty_leaf
446  * ? IP4_FIB_MTRIE_LEAF_EMPTY
447  * : ip4_fib_mtrie_leaf_set_adj_index (m - 1));
448  *
449  * Notice the outer "if (was_remapped_to_empty_leaf)"
450  * means that p[0] is always set to IP4_FIB_MTRIE_LEAF_EMPTY,
451  * and is otherwise left intact.
452  *
453  * It seems unlikely that the adjacency mapping scheme
454  * works in detail. Coverity correctly complains that the
455  * else-case of the original ternary expression is dead code.
456  */
457  if (was_remapped_to_empty_leaf)
459  }
460  }
461  return was_remapped_to_empty_leaf;
462 }
463 
465 {
466  u32 n_remapped_to_empty = 0;
467  u32 i;
468  for (i = 0; i < ARRAY_LEN (ply->leaves); i++)
469  n_remapped_to_empty += maybe_remap_leaf (lm, &ply->leaves[i]);
470  if (n_remapped_to_empty > 0)
471  {
472  ASSERT (n_remapped_to_empty <= ply->n_non_empty_leafs);
473  ply->n_non_empty_leafs -= n_remapped_to_empty;
474  if (ply->n_non_empty_leafs == 0)
475  os_panic ();
476  }
477 }
478 
480 {
481  ip4_fib_mtrie_ply_t * ply;
482  pool_foreach (ply, m->ply_pool, maybe_remap_ply (lm, ply));
483  maybe_remap_leaf (lm, &m->default_leaf);
484 }
485 
486 /* Returns number of bytes of memory used by mtrie. */
488 {
489  uword bytes, i;
490 
491  if (! p)
492  {
493  if (pool_is_free_index (m->ply_pool, 0))
494  return 0;
495  p = pool_elt_at_index (m->ply_pool, 0);
496  }
497 
498  bytes = sizeof (p[0]);
499  for (i = 0 ; i < ARRAY_LEN (p->leaves); i++)
500  {
501  ip4_fib_mtrie_leaf_t l = p->leaves[i];
503  bytes += mtrie_memory_usage (m, get_next_ply_for_leaf (m, l));
504  }
505 
506  return bytes;
507 }
508 
509 static u8 * format_ip4_fib_mtrie_leaf (u8 * s, va_list * va)
510 {
511  ip4_fib_mtrie_leaf_t l = va_arg (*va, ip4_fib_mtrie_leaf_t);
512 
514  s = format (s, "miss");
515  else if (ip4_fib_mtrie_leaf_is_terminal (l))
516  s = format (s, "adj %d", ip4_fib_mtrie_leaf_get_adj_index (l));
517  else
518  s = format (s, "next ply %d", ip4_fib_mtrie_leaf_get_next_ply_index (l));
519  return s;
520 }
521 
522 static u8 * format_ip4_fib_mtrie_ply (u8 * s, va_list * va)
523 {
524  ip4_fib_mtrie_t * m = va_arg (*va, ip4_fib_mtrie_t *);
525  u32 base_address = va_arg (*va, u32);
526  u32 ply_index = va_arg (*va, u32);
527  u32 dst_address_byte_index = va_arg (*va, u32);
529  uword i, indent;
530 
531  p = pool_elt_at_index (m->ply_pool, ply_index);
532  indent = format_get_indent (s);
533  s = format (s, "ply index %d, %d non-empty leaves", ply_index, p->n_non_empty_leafs);
534  for (i = 0; i < ARRAY_LEN (p->leaves); i++)
535  {
536  ip4_fib_mtrie_leaf_t l = p->leaves[i];
537 
538  if (! ip4_fib_mtrie_leaf_is_empty (l))
539  {
540  u32 a, ia_length;
541  ip4_address_t ia;
542 
543  a = base_address + (i << (24 - 8*dst_address_byte_index));
544  ia.as_u32 = clib_host_to_net_u32 (a);
546  ia_length = p->dst_address_bits_of_leaves[i];
547  else
548  ia_length = 8*(1 + dst_address_byte_index);
549  s = format (s, "\n%U%20U %U",
550  format_white_space, indent + 2,
551  format_ip4_address_and_length, &ia, ia_length,
553 
555  s = format (s, "\n%U%U",
556  format_white_space, indent + 2,
559  dst_address_byte_index + 1);
560  }
561  }
562 
563  return s;
564 }
565 
566 u8 * format_ip4_fib_mtrie (u8 * s, va_list * va)
567 {
568  ip4_fib_mtrie_t * m = va_arg (*va, ip4_fib_mtrie_t *);
569 
570  s = format (s, "%d plies, memory usage %U",
571  pool_elts (m->ply_pool),
573 
574  if (pool_elts (m->ply_pool) > 0)
575  {
576  ip4_address_t base_address;
577  base_address.as_u32 = 0;
578  s = format (s, "\n %U", format_ip4_fib_mtrie_ply, m, base_address, 0, 0);
579  }
580 
581  return s;
582 }
u8 dst_address_bits_of_leaves[256]
Definition: ip4_mtrie.h:108
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define clib_min(x, y)
Definition: clib.h:326
a
Definition: bitmap.h:516
static u32 ip4_fib_mtrie_leaf_get_next_ply_index(ip4_fib_mtrie_leaf_t n)
Definition: ip4_mtrie.h:83
static ip4_fib_mtrie_ply_t * get_next_ply_for_leaf(ip4_fib_mtrie_t *m, ip4_fib_mtrie_leaf_t l)
Definition: ip4_mtrie.c:102
static void ply_free(ip4_fib_mtrie_t *m, ip4_fib_mtrie_ply_t *p)
Definition: ip4_mtrie.c:111
void os_panic(void)
Definition: unix-misc.c:172
static u32 ip4_fib_mtrie_leaf_is_next_ply(ip4_fib_mtrie_leaf_t n)
Definition: ip4_mtrie.h:80
add_epi add_epi sub_epi sub_epi adds_epu subs_epu i16x8 y
Definition: vector_sse2.h:299
static ip4_fib_mtrie_leaf_t ip4_fib_mtrie_leaf_set_next_ply_index(u32 i)
Definition: ip4_mtrie.h:89
#define IP4_FIB_MTRIE_LEAF_EMPTY
Definition: ip4_mtrie.h:54
void ip4_fib_free(ip4_fib_mtrie_t *m)
Definition: ip4_mtrie.c:130
ip4_fib_mtrie_ply_t * ply_pool
Definition: ip4_mtrie.h:120
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define always_inline
Definition: clib.h:84
static uword pow2_mask(uword x)
Definition: clib.h:251
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
u32 * adjacency_remap_table
Definition: lookup.h:423
unsigned long long u32x4
Definition: ixge.c:28
int i32
Definition: types.h:81
u32 ip4_fib_mtrie_leaf_t
Definition: ip4_mtrie.h:52
void ip4_fib_mtrie_add_del_route(ip4_fib_t *fib, ip4_address_t dst_address, u32 dst_address_length, u32 adj_index, u32 is_del)
Definition: ip4_mtrie.c:363
static u32 ip4_fib_mtrie_leaf_get_adj_index(ip4_fib_mtrie_leaf_t n)
Definition: ip4_mtrie.h:66
void ip4_mtrie_init(ip4_fib_mtrie_t *m)
Definition: ip4_mtrie.c:353
#define hash_get(h, key)
Definition: hash.h:248
static u8 * format_ip4_fib_mtrie_leaf(u8 *s, va_list *va)
Definition: ip4_mtrie.c:509
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
static void ply_init(ip4_fib_mtrie_ply_t *p, ip4_fib_mtrie_leaf_t init, uword prefix_len)
Definition: ip4_mtrie.c:43
static uword format_get_indent(u8 *s)
Definition: format.h:72
static uword unset_leaf(ip4_fib_mtrie_t *m, ip4_fib_mtrie_set_unset_leaf_args_t *a, ip4_fib_mtrie_ply_t *old_ply, u32 dst_address_byte_index)
Definition: ip4_mtrie.c:299
u8 * format_ip4_fib_mtrie(u8 *s, va_list *va)
Definition: ip4_mtrie.c:566
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
static void set_leaf(ip4_fib_mtrie_t *m, ip4_fib_mtrie_set_unset_leaf_args_t *a, u32 old_ply_index, u32 dst_address_byte_index)
Definition: ip4_mtrie.c:203
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:169
static void set_ply_with_more_specific_leaf(ip4_fib_mtrie_t *m, ip4_fib_mtrie_ply_t *ply, ip4_fib_mtrie_leaf_t new_leaf, uword new_leaf_dst_address_bits)
Definition: ip4_mtrie.c:169
Definition: ip4.h:48
static ip4_fib_mtrie_leaf_t ip4_fib_mtrie_leaf_set_adj_index(u32 adj_index)
Definition: ip4_mtrie.h:72
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:211
#define ARRAY_LEN(x)
Definition: clib.h:59
static uword mtrie_memory_usage(ip4_fib_mtrie_t *m, ip4_fib_mtrie_ply_t *p)
Definition: ip4_mtrie.c:487
u8 * format_memory_size(u8 *s, va_list *va)
Definition: std-formats.c:193
#define ASSERT(truth)
ip4_fib_mtrie_leaf_t leaves[256]
Definition: ip4_mtrie.h:100
unsigned int u32
Definition: types.h:88
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
IPv4 main type.
Definition: ip4.h:114
static ip4_fib_mtrie_leaf_t ply_create(ip4_fib_mtrie_t *m, ip4_fib_mtrie_leaf_t init_leaf, uword prefix_len)
Definition: ip4_mtrie.c:90
static u32 ip4_fib_mtrie_leaf_is_non_empty(ip4_fib_mtrie_leaf_t n)
Definition: ip4_mtrie.h:60
u64 uword
Definition: types.h:112
#define vec_elt(v, i)
Get vector value at index i.
static uword maybe_remap_leaf(ip_lookup_main_t *lm, ip4_fib_mtrie_leaf_t *p)
Definition: ip4_mtrie.c:428
#define u32x4_splat(i)
unsigned char u8
Definition: types.h:56
static u32 ip4_fib_mtrie_leaf_is_empty(ip4_fib_mtrie_leaf_t n)
Definition: ip4_mtrie.h:57
ip4_fib_mtrie_t mtrie
Definition: ip4.h:56
static void maybe_remap_ply(ip_lookup_main_t *lm, ip4_fib_mtrie_ply_t *ply)
Definition: ip4_mtrie.c:464
u32 ip4_mtrie_lookup_address(ip4_fib_mtrie_t *m, ip4_address_t dst)
Definition: ip4_mtrie.c:136
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1578
uword * adj_index_by_dst_address[33]
Definition: ip4.h:50
void ip4_mtrie_maybe_remap_adjacencies(ip_lookup_main_t *lm, ip4_fib_mtrie_t *m)
Definition: ip4_mtrie.c:479
format_function_t format_ip4_address_and_length
Definition: format.h:72
#define BITS(x)
Definition: clib.h:58
static u8 * format_ip4_fib_mtrie_ply(u8 *s, va_list *va)
Definition: ip4_mtrie.c:522
static u32 ip4_fib_mtrie_leaf_is_terminal(ip4_fib_mtrie_leaf_t n)
Definition: ip4_mtrie.h:63
u32 fib_masks[33]
Definition: ip4.h:120
ip4_fib_mtrie_leaf_t default_leaf
Definition: ip4_mtrie.h:123
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109