Add reaper functions to want events APIs (VPP-1304) 78/12978/1
authorNeale Ranns <[email protected]>
Tue, 5 Jun 2018 01:41:24 +0000 (18:41 -0700)
committerNeale Ranns <[email protected]>
Sun, 10 Jun 2018 23:27:56 +0000 (19:27 -0400)
Change-Id: Iaeb52d94cb6da63ee93af7c1cf2dade6046cba1d
Signed-off-by: Neale Ranns <[email protected]>
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 0dcf11f..70f9043 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>
@@ -110,12 +111,6 @@ struct igmp_timer_t_;
 
 typedef struct igmp_timer_t_ igmp_timer_t;
 
-typedef struct igmp_api_client_t_
-{
-  u32 client_index;
-  u32 pid;
-} igmp_api_client_t;
-
 typedef struct
 {
   u8 *name;
@@ -137,7 +132,7 @@ typedef struct igmp_main_t_
   uword *igmp_api_client_by_client_index;
 
   /** pool of api clients registered for join/leave notifications */
-  igmp_api_client_t *api_clients;
+  vpe_client_registration_t *api_clients;
 
   /* get config index by config key */
   uword *igmp_config_by_sw_if_index;
@@ -262,19 +257,6 @@ igmp_sg_lookup (igmp_config_t * config, igmp_sg_key_t * key)
   return sg;
 }
 
-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 256f924..5da733b 100644 (file)
@@ -186,11 +186,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;
 
@@ -210,9 +227,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;
@@ -233,6 +250,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, igmp_sg_t * sg)
@@ -254,7 +291,7 @@ send_igmp_event (unix_shared_memory_queue_t * q, u32 context,
 void
 igmp_event (igmp_main_t * im, igmp_config_t * config, igmp_sg_t * sg)
 {
-  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 de3c09b..f0c0f84 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 0df29c6..5882d7b 100644 (file)
@@ -4447,11 +4447,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 0b0a7a9..ad0ef69 100644 (file)
@@ -2068,7 +2068,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;
@@ -2499,6 +2499,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)
 {
@@ -2582,6 +2634,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)
 {
@@ -2626,6 +2731,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 fc4b905..d60bf86 100644 (file)
@@ -297,6 +297,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]);
     }
@@ -319,13 +321,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 */
@@ -336,24 +364,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++)
@@ -363,6 +402,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.
  */