fcb453c64860ceddcb0f628a65d80b9be841e1e7
[vpp.git] / vnet / vnet / lisp-gpe / ip_forward.c
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
20 ip4_sd_fib_set_adj_index (lisp_gpe_main_t * lgm, ip4_fib_t * fib, u32 flags,
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,
41                      fib->old_hash_values);
42
43   fib->adj_index_by_dst_address[dst_address_length] = hash;
44 }
45
46 /* copied from ip4_forward since it's static */
47 static void
48 ip4_fib_init_adj_index_by_dst_address (ip_lookup_main_t * lm,
49                                        ip4_fib_t * fib,
50                                        u32 address_length)
51 {
52   hash_t * h;
53   uword max_index;
54
55   ASSERT (lm->fib_result_n_bytes >= sizeof (uword));
56   lm->fib_result_n_words = round_pow2 (lm->fib_result_n_bytes, sizeof(uword))
57       / sizeof(uword);
58
59   fib->adj_index_by_dst_address[address_length] =
60     hash_create (32 /* elts */, lm->fib_result_n_words * sizeof (uword));
61
62   hash_set_flags (fib->adj_index_by_dst_address[address_length],
63                   HASH_FLAG_NO_AUTO_SHRINK);
64
65   h = hash_header (fib->adj_index_by_dst_address[address_length]);
66   max_index = (hash_value_bytes (h) / sizeof (fib->new_hash_values[0])) - 1;
67
68   /* Initialize new/old hash value vectors. */
69   vec_validate_init_empty (fib->new_hash_values, max_index, ~0);
70   vec_validate_init_empty (fib->old_hash_values, max_index, ~0);
71 }
72
73 static void
74 ip4_sd_fib_add_del_src_route (lisp_gpe_main_t * lgm,
75                               ip4_add_del_route_args_t * a)
76 {
77   ip_lookup_main_t * lm = lgm->lm4;
78   ip4_fib_t * fib;
79   u32 dst_address, dst_address_length, adj_index, old_adj_index;
80   uword * hash, is_del;
81
82   /* Either create new adjacency or use given one depending on arguments. */
83   if (a->n_add_adj > 0)
84       ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
85   else
86     adj_index = a->adj_index;
87
88   dst_address = a->dst_address.data_u32;
89   dst_address_length = a->dst_address_length;
90
91   fib = pool_elt_at_index(lgm->ip4_src_fibs, a->table_index_or_table_id);
92
93   if (! fib->adj_index_by_dst_address[dst_address_length])
94     ip4_fib_init_adj_index_by_dst_address (lm, fib, dst_address_length);
95
96   hash = fib->adj_index_by_dst_address[dst_address_length];
97
98   is_del = (a->flags & IP4_ROUTE_FLAG_DEL) != 0;
99
100   if (is_del)
101     {
102       fib->old_hash_values[0] = ~0;
103       hash = _hash_unset (hash, dst_address, fib->old_hash_values);
104       fib->adj_index_by_dst_address[dst_address_length] = hash;
105     }
106   else
107     ip4_sd_fib_set_adj_index (lgm, fib, a->flags, dst_address,
108                               dst_address_length, adj_index);
109
110   old_adj_index = fib->old_hash_values[0];
111
112   /* Avoid spurious reference count increments */
113   if (old_adj_index == adj_index
114       && adj_index != ~0
115       && !(a->flags & IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
116     {
117       ip_adjacency_t * adj = ip_get_adjacency (lm, adj_index);
118       if (adj->share_count > 0)
119         adj->share_count --;
120     }
121
122   ip4_fib_mtrie_add_del_route (fib, a->dst_address, dst_address_length,
123                                is_del ? old_adj_index : adj_index,
124                                is_del);
125
126   /* Delete old adjacency index if present and changed. */
127   if (! (a->flags & IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY)
128       && old_adj_index != ~0
129       && old_adj_index != adj_index)
130     ip_del_adjacency (lm, old_adj_index);
131 }
132
133 static void *
134 ip4_sd_get_src_route (lisp_gpe_main_t * lgm, u32 src_fib_index,
135                       ip4_address_t * src, u32 address_length)
136 {
137   ip4_fib_t * fib = pool_elt_at_index (lgm->ip4_src_fibs, src_fib_index);
138   uword * hash, * p;
139
140   hash = fib->adj_index_by_dst_address[address_length];
141   p = hash_get (hash, src->as_u32);
142   return (void *) p;
143 }
144
145 typedef CLIB_PACKED (struct ip4_route {
146   ip4_address_t address;
147   u32 address_length : 6;
148   u32 index : 26;
149 }) ip4_route_t;
150
151 void
152 ip4_sd_fib_clear_src_fib (lisp_gpe_main_t * lgm, ip4_fib_t * fib)
153 {
154   ip4_route_t * routes = 0, * r;
155   u32 i;
156
157   vec_reset_length (routes);
158
159   for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++) {
160       uword * hash = fib->adj_index_by_dst_address[i];
161       hash_pair_t * p;
162       ip4_route_t x;
163
164       x.address_length = i;
165
166       hash_foreach_pair (p, hash,
167       ({
168           x.address.data_u32 = p->key;
169           vec_add1 (routes, x);
170       }));
171   }
172
173   vec_foreach (r, routes) {
174       ip4_add_del_route_args_t a;
175
176       memset (&a, 0, sizeof (a));
177       a.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL;
178       a.table_index_or_table_id = fib - lgm->ip4_src_fibs;
179       a.dst_address = r->address;
180       a.dst_address_length = r->address_length;
181       a.adj_index = ~0;
182
183       ip4_sd_fib_add_del_src_route (lgm, &a);
184   }
185 }
186
187 static u8
188 ip4_fib_is_empty (ip4_fib_t * fib)
189 {
190   u8 fib_is_empty;
191   int i;
192
193   fib_is_empty = 1;
194   for (i = ARRAY_LEN (fib->adj_index_by_dst_address) - 1; i >= 0; i--)
195     {
196       uword * hash = fib->adj_index_by_dst_address[i];
197       uword n_elts = hash_elts (hash);
198       if (n_elts)
199         {
200           fib_is_empty = 0;
201           break;
202         }
203     }
204   return fib_is_empty;
205 }
206
207 static int
208 ip4_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
209                           ip_prefix_t * src_prefix, u32 table_id,
210                           ip_adjacency_t * add_adj, u8 is_add)
211 {
212   uword * p;
213   ip4_add_del_route_args_t a;
214   ip_adjacency_t * dst_adjp, dst_adj;
215   ip4_address_t dst = ip_prefix_v4(dst_prefix), src;
216   u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
217   ip4_fib_t * src_fib;
218
219   if (src_prefix)
220     {
221       src = ip_prefix_v4(src_prefix);
222       src_address_length = ip_prefix_len(src_prefix);
223     }
224   else
225     memset(&src, 0, sizeof(src));
226
227   /* lookup dst adj */
228   p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
229
230   if (is_add)
231     {
232       /* insert dst prefix to ip4 fib, if it's not in yet */
233       if (p == 0)
234         {
235           /* allocate and init src ip4 fib */
236           pool_get(lgm->ip4_src_fibs, src_fib);
237           ip4_mtrie_init (&src_fib->mtrie);
238
239           /* configure adjacency */
240           memset(&dst_adj, 0, sizeof(dst_adj));
241
242           /* reuse rewrite header to store pointer to src fib */
243           dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip4_src_fibs;
244
245           /* dst adj should point to lisp gpe lookup */
246           dst_adj.lookup_next_index = lgm->ip4_lookup_next_lgpe_ip4_lookup;
247
248           /* make sure we have different signatures for adj in different tables
249            * but with the same lookup_next_index */
250           dst_adj.explicit_fib_index = table_id;
251
252           dst_adj.n_adj = 1;
253
254           memset(&a, 0, sizeof(a));
255           a.flags = IP4_ROUTE_FLAG_TABLE_ID;
256           a.table_index_or_table_id = table_id; /* vrf */
257           a.adj_index = ~0;
258           a.dst_address_length = dst_address_length;
259           a.dst_address = dst;
260           a.flags |= IP4_ROUTE_FLAG_ADD;
261           a.add_adj = &dst_adj;
262           a.n_add_adj = 1;
263
264           ip4_add_del_route (lgm->im4, &a);
265
266           /* lookup dst adj to obtain the adj index */
267           p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8,
268                              dst_address_length);
269
270           ASSERT(p != 0);
271
272           /* make sure insertion succeeded */
273           if (CLIB_DEBUG)
274             {
275               dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
276               ASSERT(dst_adjp->rewrite_header.sw_if_index
277                       == dst_adj.rewrite_header.sw_if_index);
278             }
279         }
280     }
281   else
282     {
283       if (p == 0)
284         {
285           clib_warning("Trying to delete inexistent dst route for %U. Aborting",
286                        format_ip4_address_and_length, dst.as_u8,
287                        dst_address_length);
288           return -1;
289         }
290     }
291
292   dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
293
294   /* make sure adj signature is unique, i.e., fill in mcast_group_index
295    * and saved_lookup_next index with data that makes this adj unique.
296    * All these fields are (and should stay that way) unused by LISP. */
297   add_adj->mcast_group_index = table_id;
298   add_adj->saved_lookup_next_index = dst_adjp->rewrite_header.sw_if_index;
299
300   /* add/del src prefix to src fib */
301   memset(&a, 0, sizeof(a));
302   a.flags = IP4_ROUTE_FLAG_TABLE_ID;
303   a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
304   a.adj_index = ~0;
305   a.flags |= is_add ? IP4_ROUTE_FLAG_ADD : IP4_ROUTE_FLAG_DEL;
306   a.add_adj = add_adj;
307   a.n_add_adj = is_add ? 1 : 0;
308   /* if src prefix is null, add 0/0 */
309   a.dst_address_length = src_address_length;
310   a.dst_address = src;
311   ip4_sd_fib_add_del_src_route (lgm, &a);
312
313   /* make sure insertion succeeded */
314   if (CLIB_DEBUG)
315     {
316       uword * sai;
317       ip_adjacency_t * src_adjp;
318       sai = ip4_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
319                                   &src, src_address_length);
320       src_adjp = ip_get_adjacency(lgm->lm4, sai[0]);
321       ASSERT(src_adjp->rewrite_header.node_index
322               == add_adj->rewrite_header.node_index);
323     }
324
325   /* if a delete, check if there are elements left in the src fib */
326   if (!is_add)
327     {
328       src_fib = pool_elt_at_index(lgm->ip4_src_fibs,
329                                   dst_adjp->rewrite_header.sw_if_index);
330       if (!src_fib)
331         return 0;
332
333       /* if there's nothing left */
334       if (ip4_fib_is_empty(src_fib))
335         {
336           /* remove the src fib ..  */
337           pool_put(lgm->ip4_src_fibs, src_fib);
338
339           /* .. and remove dst route */
340           memset(&a, 0, sizeof(a));
341           a.flags = IP4_ROUTE_FLAG_TABLE_ID;
342           a.table_index_or_table_id = table_id; /* vrf */
343           a.adj_index = ~0;
344           a.dst_address_length = dst_address_length;
345           a.dst_address = dst;
346           a.flags |= IP4_ROUTE_FLAG_DEL;
347
348           ip4_add_del_route (lgm->im4, &a);
349         }
350     }
351
352   return 0;
353 }
354
355 static void *
356 ip4_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
357                       ip_prefix_t * src_prefix, u32 table_id)
358 {
359   uword * p;
360   ip4_address_t dst = ip_prefix_v4(dst_prefix), src;
361   u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
362   ip_adjacency_t * dst_adj;
363
364   if (src_prefix)
365     {
366       src = ip_prefix_v4(src_prefix);
367       src_address_length = ip_prefix_len(src_prefix);
368     }
369   else
370     memset(&src, 0, sizeof(src));
371
372   /* lookup dst adj */
373   p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
374   if (p == 0)
375       return p;
376
377   dst_adj = ip_get_adjacency (lgm->lm4, p[0]);
378   return ip4_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
379                                src_address_length);
380 }
381
382 static u32
383 ip6_sd_get_src_route (lisp_gpe_main_t * lgm, u32 src_fib_index,
384                       ip6_address_t * src, u32 address_length)
385 {
386   int i, len;
387   int rv;
388   BVT(clib_bihash_kv) kv, value;
389   ip6_src_fib_t * fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
390
391   len = vec_len (fib->prefix_lengths_in_search_order);
392
393   for (i = 0; i < len; i++)
394     {
395       int dst_address_length = fib->prefix_lengths_in_search_order[i];
396       ip6_address_t * mask;
397
398       ASSERT(dst_address_length >= 0 && dst_address_length <= 128);
399
400       mask = &fib->fib_masks[dst_address_length];
401
402       kv.key[0] = src->as_u64[0] & mask->as_u64[0];
403       kv.key[1] = src->as_u64[1] & mask->as_u64[1];
404       kv.key[2] = dst_address_length;
405
406       rv = BV(clib_bihash_search_inline_2)(&fib->ip6_lookup_table, &kv, &value);
407       if (rv == 0)
408         return value.value;
409     }
410
411   return 0;
412 }
413
414 static void
415 compute_prefix_lengths_in_search_order (ip6_src_fib_t * fib)
416 {
417   int i;
418   vec_reset_length(fib->prefix_lengths_in_search_order);
419   /* Note: bitmap reversed so this is in fact a longest prefix match */
420   clib_bitmap_foreach(i, fib->non_empty_dst_address_length_bitmap, ({
421     int dst_address_length = 128 - i;
422     vec_add1 (fib->prefix_lengths_in_search_order, dst_address_length);
423   }));
424 }
425
426 /* Rewrite of ip6_add_del_route() because it uses im6 to find the fib */
427 static void
428 ip6_sd_fib_add_del_src_route (lisp_gpe_main_t * lgm,
429                               ip6_add_del_route_args_t * a)
430 {
431   ip_lookup_main_t * lm = lgm->lm6;
432   ip6_src_fib_t * fib;
433   ip6_address_t dst_address;
434   u32 dst_address_length, adj_index;
435   uword is_del;
436   u32 old_adj_index = ~0;
437   BVT(clib_bihash_kv) kv, value;
438
439   vlib_smp_unsafe_warning();
440
441   is_del = (a->flags & IP6_ROUTE_FLAG_DEL) != 0;
442
443   /* Either create new adjacency or use given one depending on arguments. */
444   if (a->n_add_adj > 0)
445     {
446       ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
447     }
448   else
449     adj_index = a->adj_index;
450
451   dst_address = a->dst_address;
452   dst_address_length = a->dst_address_length;
453   fib = pool_elt_at_index(lgm->ip6_src_fibs, a->table_index_or_table_id);
454
455   ASSERT (dst_address_length < ARRAY_LEN (fib->fib_masks));
456   ip6_address_mask (&dst_address, &fib->fib_masks[dst_address_length]);
457
458   /* refcount accounting */
459   if (is_del)
460     {
461       ASSERT(fib->dst_address_length_refcounts[dst_address_length] > 0);
462       if (--fib->dst_address_length_refcounts[dst_address_length] == 0)
463         {
464           fib->non_empty_dst_address_length_bitmap = clib_bitmap_set (
465               fib->non_empty_dst_address_length_bitmap,
466               128 - dst_address_length, 0);
467           compute_prefix_lengths_in_search_order (fib);
468         }
469     }
470   else
471     {
472       fib->dst_address_length_refcounts[dst_address_length]++;
473
474       fib->non_empty_dst_address_length_bitmap =
475         clib_bitmap_set (fib->non_empty_dst_address_length_bitmap,
476                              128 - dst_address_length, 1);
477       compute_prefix_lengths_in_search_order (fib);
478     }
479
480   kv.key[0] = dst_address.as_u64[0];
481   kv.key[1] = dst_address.as_u64[1];
482   kv.key[2] = dst_address_length;
483
484   if (BV(clib_bihash_search)(&fib->ip6_lookup_table, &kv, &value) == 0)
485     old_adj_index = value.value;
486
487   if (is_del)
488     BV(clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 0 /* is_add */);
489   else
490     {
491       /* Make sure adj index is valid. */
492       if (CLIB_DEBUG > 0)
493         (void) ip_get_adjacency (lm, adj_index);
494
495       kv.value = adj_index;
496
497       BV(clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 1 /* is_add */);
498     }
499
500   /* Avoid spurious reference count increments */
501   if (old_adj_index == adj_index
502       && !(a->flags & IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
503     {
504       ip_adjacency_t * adj = ip_get_adjacency (lm, adj_index);
505       if (adj->share_count > 0)
506         adj->share_count --;
507     }
508
509   /* Delete old adjacency index if present and changed. */
510   {
511     if (! (a->flags & IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY)
512         && old_adj_index != ~0
513         && old_adj_index != adj_index)
514       ip_del_adjacency (lm, old_adj_index);
515   }
516 }
517
518 static void
519 ip6_src_fib_init (ip6_src_fib_t * fib)
520 {
521   uword i;
522
523   for (i = 0; i < ARRAY_LEN (fib->fib_masks); i++)
524     {
525       u32 j, i0, i1;
526
527       i0 = i / 32;
528       i1 = i % 32;
529
530       for (j = 0; j < i0; j++)
531         fib->fib_masks[i].as_u32[j] = ~0;
532
533       if (i1)
534         fib->fib_masks[i].as_u32[i0] = clib_host_to_net_u32 (
535             pow2_mask (i1) << (32 - i1));
536     }
537
538   if (fib->lookup_table_nbuckets == 0)
539     fib->lookup_table_nbuckets = IP6_FIB_DEFAULT_HASH_NUM_BUCKETS;
540
541   fib->lookup_table_nbuckets = 1 << max_log2 (fib->lookup_table_nbuckets);
542
543   if (fib->lookup_table_size == 0)
544     fib->lookup_table_size = IP6_FIB_DEFAULT_HASH_MEMORY_SIZE;
545
546   BV(clib_bihash_init) (&fib->ip6_lookup_table, "ip6 lookup table",
547                         fib->lookup_table_nbuckets,
548                         fib->lookup_table_size);
549
550 }
551
552 static int
553 ip6_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
554                           ip_prefix_t * src_prefix, u32 table_id,
555                           ip_adjacency_t * add_adj, u8 is_add)
556 {
557   u32 adj_index;
558   ip6_add_del_route_args_t a;
559   ip_adjacency_t * dst_adjp, dst_adj;
560   ip6_address_t dst = ip_prefix_v6(dst_prefix), src;
561   u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
562   ip6_src_fib_t * src_fib;
563
564   if (src_prefix)
565     {
566       src = ip_prefix_v6(src_prefix);
567       src_address_length = ip_prefix_len(src_prefix);
568     }
569   else
570     memset(&src, 0, sizeof(src));
571
572   /* lookup dst adj and create it if it doesn't exist */
573   adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
574
575   if (is_add)
576     {
577       /* insert dst prefix to ip6 fib, if it's not in yet */
578       if (adj_index == 0)
579         {
580
581           /* allocate and init src ip6 fib */
582           pool_get(lgm->ip6_src_fibs, src_fib);
583           memset(src_fib, 0, sizeof(src_fib[0]));
584           ip6_src_fib_init (src_fib);
585
586           memset(&dst_adj, 0, sizeof(dst_adj));
587
588           /* reuse rewrite header to store pointer to src fib */
589           dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip6_src_fibs;
590
591           /* dst adj should point to lisp gpe ip lookup */
592           dst_adj.lookup_next_index = lgm->ip6_lookup_next_lgpe_ip6_lookup;
593
594           /* make sure we have different signatures for adj in different tables
595            * but with the same lookup_next_index */
596           dst_adj.explicit_fib_index = table_id;
597
598           memset(&a, 0, sizeof(a));
599           a.flags = IP6_ROUTE_FLAG_TABLE_ID;
600           a.table_index_or_table_id = table_id; /* vrf */
601           a.adj_index = ~0;
602           a.dst_address_length = dst_address_length;
603           a.dst_address = dst;
604           a.flags |= IP6_ROUTE_FLAG_ADD;
605           a.add_adj = &dst_adj;
606           a.n_add_adj = 1;
607
608           ip6_add_del_route (lgm->im6, &a);
609
610           /* lookup dst adj to obtain the adj index */
611           adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst,
612                                      dst_address_length);
613
614           ASSERT(adj_index != 0);
615
616           /* make sure insertion succeeded */
617           if (CLIB_DEBUG)
618             {
619               dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
620               ASSERT(dst_adjp->rewrite_header.sw_if_index
621                       == dst_adj.rewrite_header.sw_if_index);
622             }
623         }
624     }
625   else
626     {
627       if (adj_index == 0)
628         {
629           clib_warning("Trying to delete inexistent dst route for %U. Aborting",
630                        format_ip6_address_and_length, dst.as_u8,
631                        dst_address_length);
632           return -1;
633         }
634     }
635
636   dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
637
638   /* make sure adj signature is unique, i.e., fill in mcast_group_index
639    * and saved_lookup_next index with data that makes this adj unique.
640    * All these fields are (and should stay that way) unused by LISP. */
641   add_adj->mcast_group_index = table_id;
642   add_adj->saved_lookup_next_index = dst_adjp->rewrite_header.sw_if_index;
643
644   /* add/del src prefix to src fib */
645   memset(&a, 0, sizeof(a));
646   a.flags = IP6_ROUTE_FLAG_TABLE_ID;
647   a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
648   a.adj_index = ~0;
649   a.flags |= is_add ? IP6_ROUTE_FLAG_ADD : IP6_ROUTE_FLAG_DEL;
650   a.add_adj = add_adj;
651   a.n_add_adj = is_add ? 1 : 0;
652   /* if src prefix is null, add ::0 */
653   a.dst_address_length = src_address_length;
654   a.dst_address = src;
655   ip6_sd_fib_add_del_src_route (lgm, &a);
656
657   /* make sure insertion succeeded */
658   if (CLIB_DEBUG)
659     {
660       u32 sai;
661       ip_adjacency_t * src_adjp;
662       sai = ip6_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
663                                   &src, src_address_length);
664       src_adjp = ip_get_adjacency(lgm->lm6, sai);
665       ASSERT(src_adjp->rewrite_header.node_index
666               == add_adj->rewrite_header.node_index);
667     }
668
669   /* if a delete, check if there are elements left in the src fib */
670   if (!is_add)
671     {
672       src_fib = pool_elt_at_index(lgm->ip6_src_fibs,
673                                   dst_adjp->rewrite_header.sw_if_index);
674       if (!src_fib)
675         return 0;
676
677       /* if there's nothing left */
678       if (clib_bitmap_count_set_bits (
679           src_fib->non_empty_dst_address_length_bitmap) == 0)
680         {
681           /* remove src fib .. */
682           pool_put(lgm->ip6_src_fibs, src_fib);
683
684           /* .. and remove dst route */
685           memset(&a, 0, sizeof(a));
686           a.flags = IP6_ROUTE_FLAG_TABLE_ID;
687           a.table_index_or_table_id = table_id; /* vrf */
688           a.adj_index = ~0;
689           a.dst_address_length = dst_address_length;
690           a.dst_address = dst;
691           a.flags |= IP6_ROUTE_FLAG_DEL;
692
693           ip6_add_del_route (lgm->im6, &a);
694         }
695     }
696
697   return 0;
698 }
699
700 static u32
701 ip6_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
702                       ip_prefix_t * src_prefix, u32 table_id)
703 {
704   u32 adj_index;
705   ip6_address_t dst = ip_prefix_v6(dst_prefix), src;
706   u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
707   ip_adjacency_t * dst_adj;
708
709   if (src_prefix)
710     {
711       src = ip_prefix_v6(src_prefix);
712       src_address_length = ip_prefix_len(src_prefix);
713     }
714   else
715     memset(&src, 0, sizeof(src));
716
717   /* lookup dst adj */
718   adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
719   if (adj_index == 0)
720       return adj_index;
721
722   dst_adj = ip_get_adjacency (lgm->lm6, adj_index);
723   return ip6_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
724                                src_address_length);
725 }
726
727 int
728 ip_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
729                          ip_prefix_t * src_prefix, u32 table_id,
730                          ip_adjacency_t * add_adj, u8 is_add)
731 {
732   return (
733   ip_prefix_version(dst_prefix) == IP4 ?
734       ip4_sd_fib_add_del_route : ip6_sd_fib_add_del_route) (lgm, dst_prefix,
735                                                             src_prefix,
736                                                             table_id, add_adj,
737                                                             is_add);
738 }
739
740 u32
741 ip_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
742                      ip_prefix_t * src_prefix, u32 table_id)
743 {
744   if (ip_prefix_version(dst_prefix) == IP4)
745     {
746       u32 * adj_index = ip4_sd_fib_get_route (lgm, dst_prefix, src_prefix,
747                                               table_id);
748       return (adj_index == 0) ? 0 : adj_index[0];
749     }
750   else
751     return ip6_sd_fib_get_route (lgm, dst_prefix, src_prefix, table_id);
752 }
753
754 always_inline void
755 ip4_src_fib_lookup_one (lisp_gpe_main_t * lgm, u32 src_fib_index0,
756                         ip4_address_t * addr0, u32 * src_adj_index0)
757 {
758   ip4_fib_mtrie_leaf_t leaf0, leaf1;
759   ip4_fib_mtrie_t * mtrie0;
760
761   mtrie0 = &vec_elt_at_index(lgm->ip4_src_fibs, src_fib_index0)->mtrie;
762
763   leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
764   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
765   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
766   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
767   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
768
769   /* Handle default route. */
770   leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
771   src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
772 }
773
774 always_inline void
775 ip4_src_fib_lookup_two (lisp_gpe_main_t * lgm, u32 src_fib_index0,
776                         u32 src_fib_index1, ip4_address_t * addr0,
777                         ip4_address_t * addr1, u32 * src_adj_index0,
778                         u32 * src_adj_index1)
779 {
780   ip4_fib_mtrie_leaf_t leaf0, leaf1;
781   ip4_fib_mtrie_t * mtrie0, * mtrie1;
782
783   mtrie0 = &vec_elt_at_index(lgm->ip4_src_fibs, src_fib_index0)->mtrie;
784   mtrie1 = &vec_elt_at_index(lgm->ip4_src_fibs, src_fib_index1)->mtrie;
785
786   leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
787
788   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
789   leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 0);
790
791   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
792   leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 1);
793
794   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
795   leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
796
797   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
798   leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
799
800   /* Handle default route. */
801   leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
802   leaf1 = (leaf1 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie1->default_leaf : leaf1);
803   src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
804   src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
805 }
806
807 always_inline uword
808 lgpe_ip4_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
809                  vlib_frame_t * from_frame)
810 {
811   u32 n_left_from, next_index, * from, * to_next;
812   lisp_gpe_main_t * lgm = &lisp_gpe_main;
813
814   from = vlib_frame_vector_args (from_frame);
815   n_left_from = from_frame->n_vectors;
816
817   next_index = node->cached_next_index;
818
819   while (n_left_from > 0)
820     {
821       u32 n_left_to_next;
822
823       vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
824
825       while (n_left_from >= 4 && n_left_to_next >= 2)
826         {
827           u32 bi0, bi1;
828           vlib_buffer_t * b0, * b1;
829           ip4_header_t * ip0, * ip1;
830           u32 dst_adj_index0, src_adj_index0, src_fib_index0, dst_adj_index1,
831               src_adj_index1, src_fib_index1;
832           ip_adjacency_t * dst_adj0, * src_adj0, * dst_adj1, * src_adj1;
833           u32 next0, next1;
834
835           next0 = next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
836
837           /* Prefetch next iteration. */
838           {
839             vlib_buffer_t * p2, * p3;
840
841             p2 = vlib_get_buffer (vm, from[2]);
842             p3 = vlib_get_buffer (vm, from[3]);
843
844             vlib_prefetch_buffer_header (p2, LOAD);
845             vlib_prefetch_buffer_header (p3, LOAD);
846
847             CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
848             CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
849           }
850
851           bi0 = from[0];
852           bi1 = from[1];
853           to_next[0] = bi0;
854           to_next[1] = bi1;
855           from += 2;
856           to_next += 2;
857           n_left_to_next -= 2;
858           n_left_from -= 2;
859
860           b0 = vlib_get_buffer (vm, bi0);
861           b1 = vlib_get_buffer (vm, bi1);
862
863           ip0 = vlib_buffer_get_current (b0);
864           ip1 = vlib_buffer_get_current (b1);
865
866           /* dst lookup was done by ip4 lookup */
867           dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
868           dst_adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
869
870           dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
871           dst_adj1 = ip_get_adjacency (lgm->lm4, dst_adj_index1);
872
873           src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
874           src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
875
876           /* if default route not hit in ip4 lookup */
877           if (PREDICT_TRUE(src_fib_index0 != (u32) ~0
878                            && src_fib_index1 != (u32) ~0))
879             {
880               ip4_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
881                                       &ip0->src_address, &ip1->src_address,
882                                       &src_adj_index0, &src_adj_index1);
883
884               vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
885               vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
886
887               src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
888               src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
889
890               next0 = src_adj0->explicit_fib_index;
891               next1 = src_adj1->explicit_fib_index;
892
893               /* prepare buffer for lisp-gpe output node */
894               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
895                   src_adj0->rewrite_header.sw_if_index;
896               vnet_buffer (b1)->sw_if_index[VLIB_TX] =
897                   src_adj1->rewrite_header.sw_if_index;
898             }
899           else
900             {
901               if (src_fib_index0 != (u32) ~0)
902                 {
903                   ip4_src_fib_lookup_one (lgm, src_fib_index0,
904                                           &ip0->src_address, &src_adj_index0);
905                   vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
906                   src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
907                   next0 = src_adj0->explicit_fib_index;
908                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
909                       src_adj0->rewrite_header.sw_if_index;
910                 }
911               if (src_fib_index1 != (u32) ~0)
912                 {
913                   ip4_src_fib_lookup_one (lgm, src_fib_index1,
914                                           &ip1->src_address, &src_adj_index1);
915                   vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
916                   src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
917                   next1 = src_adj1->explicit_fib_index;
918                   vnet_buffer (b1)->sw_if_index[VLIB_TX] =
919                       src_adj1->rewrite_header.sw_if_index;
920                 }
921             }
922
923           vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
924                                           n_left_to_next, bi0, bi1, next0,
925                                           next1);
926         }
927
928       while (n_left_from > 0 && n_left_to_next > 0)
929         {
930           vlib_buffer_t * b0;
931           ip4_header_t * ip0;
932           u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
933           u32 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
934           ip_adjacency_t * dst_adj0, * src_adj0;
935
936           bi0 = from[0];
937           to_next[0] = bi0;
938           from += 1;
939           to_next += 1;
940           n_left_from -= 1;
941           n_left_to_next -= 1;
942
943           b0 = vlib_get_buffer (vm, bi0);
944           ip0 = vlib_buffer_get_current (b0);
945
946           /* dst lookup was done by ip4 lookup */
947           dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
948           dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
949           src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
950
951           /* if default route not hit in ip4 lookup */
952           if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0))
953             {
954               /* do src lookup */
955               ip4_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
956                                       &src_adj_index0);
957               vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
958               src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
959               next0 = src_adj0->explicit_fib_index;
960
961               /* prepare packet for lisp-gpe output node */
962               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
963                   src_adj0->rewrite_header.sw_if_index;
964             }
965
966           vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
967                                           n_left_to_next, bi0, next0);
968         }
969       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
970     }
971   return from_frame->n_vectors;
972 }
973
974 VLIB_REGISTER_NODE (lgpe_ip4_lookup_node) = {
975   .function = lgpe_ip4_lookup,
976   .name = "lgpe-ip4-lookup",
977   .vector_size = sizeof (u32),
978
979   .type = VLIB_NODE_TYPE_INTERNAL,
980
981   .n_next_nodes = LGPE_IP4_LOOKUP_N_NEXT,
982   .next_nodes = {
983 #define _(sym,str) [LGPE_IP4_LOOKUP_NEXT_##sym] = str,
984       foreach_lgpe_ip4_lookup_next
985 #undef _
986   },
987 };
988
989 static u32
990 ip6_src_fib_lookup (lisp_gpe_main_t * lgm, u32 src_fib_index,
991                     ip6_address_t * src)
992 {
993   int i, len;
994   int rv;
995   BVT(clib_bihash_kv) kv, value;
996   ip6_src_fib_t * fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
997
998   len = vec_len (fib->prefix_lengths_in_search_order);
999
1000   for (i = 0; i < len; i++)
1001     {
1002       int dst_address_length = fib->prefix_lengths_in_search_order[i];
1003       ip6_address_t * mask;
1004
1005       ASSERT(dst_address_length >= 0 && dst_address_length <= 128);
1006
1007       mask = &fib->fib_masks[dst_address_length];
1008
1009       kv.key[0] = src->as_u64[0] & mask->as_u64[0];
1010       kv.key[1] = src->as_u64[1] & mask->as_u64[1];
1011       kv.key[2] = dst_address_length;
1012
1013       rv = BV(clib_bihash_search_inline_2)(&fib->ip6_lookup_table, &kv, &value);
1014       if (rv == 0)
1015         return value.value;
1016     }
1017
1018   return 0;
1019 }
1020
1021 always_inline uword
1022 lgpe_ip6_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
1023                  vlib_frame_t * from_frame)
1024 {
1025   u32 n_left_from, next_index, * from, * to_next;
1026   lisp_gpe_main_t * lgm = &lisp_gpe_main;
1027
1028   from = vlib_frame_vector_args (from_frame);
1029   n_left_from = from_frame->n_vectors;
1030
1031   next_index = node->cached_next_index;
1032
1033   while (n_left_from > 0)
1034     {
1035       u32 n_left_to_next;
1036
1037       vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
1038
1039       while (n_left_from >= 4 && n_left_to_next >= 2)
1040         {
1041           u32 bi0, bi1;
1042           vlib_buffer_t * b0, * b1;
1043           ip6_header_t * ip0, * ip1;
1044           u32 dst_adj_index0, src_adj_index0, src_fib_index0, dst_adj_index1,
1045               src_adj_index1, src_fib_index1;
1046           ip_adjacency_t * dst_adj0, * src_adj0, * dst_adj1, * src_adj1;
1047           u32 next0, next1;
1048
1049           next0 = next1 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
1050
1051           /* Prefetch next iteration. */
1052           {
1053             vlib_buffer_t * p2, * p3;
1054
1055             p2 = vlib_get_buffer (vm, from[2]);
1056             p3 = vlib_get_buffer (vm, from[3]);
1057
1058             vlib_prefetch_buffer_header (p2, LOAD);
1059             vlib_prefetch_buffer_header (p3, LOAD);
1060
1061             CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
1062             CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
1063           }
1064
1065           bi0 = from[0];
1066           bi1 = from[1];
1067           to_next[0] = bi0;
1068           to_next[1] = bi1;
1069           from += 2;
1070           to_next += 2;
1071           n_left_to_next -= 2;
1072           n_left_from -= 2;
1073
1074           b0 = vlib_get_buffer (vm, bi0);
1075           b1 = vlib_get_buffer (vm, bi1);
1076
1077           ip0 = vlib_buffer_get_current (b0);
1078           ip1 = vlib_buffer_get_current (b1);
1079
1080           /* dst lookup was done by ip6 lookup */
1081           dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1082           dst_adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
1083
1084           dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
1085           dst_adj1 = ip_get_adjacency (lgm->lm6, dst_adj_index1);
1086
1087           src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1088           src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
1089
1090           /* if default route not hit in ip6 lookup */
1091           if (PREDICT_TRUE(src_fib_index0 != (u32) ~0
1092                            && src_fib_index1 != (u32) ~0))
1093             {
1094               /* do src lookup */
1095               src_adj_index0 = ip6_src_fib_lookup (lgm, src_fib_index0,
1096                                                    &ip0->src_address);
1097               src_adj_index1 = ip6_src_fib_lookup (lgm, src_fib_index1,
1098                                                    &ip1->src_address);
1099
1100               vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1101               vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1102
1103               src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1104               src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
1105
1106               next0 = src_adj0->explicit_fib_index;
1107               next1 = src_adj1->explicit_fib_index;
1108
1109               /* prepare buffer for lisp-gpe output node */
1110               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1111                   src_adj0->rewrite_header.sw_if_index;
1112               vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1113                   src_adj1->rewrite_header.sw_if_index;
1114             }
1115           else
1116             {
1117               if (src_fib_index0 != (u32) ~0)
1118                 {
1119                   src_adj_index0 = ip6_src_fib_lookup (lgm, src_fib_index0,
1120                                                        &ip0->src_address);
1121                   vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1122                   src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1123                   next0 = src_adj0->explicit_fib_index;
1124                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1125                       src_adj0->rewrite_header.sw_if_index;
1126                 }
1127               if (src_fib_index1 != (u32) ~0)
1128                 {
1129                   src_adj_index1 = ip6_src_fib_lookup (lgm, src_fib_index1,
1130                                                        &ip1->src_address);
1131                   vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1132                   src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
1133                   next1 = src_adj1->explicit_fib_index;
1134                   vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1135                       src_adj1->rewrite_header.sw_if_index;
1136                 }
1137             }
1138
1139           vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
1140                                           n_left_to_next, bi0, bi1, next0,
1141                                           next1);
1142         }
1143
1144       while (n_left_from > 0 && n_left_to_next > 0)
1145         {
1146           vlib_buffer_t * b0;
1147           ip6_header_t * ip0;
1148           u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
1149           u32 next0 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
1150           ip_adjacency_t * dst_adj0, * src_adj0;
1151
1152           bi0 = from[0];
1153           to_next[0] = bi0;
1154           from += 1;
1155           to_next += 1;
1156           n_left_from -= 1;
1157           n_left_to_next -= 1;
1158
1159           b0 = vlib_get_buffer (vm, bi0);
1160           ip0 = vlib_buffer_get_current (b0);
1161
1162           /* dst lookup was done by ip6 lookup */
1163           dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1164           dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
1165           src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1166
1167           /* if default route not hit in ip6 lookup */
1168           if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0))
1169             {
1170               /* do src lookup */
1171               src_adj_index0 = ip6_src_fib_lookup (lgm, src_fib_index0,
1172                                                    &ip0->src_address);
1173
1174               vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1175               src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1176               next0 = src_adj0->explicit_fib_index;
1177
1178               /* prepare packet for lisp-gpe output node */
1179               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1180                   src_adj0->rewrite_header.sw_if_index;
1181             }
1182
1183           vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1184                                           n_left_to_next, bi0, next0);
1185         }
1186       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1187     }
1188   return from_frame->n_vectors;
1189 }
1190
1191 VLIB_REGISTER_NODE (lgpe_ip6_lookup_node) = {
1192   .function = lgpe_ip6_lookup,
1193   .name = "lgpe-ip6-lookup",
1194   .vector_size = sizeof (u32),
1195
1196   .type = VLIB_NODE_TYPE_INTERNAL,
1197
1198   .n_next_nodes = LGPE_IP6_LOOKUP_N_NEXT,
1199   .next_nodes = {
1200 #define _(sym,str) [LGPE_IP6_LOOKUP_NEXT_##sym] = str,
1201       foreach_lgpe_ip6_lookup_next
1202 #undef _
1203   },
1204 };