mirror_frr/mgmtd/mgmt_be_server.c
Christian Hopps 7d65b7b7f4 mgmtd: Add MGMT Backend Interface Framework
This commit introduces the MGMT Backend Interface which can be used
by back-end management client daemons like BGPd, Staticd, Zebra to
connect with new FRR Management daemon (MGMTd) and utilize the new
FRR Management Framework to let any Frontend clients to retrieve any
operational data or manipulate any configuration data owned by the
individual Backend daemon component.

This commit includes the following functionalities in the changeset:
1. Add new Backend server for Backend daemons connect to.
2. Add a C-based Backend client library which can be used by daemons
   to communicate with MGMTd via the Backend interface.
3. Maintain a backend adapter for each connection from an appropriate
   Backend client to facilitate client requests and track one or more
   transactions initiated from Frontend client sessions that involves
   the backend client component.
4. Add the following commands to inspect various Backend client
   related information
	a. show mgmt backend-adapter all
	b. show mgmt backend-yang-xpath-registry
        c. show mgmt yang-xpath-subscription

Co-authored-by: Pushpasis Sarkar <pushpasis@gmail.com>
Co-authored-by: Abhinay Ramesh <rabhinay@vmware.com>
Co-authored-by: Ujwal P <ujwalp@vmware.com>
Signed-off-by: Yash Ranjan <ranjany@vmware.com>
2023-03-21 22:08:32 -04:00

161 lines
4.0 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* MGMTD Backend Server
*
* Copyright (C) 2021 Vmware, Inc.
* Pushpasis Sarkar <spushpasis@vmware.com>
*/
#include <zebra.h>
#include "network.h"
#include "libfrr.h"
#include "mgmtd/mgmt.h"
#include "mgmtd/mgmt_be_server.h"
#include "mgmtd/mgmt_be_adapter.h"
#ifdef REDIRECT_DEBUG_TO_STDERR
#define MGMTD_BE_SRVR_DBG(fmt, ...) \
fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
#define MGMTD_BE_SRVR_ERR(fmt, ...) \
fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
#else /* REDIRECT_DEBUG_TO_STDERR */
#define MGMTD_BE_SRVR_DBG(fmt, ...) \
do { \
if (mgmt_debug_be) \
zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
} while (0)
#define MGMTD_BE_SRVR_ERR(fmt, ...) \
zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
#endif /* REDIRECT_DEBUG_TO_STDERR */
static int mgmt_be_listen_fd;
static struct thread_master *mgmt_be_listen_tm;
static struct thread *mgmt_be_listen_ev;
static void mgmt_be_server_register_event(enum mgmt_be_event event);
static void mgmt_be_conn_accept(struct thread *thread)
{
int client_conn_fd;
union sockunion su;
if (mgmt_be_listen_fd < 0)
return;
/* We continue hearing server listen socket. */
mgmt_be_server_register_event(MGMTD_BE_SERVER);
memset(&su, 0, sizeof(union sockunion));
/* We can handle IPv4 or IPv6 socket. */
client_conn_fd = sockunion_accept(mgmt_be_listen_fd, &su);
if (client_conn_fd < 0) {
MGMTD_BE_SRVR_ERR(
"Failed to accept MGMTD Backend client connection : %s",
safe_strerror(errno));
return;
}
set_nonblocking(client_conn_fd);
set_cloexec(client_conn_fd);
MGMTD_BE_SRVR_DBG("Got a new MGMTD Backend connection");
mgmt_be_create_adapter(client_conn_fd, &su);
}
static void mgmt_be_server_register_event(enum mgmt_be_event event)
{
if (event == MGMTD_BE_SERVER) {
thread_add_read(mgmt_be_listen_tm, mgmt_be_conn_accept,
NULL, mgmt_be_listen_fd,
&mgmt_be_listen_ev);
assert(mgmt_be_listen_ev);
} else {
assert(!"mgmt_be_server_post_event() called incorrectly");
}
}
static void mgmt_be_server_start(const char *hostname)
{
int ret;
int sock;
struct sockaddr_un addr;
mode_t old_mask;
/* Set umask */
old_mask = umask(0077);
sock = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC);
if (sock < 0) {
MGMTD_BE_SRVR_ERR("Failed to create server socket: %s",
safe_strerror(errno));
goto mgmt_be_server_start_failed;
}
addr.sun_family = AF_UNIX,
strlcpy(addr.sun_path, MGMTD_BE_SERVER_PATH, sizeof(addr.sun_path));
unlink(addr.sun_path);
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
MGMTD_BE_SRVR_ERR(
"Failed to bind server socket to '%s'. Err: %s",
addr.sun_path, safe_strerror(errno));
goto mgmt_be_server_start_failed;
}
ret = listen(sock, MGMTD_BE_MAX_CONN);
if (ret < 0) {
MGMTD_BE_SRVR_ERR("Failed to listen on server socket: %s",
safe_strerror(errno));
goto mgmt_be_server_start_failed;
}
/* Restore umask */
umask(old_mask);
mgmt_be_listen_fd = sock;
mgmt_be_server_register_event(MGMTD_BE_SERVER);
MGMTD_BE_SRVR_DBG("Started MGMTD Backend Server!");
return;
mgmt_be_server_start_failed:
if (sock)
close(sock);
mgmt_be_listen_fd = -1;
exit(-1);
}
int mgmt_be_server_init(struct thread_master *master)
{
if (mgmt_be_listen_tm) {
MGMTD_BE_SRVR_DBG("MGMTD Backend Server already running!");
return 0;
}
mgmt_be_listen_tm = master;
mgmt_be_server_start("localhost");
return 0;
}
void mgmt_be_server_destroy(void)
{
if (mgmt_be_listen_tm) {
MGMTD_BE_SRVR_DBG("Closing MGMTD Backend Server!");
if (mgmt_be_listen_ev) {
THREAD_OFF(mgmt_be_listen_ev);
mgmt_be_listen_ev = NULL;
}
if (mgmt_be_listen_fd >= 0) {
close(mgmt_be_listen_fd);
mgmt_be_listen_fd = -1;
}
mgmt_be_listen_tm = NULL;
}
}