From 453844abd7bce28479d10490de513ca59cd0d490 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Sun, 22 Apr 2018 17:03:52 -0400 Subject: [PATCH] zebra: use hooks for client lifecycle callbacks zserv.c was using hardcoded callbacks to clean up various components when a client disconnected. Ergo zserv.c had to know about all these unrelated components that it should not care about. We have hooks now, let's use the proper thing instead. Signed-off-by: Quentin Young --- zebra/label_manager.c | 67 +++++++++++++++++++++++-------------------- zebra/label_manager.h | 2 +- zebra/main.c | 4 +++ zebra/table_manager.c | 19 ++++++------ zebra/table_manager.h | 2 +- zebra/zapi_msg.c | 10 +++---- zebra/zebra_mpls.c | 6 ++-- zebra/zebra_mpls.h | 6 ---- zebra/zebra_ptm.c | 19 ++++++------ zebra/zebra_ptm.h | 1 - zebra/zebra_pw.c | 6 +++- zebra/zebra_pw.h | 1 - zebra/zebra_rnh.c | 10 ++++++- zebra/zebra_rnh.h | 10 ++----- zebra/zserv.c | 34 ++++++---------------- zebra/zserv.h | 7 ++++- 16 files changed, 101 insertions(+), 103 deletions(-) diff --git a/zebra/label_manager.c b/zebra/label_manager.c index 38869e80ec..b4b82ebd17 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -235,6 +235,40 @@ static void lm_zclient_init(char *lm_zserv_path) lm_zclient_connect(NULL); } +/** + * Release label chunks from a client. + * + * Called on client disconnection or reconnection. It only releases chunks + * with empty keep value. + * + * @param proto Daemon protocol of client, to identify the owner + * @param instance Instance, to identify the owner + * @return Number of chunks released + */ +int release_daemon_label_chunks(struct zserv *client) +{ + uint8_t proto = client->proto; + uint16_t instance = client->instance; + struct listnode *node; + struct label_manager_chunk *lmc; + int count = 0; + int ret; + + for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { + if (lmc->proto == proto && lmc->instance == instance + && lmc->keep == 0) { + ret = release_label_chunk(lmc->proto, lmc->instance, + lmc->start, lmc->end); + if (ret == 0) + count++; + } + } + + zlog_debug("%s: Released %d label chunks", __func__, count); + + return count; +} + /** * Init label manager (or proxy to an external one) */ @@ -255,6 +289,8 @@ void label_manager_init(char *lm_zserv_path) ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ); obuf = stream_new(ZEBRA_MAX_PACKET_SIZ); + + hook_register(client_close, release_daemon_label_chunks); } /** @@ -353,37 +389,6 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start, return ret; } -/** - * Release label chunks from a client. - * - * Called on client disconnection or reconnection. It only releases chunks - * with empty keep value. - * - * @param proto Daemon protocol of client, to identify the owner - * @param instance Instance, to identify the owner - * @return Number of chunks released - */ -int release_daemon_label_chunks(uint8_t proto, unsigned short instance) -{ - struct listnode *node; - struct label_manager_chunk *lmc; - int count = 0; - int ret; - - for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { - if (lmc->proto == proto && lmc->instance == instance - && lmc->keep == 0) { - ret = release_label_chunk(lmc->proto, lmc->instance, - lmc->start, lmc->end); - if (ret == 0) - count++; - } - } - - zlog_debug("%s: Released %d label chunks", __func__, count); - - return count; -} void label_manager_close() { diff --git a/zebra/label_manager.h b/zebra/label_manager.h index ddd933ba28..b998372224 100644 --- a/zebra/label_manager.h +++ b/zebra/label_manager.h @@ -71,7 +71,7 @@ struct label_manager_chunk *assign_label_chunk(uint8_t proto, uint8_t keep, uint32_t size); int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start, uint32_t end); -int release_daemon_label_chunks(uint8_t proto, unsigned short instance); +int release_daemon_label_chunks(struct zserv *client); void label_manager_close(void); #endif /* _LABEL_MANAGER_H */ diff --git a/zebra/main.c b/zebra/main.c index 0b182253fc..9a495c8940 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -50,6 +50,7 @@ #include "zebra/zebra_mpls.h" #include "zebra/label_manager.h" #include "zebra/zebra_netns_notify.h" +#include "zebra/zebra_rnh.h" #define ZEBRA_PTM_SUPPORT @@ -372,6 +373,9 @@ int main(int argc, char **argv) /* Init label manager */ label_manager_init(lblmgr_path); + /* RNH init */ + zebra_rnh_init(); + frr_run(zebrad.master); /* Not reached... */ diff --git a/zebra/table_manager.c b/zebra/table_manager.c index db07f402f3..4c5c16c88a 100644 --- a/zebra/table_manager.c +++ b/zebra/table_manager.c @@ -16,12 +16,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "zebra.h" + #include #include #include -#include "zebra.h" -#include "zserv.h" #include "lib/log.h" #include "lib/memory.h" #include "lib/table.h" @@ -31,9 +31,10 @@ #include "lib/libfrr.h" #include "lib/vrf.h" -#include "zebra_vrf.h" -#include "label_manager.h" /* for NO_PROTO */ -#include "table_manager.h" +#include "zebra/zserv.h" +#include "zebra/zebra_vrf.h" +#include "zebra/label_manager.h" /* for NO_PROTO */ +#include "zebra/table_manager.h" /* routing table identifiers * @@ -77,6 +78,7 @@ void table_manager_enable(ns_id_t ns_id) return; tbl_mgr.lc_list = list_new(); tbl_mgr.lc_list->del = delete_table_chunk; + hook_register(client_close, release_daemon_table_chunks); } /** @@ -202,12 +204,13 @@ int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start, * Called on client disconnection or reconnection. It only releases chunks * with empty keep value. * - * @param proto Daemon protocol of client, to identify the owner - * @param instance Instance, to identify the owner + * @param client the client to release chunks from * @return Number of chunks released */ -int release_daemon_table_chunks(uint8_t proto, uint16_t instance) +int release_daemon_table_chunks(struct zserv *client) { + uint8_t proto = client->proto; + uint16_t instance = client->instance; struct listnode *node; struct table_manager_chunk *tmc; int count = 0; diff --git a/zebra/table_manager.h b/zebra/table_manager.h index 7aa9843d04..5196162c4c 100644 --- a/zebra/table_manager.h +++ b/zebra/table_manager.h @@ -60,7 +60,7 @@ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, uint32_t size); int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start, uint32_t end); -int release_daemon_table_chunks(uint8_t proto, uint16_t instance); +int release_daemon_table_chunks(struct zserv *client); void table_manager_disable(ns_id_t ns_id); #endif /* _TABLE_MANAGER_H */ diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 2c22dff84b..ec35f344f3 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -2334,7 +2334,7 @@ static void zread_table_manager_connect(struct zserv *client, * Release previous labels of same protocol and instance. * This is done in case it restarted from an unexpected shutdown. */ - release_daemon_table_chunks(proto, instance); + release_daemon_table_chunks(client); zsend_table_manager_connect_response(client, vrf_id, 0); @@ -2370,10 +2370,10 @@ static void zread_label_manager_connect(struct zserv *client, client->instance = instance; /* - Release previous labels of same protocol and instance. - This is done in case it restarted from an unexpected shutdown. - */ - release_daemon_label_chunks(proto, instance); + * Release previous labels of same protocol and instance. + * This is done in case it restarted from an unexpected shutdown. + */ + release_daemon_label_chunks(client); zlog_debug( " Label Manager client connected: sock %d, proto %s, vrf %u instance %u", diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 7df03efc10..115602f41f 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -1913,9 +1913,9 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p, /* * Cleanup any FECs registered by this client. */ -int zebra_mpls_cleanup_fecs_for_client(struct zebra_vrf *zvrf, - struct zserv *client) +static int zebra_mpls_cleanup_fecs_for_client(struct zserv *client) { + struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT); struct route_node *rn; zebra_fec_t *fec; struct listnode *node; @@ -2915,4 +2915,6 @@ void zebra_mpls_init(void) if (!mpls_processq_init(&zebrad)) mpls_enabled = 1; + + hook_register(client_close, zebra_mpls_cleanup_fecs_for_client); } diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 98905a2831..65204a67dc 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -210,12 +210,6 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p, int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p, struct zserv *client); -/* - * Cleanup any FECs registered by this client. - */ -int zebra_mpls_cleanup_fecs_for_client(struct zebra_vrf *zvrf, - struct zserv *client); - /* * Return FEC (if any) to which this label is bound. * Note: Only works for per-prefix binding and when the label is not diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 2fe6797eef..1c4f0ec841 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -91,6 +91,7 @@ static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt); void zebra_bfd_peer_replay_req(void); void zebra_ptm_send_status_req(void); void zebra_ptm_reset_status(int ptm_disable); +int zebra_ptm_bfd_client_deregister(struct zserv *client); const char ZEBRA_PTM_SOCK_NAME[] = "\0/var/run/ptmd.socket"; @@ -124,17 +125,12 @@ void zebra_ptm_init(void) ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; ptm_cb.ptm_sock = -1; + + hook_register(client_close, zebra_ptm_bfd_client_deregister); } void zebra_ptm_finish(void) { - int proto; - - for (proto = 0; proto < ZEBRA_ROUTE_MAX; proto++) - if (CHECK_FLAG(ptm_cb.client_flags[proto], - ZEBRA_PTM_BFD_CLIENT_FLAG_REG)) - zebra_ptm_bfd_client_deregister(proto); - buffer_flush_all(ptm_cb.wb, ptm_cb.ptm_sock); free(ptm_hdl); @@ -1013,15 +1009,16 @@ stream_failure: } /* BFD client deregister */ -void zebra_ptm_bfd_client_deregister(int proto) +int zebra_ptm_bfd_client_deregister(struct zserv *client) { + uint8_t proto = client->proto; void *out_ctxt; char tmp_buf[64]; int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP && proto != ZEBRA_ROUTE_OSPF6 && proto != ZEBRA_ROUTE_PIM) - return; + return 0; if (IS_ZEBRA_DEBUG_EVENT) zlog_err("bfd_client_deregister msg for client %s", @@ -1031,7 +1028,7 @@ void zebra_ptm_bfd_client_deregister(int proto) ptm_cb.t_timer = NULL; thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, &ptm_cb.t_timer); - return; + return 0; } ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); @@ -1051,6 +1048,8 @@ void zebra_ptm_bfd_client_deregister(int proto) zebra_ptm_send_message(ptm_cb.out_data, data_len); UNSET_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); + + return 0; } int zebra_ptm_get_enable_state(void) diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index fa95e9ea79..0e55574a02 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -75,5 +75,4 @@ void zebra_ptm_if_init(struct zebra_if *zebra_ifp); void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp); void zebra_ptm_if_write(struct vty *vty, struct zebra_if *zebra_ifp); -void zebra_ptm_bfd_client_deregister(int proto); #endif diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c index eca8fb0cff..f26226e752 100644 --- a/zebra/zebra_pw.c +++ b/zebra/zebra_pw.c @@ -269,7 +269,7 @@ static int zebra_pw_check_reachability(struct zebra_pw *pw) return 0; } -void zebra_pw_client_close(struct zserv *client) +static int zebra_pw_client_close(struct zserv *client) { struct vrf *vrf; struct zebra_vrf *zvrf; @@ -283,12 +283,16 @@ void zebra_pw_client_close(struct zserv *client) zebra_pw_del(zvrf, pw); } } + + return 0; } void zebra_pw_init(struct zebra_vrf *zvrf) { RB_INIT(zebra_pw_head, &zvrf->pseudowires); RB_INIT(zebra_static_pw_head, &zvrf->static_pseudowires); + + hook_register(client_close, zebra_pw_client_close); } void zebra_pw_exit(struct zebra_vrf *zvrf) diff --git a/zebra/zebra_pw.h b/zebra/zebra_pw.h index db464c05d5..e6e0a22c21 100644 --- a/zebra/zebra_pw.h +++ b/zebra/zebra_pw.h @@ -70,7 +70,6 @@ void zebra_pw_change(struct zebra_pw *, ifindex_t, int, int, union g_addr *, struct zebra_pw *zebra_pw_find(struct zebra_vrf *, const char *); void zebra_pw_update(struct zebra_pw *); void zebra_pw_install_failure(struct zebra_pw *); -void zebra_pw_client_close(struct zserv *); void zebra_pw_init(struct zebra_vrf *); void zebra_pw_exit(struct zebra_vrf *); void zebra_pw_vty_init(void); diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 8b89979818..6b74a3c92c 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -66,10 +66,16 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2); static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vrf_id); static void print_rnh(struct route_node *rn, struct vty *vty); +static int zebra_client_cleanup_rnh(struct zserv *client); int zebra_rnh_ip_default_route = 0; int zebra_rnh_ipv6_default_route = 0; +void zebra_rnh_init(void) +{ + hook_register(client_close, zebra_client_cleanup_rnh); +} + static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family, rnh_type_t type) { @@ -1204,7 +1210,7 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, int family, } /* Cleanup registered nexthops (across VRFs) upon client disconnect. */ -void zebra_client_cleanup_rnh(struct zserv *client) +static int zebra_client_cleanup_rnh(struct zserv *client) { struct vrf *vrf; struct zebra_vrf *zvrf; @@ -1228,4 +1234,6 @@ void zebra_client_cleanup_rnh(struct zserv *client) } } } + + return 0; } diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 4cb84bf700..ea7d5545e8 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -54,6 +54,8 @@ typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t; extern int zebra_rnh_ip_default_route; extern int zebra_rnh_ipv6_default_route; +extern void zebra_rnh_init(void); + static inline int rnh_resolve_via_default(int family) { if (((family == AF_INET) && zebra_rnh_ip_default_route) @@ -87,12 +89,4 @@ extern void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, extern void zebra_print_rnh_table(vrf_id_t vrfid, int family, struct vty *vty, rnh_type_t); extern char *rnh_str(struct rnh *rnh, char *buf, int size); -/* - * Cleanup any registered nexthops across all VRFs. This is called when closing - * down a connection to a ZAPI client. - * - * client - * the client that is shutting down - */ -extern void zebra_client_cleanup_rnh(struct zserv *client); #endif /*_ZEBRA_RNH_H */ diff --git a/zebra/zserv.c b/zebra/zserv.c index 8bdfda2288..ffc6a19245 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -34,6 +34,7 @@ #include "lib/buffer.h" /* for BUFFER_EMPTY, BUFFER_ERROR, BUFFE... */ #include "lib/command.h" /* for vty, install_element, CMD_SUCCESS... */ +#include "lib/hook.h" /* for DEFINE_HOOK, DEFINE_KOOH, hook_call */ #include "lib/linklist.h" /* for ALL_LIST_ELEMENTS_RO, ALL_LIST_EL... */ #include "lib/libfrr.h" /* for frr_zclient_addr */ #include "lib/log.h" /* for zlog_warn, zlog_debug, safe_strerror */ @@ -56,11 +57,6 @@ #include "zebra/rib.h" /* for rib_score_proto */ #include "zebra/table_manager.h" /* for release_daemon_table_chunks */ #include "zebra/zapi_msg.h" /* for zserv_handle_commands */ -#include "zebra/zebra_mpls.h" /* for zebra_mpls_cleanup_fecs_for_client */ -#include "zebra/zebra_pbr.h" /* for zebra_pbr_client_close_cleanup */ -#include "zebra/zebra_ptm.h" /* for zebra_ptm_bfd_client_deregister */ -#include "zebra/zebra_pw.h" /* for zebra_pw_client_close */ -#include "zebra/zebra_rnh.h" /* for zebra_client_cleanup_rnh */ #include "zebra/zebra_vrf.h" /* for zebra_vrf_lookup_by_id, zvrf */ #include "zebra/zserv.h" /* for zclient */ @@ -83,30 +79,14 @@ int zebra_server_send_message(struct zserv *client, struct stream *msg) /* Lifecycle ---------------------------------------------------------------- */ +/* Hooks for client connect / disconnect */ +DEFINE_HOOK(client_connect, (struct zserv *client), (client)); +DEFINE_KOOH(client_close, (struct zserv *client), (client)); + /* free zebra client information. */ static void zebra_client_free(struct zserv *client) { - /* Send client de-registration to BFD */ - zebra_ptm_bfd_client_deregister(client->proto); - - /* Cleanup any rules installed from this client */ - zebra_pbr_client_close_cleanup(client->sock); - - /* Cleanup any registered nexthops - across all VRFs. */ - zebra_client_cleanup_rnh(client); - - /* Release Label Manager chunks */ - release_daemon_label_chunks(client->proto, client->instance); - - /* Release Table Manager chunks */ - release_daemon_table_chunks(client->proto, client->instance); - - /* Cleanup any FECs registered by this client. */ - zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT), - client); - - /* Remove pseudowires associated with this client */ - zebra_pw_client_close(client); + hook_call(client_close, client); /* Close file descriptor. */ if (client->sock) { @@ -199,6 +179,8 @@ static void zebra_client_create(int sock) zebra_vrf_update_all(client); + hook_call(client_connect, client); + /* start read loop */ zebra_event(client, ZEBRA_READ); } diff --git a/zebra/zserv.h b/zebra/zserv.h index 2a148f645e..b3f3cce7e8 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -34,6 +34,7 @@ #include "lib/thread.h" /* for thread, thread_master */ #include "lib/linklist.h" /* for list */ #include "lib/workqueue.h" /* for work_queue */ +#include "lib/hook.h" /* for DECLARE_HOOK, DECLARE_KOOH */ #include "zebra/zebra_vrf.h" /* for zebra_vrf */ @@ -88,7 +89,7 @@ struct zserv { /* client's protocol */ uint8_t proto; - unsigned short instance; + uint16_t instance; uint8_t is_synchronous; /* Statistics */ @@ -141,6 +142,10 @@ struct zserv { struct zserv *client, struct zmsghdr *hdr, struct stream *msg, \ struct zebra_vrf *zvrf +/* Hooks for client connect / disconnect */ +DECLARE_HOOK(client_connect, (struct zserv *client), (client)); +DECLARE_KOOH(client_close, (struct zserv *client), (client)); + /* Zebra instance */ struct zebra_t { /* Thread master */ -- 2.39.5