Fix use of lookup_next_index in LISP src/dst FIB 39/1639/2
authorFlorin Coras <fcoras@cisco.com>
Fri, 17 Jun 2016 11:59:10 +0000 (13:59 +0200)
committerDave Barach <openvpp@barachs.net>
Sun, 19 Jun 2016 13:26:11 +0000 (13:26 +0000)
Adjacencies in LISP src/dst FIB store the index of the LISP output
interface (next node after lookup) in the lookup_next_index. Since the
values of interface node indexes are not constrained, they can collide
with the 'special' adjacencies IP_LOOKUP_NEXT_LOCAL and
IP_LOOKUP_NEXT_DROP. As a result, at allocation time, LISP ajacencies
may be automatically shared with the previous two, predefined
adjacencies and all LISP specific state stored in the rewrite area is
lost.

This fixes the problem by 'hijacking' the explicit_fib_index instead
of the lookup_next_index field.

Change-Id: I3c59121dcf0851decf5c08004143d1201dbd1ece
Signed-off-by: Florin Coras <fcoras@cisco.com>
vnet/vnet/lisp-gpe/ip_forward.c
vnet/vnet/lisp-gpe/lisp_gpe.c

index 38a274e..fcb453c 100644 (file)
@@ -245,6 +245,12 @@ ip4_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
           /* dst adj should point to lisp gpe lookup */
           dst_adj.lookup_next_index = lgm->ip4_lookup_next_lgpe_ip4_lookup;
 
+          /* make sure we have different signatures for adj in different tables
+           * but with the same lookup_next_index */
+          dst_adj.explicit_fib_index = table_id;
+
+          dst_adj.n_adj = 1;
+
           memset(&a, 0, sizeof(a));
           a.flags = IP4_ROUTE_FLAG_TABLE_ID;
           a.table_index_or_table_id = table_id; /* vrf */
@@ -262,6 +268,14 @@ ip4_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
                              dst_address_length);
 
           ASSERT(p != 0);
+
+          /* make sure insertion succeeded */
+          if (CLIB_DEBUG)
+            {
+              dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
+              ASSERT(dst_adjp->rewrite_header.sw_if_index
+                      == dst_adj.rewrite_header.sw_if_index);
+            }
         }
     }
   else
@@ -277,6 +291,12 @@ ip4_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
 
   dst_adjp = ip_get_adjacency (lgm->lm4, p[0]);
 
+  /* make sure adj signature is unique, i.e., fill in mcast_group_index
+   * and saved_lookup_next index with data that makes this adj unique.
+   * All these fields are (and should stay that way) unused by LISP. */
+  add_adj->mcast_group_index = table_id;
+  add_adj->saved_lookup_next_index = dst_adjp->rewrite_header.sw_if_index;
+
   /* add/del src prefix to src fib */
   memset(&a, 0, sizeof(a));
   a.flags = IP4_ROUTE_FLAG_TABLE_ID;
@@ -290,6 +310,18 @@ ip4_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
   a.dst_address = src;
   ip4_sd_fib_add_del_src_route (lgm, &a);
 
+  /* make sure insertion succeeded */
+  if (CLIB_DEBUG)
+    {
+      uword * sai;
+      ip_adjacency_t * src_adjp;
+      sai = ip4_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
+                                  &src, src_address_length);
+      src_adjp = ip_get_adjacency(lgm->lm4, sai[0]);
+      ASSERT(src_adjp->rewrite_header.node_index
+              == add_adj->rewrite_header.node_index);
+    }
+
   /* if a delete, check if there are elements left in the src fib */
   if (!is_add)
     {
@@ -559,6 +591,10 @@ ip6_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
           /* dst adj should point to lisp gpe ip lookup */
           dst_adj.lookup_next_index = lgm->ip6_lookup_next_lgpe_ip6_lookup;
 
+          /* make sure we have different signatures for adj in different tables
+           * but with the same lookup_next_index */
+          dst_adj.explicit_fib_index = table_id;
+
           memset(&a, 0, sizeof(a));
           a.flags = IP6_ROUTE_FLAG_TABLE_ID;
           a.table_index_or_table_id = table_id; /* vrf */
@@ -576,6 +612,14 @@ ip6_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
                                      dst_address_length);
 
           ASSERT(adj_index != 0);
+
+          /* make sure insertion succeeded */
+          if (CLIB_DEBUG)
+            {
+              dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
+              ASSERT(dst_adjp->rewrite_header.sw_if_index
+                      == dst_adj.rewrite_header.sw_if_index);
+            }
         }
     }
   else
@@ -591,6 +635,12 @@ ip6_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
 
   dst_adjp = ip_get_adjacency (lgm->lm6, adj_index);
 
+  /* make sure adj signature is unique, i.e., fill in mcast_group_index
+   * and saved_lookup_next index with data that makes this adj unique.
+   * All these fields are (and should stay that way) unused by LISP. */
+  add_adj->mcast_group_index = table_id;
+  add_adj->saved_lookup_next_index = dst_adjp->rewrite_header.sw_if_index;
+
   /* add/del src prefix to src fib */
   memset(&a, 0, sizeof(a));
   a.flags = IP6_ROUTE_FLAG_TABLE_ID;
