+ hash_unset_mem_free (&gm->tunnel_by_key, key);
+}
+
+void
+ipip_mk_key_i (ipip_transport_t transport,
+ ipip_mode_t mode,
+ const ip46_address_t * src,
+ const ip46_address_t * dst,
+ u32 fib_index, ipip_tunnel_key_t * key)
+{
+ key->transport = transport;
+ key->mode = mode;
+ key->src = *src;
+ key->dst = *dst;
+ key->fib_index = fib_index;
+ key->__pad = 0;;
+}
+
+void
+ipip_mk_key (const ipip_tunnel_t * t, ipip_tunnel_key_t * key)
+{
+ ipip_mk_key_i (t->transport, t->mode,
+ &t->tunnel_src, &t->tunnel_dst, t->fib_index, key);
+}
+
+static void
+ipip_nhrp_mk_key (const ipip_tunnel_t * t,
+ const nhrp_entry_t * ne, ipip_tunnel_key_t * key)
+{
+ const fib_prefix_t *nh;
+
+ nh = nhrp_entry_get_nh (ne);
+
+ /* construct the key using mode P2P so it can be found in the DP */
+ ipip_mk_key_i (t->transport, IPIP_MODE_P2P,
+ &t->tunnel_src, &nh->fp_addr,
+ nhrp_entry_get_fib_index (ne), key);
+}
+
+static void
+ipip_nhrp_entry_added (const nhrp_entry_t * ne)
+{
+ ipip_main_t *gm = &ipip_main;
+ const ip46_address_t *nh;
+ ipip_tunnel_key_t key;
+ ipip_tunnel_t *t;
+ u32 sw_if_index;
+ u32 t_idx;
+
+ sw_if_index = nhrp_entry_get_sw_if_index (ne);
+ if (vec_len (gm->tunnel_index_by_sw_if_index) < sw_if_index)
+ return;
+
+ t_idx = gm->tunnel_index_by_sw_if_index[sw_if_index];
+
+ if (INDEX_INVALID == t_idx)
+ return;
+
+ t = pool_elt_at_index (gm->tunnels, t_idx);
+
+ ipip_nhrp_mk_key (t, ne, &key);
+ ipip_tunnel_db_add (t, &key);
+
+ // update the rewrites for each of the adjacencies for this next-hop
+ mipip_walk_ctx_t ctx = {
+ .t = t,
+ .ne = ne
+ };
+ nh = nhrp_entry_get_peer (ne);
+ adj_nbr_walk_nh (nhrp_entry_get_sw_if_index (ne),
+ (ip46_address_is_ip4 (nh) ?
+ FIB_PROTOCOL_IP4 :
+ FIB_PROTOCOL_IP6), nh, mipip_mk_complete_walk, &ctx);
+}
+
+static void
+ipip_nhrp_entry_deleted (const nhrp_entry_t * ne)
+{
+ ipip_main_t *gm = &ipip_main;
+ const ip46_address_t *nh;
+ ipip_tunnel_key_t key;
+ ipip_tunnel_t *t;
+ u32 sw_if_index;
+ u32 t_idx;
+
+ sw_if_index = nhrp_entry_get_sw_if_index (ne);
+ if (vec_len (gm->tunnel_index_by_sw_if_index) < sw_if_index)
+ return;
+
+ t_idx = gm->tunnel_index_by_sw_if_index[sw_if_index];
+
+ if (INDEX_INVALID == t_idx)
+ return;
+
+ t = pool_elt_at_index (gm->tunnels, t_idx);
+
+ ipip_nhrp_mk_key (t, ne, &key);
+ ipip_tunnel_db_remove (t, &key);
+
+ nh = nhrp_entry_get_peer (ne);
+
+ /* make all the adjacencies incomplete */
+ adj_nbr_walk_nh (nhrp_entry_get_sw_if_index (ne),
+ (ip46_address_is_ip4 (nh) ?
+ FIB_PROTOCOL_IP4 :
+ FIB_PROTOCOL_IP6), nh, mipip_mk_incomplete_walk, t);
+}
+
+static walk_rc_t
+ipip_tunnel_delete_nhrp_walk (index_t nei, void *ctx)
+{
+ ipip_tunnel_t *t = ctx;
+ ipip_tunnel_key_t key;
+
+ ipip_nhrp_mk_key (t, nhrp_entry_get (nei), &key);
+ ipip_tunnel_db_remove (t, &key);
+
+ return (WALK_CONTINUE);
+}
+
+static walk_rc_t
+ipip_tunnel_add_nhrp_walk (index_t nei, void *ctx)
+{
+ ipip_tunnel_t *t = ctx;
+ ipip_tunnel_key_t key;
+
+ ipip_nhrp_mk_key (t, nhrp_entry_get (nei), &key);
+ ipip_tunnel_db_add (t, &key);
+
+ return (WALK_CONTINUE);