FD.io VPP  v16.09
Vector Packet Processing
ip_forward.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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 #include <vnet/lisp-gpe/lisp_gpe.h>
17 
18 /* avoids calling route callbacks for src fib */
19 static void
21  u32 dst_address_u32, u32 dst_address_length,
22  u32 adj_index)
23 {
24  ip_lookup_main_t *lm = lgm->lm4;
25  uword *hash;
26 
27  if (vec_bytes (fib->old_hash_values))
28  memset (fib->old_hash_values, ~0, vec_bytes (fib->old_hash_values));
29  if (vec_bytes (fib->new_hash_values))
30  memset (fib->new_hash_values, ~0, vec_bytes (fib->new_hash_values));
31  fib->new_hash_values[0] = adj_index;
32 
33  /* Make sure adj index is valid. */
34  if (CLIB_DEBUG > 0)
35  (void) ip_get_adjacency (lm, adj_index);
36 
37  hash = fib->adj_index_by_dst_address[dst_address_length];
38 
39  hash = _hash_set3 (hash, dst_address_u32,
40  fib->new_hash_values, fib->old_hash_values);
41 
42  fib->adj_index_by_dst_address[dst_address_length] = hash;
43 }
44 
45 /* copied from ip4_forward since it's static */
46 static void
48  ip4_fib_t * fib, u32 address_length)
49 {
50  hash_t *h;
51  uword max_index;
52 
53  ASSERT (lm->fib_result_n_bytes >= sizeof (uword));
55  / sizeof (uword);
56 
57  fib->adj_index_by_dst_address[address_length] =
58  hash_create (32 /* elts */ , lm->fib_result_n_words * sizeof (uword));
59 
60  hash_set_flags (fib->adj_index_by_dst_address[address_length],
62 
63  h = hash_header (fib->adj_index_by_dst_address[address_length]);
64  max_index = (hash_value_bytes (h) / sizeof (fib->new_hash_values[0])) - 1;
65 
66  /* Initialize new/old hash value vectors. */
67  vec_validate_init_empty (fib->new_hash_values, max_index, ~0);
68  vec_validate_init_empty (fib->old_hash_values, max_index, ~0);
69 }
70 
71 static void
74 {
75  ip_lookup_main_t *lm = lgm->lm4;
76  ip4_fib_t *fib;
77  u32 dst_address, dst_address_length, adj_index, old_adj_index;
78  uword *hash, is_del;
79 
80  /* Either create new adjacency or use given one depending on arguments. */
81  if (a->n_add_adj > 0)
82  ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
83  else
84  adj_index = a->adj_index;
85 
86  dst_address = a->dst_address.data_u32;
87  dst_address_length = a->dst_address_length;
88 
90 
91  if (!fib->adj_index_by_dst_address[dst_address_length])
92  ip4_fib_init_adj_index_by_dst_address (lm, fib, dst_address_length);
93 
94  hash = fib->adj_index_by_dst_address[dst_address_length];
95 
96  is_del = (a->flags & IP4_ROUTE_FLAG_DEL) != 0;
97 
98  if (is_del)
99  {
100  fib->old_hash_values[0] = ~0;
101  hash = _hash_unset (hash, dst_address, fib->old_hash_values);
102  fib->adj_index_by_dst_address[dst_address_length] = hash;
103  }
104  else
105  ip4_sd_fib_set_adj_index (lgm, fib, a->flags, dst_address,
106  dst_address_length, adj_index);
107 
108  old_adj_index = fib->old_hash_values[0];
109 
110  /* Avoid spurious reference count increments */
111  if (old_adj_index == adj_index
112  && adj_index != ~0 && !(a->flags & IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
113  {
114  ip_adjacency_t *adj = ip_get_adjacency (lm, adj_index);
115  if (adj->share_count > 0)
116  adj->share_count--;
117  }
118 
119  ip4_fib_mtrie_add_del_route (fib, a->dst_address, dst_address_length,
120  is_del ? old_adj_index : adj_index, is_del);
121 
122  /* Delete old adjacency index if present and changed. */
124  && old_adj_index != ~0 && old_adj_index != adj_index)
125  ip_del_adjacency (lm, old_adj_index);
126 }
127 
128 static void *
130  ip4_address_t * src, u32 address_length)
131 {
132  ip4_fib_t *fib = pool_elt_at_index (lgm->ip4_src_fibs, src_fib_index);
133  uword *hash, *p;
134 
135  hash = fib->adj_index_by_dst_address[address_length];
136  p = hash_get (hash, src->as_u32);
137  return (void *) p;
138 }
139 
140 /* *INDENT-OFF* */
141 typedef CLIB_PACKED (struct ip4_route {
142  ip4_address_t address;
143  u32 address_length : 6;
144  u32 index : 26;
145 }) ip4_route_t;
146 /* *INDENT-ON* */
147 
148 void
149 ip4_sd_fib_clear_src_fib (lisp_gpe_main_t * lgm, ip4_fib_t * fib)
150 {
151  ip4_route_t *routes = 0, *r;
152  u32 i;
153 
154  vec_reset_length (routes);
155 
156  for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++)
157  {
158  uword *hash = fib->adj_index_by_dst_address[i];
159  hash_pair_t *p;
160  ip4_route_t x;
161 
162  x.address_length = i;
163  x.index = 0; /* shut up coverity */
164 
165  /* *INDENT-OFF* */
166  hash_foreach_pair (p, hash,
167  ({
168  x.address.data_u32 = p->key;
169  vec_add1 (routes, x);
170  }));
171  /* *INDENT-ON* */
172  }
173 
174  vec_foreach (r, routes)
175  {
177 
178  memset (&a, 0, sizeof (a));
180  a.table_index_or_table_id = fib - lgm->ip4_src_fibs;
181  a.dst_address = r->address;
182  a.dst_address_length = r->address_length;
183  a.adj_index = ~0;
184 
186  }
187 }
188 
189 static u8
191 {
192  u8 fib_is_empty;
193  int i;
194 
195  fib_is_empty = 1;
196  for (i = ARRAY_LEN (fib->adj_index_by_dst_address) - 1; i >= 0; i--)
197  {
198  uword *hash = fib->adj_index_by_dst_address[i];
199  uword n_elts = hash_elts (hash);
200  if (n_elts)
201  {
202  fib_is_empty = 0;
203  break;
204  }
205  }
206  return fib_is_empty;
207 }
208 
209 static int
210 ip4_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
211  ip_prefix_t * src_prefix, u32 table_id,
212  ip_adjacency_t * add_adj, u8 is_add)
213 {
214  uword *p;
216  ip_adjacency_t *dst_adjp, dst_adj;
217  ip4_address_t dst = ip_prefix_v4 (dst_prefix), src;
218  u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
219  ip4_fib_t *src_fib;
220 
221  if (src_prefix)
222  {
223  src = ip_prefix_v4 (src_prefix);
224  src_address_length = ip_prefix_len (src_prefix);
225  }
226  else
227  memset (&src, 0, sizeof (src));
228 
229  /* lookup dst adj */
230  p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
231 
232  if (is_add)
233  {
234  /* insert dst prefix to ip4 fib, if it's not in yet */
235  if (p == 0)
236  {
237  /* allocate and init src ip4 fib */
238  pool_get (lgm->ip4_src_fibs, src_fib);
239  ip4_mtrie_init (&src_fib->mtrie);
240 
241  /* configure adjacency */
242  memset (&dst_adj, 0, sizeof (dst_adj));
243 
244  /* reuse rewrite header to store pointer to src fib */
245  dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip4_src_fibs;
246 
247  /* dst adj should point to lisp gpe lookup */
249 
250  /* explicit_fib_index is used in IP6 FIB lookup, don't reuse it */
251  dst_adj.explicit_fib_index = ~0;
252  dst_adj.n_adj = 1;
253 
254  /* make sure we have different signatures for adj in different tables
255  * but with the same lookup_next_index and for adj in the same table
256  * but associated to different destinations */
257  dst_adj.if_address_index = table_id;
258  dst_adj.indirect.next_hop.ip4 = dst;
259 
260  memset (&a, 0, sizeof (a));
262  a.table_index_or_table_id = table_id; /* vrf */
263  a.adj_index = ~0;
264  a.dst_address_length = dst_address_length;
265  a.dst_address = dst;
267  a.add_adj = &dst_adj;
268  a.n_add_adj = 1;
269 
270  ip4_add_del_route (lgm->im4, &a);
271 
272  /* lookup dst adj to obtain the adj index */
273  p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8,
274  dst_address_length);
275 
276  /* make sure insertion succeeded */
277  if (CLIB_DEBUG)
278  {
279  ASSERT (p != 0);
280  dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
281  ASSERT (dst_adjp->rewrite_header.sw_if_index
282  == dst_adj.rewrite_header.sw_if_index);
283  }
284  }
285  }
286  else
287  {
288  if (p == 0)
289  {
291  ("Trying to delete inexistent dst route for %U. Aborting",
292  format_ip4_address_and_length, dst.as_u8, dst_address_length);
293  return -1;
294  }
295  }
296 
297  dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
298 
299  /* add/del src prefix to src fib */
300  memset (&a, 0, sizeof (a));
302  a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
303  a.adj_index = ~0;
305  a.add_adj = add_adj;
306  a.n_add_adj = is_add ? 1 : 0;
307  /* if src prefix is null, add 0/0 */
308  a.dst_address_length = src_address_length;
309  a.dst_address = src;
311 
312  /* make sure insertion succeeded */
313  if (CLIB_DEBUG && is_add)
314  {
315  uword *sai;
316  ip_adjacency_t *src_adjp;
317  sai = ip4_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
318  &src, src_address_length);
319  ASSERT (sai != 0);
320  src_adjp = ip_get_adjacency (lgm->lm4, sai[0]);
321  ASSERT (src_adjp->if_address_index == add_adj->if_address_index);
322  }
323 
324  /* if a delete, check if there are elements left in the src fib */
325  if (!is_add)
326  {
327  src_fib = pool_elt_at_index (lgm->ip4_src_fibs,
328  dst_adjp->rewrite_header.sw_if_index);
329  if (!src_fib)
330  return 0;
331 
332  /* if there's nothing left */
333  if (ip4_fib_is_empty (src_fib))
334  {
335  /* remove the src fib .. */
336  pool_put (lgm->ip4_src_fibs, src_fib);
337 
338  /* .. and remove dst route */
339  memset (&a, 0, sizeof (a));
341  a.table_index_or_table_id = table_id; /* vrf */
342  a.adj_index = ~0;
343  a.dst_address_length = dst_address_length;
344  a.dst_address = dst;
346 
347  ip4_add_del_route (lgm->im4, &a);
348  }
349  }
350 
351  return 0;
352 }
353 
354 static void *
355 ip4_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
356  ip_prefix_t * src_prefix, u32 table_id)
357 {
358  uword *p;
359  ip4_address_t dst = ip_prefix_v4 (dst_prefix), src;
360  u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
361  ip_adjacency_t *dst_adj;
362 
363  if (src_prefix)
364  {
365  src = ip_prefix_v4 (src_prefix);
366  src_address_length = ip_prefix_len (src_prefix);
367  }
368  else
369  memset (&src, 0, sizeof (src));
370 
371  /* lookup dst adj */
372  p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
373  if (p == 0)
374  return p;
375 
376  dst_adj = ip_get_adjacency (lgm->lm4, p[0]);
377  return ip4_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
378  src_address_length);
379 }
380 
381 static u32
383  ip6_address_t * src, u32 address_length)
384 {
385  int rv;
386  BVT (clib_bihash_kv) kv, value;
387  ip6_src_fib_t *fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
388 
389  ip6_address_t *mask;
390 
391  ASSERT (address_length <= 128);
392 
393  mask = &fib->fib_masks[address_length];
394 
395  kv.key[0] = src->as_u64[0] & mask->as_u64[0];
396  kv.key[1] = src->as_u64[1] & mask->as_u64[1];
397  kv.key[2] = address_length;
398 
399  rv = BV (clib_bihash_search_inline_2) (&fib->ip6_lookup_table, &kv, &value);
400  if (rv == 0)
401  return value.value;
402 
403  return 0;
404 }
405 
406 static void
408 {
409  int i;
411  /* Note: bitmap reversed so this is in fact a longest prefix match */
412 
413  /* *INDENT-OFF* */
415  int dst_address_length = 128 - i;
416  vec_add1 (fib->prefix_lengths_in_search_order, dst_address_length);
417  }));
418  /* *INDENT-ON* */
419 }
420 
421 /* Rewrite of ip6_add_del_route() because it uses im6 to find the fib */
422 static void
425 {
426  ip_lookup_main_t *lm = lgm->lm6;
427  ip6_src_fib_t *fib;
428  ip6_address_t dst_address;
429  u32 dst_address_length, adj_index;
430  uword is_del;
431  u32 old_adj_index = ~0;
432  BVT (clib_bihash_kv) kv, value;
433 
435 
436  is_del = (a->flags & IP6_ROUTE_FLAG_DEL) != 0;
437 
438  /* Either create new adjacency or use given one depending on arguments. */
439  if (a->n_add_adj > 0)
440  {
441  ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
442  }
443  else
444  adj_index = a->adj_index;
445 
446  dst_address = a->dst_address;
447  dst_address_length = a->dst_address_length;
449 
450  ASSERT (dst_address_length < ARRAY_LEN (fib->fib_masks));
451  ip6_address_mask (&dst_address, &fib->fib_masks[dst_address_length]);
452 
453  /* refcount accounting */
454  if (is_del)
455  {
456  ASSERT (fib->dst_address_length_refcounts[dst_address_length] > 0);
457  if (--fib->dst_address_length_refcounts[dst_address_length] == 0)
458  {
461  128 - dst_address_length, 0);
463  }
464  }
465  else
466  {
467  fib->dst_address_length_refcounts[dst_address_length]++;
468 
471  128 - dst_address_length, 1);
473  }
474 
475  kv.key[0] = dst_address.as_u64[0];
476  kv.key[1] = dst_address.as_u64[1];
477  kv.key[2] = dst_address_length;
478 
479  if (BV (clib_bihash_search) (&fib->ip6_lookup_table, &kv, &value) == 0)
480  old_adj_index = value.value;
481 
482  if (is_del)
483  BV (clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 0 /* is_add */ );
484  else
485  {
486  /* Make sure adj index is valid. */
487  if (CLIB_DEBUG > 0)
488  (void) ip_get_adjacency (lm, adj_index);
489 
490  kv.value = adj_index;
491 
492  BV (clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 1 /* is_add */ );
493  }
494 
495  /* Avoid spurious reference count increments */
496  if (old_adj_index == adj_index
498  {
499  ip_adjacency_t *adj = ip_get_adjacency (lm, adj_index);
500  if (adj->share_count > 0)
501  adj->share_count--;
502  }
503 
504  /* Delete old adjacency index if present and changed. */
505  {
507  && old_adj_index != ~0 && old_adj_index != adj_index)
508  ip_del_adjacency (lm, old_adj_index);
509  }
510 }
511 
512 static void
514 {
515  uword i;
516 
517  for (i = 0; i < ARRAY_LEN (fib->fib_masks); i++)
518  {
519  u32 j, i0, i1;
520 
521  i0 = i / 32;
522  i1 = i % 32;
523 
524  for (j = 0; j < i0; j++)
525  fib->fib_masks[i].as_u32[j] = ~0;
526 
527  if (i1)
528  fib->fib_masks[i].as_u32[i0] =
529  clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
530  }
531 
532  if (fib->lookup_table_nbuckets == 0)
534 
536 
537  if (fib->lookup_table_size == 0)
539 
540  BV (clib_bihash_init) (&fib->ip6_lookup_table, "ip6 lookup table",
542 
543 }
544 
545 static int
546 ip6_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
547  ip_prefix_t * src_prefix, u32 table_id,
548  ip_adjacency_t * add_adj, u8 is_add)
549 {
550  u32 adj_index;
552  ip_adjacency_t *dst_adjp, dst_adj;
553  ip6_address_t dst = ip_prefix_v6 (dst_prefix), src;
554  u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
555  ip6_src_fib_t *src_fib;
556 
557  if (src_prefix)
558  {
559  src = ip_prefix_v6 (src_prefix);
560  src_address_length = ip_prefix_len (src_prefix);
561  }
562  else
563  memset (&src, 0, sizeof (src));
564 
565  /* lookup dst adj and create it if it doesn't exist */
566  adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
567 
568  if (is_add)
569  {
570  /* insert dst prefix to ip6 fib, if it's not in yet */
571  if (adj_index == 0)
572  {
573  /* allocate and init src ip6 fib */
574  pool_get (lgm->ip6_src_fibs, src_fib);
575  memset (src_fib, 0, sizeof (src_fib[0]));
576  ip6_src_fib_init (src_fib);
577 
578  memset (&dst_adj, 0, sizeof (dst_adj));
579 
580  /* reuse rewrite header to store pointer to src fib */
581  dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip6_src_fibs;
582 
583  /* dst adj should point to lisp gpe ip lookup */
585 
586  /* explicit_fib_index is used in IP6 FIB lookup, don't reuse it */
587  dst_adj.explicit_fib_index = ~0;
588  dst_adj.n_adj = 1;
589 
590  /* make sure we have different signatures for adj in different tables
591  * but with the same lookup_next_index and for adj in the same table
592  * but associated to different destinations */
593  dst_adj.if_address_index = table_id;
594  dst_adj.indirect.next_hop.ip6 = dst;
595 
596  memset (&a, 0, sizeof (a));
598  a.table_index_or_table_id = table_id; /* vrf */
599  a.adj_index = ~0;
600  a.dst_address_length = dst_address_length;
601  a.dst_address = dst;
603  a.add_adj = &dst_adj;
604  a.n_add_adj = 1;
605 
606  ip6_add_del_route (lgm->im6, &a);
607 
608  /* lookup dst adj to obtain the adj index */
609  adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst,
610  dst_address_length);
611 
612  /* make sure insertion succeeded */
613  if (CLIB_DEBUG)
614  {
615  ASSERT (adj_index != 0);
616  dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
617  ASSERT (dst_adjp->rewrite_header.sw_if_index
618  == dst_adj.rewrite_header.sw_if_index);
619  }
620  }
621  }
622  else
623  {
624  if (adj_index == 0)
625  {
627  ("Trying to delete inexistent dst route for %U. Aborting",
628  format_ip_prefix, dst_prefix);
629  return -1;
630  }
631  }
632 
633  dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
634 
635  /* add/del src prefix to src fib */
636  memset (&a, 0, sizeof (a));
638  a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
639  a.adj_index = ~0;
641  a.add_adj = add_adj;
642  a.n_add_adj = is_add ? 1 : 0;
643  /* if src prefix is null, add ::0 */
644  a.dst_address_length = src_address_length;
645  a.dst_address = src;
647 
648  /* make sure insertion succeeded */
649  if (CLIB_DEBUG && is_add)
650  {
651  u32 sai;
652  ip_adjacency_t *src_adjp;
653  sai = ip6_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
654  &src, src_address_length);
655  ASSERT (sai != 0);
656  src_adjp = ip_get_adjacency (lgm->lm6, sai);
657  ASSERT (src_adjp->if_address_index == add_adj->if_address_index);
658  }
659 
660  /* if a delete, check if there are elements left in the src fib */
661  if (!is_add)
662  {
663  src_fib = pool_elt_at_index (lgm->ip6_src_fibs,
664  dst_adjp->rewrite_header.sw_if_index);
665  if (!src_fib)
666  return 0;
667 
668  /* if there's nothing left */
670  (src_fib->non_empty_dst_address_length_bitmap) == 0)
671  {
672  /* remove src fib .. */
673  pool_put (lgm->ip6_src_fibs, src_fib);
674 
675  /* .. and remove dst route */
676  memset (&a, 0, sizeof (a));
678  a.table_index_or_table_id = table_id; /* vrf */
679  a.adj_index = ~0;
680  a.dst_address_length = dst_address_length;
681  a.dst_address = dst;
683 
684  ip6_add_del_route (lgm->im6, &a);
685  }
686  }
687 
688  return 0;
689 }
690 
691 static u32
692 ip6_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
693  ip_prefix_t * src_prefix, u32 table_id)
694 {
695  u32 adj_index;
696  ip6_address_t dst = ip_prefix_v6 (dst_prefix), src;
697  u32 dst_address_length = ip_prefix_len (dst_prefix), src_address_length = 0;
698  ip_adjacency_t *dst_adj;
699 
700  if (src_prefix)
701  {
702  src = ip_prefix_v6 (src_prefix);
703  src_address_length = ip_prefix_len (src_prefix);
704  }
705  else
706  memset (&src, 0, sizeof (src));
707 
708  /* lookup dst adj */
709  adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
710  if (adj_index == 0)
711  return adj_index;
712 
713  dst_adj = ip_get_adjacency (lgm->lm6, adj_index);
714  return ip6_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
715  src_address_length);
716 }
717 
718 int
719 ip_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
720  ip_prefix_t * src_prefix, u32 table_id,
721  ip_adjacency_t * add_adj, u8 is_add)
722 {
723  return (ip_prefix_version (dst_prefix) == IP4 ?
725  dst_prefix,
726  src_prefix,
727  table_id,
728  add_adj,
729  is_add);
730 }
731 
732 u32
733 ip_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
734  ip_prefix_t * src_prefix, u32 table_id)
735 {
736  if (ip_prefix_version (dst_prefix) == IP4)
737  {
738  u32 *adj_index = ip4_sd_fib_get_route (lgm, dst_prefix, src_prefix,
739  table_id);
740  return (adj_index == 0) ? 0 : adj_index[0];
741  }
742  else
743  return ip6_sd_fib_get_route (lgm, dst_prefix, src_prefix, table_id);
744 }
745 
746 always_inline void
748  ip4_address_t * addr0, u32 * src_adj_index0)
749 {
750  ip4_fib_mtrie_leaf_t leaf0, leaf1;
751  ip4_fib_mtrie_t *mtrie0;
752 
753  /* if default route not hit in ip4 lookup */
754  if (PREDICT_TRUE (src_fib_index0 != (u32) ~ 0))
755  {
756  mtrie0 = &vec_elt_at_index (lgm->ip4_src_fibs, src_fib_index0)->mtrie;
757 
758  leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
759  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
760  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
761  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
762  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
763 
764  /* Handle default route. */
765  leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
766  mtrie0->default_leaf : leaf0;
767  src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
768  }
769  else
770  src_adj_index0[0] = ~0;
771 }
772 
773 always_inline void
775  u32 src_fib_index1, ip4_address_t * addr0,
776  ip4_address_t * addr1, u32 * src_adj_index0,
777  u32 * src_adj_index1)
778 {
779  ip4_fib_mtrie_leaf_t leaf0, leaf1;
780  ip4_fib_mtrie_t *mtrie0, *mtrie1;
781 
782  /* if default route not hit in ip4 lookup */
783  if (PREDICT_TRUE
784  (src_fib_index0 != (u32) ~ 0 && src_fib_index1 != (u32) ~ 0))
785  {
786  mtrie0 = &vec_elt_at_index (lgm->ip4_src_fibs, src_fib_index0)->mtrie;
787  mtrie1 = &vec_elt_at_index (lgm->ip4_src_fibs, src_fib_index1)->mtrie;
788 
789  leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
790 
791  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
792  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 0);
793 
794  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
795  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 1);
796 
797  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
798  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
799 
800  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
801  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
802 
803  /* Handle default route. */
804  leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
805  mtrie0->default_leaf : leaf0;
806  leaf1 = (leaf1 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
807  mtrie1->default_leaf : leaf1;
808  src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
809  src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
810  }
811  else
812  {
813  ip4_src_fib_lookup_one (lgm, src_fib_index0, addr0, src_adj_index0);
814  ip4_src_fib_lookup_one (lgm, src_fib_index1, addr1, src_adj_index1);
815  }
816 }
817 
820  vlib_frame_t * from_frame)
821 {
822  u32 n_left_from, next_index, *from, *to_next;
824 
825  from = vlib_frame_vector_args (from_frame);
826  n_left_from = from_frame->n_vectors;
827 
828  next_index = node->cached_next_index;
829 
830  while (n_left_from > 0)
831  {
832  u32 n_left_to_next;
833 
834  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
835 
836  while (n_left_from >= 4 && n_left_to_next >= 2)
837  {
838  u32 bi0, bi1;
839  vlib_buffer_t *b0, *b1;
840  ip4_header_t *ip0, *ip1;
841  u32 dst_adj_index0, src_adj_index0, src_fib_index0;
842  u32 dst_adj_index1, src_adj_index1, src_fib_index1;
843  ip_adjacency_t *dst_adj0, *src_adj0, *dst_adj1, *src_adj1;
844  u32 next0, next1;
845 
846  next0 = next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
847 
848  /* Prefetch next iteration. */
849  {
850  vlib_buffer_t *p2, *p3;
851 
852  p2 = vlib_get_buffer (vm, from[2]);
853  p3 = vlib_get_buffer (vm, from[3]);
854 
855  vlib_prefetch_buffer_header (p2, LOAD);
856  vlib_prefetch_buffer_header (p3, LOAD);
857 
858  CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
859  CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
860  }
861 
862  bi0 = from[0];
863  bi1 = from[1];
864  to_next[0] = bi0;
865  to_next[1] = bi1;
866  from += 2;
867  to_next += 2;
868  n_left_to_next -= 2;
869  n_left_from -= 2;
870 
871  b0 = vlib_get_buffer (vm, bi0);
872  b1 = vlib_get_buffer (vm, bi1);
873 
874  ip0 = vlib_buffer_get_current (b0);
875  ip1 = vlib_buffer_get_current (b1);
876 
877  /* dst lookup was done by ip4 lookup */
878  dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
879  dst_adj_index1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX];
880 
881  dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
882  dst_adj1 = ip_get_adjacency (lgm->lm4, dst_adj_index1);
883 
884  src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
885  src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
886 
887  ip4_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
888  &ip0->src_address, &ip1->src_address,
889  &src_adj_index0, &src_adj_index1);
890 
891  /* if a source fib exists */
892  if (PREDICT_TRUE ((u32) ~ 0 != src_adj_index0
893  && (u32) ~ 0 != src_adj_index1))
894  {
895  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
896  vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
897 
898  src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
899  src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
900 
901  next0 = src_adj0->explicit_fib_index;
902  next1 = src_adj1->explicit_fib_index;
903 
904  /* prepare buffer for lisp-gpe output node */
905  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
906  src_adj0->rewrite_header.sw_if_index;
907  vnet_buffer (b1)->sw_if_index[VLIB_TX] =
908  src_adj1->rewrite_header.sw_if_index;
909 
910  /* if multipath: saved_lookup_next_index is reused to store
911  * nb of sub-tunnels. If greater than 1, multipath is on.
912  * Note that flow hash should be 0 after ipx lookup! */
913  if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
914  vnet_buffer (b0)->ip.flow_hash =
916 
917  if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
918  vnet_buffer (b1)->ip.flow_hash =
920  }
921  else
922  {
923  if ((u32) ~ 0 != src_adj_index0)
924  {
925  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
926  src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
927  next0 = src_adj0->explicit_fib_index;
928  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
929  src_adj0->rewrite_header.sw_if_index;
930 
931  if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
932  vnet_buffer (b0)->ip.flow_hash =
934  }
935  else
936  {
937  next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
938  }
939 
940  if ((u32) ~ 0 != src_adj_index1)
941  {
942  vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
943  src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
944  next1 = src_adj1->explicit_fib_index;
945  vnet_buffer (b1)->sw_if_index[VLIB_TX] =
946  src_adj1->rewrite_header.sw_if_index;
947  if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
948  vnet_buffer (b1)->ip.flow_hash =
950  }
951  else
952  {
953  next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
954  }
955  }
956 
957  /* mark the packets for CP lookup if needed */
958  if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
959  vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
960  if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next1))
961  vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_IP;
962 
963  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
964  n_left_to_next, bi0, bi1, next0,
965  next1);
966  }
967 
968  while (n_left_from > 0 && n_left_to_next > 0)
969  {
970  vlib_buffer_t *b0;
971  ip4_header_t *ip0;
972  u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
973  u32 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
974  ip_adjacency_t *dst_adj0, *src_adj0;
975 
976  bi0 = from[0];
977  to_next[0] = bi0;
978  from += 1;
979  to_next += 1;
980  n_left_from -= 1;
981  n_left_to_next -= 1;
982 
983  b0 = vlib_get_buffer (vm, bi0);
984  ip0 = vlib_buffer_get_current (b0);
985 
986  /* dst lookup was done by ip4 lookup */
987  dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
988  dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
989  src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
990 
991  /* do src lookup */
992  ip4_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
993  &src_adj_index0);
994 
995  /* if a source fib exists */
996  if (PREDICT_TRUE ((u32) ~ 0 != src_adj_index0))
997  {
998  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
999  src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
1000  next0 = src_adj0->explicit_fib_index;
1001 
1002  /* prepare packet for lisp-gpe output node */
1003  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1004  src_adj0->rewrite_header.sw_if_index;
1005 
1006  /* if multipath: saved_lookup_next_index is reused to store
1007  * nb of sub-tunnels. If greater than 1, multipath is on */
1008  if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
1009  vnet_buffer (b0)->ip.flow_hash =
1011  }
1012  else
1013  {
1014  next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1015  }
1016 
1017  if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1018  vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1019 
1020  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1021  n_left_to_next, bi0, next0);
1022  }
1023  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1024  }
1025  return from_frame->n_vectors;
1026 }
1027 
1028 /* *INDENT-OFF* */
1029 VLIB_REGISTER_NODE (lgpe_ip4_lookup_node) = {
1030  .function = lgpe_ip4_lookup,
1031  .name = "lgpe-ip4-lookup",
1032  .vector_size = sizeof (u32),
1033 
1035 
1036  .n_next_nodes = LGPE_IP4_LOOKUP_N_NEXT,
1037  .next_nodes = {
1038 #define _(sym,str) [LGPE_IP4_LOOKUP_NEXT_##sym] = str,
1040 #undef _
1041  },
1042 };
1043 /* *INDENT-ON* */
1044 
1045 static u32
1047  ip6_address_t * src)
1048 {
1049  int i, len;
1050  int rv;
1051  BVT (clib_bihash_kv) kv, value;
1052  ip6_src_fib_t *fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
1053 
1055 
1056  for (i = 0; i < len; i++)
1057  {
1058  int dst_address_length = fib->prefix_lengths_in_search_order[i];
1059  ip6_address_t *mask;
1060 
1061  ASSERT (dst_address_length >= 0 && dst_address_length <= 128);
1062 
1063  mask = &fib->fib_masks[dst_address_length];
1064 
1065  kv.key[0] = src->as_u64[0] & mask->as_u64[0];
1066  kv.key[1] = src->as_u64[1] & mask->as_u64[1];
1067  kv.key[2] = dst_address_length;
1068 
1069  rv =
1070  BV (clib_bihash_search_inline_2) (&fib->ip6_lookup_table, &kv,
1071  &value);
1072  if (rv == 0)
1073  return value.value;
1074  }
1075 
1076  return 0;
1077 }
1078 
1079 always_inline void
1081  ip6_address_t * addr0, u32 * src_adj_index0)
1082 {
1083  /* if default route not hit in ip6 lookup */
1084  if (PREDICT_TRUE (src_fib_index0 != (u32) ~ 0))
1085  src_adj_index0[0] = ip6_src_fib_lookup (lgm, src_fib_index0, addr0);
1086  else
1087  src_adj_index0[0] = ~0;
1088 }
1089 
1090 always_inline void
1092  u32 src_fib_index1, ip6_address_t * addr0,
1093  ip6_address_t * addr1, u32 * src_adj_index0,
1094  u32 * src_adj_index1)
1095 {
1096  /* if default route not hit in ip6 lookup */
1097  if (PREDICT_TRUE
1098  (src_fib_index0 != (u32) ~ 0 && src_fib_index1 != (u32) ~ 0))
1099  {
1100  src_adj_index0[0] = ip6_src_fib_lookup (lgm, src_fib_index0, addr0);
1101  src_adj_index1[0] = ip6_src_fib_lookup (lgm, src_fib_index1, addr1);
1102  }
1103  else
1104  {
1105  ip6_src_fib_lookup_one (lgm, src_fib_index0, addr0, src_adj_index0);
1106  ip6_src_fib_lookup_one (lgm, src_fib_index1, addr1, src_adj_index1);
1107  }
1108 }
1109 
1112  vlib_frame_t * from_frame)
1113 {
1114  u32 n_left_from, next_index, *from, *to_next;
1116 
1117  from = vlib_frame_vector_args (from_frame);
1118  n_left_from = from_frame->n_vectors;
1119 
1120  next_index = node->cached_next_index;
1121 
1122  while (n_left_from > 0)
1123  {
1124  u32 n_left_to_next;
1125 
1126  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1127 
1128  while (n_left_from >= 4 && n_left_to_next >= 2)
1129  {
1130  u32 bi0, bi1;
1131  vlib_buffer_t *b0, *b1;
1132  ip6_header_t *ip0, *ip1;
1133  u32 dst_adj_index0, src_adj_index0, src_fib_index0, dst_adj_index1,
1134  src_adj_index1, src_fib_index1;
1135  ip_adjacency_t *dst_adj0, *src_adj0, *dst_adj1, *src_adj1;
1136  u32 next0, next1;
1137 
1138  next0 = next1 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
1139 
1140  /* Prefetch next iteration. */
1141  {
1142  vlib_buffer_t *p2, *p3;
1143 
1144  p2 = vlib_get_buffer (vm, from[2]);
1145  p3 = vlib_get_buffer (vm, from[3]);
1146 
1147  vlib_prefetch_buffer_header (p2, LOAD);
1148  vlib_prefetch_buffer_header (p3, LOAD);
1149 
1150  CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
1151  CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
1152  }
1153 
1154  bi0 = from[0];
1155  bi1 = from[1];
1156  to_next[0] = bi0;
1157  to_next[1] = bi1;
1158  from += 2;
1159  to_next += 2;
1160  n_left_to_next -= 2;
1161  n_left_from -= 2;
1162 
1163  b0 = vlib_get_buffer (vm, bi0);
1164  b1 = vlib_get_buffer (vm, bi1);
1165 
1166  ip0 = vlib_buffer_get_current (b0);
1167  ip1 = vlib_buffer_get_current (b1);
1168 
1169  /* dst lookup was done by ip6 lookup */
1170  dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
1171  dst_adj_index1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX];
1172 
1173  dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
1174  dst_adj1 = ip_get_adjacency (lgm->lm6, dst_adj_index1);
1175 
1176  src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1177  src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
1178 
1179  ip6_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
1180  &ip0->src_address, &ip1->src_address,
1181  &src_adj_index0, &src_adj_index1);
1182 
1183  /* if a source fib exists */
1184  if (PREDICT_TRUE ((u32) ~ 0 != src_adj_index0
1185  && (u32) ~ 0 != src_adj_index1))
1186  {
1187  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1188  vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1189 
1190  src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1191  src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
1192 
1193  next0 = src_adj0->explicit_fib_index;
1194  next1 = src_adj1->explicit_fib_index;
1195 
1196  /* prepare buffer for lisp-gpe output node */
1197  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1198  src_adj0->rewrite_header.sw_if_index;
1199  vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1200  src_adj1->rewrite_header.sw_if_index;
1201 
1202  /* if multipath: saved_lookup_next_index is reused to store
1203  * nb of sub-tunnels. If greater than 1, multipath is on.
1204  * Note that flow hash should be 0 after ipx lookup! */
1205  if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
1206  vnet_buffer (b0)->ip.flow_hash =
1208 
1209  if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
1210  vnet_buffer (b1)->ip.flow_hash =
1212  }
1213  else
1214  {
1215  if (src_adj_index0 != (u32) ~ 0)
1216  {
1217  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1218  src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1219  next0 = src_adj0->explicit_fib_index;
1220  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1221  src_adj0->rewrite_header.sw_if_index;
1222 
1223  if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
1224  vnet_buffer (b0)->ip.flow_hash =
1226  }
1227  else
1228  {
1229  next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1230  }
1231 
1232  if (src_adj_index1 != (u32) ~ 0)
1233  {
1234  vnet_buffer (b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1235  src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
1236  next1 = src_adj1->explicit_fib_index;
1237  vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1238  src_adj1->rewrite_header.sw_if_index;
1239 
1240  if (PREDICT_TRUE (src_adj1->saved_lookup_next_index > 1))
1241  vnet_buffer (b1)->ip.flow_hash =
1243  }
1244  else
1245  {
1246  next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1247  }
1248  }
1249 
1250  /* mark the packets for CP lookup if needed */
1251  if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1252  vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1253  if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next1))
1254  vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_IP;
1255 
1256  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1257  n_left_to_next, bi0, bi1, next0,
1258  next1);
1259  }
1260 
1261  while (n_left_from > 0 && n_left_to_next > 0)
1262  {
1263  vlib_buffer_t *b0;
1264  ip6_header_t *ip0;
1265  u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
1266  u32 next0 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
1267  ip_adjacency_t *dst_adj0, *src_adj0;
1268 
1269  bi0 = from[0];
1270  to_next[0] = bi0;
1271  from += 1;
1272  to_next += 1;
1273  n_left_from -= 1;
1274  n_left_to_next -= 1;
1275 
1276  b0 = vlib_get_buffer (vm, bi0);
1277  ip0 = vlib_buffer_get_current (b0);
1278 
1279  /* dst lookup was done by ip6 lookup */
1280  dst_adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
1281  dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
1282  src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1283 
1284  /* do src lookup */
1285  ip6_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
1286  &src_adj_index0);
1287 
1288  /* if a source fib exists */
1289  if (PREDICT_TRUE (src_adj_index0 != (u32) ~ 0))
1290  {
1291  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1292  src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1293  next0 = src_adj0->explicit_fib_index;
1294 
1295  /* prepare packet for lisp-gpe output node */
1296  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1297  src_adj0->rewrite_header.sw_if_index;
1298 
1299  /* if multipath: saved_lookup_next_index is reused to store
1300  * nb of sub-tunnels. If greater than 1, multipath is on */
1301  if (PREDICT_TRUE (src_adj0->saved_lookup_next_index > 1))
1302  vnet_buffer (b0)->ip.flow_hash =
1304  }
1305  else
1306  {
1307  next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1308  }
1309 
1310  /* mark the packets for CP lookup if needed */
1311  if (PREDICT_FALSE (LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1312  vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1313 
1314  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1315  n_left_to_next, bi0, next0);
1316  }
1317  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1318  }
1319  return from_frame->n_vectors;
1320 }
1321 
1322 /* *INDENT-OFF* */
1323 VLIB_REGISTER_NODE (lgpe_ip6_lookup_node) = {
1324  .function = lgpe_ip6_lookup,
1325  .name = "lgpe-ip6-lookup",
1326  .vector_size = sizeof (u32),
1327 
1329 
1330  .n_next_nodes = LGPE_IP6_LOOKUP_N_NEXT,
1331  .next_nodes = {
1332 #define _(sym,str) [LGPE_IP6_LOOKUP_NEXT_##sym] = str,
1334 #undef _
1335  },
1336 };
1337 /* *INDENT-ON* */
1338 
1339 /*
1340  * fd.io coding-style-patch-verification: ON
1341  *
1342  * Local Variables:
1343  * eval: (c-set-style "gnu")
1344  * End:
1345  */
#define ip_prefix_v4(_a)
Definition: lisp_types.h:61
struct ip_adjacency_t::@143::@147 indirect
IP_LOOKUP_NEXT_INDIRECT only.
static void ip6_address_mask(ip6_address_t *a, ip6_address_t *mask)
Definition: ip6_packet.h:201
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:457
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
u32 ip4_lookup_next_lgpe_ip4_lookup
Definition: lisp_gpe.h:199
a
Definition: bitmap.h:516
u16 saved_lookup_next_index
Highest possible perf subgraph arc interposition, e.g.
Definition: lookup.h:189
static uword lgpe_ip6_lookup(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: ip_forward.c:1111
ip4_address_t src_address
Definition: ip4_packet.h:138
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
u16 n_adj
Number of adjecencies in block.
Definition: lookup.h:176
ip_lookup_next_t lookup_next_index
Definition: lookup.h:180
#define PREDICT_TRUE(x)
Definition: clib.h:98
u64 as_u64[2]
Definition: ip6_packet.h:50
IP unicast adjacency.
Definition: lookup.h:164
#define ip_prefix_len(_a)
Definition: lisp_types.h:60
i32 dst_address_length_refcounts[129]
Definition: lisp_gpe.h:155
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
u32 share_count
Number of FIB entries sharing this adjacency.
Definition: lookup.h:216
ip_adjacency_t * ip_add_adjacency(ip_lookup_main_t *lm, ip_adjacency_t *copy_adj, u32 n_adj, u32 *adj_index_return)
Definition: lookup.c:167
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
ip6_address_t fib_masks[129]
Definition: lisp_gpe.h:154
#define vec_bytes(v)
Number of data bytes in vector.
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
static void ip6_src_fib_lookup_one(lisp_gpe_main_t *lgm, u32 src_fib_index0, ip6_address_t *addr0, u32 *src_adj_index0)
Definition: ip_forward.c:1080
ip6_address_t src_address
Definition: ip6_packet.h:298
#define ip_prefix_version(_a)
Definition: lisp_types.h:59
static void vlib_smp_unsafe_warning(void)
Definition: threads.h:186
#define IP4_FIB_MTRIE_LEAF_EMPTY
Definition: ip4_mtrie.h:54
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static u8 ip4_fib_is_empty(ip4_fib_t *fib)
Definition: ip_forward.c:190
int clib_bihash_add_del(clib_bihash *h, clib_bihash_kv *add_v, int is_add)
Add or delete a (key,value) pair from a bi-hash table.
ip6_main_t * im6
Definition: lisp_gpe.h:214
#define always_inline
Definition: clib.h:84
static uword pow2_mask(uword x)
Definition: clib.h:251
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
u32 ip4_fib_mtrie_leaf_t
Definition: ip4_mtrie.h:52
uword * old_hash_values
Definition: ip4.h:53
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define IP6_FIB_DEFAULT_HASH_NUM_BUCKETS
Definition: ip6.h:55
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 int ip6_sd_fib_add_del_route(lisp_gpe_main_t *lgm, ip_prefix_t *dst_prefix, ip_prefix_t *src_prefix, u32 table_id, ip_adjacency_t *add_adj, u8 is_add)
Definition: ip_forward.c:546
static int ip4_sd_fib_add_del_route(lisp_gpe_main_t *lgm, ip_prefix_t *dst_prefix, ip_prefix_t *src_prefix, u32 table_id, ip_adjacency_t *add_adj, u8 is_add)
Definition: ip_forward.c:210
static void ip4_src_fib_lookup_two(lisp_gpe_main_t *lgm, u32 src_fib_index0, u32 src_fib_index1, ip4_address_t *addr0, ip4_address_t *addr1, u32 *src_adj_index0, u32 *src_adj_index1)
Definition: ip_forward.c:774
#define clib_warning(format, args...)
Definition: error.h:59
u32 table_index_or_table_id
Definition: ip6.h:367
static uword lgpe_ip4_lookup(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: ip_forward.c:819
static void hash_set_flags(void *v, uword flags)
Definition: hash.h:152
uword * new_hash_values
Definition: ip4.h:53
void ip6_add_del_route(ip6_main_t *im, ip6_add_del_route_args_t *args)
Definition: ip6_forward.c:208
static uword hash_value_bytes(hash_t *h)
Definition: hash.h:292
void ip_del_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.c:314
static u32 ip4_fib_mtrie_leaf_get_adj_index(ip4_fib_mtrie_leaf_t n)
Definition: ip4_mtrie.h:66
ip6_src_fib_t * ip6_src_fibs
Definition: lisp_gpe.h:190
ip4_src_fib_t * ip4_src_fibs
Definition: lisp_gpe.h:189
static hash_t * hash_header(void *v)
Definition: hash.h:110
ip6_address_t dst_address
Definition: ip6.h:370
#define hash_get(h, key)
Definition: hash.h:248
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
static void ip4_src_fib_lookup_one(lisp_gpe_main_t *lgm, u32 src_fib_index0, ip4_address_t *addr0, u32 *src_adj_index0)
Definition: ip_forward.c:747
u8 * prefix_lengths_in_search_order
Definition: lisp_gpe.h:153
typedef CLIB_PACKED(struct ip4_route{ip4_address_t address;u32 address_length:6;u32 index:26;})
Definition: ip_forward.c:141
void * ip4_get_route(ip4_main_t *im, u32 fib_index_or_table_id, u32 flags, u8 *address, u32 address_length)
Definition: ip4_forward.c:537
#define ip_prefix_v6(_a)
Definition: lisp_types.h:62
#define IP6_FIB_DEFAULT_HASH_MEMORY_SIZE
Definition: ip6.h:56
ip_adjacency_t * add_adj
Definition: ip6.h:379
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
static u32 ip6_compute_flow_hash(ip6_header_t *ip, u32 flow_hash_config)
Definition: ip6.h:526
u32 ip6_lookup_next_lgpe_ip6_lookup
Definition: lisp_gpe.h:200
#define PREDICT_FALSE(x)
Definition: clib.h:97
u32 ip6_get_route(ip6_main_t *im, u32 fib_index_or_table_id, u32 flags, ip6_address_t *address, u32 address_length)
Definition: ip6_forward.c:572
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
static ip4_fib_mtrie_leaf_t ip4_fib_mtrie_lookup_step(ip4_fib_mtrie_t *m, ip4_fib_mtrie_leaf_t current_leaf, ip4_address_t *dst_address, u32 dst_address_byte_index)
Definition: ip4_mtrie.h:145
static void * ip4_sd_fib_get_route(lisp_gpe_main_t *lgm, ip_prefix_t *dst_prefix, ip_prefix_t *src_prefix, u32 table_id)
Definition: ip_forward.c:355
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:130
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:348
void clib_bihash_init(clib_bihash *h, char *name, u32 nbuckets, uword memory_size)
initialize a bounded index extensible hash table
static void ip6_src_fib_init(ip6_src_fib_t *fib)
Definition: ip_forward.c:513
ip_adjacency_t * add_adj
Definition: ip4.h:337
BVT(clib_bihash)
Definition: l2_fib.c:577
static void * ip4_sd_get_src_route(lisp_gpe_main_t *lgm, u32 src_fib_index, ip4_address_t *src, u32 address_length)
Definition: ip_forward.c:129
u32 as_u32[4]
Definition: ip6_packet.h:49
u16 n_vectors
Definition: node.h:344
#define IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY
Definition: ip6.h:355
void ip4_mtrie_init(ip4_fib_mtrie_t *m)
Definition: ip4_mtrie.c:353
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
int ip_sd_fib_add_del_route(lisp_gpe_main_t *lgm, ip_prefix_t *dst_prefix, ip_prefix_t *src_prefix, u32 table_id, ip_adjacency_t *add_adj, u8 is_add)
Definition: ip_forward.c:719
u32 ip_sd_fib_get_route(lisp_gpe_main_t *lgm, ip_prefix_t *dst_prefix, ip_prefix_t *src_prefix, u32 table_id)
Definition: ip_forward.c:733
static void ip4_fib_init_adj_index_by_dst_address(ip_lookup_main_t *lm, ip4_fib_t *fib, u32 address_length)
Definition: ip_forward.c:47
Definition: ip4.h:48
static u32 ip6_src_fib_lookup(lisp_gpe_main_t *lgm, u32 src_fib_index, ip6_address_t *src)
Definition: ip_forward.c:1046
#define IP6_ROUTE_FLAG_DEL
Definition: ip6.h:352
#define ARRAY_LEN(x)
Definition: clib.h:59
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:272
lisp_gpe_main_t lisp_gpe_main
Definition: lisp_gpe.c:19
#define IP4_ROUTE_FLAG_DEL
Definition: ip4.h:309
#define foreach_lgpe_ip4_lookup_next
Definition: lisp_gpe.h:312
#define hash_create(elts, value_bytes)
Definition: hash.h:647
u16 cached_next_index
Definition: node.h:462
uword * non_empty_dst_address_length_bitmap
Definition: lisp_gpe.h:152
static uword hash_elts(void *v)
Definition: hash.h:117
#define ASSERT(truth)
#define IP4_FIB_MTRIE_LEAF_ROOT
Definition: ip4_mtrie.h:55
unsigned int u32
Definition: types.h:88
ip4_address_t dst_address
Definition: ip4.h:328
#define vnet_buffer(b)
Definition: buffer.h:335
#define IP4_ROUTE_FLAG_ADD
Definition: ip4.h:308
int clib_bihash_search(clib_bihash *h, clib_bihash_kv *search_v, clib_bihash_kv *return_v)
Search a bi-hash table.
static void ip4_sd_fib_add_del_src_route(lisp_gpe_main_t *lgm, ip4_add_del_route_args_t *a)
Definition: ip_forward.c:72
u32 fib_result_n_words
Definition: lookup.h:456
#define foreach_lgpe_ip6_lookup_next
Definition: lisp_gpe.h:324
#define IP_FLOW_HASH_DEFAULT
Default: 5-tuple without the "reverse" bit.
Definition: lookup.h:150
u8 * format_ip_prefix(u8 *s, va_list *args)
Definition: lisp_types.c:160
u64 uword
Definition: types.h:112
static uword clib_bitmap_count_set_bits(uword *ai)
Return the number of set bits in a bitmap.
Definition: bitmap.h:441
static void compute_prefix_lengths_in_search_order(ip6_src_fib_t *fib)
Definition: ip_forward.c:407
uword lookup_table_size
Definition: lisp_gpe.h:159
Definition: defs.h:47
ip_lookup_main_t * lm4
Definition: lisp_gpe.h:215
static void ip6_sd_fib_add_del_src_route(lisp_gpe_main_t *lgm, ip6_add_del_route_args_t *a)
Definition: ip_forward.c:423
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
ip4_main_t * im4
Definition: lisp_gpe.h:213
#define hash_foreach_pair(p, v, body)
Definition: hash.h:338
static uword max_log2(uword x)
Definition: clib.h:222
static void ip6_src_fib_lookup_two(lisp_gpe_main_t *lgm, u32 src_fib_index0, u32 src_fib_index1, ip6_address_t *addr0, ip6_address_t *addr1, u32 *src_adj_index0, u32 *src_adj_index1)
Definition: ip_forward.c:1091
#define IP4_ROUTE_FLAG_FIB_INDEX
Definition: ip4.h:311
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:251
ip4_fib_mtrie_t mtrie
Definition: ip4.h:56
u32 table_index_or_table_id
Definition: ip4.h:325
Definition: lisp_types.h:24
#define IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY
Definition: ip4.h:312
static u32 ip4_compute_flow_hash(ip4_header_t *ip, u32 flow_hash_config)
Definition: ip4.h:452
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:163
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
#define IP4_ROUTE_FLAG_TABLE_ID
Definition: ip4.h:310
u8 data[0]
Packet data.
Definition: buffer.h:151
#define IP6_ROUTE_FLAG_ADD
Definition: ip6.h:351
u32 if_address_index
Interface address index for this local/arp adjacency.
Definition: lookup.h:172
#define vec_foreach(var, vec)
Vector iterator.
i16 explicit_fib_index
Force re-lookup in a different FIB.
Definition: lookup.h:185
u32 lookup_table_nbuckets
Definition: lisp_gpe.h:158
uword * adj_index_by_dst_address[33]
Definition: ip4.h:50
#define IP6_ROUTE_FLAG_TABLE_ID
Definition: ip6.h:353
void ip4_add_del_route(ip4_main_t *im, ip4_add_del_route_args_t *args)
Definition: ip4_forward.c:228
ip_lookup_main_t * lm6
Definition: lisp_gpe.h:216
u32 flags
Definition: vhost-user.h:76
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:445
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
format_function_t format_ip4_address_and_length
Definition: format.h:72
#define HASH_FLAG_NO_AUTO_SHRINK
Definition: hash.h:64
static u32 ip6_sd_get_src_route(lisp_gpe_main_t *lgm, u32 src_fib_index, ip6_address_t *src, u32 address_length)
Definition: ip_forward.c:382
static void ip4_sd_fib_set_adj_index(lisp_gpe_main_t *lgm, ip4_fib_t *fib, u32 flags, u32 dst_address_u32, u32 dst_address_length, u32 adj_index)
Definition: ip_forward.c:20
static u32 ip6_sd_fib_get_route(lisp_gpe_main_t *lgm, ip_prefix_t *dst_prefix, ip_prefix_t *src_prefix, u32 table_id)
Definition: ip_forward.c:692
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
uword key
Definition: hash.h:161
u32 fib_result_n_bytes
Number of bytes in a fib result.
Definition: lookup.h:456
static ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:480
ip4_fib_mtrie_leaf_t default_leaf
Definition: ip4_mtrie.h:123