mgmtd: remove client specific data from mgmtd

- Clients send this same data in their subscribe message, so do so.
- Avoids conflicts when doing source management (e.g., adding/removing clients).

Signed-off-by: Christian Hopps <chopps@labn.net>
This commit is contained in:
Christian Hopps 2025-12-22 22:18:14 +00:00
parent fc33de8c47
commit 2cb1362343
7 changed files with 152 additions and 250 deletions

View file

@ -56,13 +56,13 @@ struct mgmt_be_client_txn_ctx {
struct mgmt_be_client_cbs {
void (*client_connect_notify)(struct mgmt_be_client *client, uintptr_t usr_data,
bool connected);
const char **config_xpaths;
const char *const *config_xpaths;
uint nconfig_xpaths;
const char **oper_xpaths;
const char *const *oper_xpaths;
uint noper_xpaths;
const char **notify_xpaths;
const char *const *notify_xpaths;
uint nnotify_xpaths;
const char **rpc_xpaths;
const char *const *rpc_xpaths;
uint nrpc_xpaths;
};

View file

@ -25,6 +25,17 @@
#define _log_warn(fmt, ...) zlog_warn("BE-ADAPTER: %s: WARNING: " fmt, __func__, ##__VA_ARGS__)
#define _log_err(fmt, ...) zlog_err("BE-ADAPTER: %s: ERROR: " fmt, __func__, ##__VA_ARGS__)
/* ----- */
/* Types */
/* ----- */
/*
* Mapping of YANG XPath prefixes to their corresponding backend clients.
*/
struct mgmt_be_xpath_map {
char *xpath_prefix;
uint64_t clients;
};
/* ---------- */
/* Prototypes */
@ -66,194 +77,8 @@ const char *mgmt_be_client_names[MGMTD_BE_CLIENT_ID_MAX + 1] = {
#endif
[MGMTD_BE_CLIENT_ID_MAX] = "Unknown/Invalid",
};
/* ------------------------------- */
/* Const XPath Mappings (for init) */
/* ------------------------------- */
/*
* NOTE: These mappings are more trouble than they are worth. Just convert to
* use the subscribe message exclusively.
*/
/*
* Mapping of YANG XPath prefixes to their corresponding backend clients.
*/
struct mgmt_be_xpath_map {
char *xpath_prefix;
uint64_t clients;
};
/*
* Each client gets their own map, but also union all the strings into the
* above map as well.
*/
/* clang-format off */
static const char *const zebra_config_xpaths[] = {
"/frr-affinity-map:lib",
"/frr-filter:lib",
"/frr-host:host",
"/frr-logging:logging",
"/frr-route-map:lib",
"/frr-zebra:zebra",
"/frr-interface:lib",
"/frr-vrf:lib",
NULL,
};
static const char *const zebra_oper_xpaths[] = {
"/frr-backend:clients",
"/frr-interface:lib/interface",
"/frr-vrf:lib/vrf/frr-zebra:zebra",
"/frr-zebra:zebra",
NULL,
};
static const char *const zebra_rpc_xpaths[] = {
"/frr-logging",
NULL,
};
/*
* MGMTD does not use config paths. Config is handled specially since it's own
* tree is modified directly when processing changes from the front end clients
*/
static const char *const mgmtd_oper_xpaths[] = {
"/frr-backend:clients",
NULL,
};
static const char *const mgmtd_rpc_xpaths[] = {
"/frr-logging",
NULL,
};
#ifdef HAVE_MGMTD_TESTC
static const char *const mgmtd_testc_oper_xpaths[] = {
"/frr-backend:clients",
NULL,
};
#endif
#ifdef HAVE_RIPD
static const char *const ripd_config_xpaths[] = {
"/frr-filter:lib",
"/frr-host:host",
"/frr-logging:logging",
"/frr-interface:lib/interface",
"/frr-ripd:ripd",
"/frr-route-map:lib",
"/frr-vrf:lib",
"/ietf-key-chain:key-chains",
NULL,
};
static const char *const ripd_oper_xpaths[] = {
"/frr-backend:clients",
"/frr-ripd:ripd",
"/ietf-key-chain:key-chains",
NULL,
};
static const char *const ripd_rpc_xpaths[] = {
"/frr-ripd",
"/frr-logging",
NULL,
};
#endif
#ifdef HAVE_RIPNGD
static const char *const ripngd_config_xpaths[] = {
"/frr-filter:lib",
"/frr-host:host",
"/frr-logging:logging",
"/frr-interface:lib/interface",
"/frr-ripngd:ripngd",
"/frr-route-map:lib",
"/frr-vrf:lib",
NULL,
};
static const char *const ripngd_oper_xpaths[] = {
"/frr-backend:clients",
"/frr-ripngd:ripngd",
NULL,
};
static const char *const ripngd_rpc_xpaths[] = {
"/frr-ripngd",
"/frr-logging",
NULL,
};
#endif
#ifdef HAVE_STATICD
static const char *const staticd_config_xpaths[] = {
"/frr-host:host",
"/frr-logging:logging",
"/frr-vrf:lib",
"/frr-interface:lib",
"/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd",
NULL,
};
static const char *const staticd_oper_xpaths[] = {
"/frr-backend:clients",
NULL,
};
static const char *const staticd_rpc_xpaths[] = {
"/frr-logging",
NULL,
};
#endif
/* clang-format on */
static const char *const *be_client_config_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
[MGMTD_BE_CLIENT_ID_ZEBRA] = zebra_config_xpaths,
#ifdef HAVE_RIPD
[MGMTD_BE_CLIENT_ID_RIPD] = ripd_config_xpaths,
#endif
#ifdef HAVE_RIPNGD
[MGMTD_BE_CLIENT_ID_RIPNGD] = ripngd_config_xpaths,
#endif
#ifdef HAVE_STATICD
[MGMTD_BE_CLIENT_ID_STATICD] = staticd_config_xpaths,
#endif
};
static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
[MGMTD_BE_CLIENT_ID_MGMTD] = mgmtd_oper_xpaths,
#ifdef HAVE_MGMTD_TESTC
[MGMTD_BE_CLIENT_ID_TESTC] = mgmtd_testc_oper_xpaths,
#endif
#ifdef HAVE_RIPD
[MGMTD_BE_CLIENT_ID_RIPD] = ripd_oper_xpaths,
#endif
#ifdef HAVE_RIPNGD
[MGMTD_BE_CLIENT_ID_RIPNGD] = ripngd_oper_xpaths,
#endif
#ifdef HAVE_STATICD
[MGMTD_BE_CLIENT_ID_STATICD] = staticd_oper_xpaths,
#endif
[MGMTD_BE_CLIENT_ID_ZEBRA] = zebra_oper_xpaths,
};
static const char *const *be_client_notif_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
};
static const char *const *be_client_rpc_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
[MGMTD_BE_CLIENT_ID_MGMTD] = mgmtd_rpc_xpaths,
#ifdef HAVE_RIPD
[MGMTD_BE_CLIENT_ID_RIPD] = ripd_rpc_xpaths,
#endif
#ifdef HAVE_RIPNGD
[MGMTD_BE_CLIENT_ID_RIPNGD] = ripngd_rpc_xpaths,
#endif
#ifdef HAVE_STATICD
[MGMTD_BE_CLIENT_ID_STATICD] = staticd_rpc_xpaths,
#endif
[MGMTD_BE_CLIENT_ID_ZEBRA] = zebra_rpc_xpaths,
};
/* ---------------- */
/* Global Variables */
/* ---------------- */
@ -282,7 +107,8 @@ static struct mgmt_be_client_adapter
/*
* Mgmtd has it's own special "interested-in" xpath maps since it's not actually
* a backend client of itself.
* a backend client of itself; it's own tree is modified directly when
* processing changes from the front end clients
*/
static const char *const mgmtd_config_xpaths[] = {
"/frr-logging:logging",
@ -500,57 +326,16 @@ static void be_adapter_register_client_xpath(enum mgmt_be_client_id id, const ch
}
/* we didn't find a matching entry */
map = darr_append(*maps);
map->xpath_prefix = XSTRDUP(MTYPE_MGMTD_XPATH, xpath);
map->xpath_prefix = darr_strdup(xpath);
map->clients = (1ul << id);
}
/*
* Use the global per-client constants to initialize the xpath maps.
*
* NOTE: This system was used to bootstrap the mgmtd work, and has proved to add
* complexity to the process converting daemons to use mgmtd with no real
* performance requirement, the daemon can send it's xpath regsitrations in it's
* subscribe message so we should just use that. Please convert to do that and
* remove this function at first convenience.
*/
static void be_adapter_xpath_maps_init(void)
{
enum mgmt_be_client_id id;
const char *const *init;
_dbg("Init XPath Maps");
FOREACH_MGMTD_BE_CLIENT_ID (id) {
/* Initialize the common config init map */
for (init = be_client_config_xpaths[id]; init && *init; init++) {
_dbg(" - CFG XPATH: '%s'", *init);
be_adapter_register_client_xpath(id, *init, MGMT_BE_XPATH_SUBSCR_TYPE_CFG);
}
/* Initialize the common oper init map */
for (init = be_client_oper_xpaths[id]; init && *init; init++) {
_dbg(" - OPER XPATH: '%s'", *init);
be_adapter_register_client_xpath(id, *init, MGMT_BE_XPATH_SUBSCR_TYPE_OPER);
}
/* Initialize the common NOTIF init map */
for (init = be_client_notif_xpaths[id]; init && *init; init++) {
_dbg(" - NOTIF XPATH: '%s'", *init);
be_adapter_register_client_xpath(id, *init,
MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF);
}
/* Initialize the common RPC init map */
for (init = be_client_rpc_xpaths[id]; init && *init; init++) {
_dbg(" - RPC XPATH: '%s'", *init);
be_adapter_register_client_xpath(id, *init, MGMT_BE_XPATH_SUBSCR_TYPE_RPC);
}
}
_dbg("Total Cfg XPath Maps: %u", darr_len(be_cfg_xpath_map));
_dbg("Total Oper XPath Maps: %u", darr_len(be_oper_xpath_map));
_dbg("Total Notif XPath Maps: %u", darr_len(be_notif_xpath_map));
_dbg("Total RPC XPath Maps: %u", darr_len(be_rpc_xpath_map));
be_adapter_register_client_xpath(MGMTD_BE_CLIENT_ID_MGMTD, "/frr-backend:clients",
MGMT_BE_XPATH_SUBSCR_TYPE_OPER);
be_adapter_register_client_xpath(MGMTD_BE_CLIENT_ID_MGMTD, "/frr-logging",
MGMT_BE_XPATH_SUBSCR_TYPE_RPC);
}
/*
@ -561,19 +346,19 @@ static void be_adapter_xpath_maps_cleanup(void)
struct mgmt_be_xpath_map *map;
darr_foreach_p (be_cfg_xpath_map, map)
XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix);
darr_free(map->xpath_prefix);
darr_free(be_cfg_xpath_map);
darr_foreach_p (be_oper_xpath_map, map)
XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix);
darr_free(map->xpath_prefix);
darr_free(be_oper_xpath_map);
darr_foreach_p (be_notif_xpath_map, map)
XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix);
darr_free(map->xpath_prefix);
darr_free(be_notif_xpath_map);
darr_foreach_p (be_rpc_xpath_map, map)
XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix);
darr_free(map->xpath_prefix);
darr_free(be_rpc_xpath_map);
}

View file

@ -137,6 +137,7 @@ FRR_DAEMON_INFO(mgmtd_testc, MGMTD_TESTC,
const char **_notif_xpaths;
const char **_rpc_xpaths;
const char **_oper_xpaths;
struct mgmt_be_client_cbs _client_cbs = {};
struct event *event_timeout;
@ -331,6 +332,10 @@ int main(int argc, char **argv)
_client_cbs.nnotify_xpaths = darr_len(_notif_xpaths);
}
darr_push(_oper_xpaths, "/frr-backend:clients");
_client_cbs.oper_xpaths = _oper_xpaths;
_client_cbs.noper_xpaths = darr_len(_oper_xpaths);
darr_push(_rpc_xpaths, "/frr-ripd:clear-rip-route");
_client_cbs.rpc_xpaths = _rpc_xpaths;
_client_cbs.nrpc_xpaths = darr_len(_rpc_xpaths);

View file

@ -154,6 +154,37 @@ FRR_DAEMON_INFO(ripd, RIP,
/* mgmtd will load the per-daemon config file now */
.flags = FRR_NO_SPLIT_CONFIG | FRR_MGMTD_BACKEND,
);
static const char *const ripd_config_xpaths[] = {
"/frr-filter:lib",
"/frr-host:host",
"/frr-logging:logging",
"/frr-interface:lib/interface",
"/frr-ripd:ripd",
"/frr-route-map:lib",
"/frr-vrf:lib",
"/ietf-key-chain:key-chains",
};
static const char *const ripd_oper_xpaths[] = {
"/frr-backend:clients",
"/frr-ripd:ripd",
"/ietf-key-chain:key-chains",
};
static const char *const ripd_rpc_xpaths[] = {
"/frr-ripd",
"/frr-logging",
};
struct mgmt_be_client_cbs ripd_be_client_data = {
.config_xpaths = ripd_config_xpaths,
.nconfig_xpaths = array_size(ripd_config_xpaths),
.oper_xpaths = ripd_oper_xpaths,
.noper_xpaths = array_size(ripd_oper_xpaths),
.rpc_xpaths = ripd_rpc_xpaths,
.nrpc_xpaths = array_size(ripd_rpc_xpaths),
};
/* clang-format on */
#define DEPRECATED_OPTIONS ""
@ -200,7 +231,7 @@ int main(int argc, char **argv)
rip_init();
rip_if_init();
mgmt_be_client = mgmt_be_client_create("ripd", NULL, 0, master);
mgmt_be_client = mgmt_be_client_create("ripd", &ripd_be_client_data, 0, master);
rip_zclient_init(master);
rip_bfd_init(master);

