frr/mgmtd/mgmt_main.c
Christian Hopps ef43a6329b mgmtd: Add MGMT Frontend Interface Framework
This commit introduces the Frontend Interface which can be used
by front-end management clients like Netconf server, Restconf
Server and CLI to interact with new FRR Management daemon (MGMTd)
to access and sometimes modify FRR management data.

This commit includes the following functionalities in the changeset:
1. Add new Frontend server for clients connect to.
2. Add a C-based Frontend client library which can be used by Frontend
   clients to communicate with MGMTd via the Frontend interface.
3. Maintain a frontend adapter for each connection from an appropriate
   Frontend client to facilitate client requests and track one or more
   client sessions across it.
4. Define the protobuf message format for messages to be exchanged
   between MGMTd Frontend module and the Frontend client.
5. This changeset also introduces an instance of MGMT Frontend client
   embedded within the lib/vty module that can be leveraged by any FRR
   daemon to connect to MGMTd's Frontend interface. The same has been
   integrated with and initialized within the MGMTd daemon's process
   context to implement a bunch of 'set-config', 'commit-apply',
   'get-config' and 'get-data' commands via VTYSH

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

271 lines
5.4 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Main routine of mgmt.
*
* Copyright (C) 2021 Vmware, Inc.
* Pushpasis Sarkar
*/
#include <zebra.h>
#include "lib/version.h"
#include "routemap.h"
#include "filter.h"
#include "libfrr.h"
#include "frr_pthread.h"
#include "mgmtd/mgmt.h"
#include "mgmtd/mgmt_ds.h"
#include "routing_nb.h"
/* mgmt options, we use GNU getopt library. */
static const struct option longopts[] = {
{"skip_runas", no_argument, NULL, 'S'},
{"no_zebra", no_argument, NULL, 'Z'},
{"socket_size", required_argument, NULL, 's'},
{0}
};
static void mgmt_exit(int);
static void mgmt_vrf_terminate(void);
/* privileges */
static zebra_capabilities_t _caps_p[] = {ZCAP_BIND, ZCAP_NET_RAW,
ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN};
struct zebra_privs_t mgmt_privs = {
#if defined(FRR_USER) && defined(FRR_GROUP)
.user = FRR_USER,
.group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
.cap_num_p = array_size(_caps_p),
.cap_num_i = 0,
};
static struct frr_daemon_info mgmtd_di;
char backup_config_file[256];
/* SIGHUP handler. */
static void sighup(void)
{
zlog_info("SIGHUP received, ignoring");
return;
/*
* This is turned off for the moment. There is all
* sorts of config turned off by mgmt_terminate
* that is not setup properly again in mgmt_reset.
* I see no easy way to do this nor do I see that
* this is a desirable way to reload config
* given the yang work.
*/
/* Terminate all thread. */
mgmt_terminate();
/*
* mgmt_reset();
*/
zlog_info("MGMTD restarting!");
/*
* Reload config file.
* vty_read_config(NULL, mgmtd_di.config_file, config_default);
*/
/* Try to return to normal operation. */
}
/* SIGINT handler. */
static __attribute__((__noreturn__)) void sigint(void)
{
zlog_notice("Terminating on signal");
assert(mm->terminating == false);
mm->terminating = true; /* global flag that shutting down */
mgmt_terminate();
mgmt_exit(0);
exit(0);
}
/* SIGUSR1 handler. */
static void sigusr1(void)
{
zlog_rotate();
}
/*
* Try to free up allocations we know about so that diagnostic tools such as
* valgrind are able to better illuminate leaks.
*
* Zebra route removal and protocol teardown are not meant to be done here.
* For example, "retain_mode" may be set.
*/
static __attribute__((__noreturn__)) void mgmt_exit(int status)
{
/* it only makes sense for this to be called on a clean exit */
assert(status == 0);
frr_early_fini();
/* stop pthreads (if any) */
frr_pthread_stop_all();
mgmt_vrf_terminate();
frr_fini();
exit(status);
}
static struct frr_signal_t mgmt_signals[] = {
{
.signal = SIGHUP,
.handler = &sighup,
},
{
.signal = SIGUSR1,
.handler = &sigusr1,
},
{
.signal = SIGINT,
.handler = &sigint,
},
{
.signal = SIGTERM,
.handler = &sigint,
},
};
static int mgmt_vrf_new(struct vrf *vrf)
{
zlog_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id);
return 0;
}
static int mgmt_vrf_delete(struct vrf *vrf)
{
zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id);
return 0;
}
static int mgmt_vrf_enable(struct vrf *vrf)
{
zlog_debug("VRF Enable: %s(%u)", vrf->name, vrf->vrf_id);
return 0;
}
static int mgmt_vrf_disable(struct vrf *vrf)
{
zlog_debug("VRF Disable: %s(%u)", vrf->name, vrf->vrf_id);
/* Note: This is a callback, the VRF will be deleted by the caller. */
return 0;
}
static int mgmt_vrf_config_write(struct vty *vty)
{
return 0;
}
static void mgmt_vrf_init(void)
{
vrf_init(mgmt_vrf_new, mgmt_vrf_enable, mgmt_vrf_disable,
mgmt_vrf_delete);
vrf_cmd_init(mgmt_vrf_config_write);
}
static void mgmt_vrf_terminate(void)
{
vrf_terminate();
}
/*
* List of YANG modules to be loaded in the process context of
* MGMTd.
*
* NOTE: In future this will also include the YANG modules of
* all individual Backend clients.
*/
static const struct frr_yang_module_info *const mgmt_yang_modules[] = {
&frr_filter_info, &frr_interface_info, &frr_route_map_info,
&frr_routing_info, &frr_vrf_info,
};
FRR_DAEMON_INFO(mgmtd, MGMTD, .vty_port = MGMTD_VTY_PORT,
.proghelp = "FRR Management Daemon.",
.signals = mgmt_signals, .n_signals = array_size(mgmt_signals),
.privs = &mgmt_privs, .yang_modules = mgmt_yang_modules,
.n_yang_modules = array_size(mgmt_yang_modules),
);
#define DEPRECATED_OPTIONS ""
/* Main routine of mgmt. Treatment of argument and start mgmt finite
* state machine is handled at here.
*/
int main(int argc, char **argv)
{
int opt;
int buffer_size = MGMTD_SOCKET_BUF_SIZE;
frr_preinit(&mgmtd_di, argc, argv);
frr_opt_add(
"s:" DEPRECATED_OPTIONS, longopts,
" -s, --socket_size Set MGMTD peer socket send buffer size\n");
/* Command line argument treatment. */
while (1) {
opt = frr_getopt(argc, argv, 0);
if (opt && opt < 128 && strchr(DEPRECATED_OPTIONS, opt)) {
fprintf(stderr,
"The -%c option no longer exists.\nPlease refer to the manual.\n",
opt);
continue;
}
if (opt == EOF)
break;
switch (opt) {
case 0:
break;
case 's':
buffer_size = atoi(optarg);
break;
default:
frr_help_exit(1);
break;
}
}
/* MGMTD master init. */
mgmt_master_init(frr_init(), buffer_size);
/* VRF Initializations. */
mgmt_vrf_init();
/* MGMTD related initialization. */
mgmt_init();
snprintf(backup_config_file, sizeof(backup_config_file),
"%s/zebra.conf", frr_sysconfdir);
mgmtd_di.backup_config_file = backup_config_file;
frr_config_fork();
frr_run(mm->master);
/* Not reached. */
return 0;
}