summaryrefslogtreecommitdiff
path: root/doc/developer/mgmtd-dev.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/developer/mgmtd-dev.rst')
-rw-r--r--doc/developer/mgmtd-dev.rst383
1 files changed, 383 insertions, 0 deletions
diff --git a/doc/developer/mgmtd-dev.rst b/doc/developer/mgmtd-dev.rst
new file mode 100644
index 0000000000..2404ffe2a7
--- /dev/null
+++ b/doc/developer/mgmtd-dev.rst
@@ -0,0 +1,383 @@
+..
+.. SPDX-License-Identifier: GPL-2.0-or-later
+..
+.. June 19 2023, Christian Hopps <chopps@labn.net>
+..
+.. 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.
+
+Conversion Status
+^^^^^^^^^^^^^^^^^
+
+Fully Converted To MGMTD
+""""""""""""""""""""""""
+
+- lib/distribute
+- lib/filter
+- lib/if_rmap
+- lib/routemap
+- lib/affinitymap
+- lib/if
+- lib/vrf
+- ripd
+- ripngd
+- staticd
+- zebra (* - partial)
+
+Converted To Northbound
+"""""""""""""""""""""""
+- bfdd
+- pathd
+- pbrd
+- pimd
+
+Converted To Northbound With Issues
+"""""""""""""""""""""""""""""""""""
+- eigrp
+- isisd
+
+Unconverted
+"""""""""""
+- babel
+- bgpd
+- ldpd
+- lib/event
+- lib/keychain
+- lib/log_vty
+- lib/nexthop_group
+- lib/zlog_5424_cli
+- nhrpd
+- ospfd
+- ospf6d
+- pceplib
+- qdb
+- sharpd
+- vrrpd
+
+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:
+
+#. Add YANG module file to ``mgmtd/subdir.am`` (e.g., ``yang/frr-staticd.yang.c``).
+
+#. Add CLI handler file[s] to ``mgmtd/subdir.am``. The `subdir.am` variable to
+ use is indicated in the next 2 steps.
+
+ #. [if needed] Exclude (:code:`#ifndef`) non-configuration CLI handlers from
+ CLI source file (e.g., inside :file:`staticd/static_vty.c`) and add the
+ file to :code:`nodist_mgmtd_libmgmt_be_nb_la_SOURCES` in
+ :file:`mgmtd/subdir.am`.
+
+ #. [otherwise] Remove CLI handler file from _SOURCES variable in the daemon
+ :file:`subdir.am` file (e.g in :file:`staticd/subdir.am`) and add to
+ :code:`mgmtd_libmgmtd_a_SOURCES` in :file:`mgmtd/subdir.am`.
+
+#. In order to have mgmtd try and load existing per-daemon config files, add
+ the daemon to the :code:`mgmt_daemons` array in :file:`lib/vty.c`. With the
+ official release of the mgmtd code FRR is no longer supporting per daemon log
+ files but it will take a while before all of the topotest is converted.
+
+#. In the daemon's :code:`struct frr_daemon_info` (i.e., inside it's
+ :code:`FRR_DAEMON_INFO()`) set the `.flags` bit `FRR_NO_SPLIT_CONFIG`. This
+ will keep the daemon from trying to read it's per-daemon config file as mgmtd
+ will now be doing this.
+
+#. Add the daemon's YANG module description[s] into the array
+ :code:`mgmt_yang_modules` defined in :file:`mgmtd/mgmt_main.c` (see
+ :ref:`mgmtd-config-write`). Make sure that all YANG modules that the daemon
+ uses are present in the mgmtd list. To find this list look in the daemon's
+ equivalent yang module array variable.
+
+#. Initialize the CLI handlers inside :code:`mgmt_vty_init` in :file:`mgmtd/mgmt_vty.c`.
+
+#. 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.
+
+ #. Remove initialization (and installation) of library CLI routines. These will
+ correspond with the VTYSH removals from the last step i.e.,:
+
+ - change access_list_init() to access_list_init_new(false) and remove from
+ VTYSH_ACL_CONFIG (leave in VTYSH_ACL_SHOW).
+ - remove if_cmd_init_default() => remove from VTYSH_INTERFACE_SUBSET
+ - remove if_cmd_init() => remove from VTYSH_INTERFACE_SUBSET
+ - change route_map_init() to route_map_init_new(false) and remove from
+ VTYSH_ROUTE_MAP_CONFIG (leave in VTYSH_ROUTE_MAP_SHOW).
+ - remove vrf_cmd_init(NULL) => remove from VTYSH_INTERFACE_SUBSET
+ ...
+
+Back-End Interface:
+
+#. In the daemon's main file initialize the BE client library. You add a global
+ `struct mgmt_be_client *mgmt_be_client` near the daemons `event_loop *master`
+ variable. Then where the daemon used to initialize it's CLI/VTY code replace
+ that with the client initialization by calling `mgmt_be_client_create`.
+ Likewise in the daemon's sigint cleanup code, operational walks should be
+ canceled with a call to `nb_oper_cancel_all_walks`, and then the BE client
+ should be destroyed with a call to `mgmt_be_client_destroy` and to be safe
+ NULL out the global `mgmt_be_client` variable.
+
+#. 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"). A good way to figure these paths out are to look in
+ each of the YANG modules that the daemon uses and include each of their paths
+ in the array.
+
+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 `<daemon>_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.
+
+#. The existing array remains in the same place in the daemon, but with all the
+ :code:`cli_show` handlers removed.
+
+#. 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 Client Connection
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In order for your daemon to communicate with mgmtd you need to initialize the
+backend client library. You normally do this where you used to initialize your
+CLI/VTY code.
+
+.. code-block:: c
+
+ ...
+ struct event_loop *master;
+
+ static struct mgmt_be_client *mgmt_be_client;
+ ...
+
+ int main(int argc, char **argv)
+ {
+ ...
+ rip_init();
+ rip_if_init();
+ mgmt_be_client = mgmt_be_client_create("ripd", NULL, 0, master);
+
+Likewise the client should be cleaned up in the daemon cleanup routine.
+
+.. code-block:: c
+
+ /* SIGINT handler. */
+ static void sigint(void)
+ {
+ zlog_notice("Terminating on signal");
+ ...
+ nb_oper_cancel_all_walks();
+ mgmt_be_client_destroy(mgmt_be_client);
+ mgmt_be_client = NULL;
+
+
+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