Add reaper functions to want events APIs (VPP-1304) 82/12882/8
authorNeale Ranns <nranns@cisco.com>
Tue, 5 Jun 2018 01:41:24 +0000 (18:41 -0700)
committerJohn Lo <loj@cisco.com>
Fri, 8 Jun 2018 23:11:02 +0000 (23:11 +0000)
Change-Id: Iaeb52d94cb6da63ee93af7c1cf2dade6046cba1d
Signed-off-by: Neale Ranns <nranns@cisco.com>
src/plugins/igmp/igmp.h
src/plugins/igmp/igmp_api.c
src/vlibapi/api_helper_macros.h
src/vnet/ip/ip6_neighbor.c
src/vnet/ip/ip_api.c
src/vpp/stats/stats.c

index f917be9..fc131f7 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <vlib/vlib.h>
 #include <vnet/ip/ip.h>
+#include <vlibapi/api_helper_macros.h>
 #include <vnet/ip/igmp_packet.h>
 #include <vnet/adj/adj_mcast.h>
 #include <igmp/igmp_format.h>
@@ -167,16 +168,6 @@ struct igmp_timer_t_;
 
 typedef struct igmp_timer_t_ igmp_timer_t;
 
-/** \brief igmp api client
-    @param client_index - client index
-    @param pid - pid
-*/
-typedef struct igmp_api_client_t_
-{
-  u32 client_index;
-  u32 pid;
-} igmp_api_client_t;
-
 typedef struct
 {
   u8 *name;
@@ -210,7 +201,7 @@ typedef struct igmp_main_t_
 
   uword *igmp_api_client_by_client_index;
 
-  igmp_api_client_t *api_clients;
+  vpe_client_registration_t *api_clients;
 
   uword *igmp_config_by_sw_if_index;
 
@@ -459,23 +450,6 @@ igmp_src_lookup (igmp_group_t * group, igmp_key_t * key)
   return src;
 }
 
