.. .. SPDX-License-Identifier: GPL-2.0-or-later .. .. June 19 2023, Christian Hopps .. .. Copyright (c) 2023, LabN Consulting, L.L.C. .. .. _mgmtd_dev: MGMTD Development ================= Overview ^^^^^^^^ ``mgmtd`` (Management Daemon) is a new centralized management daemon for FRR. Previously, ``vtysh`` was the only centralized management service provided. Internally ``vtysh`` connects to each daemon and sends CLI commands (both configuration and operational state queries) over a socket connection. This service only supports CLI which is no longer sufficient. An important next step was made with the addition of YANG support. A YANG infrastructure was added through a new development called *northbound*. This *northbound* interface added the capability of daemons to be configured and queried using YANG models. However, this interface was per daemon and not centralized, which is not sufficient. ``mgmtd`` harnesses this new *northbound* interface to provide a centralized interface for all daemons. It utilizes the daemons YANG models to interact with each daemon. ``mgmtd`` currently provides the CLI interface for each daemon that has been converted to it, but in the future RESTCONF and NETCONF servers can easily be added as *front-ends* to mgmtd to support those protocols as well. Converting A Daemon to MGMTD ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A daemon must first be transitioned to the new :ref:`northbound` interface if that has not already been done (see :ref:`nb-retrofit` for how to do this). Once this is done a few simple steps are all that is required move the daemon over to ``mgmtd`` control. Overview of Changes ------------------- Adding support for a *northbound* converted daemon involves very little work. It requires enabling *frontend* (CLI and YANG) and *backend* (YANG) support. ``mgmtd`` was designed to keep this as simple as possible. Front-End Interface: 1. Add YANG module file to ``mgmtd/subdir.am`` (e.g., ``yang/frr-staticd.yang.c``). 2. Add CLI handler file[s] to ``mgmtd/subdir.am`` (e.g., ``staticd/static_vty.c``). 3. [if needed] Exclude (#ifndef) non-configuration CLI handlers from CLI source file (e.g., inside ``staticd/static_vty.c``). 4. [otherwise] Remove CLI handler file from SOURCES in daemon (e.g in :file:`staticd/subdir.am`) 5. Add YANG module description into array defined in ``mgmtd/mgmt_main.c`` (see :ref:`mgmtd-config-write`). 6. Initialize the CLI handlers inside :code:`mgmt_vty_init` in :file:`mgmtd/mgmt_vty.c`. 7. Direct ``vtysh`` to send CLI commands to ``mgmtd`` by modifying ``vtysh/vtysh.h``. At the top of this file each daemon has a bit ``#define``'d (e.g., ``#define VTYSH_STATICD 0x08000``) below this there are groupings, replace all the uses of the daemons bit with ``VTYSH_MGMTD`` instead so that the CLI commands get properly routed to ``mgmtd`` rather than the daemon now. Back-End Interface: 8. In ``mgmtd/mgmt_be_adapter.c`` add xpath prefix mappings to a one or both mapping arrays (``be_client_config_xpaths`` and ``be_client_oper_xpaths``) to direct ``mgmtd`` to send config and oper-state requests to your daemon. NOTE: make sure to include library supported xpaths prefixes as well (e.g., "/frr-interface:lib"). Add YANG and CLI into MGMTD --------------------------- As an example here is the addition made to ``mgmtd/subdir.am`` for adding ``staticd`` support. .. code-block:: make if STATICD nodist_mgmtd_mgmtd_SOURCES += \ yang/frr-staticd.yang.c \ yang/frr-bfdd.yang.c \ # end nodist_mgmtd_libmgmt_be_nb_la_SOURCES += staticd/static_vty.c endif An here is the addition to the modules array in ``mgmtd/mgmt_main.c``: .. code-block:: c #ifdef HAVE_STATICD extern const struct frr_yang_module_info frr_staticd_info; #endif static const struct frr_yang_module_info *const mgmt_yang_modules[] = { &frr_filter_info, ... #ifdef HAVE_STATICD &frr_staticd_info, #endif } CLI Config and Show Handlers ---------------------------- The daemon's CLI handlers for configuration (which having been converted to the :ref:`northbound` now simply generate YANG changes) will be linked directly into ``mgmtd``. If the operational and debug CLI commands are kept in files separate from the daemon's configuration CLI commands then no extra work is required. Otherwise some CPP #ifndef's will be required. ``mgmtd`` supports both config and operational state. However, many daemons have not had their operational state CLI commands converted over to the new YANG based methods. If that is the case and if both types of CLI handlers are present in a single file (e.g. a ``xxx_vty.c`` or ``xxx_cli.c`` file) then :code:`#ifndef` will need to be used to exclude the non-config CLI handlers from ``mgmtd``. The same goes for unconverted *debug* CLI handlers. For example: .. code-block:: c DEFPY(daemon_one_config, daemon_one_config_cmd, "daemon one [optional-arg]" ... { ... } #ifndef INCLUDE_MGMTD_CMDDEFS_ONLY DEFPY(daemon_show_oper, daemon_show_oper_cmd, "show daemon oper [all]" ... { ... } #endif /* ifndef INCLUDE_MGMTD_CMDDEFS_ONLY */ void daemon_vty_init(void) { install_element(CONFIG_NODE, &daemon_one_config_cmd); ... #ifndef INCLUDE_MGMTD_CMDDEFS_ONLY install_element(ENABLE_NODE, &daemon_show_oper_cmd); #endif /* ifndef INCLUDE_MGMTD_CMDDEFS_ONLY */ } .. _mgmtd-config-write: CLI Config Write Handlers (:code:`cli_show`) -------------------------------------------- To support writing out the CLI configuration file the northbound API defines a 2 callbacks (:code:`cli_show` and :code:`cli_show_end`). Pointers to these callbacks used to live side-by-side in a daemons :code:`struct frr_yang_module_info`, with the daemons back-end configuration and operational state callbacks (normally in a file named `_nb.c`). However, these 2 functionalities need to be split up now. The *frontend* config writing callbacks (:code:`cli_show`) should now be linked into ``mgmtd`` while the *backend* config and oper-state callbacks (e.g., :code:`create`, :code:`modify`, etc) should continue to be linked into the daemon. So you will need to define 2 :code:`struct frr_yang_module_info` arrays. 1. The existing array remains in the same place in the daemon, but with all the :code:`cli_show` handlers removed. 2. The removed :code:`cli_show` handlers should be added to a new :code:`struct frr_yang_module_info` array. This second array should be included in the same file that includes that actual function pointed to by the the :code:`cli_show` callbacks (i.e., the file is compiled into ``mgmtd``). This new :code:`struct frr_yang_module_info` array is the one to be included in mgmtd in `mgmt_yang_modules` inside ``mgmtd/mgmt_main.c``. Back-End XPATH mappings ----------------------- In order for ``mgmtd`` to direct configuration to your daemon you need to add some XPATH mappings to ``mgmtd/mgmt_be_adapter.c``. These XPATHs determine which configuration changes get sent over the *back-end* interface to your daemon. There are 2 arrays to update the first for config support and the second for operational state. Below are the strings added for staticd config support: .. code-block:: c #if HAVE_STATICD static const char *const staticd_xpaths[] = { "/frr-vrf:lib", "/frr-interface:lib", "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd", NULL, }; #endif static const char *const *be_client_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { #ifdef HAVE_STATICD [MGMTD_BE_CLIENT_ID_STATICD] = staticd_xpaths, #endif }; Below are the strings added for zebra operational state support (note zebra is not conditionalized b/c it should always be present): .. code-block:: c static const char *const zebra_oper_xpaths[] = { "/frr-interface:lib/interface", "/frr-vrf:lib/vrf/frr-zebra:zebra", "/frr-zebra:zebra", NULL, }; static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { [MGMTD_BE_CLIENT_ID_ZEBRA] = zebra_oper_xpaths, }; MGMTD Internals ^^^^^^^^^^^^^^^ This section will describe the internal functioning of ``mgmtd``, for now a couple diagrams are included to aide in source code perusal. The client side of a CLI configuration change .. figure:: ../figures/cli-change-client.svg :align: center The server (mgmtd) side of a CLI configuration change .. figure:: ../figures/cli-change-mgmtd.svg :align: center The client and server sides of oper-state query .. figure:: ../figures/cli-oper-state.svg :align: center