summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2018-06-04 18:41:24 -0700
committerJohn Lo <loj@cisco.com>2018-06-08 23:11:02 +0000
commitf12dad658d03030d1a61ba970e27c8f01763f2e0 (patch)
treef1abcab45724641e78b7d1733905626989a59b52
parent81119e86bdf47f41f06218f91e52024bc4d00e7c (diff)
Add reaper functions to want events APIs (VPP-1304)
Change-Id: Iaeb52d94cb6da63ee93af7c1cf2dade6046cba1d Signed-off-by: Neale Ranns <nranns@cisco.com>
-rw-r--r--src/plugins/igmp/igmp.h30
-rw-r--r--src/plugins/igmp/igmp_api.c45
-rw-r--r--src/vlibapi/api_helper_macros.h20
-rw-r--r--src/vnet/ip/ip6_neighbor.c12
-rw-r--r--src/vnet/ip/ip_api.c127
-rw-r--r--src/vpp/stats/stats.c80
6 files changed, 263 insertions, 51 deletions
diff --git a/src/plugins/igmp/igmp.h b/src/plugins/igmp/igmp.h
index f917be95dc3..fc131f7843b 100644
--- a/src/plugins/igmp/igmp.h
+++ b/src/plugins/igmp/igmp.h
@@ -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_ */
/*
diff --git a/src/plugins/igmp/igmp_api.c b/src/plugins/igmp/igmp_api.c
index 7044e7f8c76..164779c3e5a 100644
--- a/src/plugins/igmp/igmp_api.c
+++ b/src/plugins/igmp/igmp_api.c
@@ -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,
diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h
index ce80f0e0e20..fe9cde03d4d 100644
--- a/src/vlibapi/api_helper_macros.h
+++ b/src/vlibapi/api_helper_macros.h
@@ -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) \
diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c
index a76decf3431..fe78eae8e5b 100644
--- a/src/vnet/ip/ip6_neighbor.c
+++ b/src/vnet/ip/ip6_neighbor.c
@@ -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;
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index 8464b1ddc98..48e523f381a 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -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)
{
diff --git a/src/vpp/stats/stats.c b/src/vpp/stats/stats.c
index bf0bc50cafc..f1c40e630d2 100644
--- a/src/vpp/stats/stats.c
+++ b/src/vpp/stats/stats.c
@@ -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.
*/