VPP-196 LISP L2/L3 tunnel multihoming
[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           /* explicit_fib_index is used in IP6 FIB lookup, don't reuse it */
249           dst_adj.explicit_fib_index = ~0;
250           dst_adj.n_adj = 1;
251
252           /* make sure we have different signatures for adj in different tables
253            * but with the same lookup_next_index and for adj in the same table
254            * but associated to different destinations */
255           dst_adj.if_address_index = table_id;
256           dst_adj.indirect.next_hop.ip4 = dst;
257
258           memset(&a, 0, sizeof(a));
259           a.flags = IP4_ROUTE_FLAG_TABLE_ID;
260           a.table_index_or_table_id = table_id; /* vrf */
261           a.adj_index = ~0;
262           a.dst_address_length = dst_address_length;
263           a.dst_address = dst;
264           a.flags |= IP4_ROUTE_FLAG_ADD;
265           a.add_adj = &dst_adj;
266           a.n_add_adj = 1;
267
268           ip4_add_del_route (lgm->im4, &a);
269
270           /* lookup dst adj to obtain the adj index */
271           p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8,
272                              dst_address_length);
273
274           /* make sure insertion succeeded */
275           if (CLIB_DEBUG)
276             {
277               ASSERT(p != 0);
278               dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
279               ASSERT(dst_adjp->rewrite_header.sw_if_index
280                       == dst_adj.rewrite_header.sw_if_index);
281             }
282         }
283     }
284   else
285     {
286       if (p == 0)
287         {
288           clib_warning("Trying to delete inexistent dst route for %U. Aborting",
289                        format_ip4_address_and_length, dst.as_u8,
290                        dst_address_length);
291           return -1;
292         }
293     }
294
295   dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
296
297   /* add/del src prefix to src fib */
298   memset(&a, 0, sizeof(a));
299   a.flags = IP4_ROUTE_FLAG_TABLE_ID;
300   a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
301   a.adj_index = ~0;
302   a.flags |= is_add ? IP4_ROUTE_FLAG_ADD : IP4_ROUTE_FLAG_DEL;
303   a.add_adj = add_adj;
304   a.n_add_adj = is_add ? 1 : 0;
305   /* if src prefix is null, add 0/0 */
306   a.dst_address_length = src_address_length;
307   a.dst_address = src;
308   ip4_sd_fib_add_del_src_route (lgm, &a);
309
310   /* make sure insertion succeeded */
311   if (CLIB_DEBUG && is_add)
312     {
313       uword * sai;
314       ip_adjacency_t * src_adjp;
315       sai = ip4_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
316                                   &src, src_address_length);
317       ASSERT(sai != 0);
318       src_adjp = ip_get_adjacency(lgm->lm4, sai[0]);
319       ASSERT(src_adjp->if_address_index == add_adj->if_address_index);
320     }
321
322   /* if a delete, check if there are elements left in the src fib */
323   if (!is_add)
324     {
325       src_fib = pool_elt_at_index(lgm->ip4_src_fibs,
326                                   dst_adjp->rewrite_header.sw_if_index);
327       if (!src_fib)
328         return 0;
329
330       /* if there's nothing left */
331       if (ip4_fib_is_empty(src_fib))
332         {
333           /* remove the src fib ..  */
334           pool_put(lgm->ip4_src_fibs, src_fib);
335
336           /* .. and remove dst route */
337           memset(&a, 0, sizeof(a));
338           a.flags = IP4_ROUTE_FLAG_TABLE_ID;
339           a.table_index_or_table_id = table_id; /* vrf */
340           a.adj_index = ~0;
341           a.dst_address_length = dst_address_length;
342           a.dst_address = dst;
343           a.flags |= IP4_ROUTE_FLAG_DEL;
344
345           ip4_add_del_route (lgm->im4, &a);
346         }
347     }
348
349   return 0;
350 }
351
352 static void *
353 ip4_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
354                       ip_prefix_t * src_prefix, u32 table_id)
355 {
356   uword * p;
357   ip4_address_t dst = ip_prefix_v4(dst_prefix), src;
358   u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
359   ip_adjacency_t * dst_adj;
360
361   if (src_prefix)
362     {
363       src = ip_prefix_v4(src_prefix);
364       src_address_length = ip_prefix_len(src_prefix);
365     }
366   else
367     memset(&src, 0, sizeof(src));
368
369   /* lookup dst adj */
370   p = ip4_get_route (lgm->im4, table_id, 0, dst.as_u8, dst_address_length);
371   if (p == 0)
372       return p;
373
374   dst_adj = ip_get_adjacency (lgm->lm4, p[0]);
375   return ip4_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
376                                src_address_length);
377 }
378
379 static u32
380 ip6_sd_get_src_route (lisp_gpe_main_t * lgm, u32 src_fib_index,
381                       ip6_address_t * src, u32 address_length)
382 {
383   int rv;
384   BVT(clib_bihash_kv) kv, value;
385   ip6_src_fib_t * fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
386
387   ip6_address_t * mask;
388
389   ASSERT(address_length <= 128);
390
391   mask = &fib->fib_masks[address_length];
392
393   kv.key[0] = src->as_u64[0] & mask->as_u64[0];
394   kv.key[1] = src->as_u64[1] & mask->as_u64[1];
395   kv.key[2] = address_length;
396
397   rv = BV(clib_bihash_search_inline_2)(&fib->ip6_lookup_table, &kv, &value);
398   if (rv == 0)
399     return value.value;
400
401   return 0;
402 }
403
404 static void
405 compute_prefix_lengths_in_search_order (ip6_src_fib_t * fib)
406 {
407   int i;
408   vec_reset_length(fib->prefix_lengths_in_search_order);
409   /* Note: bitmap reversed so this is in fact a longest prefix match */
410   clib_bitmap_foreach(i, fib->non_empty_dst_address_length_bitmap, ({
411     int dst_address_length = 128 - i;
412     vec_add1 (fib->prefix_lengths_in_search_order, dst_address_length);
413   }));
414 }
415
416 /* Rewrite of ip6_add_del_route() because it uses im6 to find the fib */
417 static void
418 ip6_sd_fib_add_del_src_route (lisp_gpe_main_t * lgm,
419                               ip6_add_del_route_args_t * a)
420 {
421   ip_lookup_main_t * lm = lgm->lm6;
422   ip6_src_fib_t * fib;
423   ip6_address_t dst_address;
424   u32 dst_address_length, adj_index;
425   uword is_del;
426   u32 old_adj_index = ~0;
427   BVT(clib_bihash_kv) kv, value;
428
429   vlib_smp_unsafe_warning();
430
431   is_del = (a->flags & IP6_ROUTE_FLAG_DEL) != 0;
432
433   /* Either create new adjacency or use given one depending on arguments. */
434   if (a->n_add_adj > 0)
435     {
436       ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
437     }
438   else
439     adj_index = a->adj_index;
440
441   dst_address = a->dst_address;
442   dst_address_length = a->dst_address_length;
443   fib = pool_elt_at_index(lgm->ip6_src_fibs, a->table_index_or_table_id);
444
445   ASSERT (dst_address_length < ARRAY_LEN (fib->fib_masks));
446   ip6_address_mask (&dst_address, &fib->fib_masks[dst_address_length]);
447
448   /* refcount accounting */
449   if (is_del)
450     {
451       ASSERT(fib->dst_address_length_refcounts[dst_address_length] > 0);
452       if (--fib->dst_address_length_refcounts[dst_address_length] == 0)
453         {
454           fib->non_empty_dst_address_length_bitmap = clib_bitmap_set (
455               fib->non_empty_dst_address_length_bitmap,
456               128 - dst_address_length, 0);
457           compute_prefix_lengths_in_search_order (fib);
458         }
459     }
460   else
461     {
462       fib->dst_address_length_refcounts[dst_address_length]++;
463
464       fib->non_empty_dst_address_length_bitmap =
465         clib_bitmap_set (fib->non_empty_dst_address_length_bitmap,
466                              128 - dst_address_length, 1);
467       compute_prefix_lengths_in_search_order (fib);
468     }
469
470   kv.key[0] = dst_address.as_u64[0];
471   kv.key[1] = dst_address.as_u64[1];
472   kv.key[2] = dst_address_length;
473
474   if (BV(clib_bihash_search)(&fib->ip6_lookup_table, &kv, &value) == 0)
475     old_adj_index = value.value;
476
477   if (is_del)
478     BV(clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 0 /* is_add */);
479   else
480     {
481       /* Make sure adj index is valid. */
482       if (CLIB_DEBUG > 0)
483         (void) ip_get_adjacency (lm, adj_index);
484
485       kv.value = adj_index;
486
487       BV(clib_bihash_add_del) (&fib->ip6_lookup_table, &kv, 1 /* is_add */);
488     }
489
490   /* Avoid spurious reference count increments */
491   if (old_adj_index == adj_index
492       && !(a->flags & IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY))
493     {
494       ip_adjacency_t * adj = ip_get_adjacency (lm, adj_index);
495       if (adj->share_count > 0)
496         adj->share_count --;
497     }
498
499   /* Delete old adjacency index if present and changed. */
500   {
501     if (! (a->flags & IP6_ROUTE_FLAG_KEEP_OLD_ADJACENCY)
502         && old_adj_index != ~0
503         && old_adj_index != adj_index)
504       ip_del_adjacency (lm, old_adj_index);
505   }
506 }
507
508 static void
509 ip6_src_fib_init (ip6_src_fib_t * fib)
510 {
511   uword i;
512
513   for (i = 0; i < ARRAY_LEN (fib->fib_masks); i++)
514     {
515       u32 j, i0, i1;
516
517       i0 = i / 32;
518       i1 = i % 32;
519
520       for (j = 0; j < i0; j++)
521         fib->fib_masks[i].as_u32[j] = ~0;
522
523       if (i1)
524         fib->fib_masks[i].as_u32[i0] = clib_host_to_net_u32 (
525             pow2_mask (i1) << (32 - i1));
526     }
527
528   if (fib->lookup_table_nbuckets == 0)
529     fib->lookup_table_nbuckets = IP6_FIB_DEFAULT_HASH_NUM_BUCKETS;
530
531   fib->lookup_table_nbuckets = 1 << max_log2 (fib->lookup_table_nbuckets);
532
533   if (fib->lookup_table_size == 0)
534     fib->lookup_table_size = IP6_FIB_DEFAULT_HASH_MEMORY_SIZE;
535
536   BV(clib_bihash_init) (&fib->ip6_lookup_table, "ip6 lookup table",
537                         fib->lookup_table_nbuckets,
538                         fib->lookup_table_size);
539
540 }
541
542 static int
543 ip6_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
544                           ip_prefix_t * src_prefix, u32 table_id,
545                           ip_adjacency_t * add_adj, u8 is_add)
546 {
547   u32 adj_index;
548   ip6_add_del_route_args_t a;
549   ip_adjacency_t * dst_adjp, dst_adj;
550   ip6_address_t dst = ip_prefix_v6(dst_prefix), src;
551   u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
552   ip6_src_fib_t * src_fib;
553
554   if (src_prefix)
555     {
556       src = ip_prefix_v6(src_prefix);
557       src_address_length = ip_prefix_len(src_prefix);
558     }
559   else
560     memset(&src, 0, sizeof(src));
561
562   /* lookup dst adj and create it if it doesn't exist */
563   adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
564
565   if (is_add)
566     {
567       /* insert dst prefix to ip6 fib, if it's not in yet */
568       if (adj_index == 0)
569         {
570           /* allocate and init src ip6 fib */
571           pool_get(lgm->ip6_src_fibs, src_fib);
572           memset(src_fib, 0, sizeof(src_fib[0]));
573           ip6_src_fib_init (src_fib);
574
575           memset(&dst_adj, 0, sizeof(dst_adj));
576
577           /* reuse rewrite header to store pointer to src fib */
578           dst_adj.rewrite_header.sw_if_index = src_fib - lgm->ip6_src_fibs;
579
580           /* dst adj should point to lisp gpe ip lookup */
581           dst_adj.lookup_next_index = lgm->ip6_lookup_next_lgpe_ip6_lookup;
582
583           /* explicit_fib_index is used in IP6 FIB lookup, don't reuse it */
584           dst_adj.explicit_fib_index = ~0;
585           dst_adj.n_adj = 1;
586
587           /* make sure we have different signatures for adj in different tables
588            * but with the same lookup_next_index and for adj in the same table
589            * but associated to different destinations */
590           dst_adj.if_address_index = table_id;
591           dst_adj.indirect.next_hop.ip6 = dst;
592
593           memset(&a, 0, sizeof(a));
594           a.flags = IP6_ROUTE_FLAG_TABLE_ID;
595           a.table_index_or_table_id = table_id; /* vrf */
596           a.adj_index = ~0;
597           a.dst_address_length = dst_address_length;
598           a.dst_address = dst;
599           a.flags |= IP6_ROUTE_FLAG_ADD;
600           a.add_adj = &dst_adj;
601           a.n_add_adj = 1;
602
603           ip6_add_del_route (lgm->im6, &a);
604
605           /* lookup dst adj to obtain the adj index */
606           adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst,
607                                      dst_address_length);
608
609           /* make sure insertion succeeded */
610           if (CLIB_DEBUG)
611             {
612               ASSERT(adj_index != 0);
613               dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
614               ASSERT(dst_adjp->rewrite_header.sw_if_index
615                       == dst_adj.rewrite_header.sw_if_index);
616             }
617         }
618     }
619   else
620     {
621       if (adj_index == 0)
622         {
623           clib_warning("Trying to delete inexistent dst route for %U. Aborting",
624                        format_ip_prefix, dst_prefix);
625           return -1;
626         }
627     }
628
629   dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
630
631   /* add/del src prefix to src fib */
632   memset(&a, 0, sizeof(a));
633   a.flags = IP6_ROUTE_FLAG_TABLE_ID;
634   a.table_index_or_table_id = dst_adjp->rewrite_header.sw_if_index;
635   a.adj_index = ~0;
636   a.flags |= is_add ? IP6_ROUTE_FLAG_ADD : IP6_ROUTE_FLAG_DEL;
637   a.add_adj = add_adj;
638   a.n_add_adj = is_add ? 1 : 0;
639   /* if src prefix is null, add ::0 */
640   a.dst_address_length = src_address_length;
641   a.dst_address = src;
642   ip6_sd_fib_add_del_src_route (lgm, &a);
643
644   /* make sure insertion succeeded */
645   if (CLIB_DEBUG && is_add)
646     {
647       u32 sai;
648       ip_adjacency_t * src_adjp;
649       sai = ip6_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
650                                   &src, src_address_length);
651       ASSERT(sai != 0);
652       src_adjp = ip_get_adjacency(lgm->lm6, sai);
653       ASSERT(src_adjp->if_address_index == add_adj->if_address_index);
654     }
655
656   /* if a delete, check if there are elements left in the src fib */
657   if (!is_add)
658     {
659       src_fib = pool_elt_at_index(lgm->ip6_src_fibs,
660                                   dst_adjp->rewrite_header.sw_if_index);
661       if (!src_fib)
662         return 0;
663
664       /* if there's nothing left */
665       if (clib_bitmap_count_set_bits (
666           src_fib->non_empty_dst_address_length_bitmap) == 0)
667         {
668           /* remove src fib .. */
669           pool_put(lgm->ip6_src_fibs, src_fib);
670
671           /* .. and remove dst route */
672           memset(&a, 0, sizeof(a));
673           a.flags = IP6_ROUTE_FLAG_TABLE_ID;
674           a.table_index_or_table_id = table_id; /* vrf */
675           a.adj_index = ~0;
676           a.dst_address_length = dst_address_length;
677           a.dst_address = dst;
678           a.flags |= IP6_ROUTE_FLAG_DEL;
679
680           ip6_add_del_route (lgm->im6, &a);
681         }
682     }
683
684   return 0;
685 }
686
687 static u32
688 ip6_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
689                       ip_prefix_t * src_prefix, u32 table_id)
690 {
691   u32 adj_index;
692   ip6_address_t dst = ip_prefix_v6(dst_prefix), src;
693   u32 dst_address_length = ip_prefix_len(dst_prefix), src_address_length = 0;
694   ip_adjacency_t * dst_adj;
695
696   if (src_prefix)
697     {
698       src = ip_prefix_v6(src_prefix);
699       src_address_length = ip_prefix_len(src_prefix);
700     }
701   else
702     memset(&src, 0, sizeof(src));
703
704   /* lookup dst adj */
705   adj_index = ip6_get_route (lgm->im6, table_id, 0, &dst, dst_address_length);
706   if (adj_index == 0)
707       return adj_index;
708
709   dst_adj = ip_get_adjacency (lgm->lm6, adj_index);
710   return ip6_sd_get_src_route (lgm, dst_adj->rewrite_header.sw_if_index, &src,
711                                src_address_length);
712 }
713
714 int
715 ip_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
716                          ip_prefix_t * src_prefix, u32 table_id,
717                          ip_adjacency_t * add_adj, u8 is_add)
718 {
719   return (
720   ip_prefix_version(dst_prefix) == IP4 ?
721       ip4_sd_fib_add_del_route : ip6_sd_fib_add_del_route) (lgm, dst_prefix,
722                                                             src_prefix,
723                                                             table_id, add_adj,
724                                                             is_add);
725 }
726
727 u32
728 ip_sd_fib_get_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
729                      ip_prefix_t * src_prefix, u32 table_id)
730 {
731   if (ip_prefix_version(dst_prefix) == IP4)
732     {
733       u32 * adj_index = ip4_sd_fib_get_route (lgm, dst_prefix, src_prefix,
734                                               table_id);
735       return (adj_index == 0) ? 0 : adj_index[0];
736     }
737   else
738     return ip6_sd_fib_get_route (lgm, dst_prefix, src_prefix, table_id);
739 }
740
741 always_inline void
742 ip4_src_fib_lookup_one (lisp_gpe_main_t * lgm, u32 src_fib_index0,
743                         ip4_address_t * addr0, u32 * src_adj_index0)
744 {
745   ip4_fib_mtrie_leaf_t leaf0, leaf1;
746   ip4_fib_mtrie_t * mtrie0;
747
748   /* if default route not hit in ip4 lookup */
749   if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0))
750     {
751       mtrie0 = &vec_elt_at_index(lgm->ip4_src_fibs, src_fib_index0)->mtrie;
752
753       leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
754       leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
755       leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
756       leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
757       leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
758
759       /* Handle default route. */
760       leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
761           mtrie0->default_leaf : leaf0;
762       src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
763     }
764   else
765     src_adj_index0[0] = ~0;
766 }
767
768 always_inline void
769 ip4_src_fib_lookup_two (lisp_gpe_main_t * lgm, u32 src_fib_index0,
770                         u32 src_fib_index1, ip4_address_t * addr0,
771                         ip4_address_t * addr1, u32 * src_adj_index0,
772                         u32 * src_adj_index1)
773 {
774   ip4_fib_mtrie_leaf_t leaf0, leaf1;
775   ip4_fib_mtrie_t * mtrie0, * mtrie1;
776
777   /* if default route not hit in ip4 lookup */
778   if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0 && src_fib_index1 != (u32 ) ~0))
779     {
780       mtrie0 = &vec_elt_at_index(lgm->ip4_src_fibs, src_fib_index0)->mtrie;
781       mtrie1 = &vec_elt_at_index(lgm->ip4_src_fibs, src_fib_index1)->mtrie;
782
783       leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
784
785       leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
786       leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 0);
787
788       leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
789       leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 1);
790
791       leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
792       leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
793
794       leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
795       leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
796
797       /* Handle default route. */
798       leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
799               mtrie0->default_leaf : leaf0;
800       leaf1 = (leaf1 == IP4_FIB_MTRIE_LEAF_EMPTY) ?
801               mtrie1->default_leaf : leaf1;
802       src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
803       src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
804     }
805   else
806     {
807       ip4_src_fib_lookup_one (lgm, src_fib_index0, addr0, src_adj_index0);
808       ip4_src_fib_lookup_one (lgm, src_fib_index1, addr1, src_adj_index1);
809     }
810 }
811
812 always_inline uword
813 lgpe_ip4_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
814                  vlib_frame_t * from_frame)
815 {
816   u32 n_left_from, next_index, * from, * to_next;
817   lisp_gpe_main_t * lgm = &lisp_gpe_main;
818
819   from = vlib_frame_vector_args (from_frame);
820   n_left_from = from_frame->n_vectors;
821
822   next_index = node->cached_next_index;
823
824   while (n_left_from > 0)
825     {
826       u32 n_left_to_next;
827
828       vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
829
830       while (n_left_from >= 4 && n_left_to_next >= 2)
831         {
832           u32 bi0, bi1;
833           vlib_buffer_t * b0, * b1;
834           ip4_header_t * ip0, * ip1;
835           u32 dst_adj_index0, src_adj_index0, src_fib_index0;
836           u32 dst_adj_index1, src_adj_index1, src_fib_index1;
837           ip_adjacency_t * dst_adj0, * src_adj0, * dst_adj1, * src_adj1;
838           u32 next0, next1;
839
840           next0 = next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
841
842           /* Prefetch next iteration. */
843           {
844             vlib_buffer_t * p2, * p3;
845
846             p2 = vlib_get_buffer (vm, from[2]);
847             p3 = vlib_get_buffer (vm, from[3]);
848
849             vlib_prefetch_buffer_header (p2, LOAD);
850             vlib_prefetch_buffer_header (p3, LOAD);
851
852             CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
853             CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
854           }
855
856           bi0 = from[0];
857           bi1 = from[1];
858           to_next[0] = bi0;
859           to_next[1] = bi1;
860           from += 2;
861           to_next += 2;
862           n_left_to_next -= 2;
863           n_left_from -= 2;
864
865           b0 = vlib_get_buffer (vm, bi0);
866           b1 = vlib_get_buffer (vm, bi1);
867
868           ip0 = vlib_buffer_get_current (b0);
869           ip1 = vlib_buffer_get_current (b1);
870
871           /* dst lookup was done by ip4 lookup */
872           dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
873           dst_adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
874
875           dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
876           dst_adj1 = ip_get_adjacency (lgm->lm4, dst_adj_index1);
877
878           src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
879           src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
880
881           ip4_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
882                                   &ip0->src_address, &ip1->src_address,
883                                   &src_adj_index0, &src_adj_index1);
884
885           /* if a source fib exists */
886           if (PREDICT_TRUE((u32) ~0 != src_adj_index0
887                            && (u32) ~0 != src_adj_index1))
888             {
889               vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
890               vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
891
892               src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
893               src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
894
895               next0 = src_adj0->explicit_fib_index;
896               next1 = src_adj1->explicit_fib_index;
897
898               /* prepare buffer for lisp-gpe output node */
899               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
900                   src_adj0->rewrite_header.sw_if_index;
901               vnet_buffer (b1)->sw_if_index[VLIB_TX] =
902                   src_adj1->rewrite_header.sw_if_index;
903
904               /* if multipath: saved_lookup_next_index is reused to store
905                * nb of sub-tunnels. If greater than 1, multipath is on.
906                * Note that flow hash should be 0 after ipx lookup! */
907               if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
908                 vnet_buffer (b0)->ip.flow_hash = ip4_compute_flow_hash (
909                     ip0, IP_FLOW_HASH_DEFAULT);
910
911               if (PREDICT_TRUE(src_adj1->saved_lookup_next_index > 1))
912                 vnet_buffer (b1)->ip.flow_hash = ip4_compute_flow_hash (
913                     ip1, IP_FLOW_HASH_DEFAULT);
914             }
915           else
916             {
917               if ((u32) ~0 != src_adj_index0)
918                 {
919                   vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
920                   src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
921                   next0 = src_adj0->explicit_fib_index;
922                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
923                       src_adj0->rewrite_header.sw_if_index;
924
925                   if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
926                     vnet_buffer (b0)->ip.flow_hash = ip4_compute_flow_hash (
927                         ip0, IP_FLOW_HASH_DEFAULT);
928                 }
929               else
930                 {
931                   next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
932                 }
933
934               if ((u32) ~0 != src_adj_index1)
935                 {
936                   vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
937                   src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
938                   next1 = src_adj1->explicit_fib_index;
939                   vnet_buffer (b1)->sw_if_index[VLIB_TX] =
940                       src_adj1->rewrite_header.sw_if_index;
941                   if (PREDICT_TRUE(src_adj1->saved_lookup_next_index > 1))
942                     vnet_buffer (b1)->ip.flow_hash = ip4_compute_flow_hash (
943                         ip1, IP_FLOW_HASH_DEFAULT);
944                 }
945               else
946                 {
947                   next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
948                 }
949             }
950
951           /* mark the packets for CP lookup if needed*/
952           if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
953             vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
954           if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next1))
955             vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_IP;
956
957           vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
958                                           n_left_to_next, bi0, bi1, next0,
959                                           next1);
960         }
961
962       while (n_left_from > 0 && n_left_to_next > 0)
963         {
964           vlib_buffer_t * b0;
965           ip4_header_t * ip0;
966           u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
967           u32 next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
968           ip_adjacency_t * dst_adj0, * src_adj0;
969
970           bi0 = from[0];
971           to_next[0] = bi0;
972           from += 1;
973           to_next += 1;
974           n_left_from -= 1;
975           n_left_to_next -= 1;
976
977           b0 = vlib_get_buffer (vm, bi0);
978           ip0 = vlib_buffer_get_current (b0);
979
980           /* dst lookup was done by ip4 lookup */
981           dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
982           dst_adj0 = ip_get_adjacency (lgm->lm4, dst_adj_index0);
983           src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
984
985           /* do src lookup */
986           ip4_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
987                                   &src_adj_index0);
988
989           /* if a source fib exists */
990           if (PREDICT_TRUE((u32) ~0 != src_adj_index0))
991             {
992               vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
993               src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
994               next0 = src_adj0->explicit_fib_index;
995
996               /* prepare packet for lisp-gpe output node */
997               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
998                   src_adj0->rewrite_header.sw_if_index;
999
1000               /* if multipath: saved_lookup_next_index is reused to store
1001                * nb of sub-tunnels. If greater than 1, multipath is on */
1002               if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
1003                 vnet_buffer (b0)->ip.flow_hash = ip4_compute_flow_hash (
1004                     ip0, IP_FLOW_HASH_DEFAULT);
1005             }
1006           else
1007             {
1008               next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1009             }
1010
1011           if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1012             vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1013
1014           vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1015                                           n_left_to_next, bi0, next0);
1016         }
1017       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1018     }
1019   return from_frame->n_vectors;
1020 }
1021
1022 VLIB_REGISTER_NODE (lgpe_ip4_lookup_node) = {
1023   .function = lgpe_ip4_lookup,
1024   .name = "lgpe-ip4-lookup",
1025   .vector_size = sizeof (u32),
1026
1027   .type = VLIB_NODE_TYPE_INTERNAL,
1028
1029   .n_next_nodes = LGPE_IP4_LOOKUP_N_NEXT,
1030   .next_nodes = {
1031 #define _(sym,str) [LGPE_IP4_LOOKUP_NEXT_##sym] = str,
1032       foreach_lgpe_ip4_lookup_next
1033 #undef _
1034   },
1035 };
1036
1037 static u32
1038 ip6_src_fib_lookup (lisp_gpe_main_t * lgm, u32 src_fib_index,
1039                     ip6_address_t * src)
1040 {
1041   int i, len;
1042   int rv;
1043   BVT(clib_bihash_kv) kv, value;
1044   ip6_src_fib_t * fib = pool_elt_at_index (lgm->ip6_src_fibs, src_fib_index);
1045
1046   len = vec_len (fib->prefix_lengths_in_search_order);
1047
1048   for (i = 0; i < len; i++)
1049     {
1050       int dst_address_length = fib->prefix_lengths_in_search_order[i];
1051       ip6_address_t * mask;
1052
1053       ASSERT(dst_address_length >= 0 && dst_address_length <= 128);
1054
1055       mask = &fib->fib_masks[dst_address_length];
1056
1057       kv.key[0] = src->as_u64[0] & mask->as_u64[0];
1058       kv.key[1] = src->as_u64[1] & mask->as_u64[1];
1059       kv.key[2] = dst_address_length;
1060
1061       rv = BV(clib_bihash_search_inline_2)(&fib->ip6_lookup_table, &kv, &value);
1062       if (rv == 0)
1063         return value.value;
1064     }
1065
1066   return 0;
1067 }
1068
1069 always_inline void
1070 ip6_src_fib_lookup_one (lisp_gpe_main_t * lgm, u32 src_fib_index0,
1071                         ip6_address_t * addr0, u32 * src_adj_index0)
1072 {
1073   /* if default route not hit in ip6 lookup */
1074   if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0))
1075     src_adj_index0[0] = ip6_src_fib_lookup (lgm, src_fib_index0, addr0);
1076   else
1077     src_adj_index0[0] = ~0;
1078 }
1079
1080 always_inline void
1081 ip6_src_fib_lookup_two (lisp_gpe_main_t * lgm, u32 src_fib_index0,
1082                         u32 src_fib_index1, ip6_address_t * addr0,
1083                         ip6_address_t * addr1, u32 * src_adj_index0,
1084                         u32 * src_adj_index1)
1085 {
1086   /* if default route not hit in ip6 lookup */
1087   if (PREDICT_TRUE(src_fib_index0 != (u32 ) ~0 && src_fib_index1 != (u32 ) ~0))
1088     {
1089       src_adj_index0[0] = ip6_src_fib_lookup(lgm, src_fib_index0, addr0);
1090       src_adj_index1[0] = ip6_src_fib_lookup(lgm, src_fib_index1, addr1);
1091     }
1092   else
1093     {
1094       ip6_src_fib_lookup_one (lgm, src_fib_index0, addr0, src_adj_index0);
1095       ip6_src_fib_lookup_one (lgm, src_fib_index1, addr1, src_adj_index1);
1096     }
1097 }
1098
1099 always_inline uword
1100 lgpe_ip6_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
1101                  vlib_frame_t * from_frame)
1102 {
1103   u32 n_left_from, next_index, * from, * to_next;
1104   lisp_gpe_main_t * lgm = &lisp_gpe_main;
1105
1106   from = vlib_frame_vector_args (from_frame);
1107   n_left_from = from_frame->n_vectors;
1108
1109   next_index = node->cached_next_index;
1110
1111   while (n_left_from > 0)
1112     {
1113       u32 n_left_to_next;
1114
1115       vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
1116
1117       while (n_left_from >= 4 && n_left_to_next >= 2)
1118         {
1119           u32 bi0, bi1;
1120           vlib_buffer_t * b0, * b1;
1121           ip6_header_t * ip0, * ip1;
1122           u32 dst_adj_index0, src_adj_index0, src_fib_index0, dst_adj_index1,
1123               src_adj_index1, src_fib_index1;
1124           ip_adjacency_t * dst_adj0, * src_adj0, * dst_adj1, * src_adj1;
1125           u32 next0, next1;
1126
1127           next0 = next1 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
1128
1129           /* Prefetch next iteration. */
1130           {
1131             vlib_buffer_t * p2, * p3;
1132
1133             p2 = vlib_get_buffer (vm, from[2]);
1134             p3 = vlib_get_buffer (vm, from[3]);
1135
1136             vlib_prefetch_buffer_header (p2, LOAD);
1137             vlib_prefetch_buffer_header (p3, LOAD);
1138
1139             CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
1140             CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
1141           }
1142
1143           bi0 = from[0];
1144           bi1 = from[1];
1145           to_next[0] = bi0;
1146           to_next[1] = bi1;
1147           from += 2;
1148           to_next += 2;
1149           n_left_to_next -= 2;
1150           n_left_from -= 2;
1151
1152           b0 = vlib_get_buffer (vm, bi0);
1153           b1 = vlib_get_buffer (vm, bi1);
1154
1155           ip0 = vlib_buffer_get_current (b0);
1156           ip1 = vlib_buffer_get_current (b1);
1157
1158           /* dst lookup was done by ip6 lookup */
1159           dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1160           dst_adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
1161
1162           dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
1163           dst_adj1 = ip_get_adjacency (lgm->lm6, dst_adj_index1);
1164
1165           src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1166           src_fib_index1 = dst_adj1->rewrite_header.sw_if_index;
1167
1168           ip6_src_fib_lookup_two (lgm, src_fib_index0, src_fib_index1,
1169                                   &ip0->src_address, &ip1->src_address,
1170                                   &src_adj_index0, &src_adj_index1);
1171
1172           /* if a source fib exists */
1173           if (PREDICT_TRUE((u32) ~0 != src_adj_index0
1174                            && (u32) ~0 != src_adj_index1))
1175             {
1176               vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1177               vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1178
1179               src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1180               src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
1181
1182               next0 = src_adj0->explicit_fib_index;
1183               next1 = src_adj1->explicit_fib_index;
1184
1185               /* prepare buffer for lisp-gpe output node */
1186               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1187                   src_adj0->rewrite_header.sw_if_index;
1188               vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1189                   src_adj1->rewrite_header.sw_if_index;
1190
1191               /* if multipath: saved_lookup_next_index is reused to store
1192                * nb of sub-tunnels. If greater than 1, multipath is on.
1193                * Note that flow hash should be 0 after ipx lookup! */
1194               if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
1195                 vnet_buffer (b0)->ip.flow_hash = ip6_compute_flow_hash (
1196                     ip0, IP_FLOW_HASH_DEFAULT);
1197
1198               if (PREDICT_TRUE(src_adj1->saved_lookup_next_index > 1))
1199                 vnet_buffer (b1)->ip.flow_hash = ip6_compute_flow_hash (
1200                     ip1, IP_FLOW_HASH_DEFAULT);
1201             }
1202           else
1203             {
1204               if (src_adj_index0 != (u32) ~0)
1205                 {
1206                   vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1207                   src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1208                   next0 = src_adj0->explicit_fib_index;
1209                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1210                       src_adj0->rewrite_header.sw_if_index;
1211
1212                   if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
1213                     vnet_buffer (b0)->ip.flow_hash = ip6_compute_flow_hash (
1214                         ip0, IP_FLOW_HASH_DEFAULT);
1215                 }
1216               else
1217                 {
1218                   next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1219                 }
1220
1221               if (src_adj_index1 != (u32) ~0)
1222                 {
1223                   vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
1224                   src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
1225                   next1 = src_adj1->explicit_fib_index;
1226                   vnet_buffer (b1)->sw_if_index[VLIB_TX] =
1227                       src_adj1->rewrite_header.sw_if_index;
1228
1229                   if (PREDICT_TRUE(src_adj1->saved_lookup_next_index > 1))
1230                     vnet_buffer (b1)->ip.flow_hash = ip6_compute_flow_hash (
1231                         ip1, IP_FLOW_HASH_DEFAULT);
1232                 }
1233               else
1234                 {
1235                   next1 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1236                 }
1237             }
1238
1239           /* mark the packets for CP lookup if needed*/
1240           if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1241             vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1242           if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next1))
1243             vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_IP;
1244
1245           vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
1246                                           n_left_to_next, bi0, bi1, next0,
1247                                           next1);
1248         }
1249
1250       while (n_left_from > 0 && n_left_to_next > 0)
1251         {
1252           vlib_buffer_t * b0;
1253           ip6_header_t * ip0;
1254           u32 bi0, dst_adj_index0, src_adj_index0, src_fib_index0;
1255           u32 next0 = LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP;
1256           ip_adjacency_t * dst_adj0, * src_adj0;
1257
1258           bi0 = from[0];
1259           to_next[0] = bi0;
1260           from += 1;
1261           to_next += 1;
1262           n_left_from -= 1;
1263           n_left_to_next -= 1;
1264
1265           b0 = vlib_get_buffer (vm, bi0);
1266           ip0 = vlib_buffer_get_current (b0);
1267
1268           /* dst lookup was done by ip6 lookup */
1269           dst_adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1270           dst_adj0 = ip_get_adjacency (lgm->lm6, dst_adj_index0);
1271           src_fib_index0 = dst_adj0->rewrite_header.sw_if_index;
1272
1273           /* do src lookup */
1274           ip6_src_fib_lookup_one (lgm, src_fib_index0, &ip0->src_address,
1275                                   &src_adj_index0);
1276
1277           /* if a source fib exists */
1278           if (PREDICT_TRUE(src_adj_index0 != (u32 ) ~0))
1279             {
1280               vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
1281               src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
1282               next0 = src_adj0->explicit_fib_index;
1283
1284               /* prepare packet for lisp-gpe output node */
1285               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
1286                   src_adj0->rewrite_header.sw_if_index;
1287
1288               /* if multipath: saved_lookup_next_index is reused to store
1289                * nb of sub-tunnels. If greater than 1, multipath is on */
1290               if (PREDICT_TRUE(src_adj0->saved_lookup_next_index > 1))
1291                 vnet_buffer (b0)->ip.flow_hash = ip6_compute_flow_hash (
1292                     ip0, IP_FLOW_HASH_DEFAULT);
1293             }
1294           else
1295             {
1296               next0 = LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP;
1297             }
1298
1299           /* mark the packets for CP lookup if needed*/
1300           if (PREDICT_FALSE(LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP == next0))
1301             vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_IP;
1302
1303           vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1304                                           n_left_to_next, bi0, next0);
1305         }
1306       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1307     }
1308   return from_frame->n_vectors;
1309 }
1310
1311 VLIB_REGISTER_NODE (lgpe_ip6_lookup_node) = {
1312   .function = lgpe_ip6_lookup,
1313   .name = "lgpe-ip6-lookup",
1314   .vector_size = sizeof (u32),
1315
1316   .type = VLIB_NODE_TYPE_INTERNAL,
1317
1318   .n_next_nodes = LGPE_IP6_LOOKUP_N_NEXT,
1319   .next_nodes = {
1320 #define _(sym,str) [LGPE_IP6_LOOKUP_NEXT_##sym] = str,
1321       foreach_lgpe_ip6_lookup_next
1322 #undef _
1323   },
1324 };