From 5a40f2b0e75bbb43c0d6e2f9cfe190dfaa61f386 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 23 Nov 2023 15:40:38 +0100 Subject: [PATCH] lib, bgp/vnc: add `.auxiliary` zclient option Avoids calling VRF/interface/... handlers in library code more than once. It's kinda surprising that this hasn't been blowing up already for the VNC code, luckily these handlers are (mostly?) idempotent. Signed-off-by: David Lamparter --- bgpd/rfapi/vnc_zebra.c | 2 +- lib/zclient.c | 11 ++++++++++- lib/zclient.h | 12 ++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index c886beea91..82c08cabde 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -872,7 +872,7 @@ static zclient_handler *const vnc_handlers[] = { void vnc_zebra_init(struct event_loop *master) { /* Set default values. */ - zclient_vnc = zclient_new(master, &zclient_options_default, + zclient_vnc = zclient_new(master, &zclient_options_auxiliary, vnc_handlers, array_size(vnc_handlers)); zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs); } diff --git a/lib/zclient.c b/lib/zclient.c index 61533aecc6..1b2ff02f61 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -43,10 +43,17 @@ static void zebra_interface_if_set_value(struct stream *s, const struct zclient_options zclient_options_default = { .synchronous = false, + .auxiliary = false, }; const struct zclient_options zclient_options_sync = { .synchronous = true, + .auxiliary = true, +}; + +const struct zclient_options zclient_options_auxiliary = { + .synchronous = false, + .auxiliary = true, }; struct sockaddr_storage zclient_addr; @@ -75,6 +82,7 @@ struct zclient *zclient_new(struct event_loop *master, zclient->n_handlers = n_handlers; zclient->synchronous = opt->synchronous; + zclient->auxiliary = opt->auxiliary; return zclient; } @@ -4444,7 +4452,8 @@ static void zclient_read(struct event *thread) zlog_debug("zclient %p command %s VRF %u", zclient, zserv_command_string(command), vrf_id); - if (command < array_size(lib_handlers) && lib_handlers[command]) + if (!zclient->auxiliary && command < array_size(lib_handlers) && + lib_handlers[command]) lib_handlers[command](command, zclient, length, vrf_id); if (command < zclient->n_handlers && zclient->handlers[command]) zclient->handlers[command](command, zclient, length, vrf_id); diff --git a/lib/zclient.h b/lib/zclient.h index c8dff18bb9..05eb6b20ee 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -306,6 +306,11 @@ struct zclient { /* Is this a synchronous client? */ bool synchronous; + /* Auxiliary clients don't execute standard library handlers + * (which otherwise would duplicate VRF/interface add/delete/etc. + */ + bool auxiliary; + /* BFD enabled with bfd_protocol_integration_init() */ bool bfd_integration; @@ -832,10 +837,17 @@ enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 }; struct zclient_options { bool synchronous; + + /* auxiliary = don't call common lib/ handlers that manage bits. + * Those should only run once, on the "main" zclient, which this is + * not. (This is also set for synchronous clients.) + */ + bool auxiliary; }; extern const struct zclient_options zclient_options_default; extern const struct zclient_options zclient_options_sync; +extern const struct zclient_options zclient_options_auxiliary; /* link layer representation for GRE like interfaces * ip_in is the underlay IP, ip_out is the tunnel dest -- 2.39.5