From 78f487e113fb0fbd1a06b90f3681d237f7edc495 Mon Sep 17 00:00:00 2001 From: Matthew Smith Date: Thu, 8 Oct 2020 11:11:27 -0500 Subject: [PATCH] vrrp: asynchronous events on VR state change Type: feature Add API message for an API client to subscribe/unsubscribe to receive an event when a VRRP VR changes state. Add code to build and send the events. Change-Id: Ie92cadd4850d4352c1aaa79c4b0a7daa0f3b04e7 Signed-off-by: Matthew Smith --- src/plugins/vrrp/vrrp.api | 35 ++++++++++++++++++ src/plugins/vrrp/vrrp.c | 2 ++ src/plugins/vrrp/vrrp.h | 1 + src/plugins/vrrp/vrrp_api.c | 80 +++++++++++++++++++++++++++++------------ src/plugins/vrrp/vrrp_test.c | 32 +++++++++++++++++ src/vlibapi/api_helper_macros.h | 3 +- 6 files changed, 130 insertions(+), 23 deletions(-) diff --git a/src/plugins/vrrp/vrrp.api b/src/plugins/vrrp/vrrp.api index da485adf9b8..a34b06ffc57 100644 --- a/src/plugins/vrrp/vrrp.api +++ b/src/plugins/vrrp/vrrp.api @@ -242,3 +242,38 @@ define vrrp_vr_track_if_details { u8 n_ifs; vl_api_vrrp_vr_track_if_t ifs[n_ifs]; }; + +/** \brief Notification about VRRP VR state change event + @param client_index - opaque cookie to identify the sender + @param pid - client pid registered to receive notification + @param vr - configuration parameters identifying the VR + @param old_state - old state of VR + @param new_state - new state of VR +*/ +define vrrp_vr_event +{ + u32 client_index; + u32 pid; + vl_api_vrrp_vr_key_t vr; + vl_api_vrrp_vr_state_t old_state; + vl_api_vrrp_vr_state_t new_state; +}; + +service { + rpc want_vrrp_vr_events returns want_vrrp_vr_events_reply + events vrrp_vr_event; +}; + +/** \brief Register for VRRP VR state change events + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param enable_disable - 1 to register, 0 to cancel registration + @param pid - sender's pid +*/ +autoreply define want_vrrp_vr_events +{ + u32 client_index; + u32 context; + bool enable_disable; + u32 pid; +}; diff --git a/src/plugins/vrrp/vrrp.c b/src/plugins/vrrp/vrrp.c index 37ee9ec25a6..771cd709a2a 100644 --- a/src/plugins/vrrp/vrrp.c +++ b/src/plugins/vrrp/vrrp.c @@ -351,6 +351,8 @@ vrrp_vr_transition (vrrp_vr_t * vr, vrrp_vr_state_t new_state, void *data) /* add/delete virtual MAC address on NIC if necessary */ vrrp_vr_transition_vmac (vr, new_state); + vrrp_vr_event (vr, new_state); + vr->runtime.state = new_state; } diff --git a/src/plugins/vrrp/vrrp.h b/src/plugins/vrrp/vrrp.h index 0eda5d66164..c9325921959 100644 --- a/src/plugins/vrrp/vrrp.h +++ b/src/plugins/vrrp/vrrp.h @@ -207,6 +207,7 @@ int vrrp_vr_tracking_if_add_del (vrrp_vr_t * vr, u32 sw_if_index, int vrrp_vr_tracking_ifs_add_del (vrrp_vr_t * vr, vrrp_vr_tracking_if_t * track_ifs, u8 is_add); +void vrrp_vr_event (vrrp_vr_t * vr, vrrp_vr_state_t new_state); always_inline void diff --git a/src/plugins/vrrp/vrrp_api.c b/src/plugins/vrrp/vrrp_api.c index 500569ef1b8..27ca56a6b55 100644 --- a/src/plugins/vrrp/vrrp_api.c +++ b/src/plugins/vrrp/vrrp_api.c @@ -20,14 +20,13 @@ #include #include -#define REPLY_MSG_ID_BASE vmp->msg_id_base +#define REPLY_MSG_ID_BASE vrrp_main.msg_id_base #include /* API message handlers */ static void vl_api_vrrp_vr_add_del_t_handler (vl_api_vrrp_vr_add_del_t * mp) { - vrrp_main_t *vmp = &vrrp_main; vl_api_vrrp_vr_add_del_reply_t *rmp; vrrp_vr_config_t vr_conf; u32 api_flags; @@ -112,6 +111,19 @@ vl_api_vrrp_vr_add_del_t_handler (vl_api_vrrp_vr_add_del_t * mp) REPLY_MACRO (VL_API_VRRP_VR_ADD_DEL_REPLY); } +static vl_api_vrrp_vr_state_t +vrrp_vr_state_encode (vrrp_vr_state_t vr_state) +{ + if (vr_state == VRRP_VR_STATE_BACKUP) + return VRRP_API_VR_STATE_BACKUP; + if (vr_state == VRRP_VR_STATE_MASTER) + return VRRP_API_VR_STATE_MASTER; + if (vr_state == VRRP_VR_STATE_INTF_DOWN) + return VRRP_API_VR_STATE_INTF_DOWN; + + return VRRP_API_VR_STATE_INIT; +} + static void send_vrrp_vr_details (vrrp_vr_t * vr, vl_api_registration_t * reg, u32 context) @@ -150,23 +162,7 @@ send_vrrp_vr_details (vrrp_vr_t * vr, vl_api_registration_t * reg, mp->config.flags = htonl (api_flags); /* runtime */ - switch (vr->runtime.state) - { - case VRRP_VR_STATE_INIT: - mp->runtime.state = htonl (VRRP_API_VR_STATE_INIT); - break; - case VRRP_VR_STATE_BACKUP: - mp->runtime.state = htonl (VRRP_API_VR_STATE_BACKUP); - break; - case VRRP_VR_STATE_MASTER: - mp->runtime.state = htonl (VRRP_API_VR_STATE_MASTER); - break; - case VRRP_VR_STATE_INTF_DOWN: - mp->runtime.state = htonl (VRRP_API_VR_STATE_INTF_DOWN); - break; - default: - break; - } + mp->runtime.state = htonl (vrrp_vr_state_encode (vr->runtime.state)); mp->runtime.master_adv_int = htons (vr->runtime.master_adv_int); mp->runtime.skew = htons (vr->runtime.skew); @@ -234,7 +230,6 @@ vl_api_vrrp_vr_dump_t_handler (vl_api_vrrp_vr_dump_t * mp) static void vl_api_vrrp_vr_start_stop_t_handler (vl_api_vrrp_vr_start_stop_t * mp) { - vrrp_main_t *vmp = &vrrp_main; vl_api_vrrp_vr_start_stop_reply_t *rmp; vrrp_vr_key_t vr_key; int rv; @@ -253,7 +248,6 @@ vl_api_vrrp_vr_start_stop_t_handler (vl_api_vrrp_vr_start_stop_t * mp) static void vl_api_vrrp_vr_set_peers_t_handler (vl_api_vrrp_vr_set_peers_t * mp) { - vrrp_main_t *vmp = &vrrp_main; vl_api_vrrp_vr_set_peers_reply_t *rmp; vrrp_vr_key_t vr_key; ip46_address_t *peer_addrs = 0; @@ -385,7 +379,6 @@ static void vl_api_vrrp_vr_track_if_add_del_t_handler (vl_api_vrrp_vr_track_if_add_del_t * mp) { - vrrp_main_t *vmp = &vrrp_main; vl_api_vrrp_vr_track_if_add_del_reply_t *rmp; vrrp_vr_t *vr; vrrp_vr_tracking_if_t *track_if, *track_ifs = 0; @@ -486,6 +479,49 @@ vl_api_vrrp_vr_track_if_dump_t_handler (vl_api_vrrp_vr_track_if_dump_t * mp) /* *INDENT-ON* */ } +static void +send_vrrp_vr_event (vpe_client_registration_t * reg, + vl_api_registration_t * vl_reg, + vrrp_vr_t * vr, vrrp_vr_state_t new_state) +{ + vrrp_main_t *vmp = &vrrp_main; + vl_api_vrrp_vr_event_t *mp; + + mp = vl_msg_api_alloc (sizeof (*mp)); + + clib_memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_VRRP_VR_EVENT + vmp->msg_id_base); + mp->client_index = reg->client_index; + mp->pid = reg->client_pid; + mp->vr.sw_if_index = ntohl (vr->config.sw_if_index); + mp->vr.vr_id = vr->config.vr_id; + mp->vr.is_ipv6 = ((vr->config.flags & VRRP_VR_IPV6) != 0); + + mp->old_state = htonl (vrrp_vr_state_encode (vr->runtime.state)); + mp->new_state = htonl (vrrp_vr_state_encode (new_state)); + + vl_api_send_msg (vl_reg, (u8 *) mp); +} + +void +vrrp_vr_event (vrrp_vr_t * vr, vrrp_vr_state_t new_state) +{ + vpe_api_main_t *vam = &vpe_api_main; + vpe_client_registration_t *reg; + vl_api_registration_t *vl_reg; + + /* *INDENT-OFF* */ + pool_foreach(reg, vam->vrrp_vr_events_registrations, + ({ + vl_reg = vl_api_client_index_to_registration (reg->client_index); + if (vl_reg) + send_vrrp_vr_event (reg, vl_reg, vr, new_state); + })); + /* *INDENT-ON* */ +} + +pub_sub_handler (vrrp_vr_events, VRRP_VR_EVENTS); + /* Set up the API message handling tables */ #include clib_error_t * diff --git a/src/plugins/vrrp/vrrp_test.c b/src/plugins/vrrp/vrrp_test.c index eaa0c40ecd0..199f5417f1a 100644 --- a/src/plugins/vrrp/vrrp_test.c +++ b/src/plugins/vrrp/vrrp_test.c @@ -690,6 +690,38 @@ vl_api_vrrp_vr_peer_details_t_handler (vl_api_vrrp_vr_peer_details_t * mp) fformat (vam->ofp, "\n"); } +static int +api_want_vrrp_vr_events (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_want_vrrp_vr_events_t *mp; + int enable = -1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + break; + } + + if (enable == -1) + { + errmsg ("missing enable|disable"); + return -99; + } + + M (WANT_VRRP_VR_EVENTS, mp); + mp->enable_disable = enable; + S (mp); + W (ret); + + return ret; +} + #include /* * fd.io coding-style-patch-verification: ON diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index 983b688c02d..8064d67a14e 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -390,7 +390,8 @@ _(bfd_events) \ _(l2_arp_term_events) \ _(ip6_ra_events) \ _(dhcp6_pd_reply_events) \ -_(dhcp6_reply_events) +_(dhcp6_reply_events) \ +_(vrrp_vr_events) typedef struct { -- 2.16.6