From d54ab3b112facf863b4b4065767e984b2dc8eb03 Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Thu, 16 Jan 2025 06:14:54 +0000 Subject: [PATCH] mgmtd: testc: add listen for datastore notifications Signed-off-by: Christian Hopps --- mgmtd/mgmt_be_adapter.c | 10 ++++ mgmtd/mgmt_testc.c | 101 +++++++++++++++++++++++++++++++++++----- 2 files changed, 100 insertions(+), 11 deletions(-) diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c index 1c32f936b0..8f70490379 100644 --- a/mgmtd/mgmt_be_adapter.c +++ b/mgmtd/mgmt_be_adapter.c @@ -84,6 +84,13 @@ static const char *const zebra_oper_xpaths[] = { 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", @@ -154,6 +161,9 @@ static const char *const *be_client_config_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { }; static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { +#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 diff --git a/mgmtd/mgmt_testc.c b/mgmtd/mgmt_testc.c index 8bb07ed068..ab8ea9a04d 100644 --- a/mgmtd/mgmt_testc.c +++ b/mgmtd/mgmt_testc.c @@ -9,8 +9,10 @@ #include #include #include "darr.h" +#include "debug.h" #include "libfrr.h" #include "mgmt_be_client.h" +#include "mgmt_msg_native.h" #include "northbound.h" /* ---------------- */ @@ -43,15 +45,15 @@ struct zebra_privs_t __privs = { .cap_num_i = 0, }; -#define OPTION_LISTEN 2000 -#define OPTION_NOTIF_COUNT 2001 -#define OPTION_TIMEOUT 2002 -const struct option longopts[] = { - { "listen", no_argument, NULL, OPTION_LISTEN }, - { "notif-count", required_argument, NULL, OPTION_NOTIF_COUNT }, - { "timeout", required_argument, NULL, OPTION_TIMEOUT }, - { 0 } -}; +#define OPTION_DATASTORE 2000 +#define OPTION_LISTEN 2001 +#define OPTION_NOTIF_COUNT 2002 +#define OPTION_TIMEOUT 2003 +const struct option longopts[] = { { "datastore", no_argument, NULL, OPTION_DATASTORE }, + { "listen", no_argument, NULL, OPTION_LISTEN }, + { "notify-count", required_argument, NULL, OPTION_NOTIF_COUNT }, + { "timeout", required_argument, NULL, OPTION_TIMEOUT }, + { 0 } }; /* Master of threads. */ @@ -79,6 +81,20 @@ struct frr_signal_t __signals[] = { #define MGMTD_TESTC_VTY_PORT 2624 /* clang-format off */ +static const struct frr_yang_module_info frr_if_info = { + .name = "frr-interface", + .ignore_cfg_cbs = true, + .nodes = { + { + .xpath = "/frr-interface:lib/interface", + .cbs.notify = async_notification, + }, + { + .xpath = NULL, + } + } +}; + static const struct frr_yang_module_info frr_ripd_info = { .name = "frr-ripd", .ignore_cfg_cbs = true, @@ -98,6 +114,8 @@ static const struct frr_yang_module_info frr_ripd_info = { }; static const struct frr_yang_module_info *const mgmt_yang_modules[] = { + &frr_backend_info, + &frr_if_info, &frr_ripd_info, }; @@ -123,6 +141,7 @@ const char **__rpc_xpaths; struct mgmt_be_client_cbs __client_cbs = {}; struct event *event_timeout; +int f_datastore; int o_notif_count = 1; int o_timeout; @@ -165,10 +184,56 @@ static void success(struct event *event) quit(0); } -static void async_notification(struct nb_cb_notify_args *args) +static void __ds_notification(struct nb_cb_notify_args *args) { - zlog_notice("Received YANG notification"); + uint8_t *output = NULL; + zlog_notice("Received YANG datastore notification: op %u", args->op); + + if (args->op == NOTIFY_OP_NOTIFICATION) { + zlog_warn("ignoring non-datastore op notification: %s", args->xpath); + return; + } + + /* datastore notification */ + switch (args->op) { + case NOTIFY_OP_DS_REPLACE: + printfrr("#OP=REPLACE: %s\n", args->xpath); + break; + case NOTIFY_OP_DS_DELETE: + printfrr("#OP=DELETE: %s\n", args->xpath); + break; + case NOTIFY_OP_DS_PATCH: + printfrr("#OP=PATCH: %s\n", args->xpath); + break; + default: + printfrr("#OP=%u: unknown notify op\n", args->op); + quit(1); + } + + if (args->dnode && args->op != NOTIFY_OP_DS_DELETE) { + output = yang_print_tree(args->dnode, LYD_JSON, LYD_PRINT_SHRINK); + if (output) { + printfrr("%s\n", output); + darr_free(output); + } + } + fflush(stdout); + + if (o_notif_count && !--o_notif_count) + quit(0); +} + +static void __notification(struct nb_cb_notify_args *args) +{ + zlog_notice("Received YANG notification: op: %u", args->op); + + if (args->op != NOTIFY_OP_NOTIFICATION) { + zlog_warn("ignoring datastore notification: op: %u: path %s", args->op, args->xpath); + return; + } + + /* bogus, we should print the actual data */ printf("{\"frr-ripd:authentication-failure\": {\"interface-name\": \"%s\"}}\n", yang_dnode_get_string(args->dnode, "interface-name")); @@ -176,6 +241,14 @@ static void async_notification(struct nb_cb_notify_args *args) quit(0); } +static void async_notification(struct nb_cb_notify_args *args) +{ + if (f_datastore) + __ds_notification(args); + else + __notification(args); +} + static int rpc_callback(struct nb_cb_rpc_args *args) { const char *vrf = NULL; @@ -210,6 +283,9 @@ int main(int argc, char **argv) break; switch (opt) { + case OPTION_DATASTORE: + f_datastore = 1; + break; case OPTION_LISTEN: f_listen = 1; break; @@ -228,6 +304,9 @@ int main(int argc, char **argv) master = frr_init(); + mgmt_be_client_lib_vty_init(); + mgmt_dbg_be_client.flags = DEBUG_MODE_ALL; + /* * Setup notification listen */