gre: multipoint ingress lookup fix

Type: fix

Change-Id: I170edd62220a63cb19efea3032e173fb87730b1b
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/nhrp/nhrp.c b/src/vnet/nhrp/nhrp.c
index a89f6cd..e97fbe0 100644
--- a/src/vnet/nhrp/nhrp.c
+++ b/src/vnet/nhrp/nhrp.c
@@ -20,8 +20,55 @@
 #include <vnet/fib/fib_table.h>
 #include <vnet/adj/adj_midchain.h>
 
+typedef struct nhrp_key_t_
+{
+  ip46_address_t nk_peer;
+  u32 nk_sw_if_index;
+} nhrp_key_t;
+
+struct nhrp_entry_t_
+{
+  nhrp_key_t *ne_key;
+  fib_prefix_t ne_nh;
+  u32 ne_fib_index;
+};
+
 static uword *nhrp_db;
 static nhrp_entry_t *nhrp_pool;
+static nhrp_vft_t *nhrp_vfts;
+
+#define NHRP_NOTIFY(_ne, _fn) {                 \
+  nhrp_vft_t *_vft;                             \
+  vec_foreach(_vft, nhrp_vfts) {                \
+    if (_vft->_fn) {                             \
+      _vft->_fn(_ne);                            \
+    }                                           \
+  }                                             \
+}
+
+u32
+nhrp_entry_get_sw_if_index (const nhrp_entry_t * ne)
+{
+  return (ne->ne_key->nk_sw_if_index);
+}
+
+u32
+nhrp_entry_get_fib_index (const nhrp_entry_t * ne)
+{
+  return (ne->ne_fib_index);
+}
+
+const ip46_address_t *
+nhrp_entry_get_peer (const nhrp_entry_t * ne)
+{
+  return (&ne->ne_key->nk_peer);
+}
+
+const fib_prefix_t *
+nhrp_entry_get_nh (const nhrp_entry_t * ne)
+{
+  return (&ne->ne_nh);
+}
 
 void
 nhrp_entry_adj_stack (const nhrp_entry_t * ne, adj_index_t ai)
@@ -113,6 +160,8 @@
       adj_nbr_walk_nh (sw_if_index,
 		       ne->ne_nh.fp_proto,
 		       &ne->ne_key->nk_peer, nhrp_entry_add_adj_walk, ne);
+
+      NHRP_NOTIFY (ne, nv_added);
     }
   else
     return (VNET_API_ERROR_ENTRY_ALREADY_EXISTS);
@@ -135,6 +184,8 @@
 		       ne->ne_nh.fp_proto,
 		       &ne->ne_key->nk_peer, nhrp_entry_del_adj_walk, ne);
 
+      NHRP_NOTIFY (ne, nv_deleted);
+
       clib_mem_free (ne->ne_key);
       pool_put (nhrp_pool, ne);
     }
@@ -178,6 +229,26 @@
   /* *INDENT-ON* */
 }
 
