LISP-GPE: add dump call for VNIs in use

Change-Id: I394af7c1ac9fd0177ff5d298e4008245df54b436
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
diff --git a/src/vnet/lisp-gpe/lisp_gpe.api b/src/vnet/lisp-gpe/lisp_gpe.api
index f79d18c..7af1533 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.api
+++ b/src/vnet/lisp-gpe/lisp_gpe.api
@@ -87,6 +87,20 @@
   u32 vni;
 };
 
+define gpe_fwd_entry_vnis_get
+{
+  u32 client_index;
+  u32 context;
+};
+
+manual_print manual_endian define gpe_fwd_entry_vnis_get_reply
+{
+  u32 context;
+  i32 retval;
+  u32 count;
+  u32 vnis[count];
+};
+
 define gpe_fwd_entries_get
 {
   u32 client_index;
@@ -103,6 +117,8 @@
   u8 reid_prefix_len;
   u8 leid[16];
   u8 reid[16];
+  u32 vni;
+  u8 action;
 };
 
 manual_print manual_endian define gpe_fwd_entries_get_reply
diff --git a/src/vnet/lisp-gpe/lisp_gpe.h b/src/vnet/lisp-gpe/lisp_gpe.h
index 38d7699..d86a225 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.h
+++ b/src/vnet/lisp-gpe/lisp_gpe.h
@@ -271,6 +271,7 @@
   u32 fwd_entry_index;
   u32 dp_table;
   u32 vni;
+  u8 action;
   dp_address_t leid;
   dp_address_t reid;
 } lisp_api_gpe_fwd_entry_t;
diff --git a/src/vnet/lisp-gpe/lisp_gpe_api.c b/src/vnet/lisp-gpe/lisp_gpe_api.c
index f6bd544..9edffa1 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_api.c
+++ b/src/vnet/lisp-gpe/lisp_gpe_api.c
@@ -57,6 +57,7 @@
 _(GPE_FWD_ENTRY_PATH_DUMP, gpe_fwd_entry_path_dump)           \
 _(GPE_ENABLE_DISABLE, gpe_enable_disable)                     \
 _(GPE_ADD_DEL_IFACE, gpe_add_del_iface)                       \
+_(GPE_FWD_ENTRY_VNIS_GET, gpe_fwd_entry_vnis_get)             \
 _(GPE_SET_ENCAP_MODE, gpe_set_encap_mode)                     \
 _(GPE_GET_ENCAP_MODE, gpe_get_encap_mode)
 
@@ -200,6 +201,8 @@
     memset (dst, 0, sizeof (*dst));
     dst[i].dp_table = src->dp_table;
     dst[i].fwd_entry_index = src->fwd_entry_index;
+    dst[i].vni = src->vni;
+    dst[i].action = src->action;
     switch (fid_addr_type (&e->leid))
       {
       case FID_ADDR_IP_PREF:
@@ -242,6 +245,7 @@
 {
   e->fwd_entry_index = clib_host_to_net_u32 (e->fwd_entry_index);
   e->dp_table = clib_host_to_net_u32 (e->dp_table);
+  e->vni = clib_host_to_net_u32 (e->vni);
 }
 
 static void
@@ -260,6 +264,31 @@
 }
 
 static void
+vl_api_gpe_fwd_entry_vnis_get_t_handler (vl_api_gpe_fwd_entry_vnis_get_t * mp)
+{
+  vl_api_gpe_fwd_entry_vnis_get_reply_t *rmp = 0;
+  hash_pair_t *p;
+  u32 i = 0;
+  int rv = 0;
+
+  u32 *vnis = vnet_lisp_gpe_get_fwd_entry_vnis ();
+  u32 size = hash_elts (vnis) * sizeof (u32);
+
+  /* *INDENT-OFF* */
+  REPLY_MACRO4 (VL_API_GPE_FWD_ENTRY_VNIS_GET_REPLY, size,
+  {
+    rmp->count = clib_host_to_net_u32 (hash_elts (vnis));
+    hash_foreach_pair (p, vnis,
+    ({
+      rmp->vnis[i++] = clib_host_to_net_u32 (p->key);
+    }));
+  });
+  /* *INDENT-ON* */
+
+  hash_free (vnis);
+}
+
+static void
 vl_api_gpe_fwd_entries_get_t_handler (vl_api_gpe_fwd_entries_get_t * mp)
 {
   lisp_api_gpe_fwd_entry_t *e;
@@ -315,7 +344,7 @@
     }
   pairs = unformat_gpe_loc_pairs (mp->locs, mp->loc_num / 2);
 
-  if (rv || 0 == pairs)
+  if (rv)
     goto send_reply;
 
   a->is_add = mp->is_add;
@@ -323,6 +352,8 @@
   a->dp_table = mp->dp_table;
   a->vni = mp->vni;
   a->action = mp->action;
+  if (mp->loc_num == 0)
+    a->is_negative = 1;
 
   rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
   vec_free (pairs);
diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
index 6d400f7..1c34e6e 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
+++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
@@ -495,6 +495,10 @@
     {
       lisp_gpe_fwd_entry_mk_paths (lfe, a);
     }
+  else
+    {
+      lfe->action = a->action;
+    }
 
   create_fib_entries (lfe);
   return (0);
@@ -1438,6 +1442,23 @@
   return (error);
 }
 
+u32 *
+vnet_lisp_gpe_get_fwd_entry_vnis (void)
+{
+  lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+  lisp_gpe_fwd_entry_t *lfe;
+  u32 *vnis = 0;
+
+  /* *INDENT-OFF* */
+  pool_foreach (lfe, lgm->lisp_fwd_entry_pool,
+  ({
+    hash_set (vnis, lfe->key->vni, 0);
+  }));
+  /* *INDENT-ON* */
+
+  return vnis;
+}
+
 lisp_api_gpe_fwd_entry_t *
 vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni)
 {
@@ -1453,6 +1474,8 @@
         memset (&e, 0, sizeof (e));
         e.dp_table = lfe->eid_table_id;
         e.vni = lfe->key->vni;
+        if (lfe->type == LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE)
+          e.action = lfe->action;
         e.fwd_entry_index = lfe - lgm->lisp_fwd_entry_pool;
         memcpy (&e.reid, &lfe->key->rmt, sizeof (e.reid));
         memcpy (&e.leid, &lfe->key->lcl, sizeof (e.leid));
diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h
index b9d9c98..1580351 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h
+++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h
@@ -217,6 +217,8 @@
 extern void
 vnet_lisp_gpe_add_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
 				u32 fwd_entry_index);
+extern u32 *vnet_lisp_gpe_get_fwd_entry_vnis (void);
+
 #endif
 
 /*