Skip to content

Commit

Permalink
Merge pull request #15272 from LabNConsulting/chopps/mgmtd-notif-test
Browse files Browse the repository at this point in the history
tests: add mgmtd backend notification test
  • Loading branch information
donaldsharp authored Feb 1, 2024
2 parents 62443d7 + 7521918 commit e24f43e
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 21 deletions.
102 changes: 83 additions & 19 deletions mgmtd/mgmt_testc.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@

#include <zebra.h>
#include <lib/version.h>
#include "darr.h"
#include "libfrr.h"
#include "mgmt_be_client.h"

/* ---------------- */
/* Local Prototypes */
/* ---------------- */

static void ripd_notification(struct mgmt_be_client *client, uintptr_t usr_data,
struct mgmt_be_client_notification_cb *this,
const char *notif_data);
static void async_notification(struct mgmt_be_client *client, uintptr_t usr_data,
struct mgmt_be_client_notification_cb *this,
const char *notif_data);

static void sigusr1(void);
static void sigint(void);
Expand All @@ -42,7 +43,16 @@ struct zebra_privs_t __privs = {
.cap_num_i = 0,
};

struct option longopts[] = {{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 }
};


/* Master of threads. */
struct event_loop *master;
Expand Down Expand Up @@ -85,17 +95,13 @@ FRR_DAEMON_INFO(mgmtd_testc, MGMTD_TESTC,
);
/* clang-format on */

struct mgmt_be_client_notification_cb __notify_cbs[] = { {
.xpath = "frr-ripd",
.format = LYD_JSON,
.callback = ripd_notification,
} };
struct mgmt_be_client_notification_cb *__notify_cbs;

struct mgmt_be_client_cbs __client_cbs = {
.notify_cbs = __notify_cbs,
.nnotify_cbs = array_size(__notify_cbs),
};
struct mgmt_be_client_cbs __client_cbs = {};
struct event *event_timeout;

int o_notif_count = 1;
int o_timeout;

/* --------- */
/* Functions */
Expand All @@ -107,22 +113,43 @@ static void sigusr1(void)
zlog_rotate();
}

static void quit(int exit_code)
{
EVENT_OFF(event_timeout);
frr_fini();
darr_free(__client_cbs.notify_cbs);
exit(exit_code);
}

static void sigint(void)
{
zlog_notice("Terminating on signal");
frr_fini();
exit(0);
quit(0);
}

static void ripd_notification(struct mgmt_be_client *client, uintptr_t usr_data,
struct mgmt_be_client_notification_cb *this,
const char *notif_data)
static void timeout(struct event *event)
{
zlog_notice("Received RIPd notification");
zlog_notice("Timeout, exiting");
quit(1);
}

static void async_notification(struct mgmt_be_client *client, uintptr_t usr_data,
struct mgmt_be_client_notification_cb *this,
const char *notif_data)
{
zlog_notice("Received YANG notification");

printf("%s\n", notif_data);

if (o_notif_count && !--o_notif_count)
quit(0);
}

int main(int argc, char **argv)
{
int f_listen = 0;
int i;

frr_preinit(&mgmtd_testc_di, argc, argv);
frr_opt_add("", longopts, "");

Expand All @@ -135,6 +162,15 @@ int main(int argc, char **argv)
break;

switch (opt) {
case OPTION_LISTEN:
f_listen = 1;
break;
case OPTION_NOTIF_COUNT:
o_notif_count = atoi(optarg);
break;
case OPTION_TIMEOUT:
o_timeout = atoi(optarg);
break;
case 0:
break;
default:
Expand All @@ -144,10 +180,38 @@ int main(int argc, char **argv)

master = frr_init();

/*
* Setup notification listen
*/
argv += optind;
argc -= optind;
if (!argc && f_listen) {
fprintf(stderr,
"Must specify at least one notification xpath to listen to\n");
exit(1);
}
if (argc && f_listen) {
struct mgmt_be_client_notification_cb *cb;

for (i = 0; i < argc; i++) {
zlog_notice("Listen on xpath: %s", argv[i]);
cb = darr_append(__notify_cbs);
cb->xpath = argv[i];
cb->format = LYD_JSON;
cb->callback = async_notification;
}
__client_cbs.notify_cbs = __notify_cbs;
__client_cbs.nnotify_cbs = darr_len(__notify_cbs);
}

mgmt_be_client = mgmt_be_client_create("mgmtd-testc", &__client_cbs, 0,
master);

frr_config_fork();

if (o_timeout)
event_add_timer(master, timeout, NULL, o_timeout, &event_timeout);

frr_run(master);

/* Reached. */
Expand Down
41 changes: 39 additions & 2 deletions tests/topotests/mgmt_notif/test_notif.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def tgen(request):
tgen.stop_topology()


def test_oper_simple(tgen):
def test_frontend_notification(tgen):
if tgen.routers_have_failure():
pytest.skip(tgen.errors)

Expand All @@ -57,9 +57,46 @@ def test_oper_simple(tgen):
if rc:
pytest.skip("No protoc or present cannot run test")

# The first notifications is a frr-ripd:authentication-type-failure
# So we filter to avoid that, all the rest are frr-ripd:authentication-failure
# making our test deterministic
output = r1.cmd_raises(
fe_client_path + " --listen frr-ripd:authentication-failure"
)
jsout = json.loads(output)

expected = {"frr-ripd:authentication-failure": {"interface-name": "r1-eth0"}}
result = json_cmp(jsout, expected)
assert result is None

output = r1.cmd_raises(fe_client_path + " --listen")
jsout = json.loads(output)

expected = {"frr-ripd:authentication-type-failure": {"interface-name": "r1-eth0"}}
expected = {"frr-ripd:authentication-failure": {"interface-name": "r1-eth0"}}
result = json_cmp(jsout, expected)
assert result is None


def test_backend_notification(tgen):
if tgen.routers_have_failure():
pytest.skip(tgen.errors)

r1 = tgen.gears["r1"].net

check_kernel_32(r1, "11.11.11.11", 1, "")

be_client_path = "/usr/lib/frr/mgmtd_testc"
rc, _, _ = r1.cmd_status(be_client_path + " --help")

if rc:
pytest.skip("No mgmtd_testc")

output = r1.cmd_raises(
be_client_path + " --timeout 20 --log file:mgmt_testc.log --listen frr-ripd"
)

jsout = json.loads(output)

expected = {"frr-ripd:authentication-failure": {"interface-name": "r1-eth0"}}
result = json_cmp(jsout, expected)
assert result is None

0 comments on commit e24f43e

Please sign in to comment.