View file

@ -147,6 +147,35 @@ FRR_DAEMON_INFO(ripngd, RIPNG,
/* mgmtd will load the per-daemon config file now */
.flags = FRR_NO_SPLIT_CONFIG | FRR_MGMTD_BACKEND,
);
static const char *const ripngd_config_xpaths[] = {
"/frr-filter:lib",
"/frr-host:host",
"/frr-logging:logging",
"/frr-interface:lib/interface",
"/frr-ripngd:ripngd",
"/frr-route-map:lib",
"/frr-vrf:lib",
};
static const char *const ripngd_oper_xpaths[] = {
"/frr-backend:clients",
"/frr-ripngd:ripngd",
};
static const char *const ripngd_rpc_xpaths[] = {
"/frr-ripngd",
"/frr-logging",
};
struct mgmt_be_client_cbs ripngd_be_client_data = {
.config_xpaths = ripngd_config_xpaths,
.nconfig_xpaths = array_size(ripngd_config_xpaths),
.oper_xpaths = ripngd_oper_xpaths,
.noper_xpaths = array_size(ripngd_oper_xpaths),
.rpc_xpaths = ripngd_rpc_xpaths,
.nrpc_xpaths = array_size(ripngd_rpc_xpaths),
};
/* clang-format on */
#define DEPRECATED_OPTIONS ""
@ -189,7 +218,7 @@ int main(int argc, char **argv)
/* RIPngd inits. */
ripng_init();
mgmt_be_client = mgmt_be_client_create("ripngd", NULL, 0, master);
mgmt_be_client = mgmt_be_client_create("ripngd", &ripngd_be_client_data, 0, master);
zebra_init(master);

