summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Hopps <chopps@labn.net>2025-01-16 06:14:54 +0000
committerChristian Hopps <chopps@labn.net>2025-01-18 16:14:29 +0000
commitd54ab3b112facf863b4b4065767e984b2dc8eb03 (patch)
treed14669737556b9f8361c7c996be9d8a710ce6117
parent597d79a89e6628645e3648bdc03db0d7bdc7e0f4 (diff)
mgmtd: testc: add listen for datastore notifications
Signed-off-by: Christian Hopps <chopps@labn.net>
-rw-r--r--mgmtd/mgmt_be_adapter.c10
-rw-r--r--mgmtd/mgmt_testc.c101
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 <zebra.h>
#include <lib/version.h>
#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
*/