-/** \brief igmp group lookup
-    @param im - igmp main
-    @param client_index - client index
-*/
-always_inline igmp_api_client_t *
-igmp_api_client_lookup (igmp_main_t * im, u32 client_index)
-{
-  uword *p;
-  igmp_api_client_t *api_client = NULL;
-
-  p = hash_get_mem (im->igmp_api_client_by_client_index, &client_index);
-  if (p)
-    api_client = vec_elt_at_index (im->api_clients, p[0]);
-
-  return api_client;
-}
-
 #endif /* _IGMP_H_ */
 
 /*
index 7044e7f..164779c 100644 (file)
@@ -194,11 +194,28 @@ vl_api_igmp_clear_interface_t_handler (vl_api_igmp_clear_interface_t * mp)
   vl_msg_api_send_shmem (q, (u8 *) & rmp);
 }
 
+/** \brief igmp group lookup
+    @param im - igmp main
+    @param client_index - client index
+*/
+static vpe_client_registration_t *
+igmp_api_client_lookup (igmp_main_t * im, u32 client_index)
+{
+  uword *p;
+  vpe_client_registration_t *api_client = NULL;
+
+  p = hash_get_mem (im->igmp_api_client_by_client_index, &client_index);
+  if (p)
+    api_client = vec_elt_at_index (im->api_clients, p[0]);
+
+  return api_client;
+}
+
 static void
 vl_api_want_igmp_events_t_handler (vl_api_want_igmp_events_t * mp)
 {
   igmp_main_t *im = &igmp_main;
-  igmp_api_client_t *api_client;
+  vpe_client_registration_t *api_client;
   vl_api_want_igmp_events_reply_t *rmp;
   int rv = 0;
 
@@ -218,9 +235,9 @@ vl_api_want_igmp_events_t_handler (vl_api_want_igmp_events_t * mp)
   if (mp->enable)
     {
       pool_get (im->api_clients, api_client);
-      memset (api_client, 0, sizeof (igmp_api_client_t));
+      memset (api_client, 0, sizeof (vpe_client_registration_t));
       api_client->client_index = mp->client_index;
-      api_client->pid = mp->pid;
+      api_client->client_pid = mp->pid;
       hash_set_mem (im->igmp_api_client_by_client_index,
                    &mp->client_index, api_client - im->api_clients);
       goto done;
@@ -241,6 +258,26 @@ done:;
   vl_msg_api_send_shmem (q, (u8 *) & rmp);
 }
 
+static clib_error_t *
+want_igmp_events_reaper (u32 client_index)
+{
+  igmp_main_t *im = &igmp_main;
+  vpe_client_registration_t *api_client;
+  uword *p;
+
+  p = hash_get_mem (im->igmp_api_client_by_client_index, &client_index);
+
+  if (p)
+    {
+      api_client = pool_elt_at_index (im->api_clients, p[0]);
+      pool_put (im->api_clients, api_client);
+      hash_unset_mem (im->igmp_api_client_by_client_index, &client_index);
+    }
+  return (NULL);
+}
+
+VL_MSG_API_REAPER_FUNCTION (want_igmp_events_reaper);
+
 void
 send_igmp_event (unix_shared_memory_queue_t * q, u32 context,
                 igmp_main_t * im, igmp_config_t * config,
@@ -264,7 +301,7 @@ void
 igmp_event (igmp_main_t * im, igmp_config_t * config, igmp_group_t * group,
            igmp_src_t * src)
 {
-  igmp_api_client_t *api_client;
+  vpe_client_registration_t *api_client;
   unix_shared_memory_queue_t *q;
   /* *INDENT-OFF* */
   pool_foreach (api_client, im->api_clients,
index ce80f0e..fe9cde0 100644 (file)
@@ -207,7 +207,25 @@ static void vl_api_want_##lca##_t_handler (                             \
                                                                         \
 reply:                                                                  \
     REPLY_MACRO (VL_API_WANT_##UCA##_REPLY);                            \
-}
+}                                                                       \
+                                                                        \
+static clib_error_t * vl_api_want_##lca##_t_reaper (u32 client_index)   \
+{                                                                       \
+    vpe_api_main_t *vam = &vpe_api_main;                                \
+    vpe_client_registration_t *rp;                                      \
+    uword *p;                                                           \
+                                                                        \
+    p = hash_get (vam->lca##_registrations, client_index);              \
+    if (p)                                                              \
+      {                                                                 \
+        rp = pool_elt_at_index (vam->lca##_registrations, p[0]);        \
+        pool_put (vam->lca##_registrations, rp);                        \
+        hash_unset (vam->lca##_registration_hash, client_index);        \
+      }                                                                 \
+    return (NULL);                                                      \
+}                                                                       \
+                                                                        \
+VL_MSG_API_REAPER_FUNCTION (vl_api_want_##lca##_t_reaper);              \
 
 #define foreach_registration_hash               \
 _(interface_events)                             \
index a76decf..fe78eae 100644 (file)
@@ -4780,11 +4780,17 @@ vnet_add_del_ip6_nd_change_event (vnet_main_t * vnm,
        return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
 
       pool_get (nm->mac_changes, mc);
+      /* *INDENT-OFF* */
       *mc = (pending_resolution_t)
       {
-      .next_index = ~0,.node_index = node_index,.type_opaque =
-         type_opaque,.data = data,.data_callback = data_callback,.pid =
-         pid,};
+        .next_index = ~0,
+        .node_index = node_index,
+        .type_opaque = type_opaque,
+        .data = data,
+        .data_callback = data_callback,
+        .pid = pid,
+      };
+      /* *INDENT-ON* */
 
       /* Insert new resolution at the end of the list */
       u32 new_idx = mc - nm->mac_changes;
index 8464b1d..48e523f 100644 (file)
@@ -2152,7 +2152,7 @@ handle_ip4_arp_event (u32 pool_index)
     }
 }
 
-void
+static void
 handle_ip6_nd_event (u32 pool_index)
 {
   vpe_api_main_t *vam = &vpe_api_main;
@@ -2587,6 +2587,58 @@ reply:
   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
 }
 
+static clib_error_t *
+want_ip4_arp_events_reaper (u32 client_index)
+{
+  vpe_client_registration_t *rp;
+  vl_api_ip4_arp_event_t *event;
+  u32 *to_delete, *event_id;
+  vpe_api_main_t *am;
+  vnet_main_t *vnm;
+  uword *p;
+
+  am = &vpe_api_main;
+  vnm = vnet_get_main ();
+  to_delete = NULL;
+
+  /* clear out all of its pending resolutions */
+  /* *INDENT-OFF* */
+  pool_foreach(event, am->arp_events,
+  ({
+    if (event->client_index == client_index)
+      {
+        vec_add1(to_delete, event - am->arp_events);
+      }
+  }));
+  /* *INDENT-ON* */
+
+  vec_foreach (event_id, to_delete)
+  {
+    event = pool_elt_at_index (am->arp_events, *event_id);
+    vnet_add_del_ip4_arp_change_event
+      (vnm, arp_change_delete_callback,
+       event->pid, &event->address,
+       ip_resolver_process_node.index, IP4_ARP_EVENT,
+       ~0 /* pool index, notused */ , 0 /* is_add */ );
+  }
+  vec_free (to_delete);
+
+  /* remove from the registration hash */
+  p = hash_get (am->wc_ip4_arp_events_registration_hash, client_index);
+
+  if (p)
+    {
+      rp = pool_elt_at_index (am->wc_ip4_arp_events_registrations, p[0]);
+      pool_put (am->wc_ip4_arp_events_registrations, rp);
+      hash_unset (am->wc_ip4_arp_events_registration_hash, client_index);
+      if (pool_elts (am->wc_ip4_arp_events_registrations) == 0)
+       wc_arp_set_publisher_node (~0, REPORT_MAX);
+    }
+  return (NULL);
+}
+
+VL_MSG_API_REAPER_FUNCTION (want_ip4_arp_events_reaper);
+
 static void
 vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
 {
@@ -2670,6 +2722,59 @@ reply:
   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
 }
 
+static clib_error_t *
+want_ip6_nd_events_reaper (u32 client_index)
+{
+
+  vpe_client_registration_t *rp;
+  vl_api_ip6_nd_event_t *event;
+  u32 *to_delete, *event_id;
+  vpe_api_main_t *am;
+  vnet_main_t *vnm;
+  uword *p;
+
+  am = &vpe_api_main;
+  vnm = vnet_get_main ();
+  to_delete = NULL;
+
+  /* clear out all of its pending resolutions */
+  /* *INDENT-OFF* */
+  pool_foreach(event, am->nd_events,
+  ({
+    if (event->client_index == client_index)
+      {
+        vec_add1(to_delete, event - am->nd_events);
+      }
+  }));
+  /* *INDENT-ON* */
+
+  vec_foreach (event_id, to_delete)
+  {
+    event = pool_elt_at_index (am->nd_events, *event_id);
+    vnet_add_del_ip6_nd_change_event
+      (vnm, nd_change_delete_callback,
+       event->pid, &event->address,
+       ip_resolver_process_node.index, IP6_ND_EVENT,
+       ~0 /* pool index, notused */ , 0 /* is_add */ );
+  }
+  vec_free (to_delete);
+
+  /* remove from the registration hash */
+  p = hash_get (am->wc_ip6_nd_events_registration_hash, client_index);
+
+  if (p)
+    {
+      rp = pool_elt_at_index (am->wc_ip6_nd_events_registrations, p[0]);
+      pool_put (am->wc_ip6_nd_events_registrations, rp);
+      hash_unset (am->wc_ip6_nd_events_registration_hash, client_index);
+      if (pool_elts (am->wc_ip6_nd_events_registrations) == 0)
+       wc_nd_set_publisher_node (~0, REPORT_MAX);
+    }
+  return (NULL);
+}
+
+VL_MSG_API_REAPER_FUNCTION (want_ip6_nd_events_reaper);
+
 static void
 vl_api_want_ip6_ra_events_t_handler (vl_api_want_ip6_ra_events_t * mp)
 {
@@ -2711,6 +2816,26 @@ reply:
   REPLY_MACRO (VL_API_WANT_IP6_RA_EVENTS_REPLY);
 }
 
+static clib_error_t *
+want_ip6_ra_events_reaper (u32 client_index)
+{
+  vpe_api_main_t *am = &vpe_api_main;
+  vpe_client_registration_t *rp;
+  uword *p;
+
+  p = hash_get (am->ip6_ra_events_registration_hash, client_index);
+
+  if (p)
+    {
+      rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
+      pool_put (am->ip6_ra_events_registrations, rp);
+      hash_unset (am->ip6_ra_events_registration_hash, client_index);
+    }
+  return (NULL);
+}
+
+VL_MSG_API_REAPER_FUNCTION (want_ip6_ra_events_reaper);
+
 static void
 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
 {
index bf0bc50..f1c40e6 100644 (file)
@@ -298,6 +298,8 @@ set_client_for_stat (u32 reg, u32 item, vpe_client_registration_t * client)
     {
       pool_get (sm->stats_registrations[reg], registration);
       registration->item = item;
+      registration->client_hash = NULL;
+      registration->clients = NULL;
       hash_set (sm->stats_registration_hash[reg], item,
                registration - sm->stats_registrations[reg]);
     }
@@ -320,13 +322,39 @@ set_client_for_stat (u32 reg, u32 item, vpe_client_registration_t * client)
   return 1;                    //At least one client is doing something ... poll
 }
 
-int
-clear_client_for_stat (u32 reg, u32 item, u32 client_index)
+static void
+clear_one_client (u32 reg_index, u32 reg, u32 item, u32 client_index)
 {
   stats_main_t *sm = &stats_main;
   vpe_client_stats_registration_t *registration;
   vpe_client_registration_t *client;
   uword *p;
+
+  registration = pool_elt_at_index (sm->stats_registrations[reg], reg_index);
+  p = hash_get (registration->client_hash, client_index);
+
+  if (p)
+    {
+      client = pool_elt_at_index (registration->clients, p[0]);
+      hash_unset (registration->client_hash, client->client_index);
+      pool_put (registration->clients, client);
+
+      /* Now check if that was the last client for that item */
+      if (0 == pool_elts (registration->clients))
+       {
+         hash_unset (sm->stats_registration_hash[reg], item);
+         hash_free (registration->client_hash);
+         pool_free (registration->clients);
+         pool_put (sm->stats_registrations[reg], registration);
+       }
+    }
+}
+
+int
+clear_client_for_stat (u32 reg, u32 item, u32 client_index)
+{
+  stats_main_t *sm = &stats_main;
+  uword *p;
   int i, elts;
 
   /* Clear the client first */
@@ -337,24 +365,35 @@ clear_client_for_stat (u32 reg, u32 item, u32 client_index)
     goto exit;
 
   /* If there is, is our client_index one of them */
-  registration = pool_elt_at_index (sm->stats_registrations[reg], p[0]);
-  p = hash_get (registration->client_hash, client_index);
+  clear_one_client (p[0], reg, item, client_index);
 
-  if (!p)
-    goto exit;
+exit:
+  elts = 0;
+  /* Now check if that was the last item in any of the listened to stats */
+  for (i = 0; i < STATS_REG_N_IDX; i++)
+    {
+      elts += pool_elts (sm->stats_registrations[i]);
+    }
+  return elts;
+}
 
-  client = pool_elt_at_index (registration->clients, p[0]);
-  hash_unset (registration->client_hash, client->client_index);
-  pool_put (registration->clients, client);
+static int
+clear_client_for_all_stats (u32 client_index)
+{
+  stats_main_t *sm = &stats_main;
+  u32 reg_index, item, reg;
+  int i, elts;
 
-  /* Now check if that was the last client for that item */
-  if (0 == pool_elts (registration->clients))
+  /* *INDENT-OFF* */
+  vec_foreach_index(reg, sm->stats_registration_hash)
     {
-      hash_unset (sm->stats_registration_hash[reg], item);
-      pool_put (sm->stats_registrations[reg], registration);
+      hash_foreach(item, reg_index, sm->stats_registration_hash[reg],
+      ({
+        clear_one_client(reg_index, reg, item, client_index);
+      }));
     }
+  /* *INDENT-OFF* */
 
-exit:
   elts = 0;
   /* Now check if that was the last item in any of the listened to stats */
   for (i = 0; i < STATS_REG_N_IDX; i++)
@@ -364,6 +403,19 @@ exit:
   return elts;
 }
 
+static clib_error_t *
+want_stats_reaper (u32 client_index)
+{
+  stats_main_t *sm = &stats_main;
+
+  sm->enable_poller = clear_client_for_all_stats (client_index);
+
+  return (NULL);
+}
+
+VL_MSG_API_REAPER_FUNCTION (want_stats_reaper);
+
+
 /*
  * Return a copy of the clients list.
  */