View file

@ -120,13 +120,12 @@ static const struct frr_yang_module_info *const staticd_yang_modules[] = {
&frr_staticd_info,
&ietf_srv6_types_info,
};
/* clang-format on */
/*
* NOTE: .flags == FRR_NO_SPLIT_CONFIG to avoid reading split config, mgmtd will
* do this for us now
*/
/* clang-format off */
FRR_DAEMON_INFO(staticd, STATIC,
.vty_port = STATIC_VTY_PORT,
.proghelp = "Implementation of STATIC.",
@ -141,6 +140,31 @@ FRR_DAEMON_INFO(staticd, STATIC,
.flags = FRR_NO_SPLIT_CONFIG | FRR_MGMTD_BACKEND,
);
static const char *const staticd_config_xpaths[] = {
"/frr-host:host",
"/frr-logging:logging",
"/frr-vrf:lib",
"/frr-interface:lib",
"/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd",
};
static const char *const staticd_oper_xpaths[] = {
"/frr-backend:clients",
};
static const char *const staticd_rpc_xpaths[] = {
"/frr-logging",
};
struct mgmt_be_client_cbs staticd_be_client_data = {
.config_xpaths = staticd_config_xpaths,
.nconfig_xpaths = array_size(staticd_config_xpaths),
.oper_xpaths = staticd_oper_xpaths,
.noper_xpaths = array_size(staticd_oper_xpaths),
.rpc_xpaths = staticd_rpc_xpaths,
.nrpc_xpaths = array_size(staticd_rpc_xpaths),
};
/* clang-format on */
int main(int argc, char **argv, char **envp)
@ -176,7 +200,7 @@ int main(int argc, char **argv, char **envp)
static_vty_init();
/* Initialize MGMT backend functionalities */
mgmt_be_client = mgmt_be_client_create("staticd", NULL, 0, master);
mgmt_be_client = mgmt_be_client_create("staticd", &staticd_be_client_data, 0, master);
hook_register(routing_conf_event,
routing_control_plane_protocols_name_validate);

View file

@ -301,9 +301,7 @@ static const struct frr_yang_module_info *const zebra_yang_modules[] = {
&frr_affinity_map_info,
&frr_zebra_route_map_info,
};
/* clang-format on */
/* clang-format off */
FRR_DAEMON_INFO(zebra, ZEBRA,
.vty_port = ZEBRA_VTY_PORT,
.proghelp =
@ -319,6 +317,37 @@ FRR_DAEMON_INFO(zebra, ZEBRA,
.yang_modules = zebra_yang_modules,
.n_yang_modules = array_size(zebra_yang_modules),
);
static const char *const zebra_config_xpaths[] = {
"/frr-affinity-map:lib",
"/frr-filter:lib",
"/frr-host:host",
"/frr-logging:logging",
"/frr-route-map:lib",
"/frr-zebra:zebra",
"/frr-interface:lib",
"/frr-vrf:lib",
};
static const char *const zebra_oper_xpaths[] = {
"/frr-backend:clients",
"/frr-interface:lib/interface",
"/frr-vrf:lib/vrf/frr-zebra:zebra",
"/frr-zebra:zebra",
};
static const char *const zebra_rpc_xpaths[] = {
"/frr-logging",
};
struct mgmt_be_client_cbs zebra_be_client_data = {
.config_xpaths = zebra_config_xpaths,
.nconfig_xpaths = array_size(zebra_config_xpaths),
.oper_xpaths = zebra_oper_xpaths,
.noper_xpaths = array_size(zebra_oper_xpaths),
.rpc_xpaths = zebra_rpc_xpaths,
.nrpc_xpaths = array_size(zebra_rpc_xpaths),
};
/* clang-format on */
void zebra_main_router_started(void)
@ -489,8 +518,7 @@ int main(int argc, char **argv)
zebra_ns_init();
router_id_cmd_init();
zebra_vty_init();
mgmt_be_client = mgmt_be_client_create("zebra", NULL, 0,
zrouter.master);
mgmt_be_client = mgmt_be_client_create("zebra", &zebra_be_client_data, 0, zrouter.master);
access_list_init_new(true);
prefix_list_init();