@@ -604,6 +654,18 @@ ip6_sd_fib_add_del_route (lisp_gpe_main_t * lgm, ip_prefix_t * dst_prefix,
   a.dst_address = src;
   ip6_sd_fib_add_del_src_route (lgm, &a);
 
+  /* make sure insertion succeeded */
+  if (CLIB_DEBUG)
+    {
+      u32 sai;
+      ip_adjacency_t * src_adjp;
+      sai = ip6_sd_get_src_route (lgm, dst_adjp->rewrite_header.sw_if_index,
+                                  &src, src_address_length);
+      src_adjp = ip_get_adjacency(lgm->lm6, sai);
+      ASSERT(src_adjp->rewrite_header.node_index
+              == add_adj->rewrite_header.node_index);
+    }
+
   /* if a delete, check if there are elements left in the src fib */
   if (!is_add)
     {
@@ -825,8 +887,8 @@ lgpe_ip4_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
               src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
               src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
 
-              next0 = src_adj0->lookup_next_index;
-              next1 = src_adj1->lookup_next_index;
+              next0 = src_adj0->explicit_fib_index;
+              next1 = src_adj1->explicit_fib_index;
 
               /* prepare buffer for lisp-gpe output node */
               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
@@ -842,7 +904,7 @@ lgpe_ip4_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
                                           &ip0->src_address, &src_adj_index0);
                   vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
                   src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
-                  next0 = src_adj0->lookup_next_index;
+                  next0 = src_adj0->explicit_fib_index;
                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
                       src_adj0->rewrite_header.sw_if_index;
                 }
@@ -852,7 +914,7 @@ lgpe_ip4_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
                                           &ip1->src_address, &src_adj_index1);
                   vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
                   src_adj1 = ip_get_adjacency (lgm->lm4, src_adj_index1);
-                  next1 = src_adj1->lookup_next_index;
+                  next1 = src_adj1->explicit_fib_index;
                   vnet_buffer (b1)->sw_if_index[VLIB_TX] =
                       src_adj1->rewrite_header.sw_if_index;
                 }
@@ -894,7 +956,7 @@ lgpe_ip4_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
                                       &src_adj_index0);
               vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
               src_adj0 = ip_get_adjacency (lgm->lm4, src_adj_index0);
-              next0 = src_adj0->lookup_next_index;
+              next0 = src_adj0->explicit_fib_index;
 
               /* prepare packet for lisp-gpe output node */
               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
@@ -1041,8 +1103,8 @@ lgpe_ip6_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
               src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
               src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
 
-              next0 = src_adj0->lookup_next_index;
-              next1 = src_adj1->lookup_next_index;
+              next0 = src_adj0->explicit_fib_index;
+              next1 = src_adj1->explicit_fib_index;
 
               /* prepare buffer for lisp-gpe output node */
               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
@@ -1058,7 +1120,7 @@ lgpe_ip6_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
                                                        &ip0->src_address);
                   vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
                   src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
-                  next0 = src_adj0->lookup_next_index;
+                  next0 = src_adj0->explicit_fib_index;
                   vnet_buffer (b0)->sw_if_index[VLIB_TX] =
                       src_adj0->rewrite_header.sw_if_index;
                 }
@@ -1068,7 +1130,7 @@ lgpe_ip6_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
                                                        &ip1->src_address);
                   vnet_buffer(b1)->ip.adj_index[VLIB_TX] = src_adj_index1;
                   src_adj1 = ip_get_adjacency (lgm->lm6, src_adj_index1);
-                  next1 = src_adj1->lookup_next_index;
+                  next1 = src_adj1->explicit_fib_index;
                   vnet_buffer (b1)->sw_if_index[VLIB_TX] =
                       src_adj1->rewrite_header.sw_if_index;
                 }
@@ -1111,7 +1173,7 @@ lgpe_ip6_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
 
               vnet_buffer(b0)->ip.adj_index[VLIB_TX] = src_adj_index0;
               src_adj0 = ip_get_adjacency (lgm->lm6, src_adj_index0);
-              next0 = src_adj0->lookup_next_index;
+              next0 = src_adj0->explicit_fib_index;
 
               /* prepare packet for lisp-gpe output node */
               vnet_buffer (b0)->sw_if_index[VLIB_TX] =
index 35e16bb..f594e92 100644 (file)
@@ -243,7 +243,11 @@ vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
   /* setup adjacency for eid */
   memset (&adj, 0, sizeof(adj));
   adj.n_adj = 1;
-  adj.explicit_fib_index = ~0;
+
+  /* fill in lookup_next_index with a 'legal' value to avoid problems */
+  adj.lookup_next_index = (ip_ver == IP4) ?
+          lgm->ip4_lookup_next_lgpe_ip4_lookup :
+          lgm->ip6_lookup_next_lgpe_ip6_lookup;
 
   if (a->is_add)
     {
@@ -261,7 +265,8 @@ vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
       ASSERT(lookup_next_index != 0);
       ASSERT(lgpe_sw_if_index != 0);
 
-      adj.lookup_next_index = lookup_next_index[0];
+      /* hijack explicit fib index to store lisp interface node index */
+      adj.explicit_fib_index = lookup_next_index[0];
       adj.rewrite_header.node_index = tun_index;
       adj.rewrite_header.sw_if_index = lgpe_sw_if_index[0];
     }