+void
+nhrp_walk_itf (u32 sw_if_index, nhrp_walk_cb_t fn, void *ctx)
+{
+  index_t nei;
+
+  /* *INDENT-OFF* */
+  pool_foreach_index(nei, nhrp_pool,
+  ({
+    if (sw_if_index == nhrp_entry_get_sw_if_index(nhrp_entry_get(nei)))
+      fn(nei, ctx);
+  }));
+  /* *INDENT-ON* */
+}
+
+void
+nhrp_register (const nhrp_vft_t * vft)
+{
+  vec_add1 (nhrp_vfts, *vft);
+}
+
 static clib_error_t *
 nhrp_init (vlib_main_t * vm)
 {
diff --git a/src/vnet/nhrp/nhrp.h b/src/vnet/nhrp/nhrp.h
index fa842fe..5b46b0d 100644
--- a/src/vnet/nhrp/nhrp.h
+++ b/src/vnet/nhrp/nhrp.h
@@ -20,21 +20,25 @@
 
 #include <vnet/ip/ip.h>
 
-typedef struct nhrp_key_t_
-{
-  ip46_address_t nk_peer;
-  u32 nk_sw_if_index;
-} nhrp_key_t;
+/**
+ * An NHRP entry represents the mapping between a peer on an interface in the overlay
+ * and a next-hop address in the underlay.
+ *  i.e. there's a multipoint tunnel providing the overlay (henace a peer on
+ *   that tunnel) which is reachable via 'tunnel destination' address in the
+ *   underlay.
+ */
+typedef struct nhrp_entry_t_ nhrp_entry_t;
 
-typedef struct nhrp_entry_t_
-{
-  nhrp_key_t *ne_key;
-  fib_prefix_t ne_nh;
-  u32 ne_fib_index;
-} nhrp_entry_t;
-
+/** accessors for the opaque struct */
+extern u32 nhrp_entry_get_sw_if_index (const nhrp_entry_t * ne);
+extern u32 nhrp_entry_get_fib_index (const nhrp_entry_t * ne);
+extern const ip46_address_t *nhrp_entry_get_peer (const nhrp_entry_t * ne);
+extern const fib_prefix_t *nhrp_entry_get_nh (const nhrp_entry_t * ne);
 extern u8 *format_nhrp_entry (u8 * s, va_list * args);
 
+/**
+ * Create a new NHRP entry
+ */
 extern int nhrp_entry_add (u32 sw_if_index,
 			   const ip46_address_t * peer,
 			   u32 nh_table_id, const ip46_address_t * nh);
@@ -50,6 +54,21 @@
 typedef walk_rc_t (*nhrp_walk_cb_t) (index_t nei, void *ctx);
 
 extern void nhrp_walk (nhrp_walk_cb_t fn, void *ctx);
+extern void nhrp_walk_itf (u32 sw_if_index, nhrp_walk_cb_t fn, void *ctx);
+
+/**
+ * Notifications for the creation and deletion of NHRP entries
+ */
+typedef void (*nhrp_entry_added_t) (const nhrp_entry_t * ne);
+typedef void (*nhrp_entry_deleted_t) (const nhrp_entry_t * ne);
+
+typedef struct nhrp_vft_t_
+{
+  nhrp_entry_added_t nv_added;
+  nhrp_entry_deleted_t nv_deleted;
+} nhrp_vft_t;
+
+extern void nhrp_register (const nhrp_vft_t * vft);
 
 #endif
 
diff --git a/src/vnet/nhrp/nhrp_api.c b/src/vnet/nhrp/nhrp_api.c
index 6f07eb7..d36adf9 100644
--- a/src/vnet/nhrp/nhrp_api.c
+++ b/src/vnet/nhrp/nhrp_api.c
@@ -70,6 +70,7 @@
   vl_api_nhrp_details_t *mp;
   vl_api_nhrp_send_t *ctx = arg;
   const nhrp_entry_t *ne;
+  const fib_prefix_t *pfx;
 
   mp = vl_msg_api_alloc (sizeof (*mp));
   clib_memset (mp, 0, sizeof (*mp));
@@ -77,12 +78,15 @@
   mp->context = ctx->context;
 
   ne = nhrp_entry_get (nei);
+  pfx = nhrp_entry_get_nh (ne);
 
-  ip_address_encode (&ne->ne_key->nk_peer, IP46_TYPE_ANY, &mp->entry.peer);
-  ip_address_encode (&ne->ne_nh.fp_addr, IP46_TYPE_ANY, &mp->entry.nh);
+  ip_address_encode (nhrp_entry_get_peer (ne), IP46_TYPE_ANY,
+		     &mp->entry.peer);
+  ip_address_encode (&pfx->fp_addr, IP46_TYPE_ANY, &mp->entry.nh);
   mp->entry.nh_table_id =
-    htonl (fib_table_get_table_id (ne->ne_fib_index, ne->ne_nh.fp_proto));
-  mp->entry.sw_if_index = htonl (ne->ne_key->nk_sw_if_index);
+    htonl (fib_table_get_table_id
+	   (nhrp_entry_get_fib_index (ne), pfx->fp_proto));
+  mp->entry.sw_if_index = htonl (nhrp_entry_get_sw_if_index (ne));
 
   vl_api_send_msg (ctx->reg, (u8 *) mp);