summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_mplsvpn.c14
-rw-r--r--doc/developer/mgmtd-dev.rst172
-rw-r--r--doc/developer/northbound/advanced-topics.rst95
-rw-r--r--doc/developer/northbound/architecture.rst55
-rw-r--r--doc/developer/northbound/demos.rst3
-rw-r--r--doc/developer/northbound/links.rst3
-rw-r--r--doc/developer/northbound/northbound.rst2
-rw-r--r--doc/developer/northbound/operational-data-rpcs-and-notifications.rst18
-rw-r--r--doc/developer/northbound/plugins-sysrepo.rst3
-rw-r--r--doc/developer/northbound/ppr-basic-test-topology.rst17
-rw-r--r--doc/developer/northbound/ppr-mpls-basic-test-topology.rst17
-rw-r--r--doc/developer/northbound/retrofitting-configuration-commands.rst160
-rw-r--r--doc/developer/northbound/transactional-cli.rst150
-rw-r--r--doc/developer/northbound/yang-module-translator.rst36
-rw-r--r--doc/developer/northbound/yang-tools.rst12
-rw-r--r--lib/filter.c12
-rw-r--r--lib/filter.h5
-rw-r--r--lib/filter_cli.c257
-rw-r--r--lib/filter_nb.c32
-rw-r--r--lib/routemap.c12
-rw-r--r--lib/routemap.h2
-rw-r--r--lib/routemap_northbound.c42
-rw-r--r--lib/vty.c6
-rw-r--r--lib/yang.c24
-rw-r--r--lib/yang.h15
-rw-r--r--mgmtd/mgmt_be_adapter.c72
-rw-r--r--mgmtd/mgmt_be_adapter.h8
-rw-r--r--mgmtd/mgmt_fe_adapter.c5
-rw-r--r--mgmtd/mgmt_main.c16
-rw-r--r--mgmtd/mgmt_txn.c54
-rw-r--r--mgmtd/mgmt_txn.h6
-rw-r--r--mgmtd/mgmt_vty.c18
-rw-r--r--mgmtd/subdir.am35
-rw-r--r--python/xref2vtysh.py17
-rw-r--r--ripd/rip_cli.c139
-rw-r--r--ripd/rip_interface.c1
-rw-r--r--ripd/rip_main.c15
-rw-r--r--ripd/rip_nb.c38
-rw-r--r--ripd/rip_nb.h3
-rw-r--r--ripd/rip_routemap.c2
-rw-r--r--ripd/ripd.c50
-rw-r--r--ripd/ripd.h1
-rw-r--r--ripd/subdir.am1
-rw-r--r--ripngd/ripng_cli.c102
-rw-r--r--ripngd/ripng_interface.c1
-rw-r--r--ripngd/ripng_main.c14
-rw-r--r--ripngd/ripng_nb.c18
-rw-r--r--ripngd/ripng_nb.h3
-rw-r--r--ripngd/ripng_routemap.c2
-rw-r--r--ripngd/ripngd.c52
-rw-r--r--ripngd/ripngd.h1
-rw-r--r--ripngd/subdir.am1
-rw-r--r--sharpd/sharp_vty.c5
-rw-r--r--sharpd/sharp_zebra.c7
-rw-r--r--sharpd/sharp_zebra.h2
-rw-r--r--staticd/static_nb.h1
-rw-r--r--staticd/static_vty.c4
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py9
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf13
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py16
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py2
-rwxr-xr-xtests/topotests/srv6_locator_custom_bits_length/test_srv6_locator_custom_bits_length.py (renamed from tests/topotests/srv6_locator_custom_bits_length/test_srv6_locator.py)0
-rwxr-xr-xtests/topotests/zebra_seg6_route/test_zebra_seg6_route.py4
-rw-r--r--vtysh/vtysh.c20
-rw-r--r--vtysh/vtysh.h25
65 files changed, 1222 insertions, 725 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index cf57d95eb0..5aa752d6e7 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -1011,9 +1011,11 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
{
struct bgp_path_info *bpi_ultimate;
struct bgp *bgp_nexthop;
+ struct bgp_table *table;
bool nh_valid;
bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi);
+ table = bgp_dest_table(bpi_ultimate->net);
if (bpi->extra && bpi->extra->vrfleak && bpi->extra->vrfleak->bgp_orig)
bgp_nexthop = bpi->extra->vrfleak->bgp_orig;
@@ -1029,7 +1031,17 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
is_pi_family_evpn(bpi_ultimate) ||
CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_ACCEPT_OWN))
nh_valid = true;
- else
+ else if (bpi_ultimate->type == ZEBRA_ROUTE_BGP &&
+ bpi_ultimate->sub_type == BGP_ROUTE_STATIC && table &&
+ (table->safi == SAFI_UNICAST ||
+ table->safi == SAFI_LABELED_UNICAST) &&
+ !CHECK_FLAG(bgp_nexthop->flags, BGP_FLAG_IMPORT_CHECK)) {
+ /* if the route is defined with the "network <prefix>" command
+ * and "no bgp network import-check" is set,
+ * then mark the nexthop as valid.
+ */
+ nh_valid = true;
+ } else
/*
* TBD do we need to do anything about the
* 'connected' parameter?
diff --git a/doc/developer/mgmtd-dev.rst b/doc/developer/mgmtd-dev.rst
index d611f9c11b..e557d3a84a 100644
--- a/doc/developer/mgmtd-dev.rst
+++ b/doc/developer/mgmtd-dev.rst
@@ -12,7 +12,7 @@ MGMTD Development
=================
Overview
-^^^^^^^^
+--------
``mgmtd`` (Management Daemon) is a new centralized management daemon for FRR.
@@ -33,9 +33,55 @@ 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
+- ripd
+- staticd
+- zebra (* - partial)
+
+Converted To Northbound
+"""""""""""""""""""""""
+- bfdd
+- lib/affinitymap
+- lib/if
+- pathd
+- pbrd
+- pimd
+- ripngd
+
+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
@@ -43,7 +89,7 @@ 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.
@@ -51,31 +97,78 @@ requires enabling *frontend* (CLI and YANG) and *backend* (YANG) support.
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
+#. 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:
-8. In ``mgmtd/mgmt_be_adapter.c`` add xpath prefix mappings to a one or both
+#. 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").
-
+ "/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.
@@ -108,7 +201,7 @@ An here is the addition to the modules array in ``mgmtd/mgmt_main.c``:
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
@@ -157,7 +250,7 @@ are present in a single file (e.g. a ``xxx_vty.c`` or ``xxx_cli.c`` file) then
.. _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
@@ -172,10 +265,10 @@ the *backend* config and oper-state callbacks (e.g., :code:`create`,
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
+#. 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
+#. 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
@@ -184,8 +277,44 @@ So you will need to define 2 :code:`struct frr_yang_module_info` arrays.
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
@@ -228,9 +357,8 @@ not conditionalized b/c it should always be present):
[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.
diff --git a/doc/developer/northbound/advanced-topics.rst b/doc/developer/northbound/advanced-topics.rst
index bee29a95a9..edfc10bcbd 100644
--- a/doc/developer/northbound/advanced-topics.rst
+++ b/doc/developer/northbound/advanced-topics.rst
@@ -1,3 +1,11 @@
+Advanced Topics
+===============
+
+.. contents:: Table of contents
+ :local:
+ :backlinks: entry
+ :depth: 1
+
Auto-generated CLI commands
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -34,13 +42,16 @@ CLI on a separate program
The flexible design of the northbound architecture opens the door to
move the CLI to a separate program in the long-term future. Some
-advantages of doing so would be: \* Treat the CLI as just another
-northbound client, instead of having CLI commands embedded in the
-binaries of all FRR daemons. \* Improved robustness: bugs in CLI
-commands (e.g. null-pointer dereferences) or in the CLI code itself
-wouldn’t affect the FRR daemons. \* Foster innovation by allowing other
-CLI programs to be implemented, possibly using higher level programming
-languages.
+advantages of doing so would be:
+
+* Treat the CLI as just another northbound client, instead of having CLI
+ commands embedded in the binaries of all FRR daemons.
+
+* Improved robustness: bugs in CLI commands (e.g. null-pointer dereferences) or
+ in the CLI code itself wouldn’t affect the FRR daemons.
+
+* Foster innovation by allowing other CLI programs to be implemented, possibly
+ using higher level programming languages.
The problem, however, is that the northbound retrofitting process will
convert only the CLI configuration commands and EXEC commands in a first
@@ -232,40 +243,42 @@ vtysh support
As explained in the [[Transactional CLI]] page, all commands introduced
by the transactional CLI are not yet available in *vtysh*. This needs to
be addressed in the short term future. Some challenges for doing that
-work include: \* How to display configurations (running, candidates and
-rollbacks) in a more clever way? The implementation of the
-``show running-config`` command in *vtysh* is not something that should
-be followed as an example. A better idea would be to fetch the desired
-configuration from all daemons (encoded in JSON for example), merge them
-all into a single ``lyd_node`` variable and then display the combined
-configurations from this variable (the configuration merges would
-transparently take care of combining the shared configuration objects).
-In order to be able to manipulate the JSON configurations, *vtysh* will
-need to load the YANG modules from all daemons at startup (this might
-have a minimal impact on startup time). The only issue with this
-approach is that the ``cli_show()`` callbacks from all daemons are
-embedded in their binaries and thus not accessible externally. It might
-be necessary to compile these callbacks on a separate shared library so
-that they are accessible to *vtysh* too. Other than that, displaying the
-combined configurations in the JSON/XML formats should be
-straightforward. \* With the current design, transaction IDs are
-per-daemon and not global across all FRR daemons. This means that the
-same transaction ID can represent different transactions on different
-daemons. Given this observation, how to implement the
-``rollback configuration`` command in *vtysh*? The easy solution would
-be to add a ``daemon WORD`` argument to specify the context of the
-rollback, but per-daemon rollbacks would certainly be confusing and
-convoluted to end users. A better idea would be to attack the root of
-the problem: change configuration transactions to be global instead of
-being per-daemon. This involves a bigger change in the northbound
-architecture, and would have implications on how transactions are stored
-in the SQL database (daemon-specific and shared configuration objects
-would need to have their own tables or columns). \* Loading
-configuration files in the JSON or XML formats will be tricky, as
-*vtysh* will need to know which sections of the configuration should be
-sent to which daemons. *vtysh* will either need to fetch the YANG
-modules implemented by all daemons at runtime or obtain this information
-at compile-time somehow.
+work include:
+
+* How to display configurations (running, candidates and rollbacks) in a more
+ clever way? The implementation of the ``show running-config`` command in
+ *vtysh* is not something that should be followed as an example. A better idea
+ would be to fetch the desired configuration from all daemons (encoded in JSON
+ for example), merge them all into a single ``lyd_node`` variable and then
+ display the combined configurations from this variable (the configuration
+ merges would transparently take care of combining the shared configuration
+ objects). In order to be able to manipulate the JSON configurations, *vtysh*
+ will need to load the YANG modules from all daemons at startup (this might
+ have a minimal impact on startup time). The only issue with this approach is
+ that the ``cli_show()`` callbacks from all daemons are embedded in their
+ binaries and thus not accessible externally. It might be necessary to compile
+ these callbacks on a separate shared library so that they are accessible to
+ *vtysh* too. Other than that, displaying the combined configurations in the
+ JSON/XML formats should be straightforward.
+
+* With the current design, transaction IDs are per-daemon and not global across
+ all FRR daemons. This means that the same transaction ID can represent
+ different transactions on different daemons. Given this observation, how to
+ implement the ``rollback configuration`` command in *vtysh*? The easy solution
+ would be to add a ``daemon WORD`` argument to specify the context of the
+ rollback, but per-daemon rollbacks would certainly be confusing and convoluted
+ to end users. A better idea would be to attack the root of the problem: change
+ configuration transactions to be global instead of being per-daemon. This
+ involves a bigger change in the northbound architecture, and would have
+ implications on how transactions are stored in the SQL database
+ (daemon-specific and shared configuration objects would need to have their own
+ tables or columns).
+
+* Loading configuration files in the JSON or XML formats will be tricky, as
+ *vtysh* will need to know which sections of the configuration should be sent
+ to which daemons. *vtysh* will either need to fetch the YANG modules
+ implemented by all daemons at runtime or obtain this information at
+ compile-time somehow.
Detecting type mismatches at compile-time
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/developer/northbound/architecture.rst b/doc/developer/northbound/architecture.rst
index e571971c7f..5fd89c32f1 100644
--- a/doc/developer/northbound/architecture.rst
+++ b/doc/developer/northbound/architecture.rst
@@ -1,3 +1,6 @@
+Architecture
+============
+
Introduction
------------
@@ -42,30 +45,34 @@ and
`CoAP <https://www.ietf.org/archive/id/draft-vanderstok-core-comi-11.txt>`__.
In addition to being management-protocol independent, some other
-advantages of using YANG in FRR are listed below: \* Have a formal
-contract between FRR and application developers (management clients). A
-management client that has access to the FRR YANG models knows about all
-existing configuration options available for use. This information can
-be used to auto-generate user-friendly interfaces like Web-UIs, custom
-CLIs and even code bindings for several different programming languages.
-Using `PyangBind <https://github.com/robshakir/pyangbind>`__, for
-example, it’s possible to generate Python class hierarchies from YANG
-models and use these classes to instantiate objects that mirror the
-structure of the YANG modules and can be serialized/deserialized using
-different encoding formats. \* Support different encoding formats for
-instance data. Currently only JSON and XML are supported, but
-`GPB <https://developers.google.com/protocol-buffers/>`__ and
-`CBOR <http://cbor.io/>`__ are other viable options in the long term.
-Additional encoding formats can be implemented in the *libyang* library
-for optimal performance, or externally by translating data to/from one
-of the supported formats (with a performance penalty). \* Have a formal
-mechanism to introduce backward-incompatible changes based on `semantic
-versioning <http://www.openconfig.net/docs/semver/>`__ (not part of the
-YANG standard, which allows backward-compatible module updates only). \*
-Provide seamless support to the industry-standard NETCONF/RESTCONF
-protocols as alternative management APIs. If FRR configuration/state
-data is modeled using YANG, supporting YANG-based protocols like NETCONF
-and RESTCONF is much easier.
+advantages of using YANG in FRR are listed below:
+
+* Have a formal contract between FRR and application developers (management
+ clients). A management client that has access to the FRR YANG models knows
+ about all existing configuration options available for use. This information
+ can be used to auto-generate user-friendly interfaces like Web-UIs, custom
+ CLIs and even code bindings for several different programming languages. Using
+ `PyangBind <https://github.com/robshakir/pyangbind>`__, for example, it’s
+ possible to generate Python class hierarchies from YANG models and use these
+ classes to instantiate objects that mirror the structure of the YANG modules
+ and can be serialized/deserialized using different encoding formats.
+
+* Support different encoding formats for instance data. Currently only JSON and
+ XML are supported, but `GPB
+ <https://developers.google.com/protocol-buffers/>`__ and `CBOR
+ <http://cbor.io/>`__ are other viable options in the long term. Additional
+ encoding formats can be implemented in the *libyang* library for optimal
+ performance, or externally by translating data to/from one of the supported
+ formats (with a performance penalty).
+
+* Have a formal mechanism to introduce backward-incompatible changes based on
+ `semantic versioning <http://www.openconfig.net/docs/semver/>`__ (not part of
+ the YANG standard, which allows backward-compatible module updates only).
+
+* Provide seamless support to the industry-standard NETCONF/RESTCONF protocols
+ as alternative management APIs. If FRR configuration/state data is modeled
+ using YANG, supporting YANG-based protocols like NETCONF and RESTCONF is much
+ easier.
As important as shifting to a model-driven management paradigm, the new
northbound architecture also introduces the concept of configuration
diff --git a/doc/developer/northbound/demos.rst b/doc/developer/northbound/demos.rst
index 876bd25222..8a0f6ad6b2 100644
--- a/doc/developer/northbound/demos.rst
+++ b/doc/developer/northbound/demos.rst
@@ -1,3 +1,6 @@
+Demos
+=====
+
Transactional CLI
-----------------
diff --git a/doc/developer/northbound/links.rst b/doc/developer/northbound/links.rst
index e80374c57b..6cec176f8b 100644
--- a/doc/developer/northbound/links.rst
+++ b/doc/developer/northbound/links.rst
@@ -1,3 +1,6 @@
+Links
+=====
+
RFCs
~~~~
diff --git a/doc/developer/northbound/northbound.rst b/doc/developer/northbound/northbound.rst
index 7dddf06460..c5f4e2f7e6 100644
--- a/doc/developer/northbound/northbound.rst
+++ b/doc/developer/northbound/northbound.rst
@@ -11,11 +11,11 @@ Northbound API
transactional-cli
retrofitting-configuration-commands
operational-data-rpcs-and-notifications
- plugins-sysrepo
advanced-topics
yang-tools
yang-module-translator
demos
links
+ plugins-sysrepo
ppr-basic-test-topology
ppr-mpls-basic-test-topology
diff --git a/doc/developer/northbound/operational-data-rpcs-and-notifications.rst b/doc/developer/northbound/operational-data-rpcs-and-notifications.rst
index 554bc17c80..5cb70ca6f1 100644
--- a/doc/developer/northbound/operational-data-rpcs-and-notifications.rst
+++ b/doc/developer/northbound/operational-data-rpcs-and-notifications.rst
@@ -1,3 +1,11 @@
+Operational Data, RPCs and Notifications
+========================================
+
+.. contents:: Table of contents
+ :local:
+ :backlinks: entry
+ :depth: 1
+
Operational data
~~~~~~~~~~~~~~~~
@@ -330,10 +338,12 @@ CLI can take too long, potentially long enough to the point of
triggering some protocol timeouts and bringing sessions down.
To avoid this kind of problem, northbound clients are encouraged to do
-one of the following: \* Create a separate pthread for handling requests
-to fetch operational data. \* Iterate over YANG lists and leaf-lists
-asynchronously, returning a maximum number of elements per time instead
-of returning all elements in one shot.
+one of the following:
+
+* Create a separate pthread for handling requests to fetch operational data.
+
+* Iterate over YANG lists and leaf-lists asynchronously, returning a maximum
+ number of elements per time instead of returning all elements in one shot.
In order to handle both cases correctly, the ``get_next`` callbacks need
to use locks to prevent the YANG lists from being modified while they
diff --git a/doc/developer/northbound/plugins-sysrepo.rst b/doc/developer/northbound/plugins-sysrepo.rst
index 186c3a0177..1797157573 100644
--- a/doc/developer/northbound/plugins-sysrepo.rst
+++ b/doc/developer/northbound/plugins-sysrepo.rst
@@ -1,3 +1,6 @@
+Plugins Sysrepo (old)
+=====================
+
Installation
------------
diff --git a/doc/developer/northbound/ppr-basic-test-topology.rst b/doc/developer/northbound/ppr-basic-test-topology.rst
index a680ed7dfa..4929c9b285 100644
--- a/doc/developer/northbound/ppr-basic-test-topology.rst
+++ b/doc/developer/northbound/ppr-basic-test-topology.rst
@@ -1,15 +1,10 @@
-Table of Contents
-~~~~~~~~~~~~~~~~~
+IS-IS PPR Basic
+===============
-- `Software <#software>`__
-- `Topology <#topology>`__
-- `Configuration <#configuration>`__
-
- - `CLI <#configuration-cli>`__
- - `YANG <#configuration-yang>`__
-
-- `Verification - Control Plane <#verification-cplane>`__
-- `Verification - Forwarding Plane <#verification-fplane>`__
+.. contents:: Table of contents
+ :local:
+ :backlinks: entry
+ :depth: 2
Software
~~~~~~~~
diff --git a/doc/developer/northbound/ppr-mpls-basic-test-topology.rst b/doc/developer/northbound/ppr-mpls-basic-test-topology.rst
index cedb795da9..aceec5fa2f 100644
--- a/doc/developer/northbound/ppr-mpls-basic-test-topology.rst
+++ b/doc/developer/northbound/ppr-mpls-basic-test-topology.rst
@@ -1,15 +1,10 @@
-Table of Contents
-~~~~~~~~~~~~~~~~~
+IS-IS PPR Basic MPLS
+====================
-- `Software <#software>`__
-- `Topology <#topology>`__
-- `Configuration <#configuration>`__
-
- - `CLI <#configuration-cli>`__
- - `YANG <#configuration-yang>`__
-
-- `Verification - Control Plane <#verification-cplane>`__
-- `Verification - Forwarding Plane <#verification-fplane>`__
+.. contents:: Table of contents
+ :local:
+ :backlinks: entry
+ :depth: 2
Software
~~~~~~~~
diff --git a/doc/developer/northbound/retrofitting-configuration-commands.rst b/doc/developer/northbound/retrofitting-configuration-commands.rst
index 6ccc578a0d..4772610856 100644
--- a/doc/developer/northbound/retrofitting-configuration-commands.rst
+++ b/doc/developer/northbound/retrofitting-configuration-commands.rst
@@ -2,7 +2,15 @@
.. _nb-retrofit:
Retrofitting Configuration Commands
------------------------------------
+===================================
+
+.. contents:: Table of contents
+ :local:
+ :backlinks: entry
+ :depth: 2
+
+Retrofitting process
+--------------------
This page explains how to convert existing CLI configuration commands to
the new northbound model. This documentation is meant to be the primary
@@ -10,9 +18,6 @@ reference for developers working on the northbound retrofitting process.
We’ll show several examples taken from the ripd northbound conversion to
illustrate some concepts described herein.
-Retrofitting process
---------------------
-
Step 1: writing a YANG module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -33,34 +38,41 @@ possible to facilitate the process of writing module translators using
the [[YANG module translator]]. As an example, the frr-ripd YANG module
incorporated several parts of the IETF RIP YANG module. The repositories
below contain big collections of YANG models that might be used as a
-reference: \* https://github.com/YangModels/yang \*
-https://github.com/openconfig/public
+reference:
+
+* https://github.com/YangModels/yang
+
+* https://github.com/openconfig/public
When writing a YANG module, it’s highly recommended to follow the
guidelines from `RFC 6087 <https://tools.ietf.org/html/rfc6087>`__. In
general, most commands should be modeled fairly easy. Here are a few
-guidelines specific to authors of FRR YANG models: \* Use
-presence-containers or lists to model commands that change the CLI node
-(e.g. ``router rip``, ``interface eth0``). This way, if the
-presence-container or list entry is removed, all configuration options
-below them are removed automatically (exactly like the CLI behaves when
-a configuration object is removed using a *no* command). This
-recommendation is orthogonal to the `YANG authoring guidelines for
-OpenConfig
-models <https://github.com/openconfig/public/blob/master/doc/openconfig_style_guide.md>`__
-where the use of presence containers is discouraged. OpenConfig YANG
-models however were not designed to replicate the behavior of legacy CLI
-commands. \* When using YANG lists, be careful to identify what should
-be the key leaves. In the ``offset-list WORD <in|out> (0-16) IFNAME``
-command, for example, both the direction (``<in|out>``) and the
-interface name should be the keys of the list. This can be only known by
-analyzing the data structures used to store the commands. \* For
-clarity, use non-presence containers to group leaves that are associated
-to the same configuration command (as we’ll see later, this also
-facilitate the process of writing ``cli_show`` callbacks). \* YANG
-leaves of type *enumeration* should define explicitly the value of each
-*enum* option based on the value used in the FRR source code. \* Default
-values should be taken from the source code whenever they exist.
+guidelines specific to authors of FRR YANG models:
+
+* Use presence-containers or lists to model commands that change the CLI node
+ (e.g. ``router rip``, ``interface eth0``). This way, if the presence-container
+ or list entry is removed, all configuration options below them are removed
+ automatically (exactly like the CLI behaves when a configuration object is
+ removed using a *no* command). This recommendation is orthogonal to the `YANG
+ authoring guidelines for OpenConfig models
+ <https://github.com/openconfig/public/blob/master/doc/openconfig_style_guide.md>`__
+ where the use of presence containers is discouraged. OpenConfig YANG models
+ however were not designed to replicate the behavior of legacy CLI commands.
+
+* When using YANG lists, be careful to identify what should be the key leaves.
+ In the ``offset-list WORD <in|out> (0-16) IFNAME`` command, for example, both
+ the direction (``<in|out>``) and the interface name should be the keys of the
+ list. This can be only known by analyzing the data structures used to store
+ the commands.
+
+* For clarity, use non-presence containers to group leaves that are associated
+ to the same configuration command (as we’ll see later, this also facilitate
+ the process of writing ``cli_show`` callbacks).
+
+* YANG leaves of type *enumeration* should define explicitly the value of each
+ *enum* option based on the value used in the FRR source code.
+
+* Default values should be taken from the source code whenever they exist.
Some commands are more difficult to model and demand the use of more
advanced YANG constructs like *choice*, *when* and *must* statements.
@@ -729,15 +741,17 @@ Configuration options are edited individually
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Several CLI commands edit multiple configuration options at the same
-time. Some examples taken from ripd: \*
-``timers basic (5-2147483647) (5-2147483647) (5-2147483647)`` -
-*/frr-ripd:ripd/instance/timers/flush-interval* -
-*/frr-ripd:ripd/instance/timers/holddown-interval* -
-*/frr-ripd:ripd/instance/timers/update-interval* \*
-``distance (1-255) A.B.C.D/M [WORD]`` -
-*/frr-ripd:ripd/instance/distance/source/prefix* -
-*/frr-ripd:ripd/instance/distance/source/distance* -
-*/frr-ripd:ripd/instance/distance/source/access-list*
+time. Some examples taken from ripd:
+
+* ``timers basic (5-2147483647) (5-2147483647) (5-2147483647)``
+ * */frr-ripd:ripd/instance/timers/flush-interval*
+ * */frr-ripd:ripd/instance/timers/holddown-interval*
+ * */frr-ripd:ripd/instance/timers/update-interval*
+
+* ``distance (1-255) A.B.C.D/M [WORD]``
+ * */frr-ripd:ripd/instance/distance/source/prefix*
+ * */frr-ripd:ripd/instance/distance/source/distance*
+ * */frr-ripd:ripd/instance/distance/source/access-list*
In the new northbound model, there’s one or more separate callbacks for
each configuration option. This usually has implications when converting
@@ -1037,16 +1051,23 @@ changing the candidate configuration.
the northbound callbacks are not involved).
Other important details to keep in mind while rewriting the CLI
-commands: \* ``nb_cli_cfg_change()`` returns CLI errors codes
-(e.g. ``CMD_SUCCESS``, ``CMD_WARNING``), so the return value of this
-function can be used as the return value of CLI commands. \* Calls to
-``VTY_PUSH_CONTEXT`` and ``VTY_PUSH_CONTEXT_SUB`` should be converted to
-calls to ``VTY_PUSH_XPATH``. Similarly, the following macros aren’t
-necessary anymore and can be removed: ``VTY_DECLVAR_CONTEXT``,
-``VTY_DECLVAR_CONTEXT_SUB``, ``VTY_GET_CONTEXT`` and
-``VTY_CHECK_CONTEXT``. The ``nb_cli_cfg_change()`` functions uses the
-``VTY_CHECK_XPATH`` macro to check if the data node being edited still
-exists before doing anything else.
+commands:
+
+* ``nb_cli_cfg_change()`` returns CLI errors codes (e.g. ``CMD_SUCCESS``,
+ ``CMD_WARNING``), so the return value of this function can be used as the
+ return value of CLI commands.
+
+* Calls to ``VTY_PUSH_CONTEXT`` and ``VTY_PUSH_CONTEXT_SUB`` should be converted
+ to calls to ``VTY_PUSH_XPATH``. Similarly, the following macros aren’t
+ necessary anymore and can be removed:
+
+ * ``VTY_DECLVAR_CONTEXT``
+ * ``VTY_DECLVAR_CONTEXT_SUB``
+ * ``VTY_GET_CONTEXT``
+ * ``VTY_CHECK_CONTEXT``.
+
+ The ``nb_cli_cfg_change()`` functions uses the ``VTY_CHECK_XPATH`` macro to
+ check if the data node being edited still exists before doing anything else.
The examples below provide additional details about how the conversion
should be done.
@@ -1788,10 +1809,13 @@ Implementation of the ``cli_show`` callback:
}
This is the most complex ``cli_show`` callback we have in ripd. Its
-complexity comes from the following: \* The
-``ip rip authentication mode ...`` command changes two YANG leaves at
-the same time. \* Part of the command should be hidden when the
-``show_defaults`` parameter is set to false.
+complexity comes from the following:
+
+* The ``ip rip authentication mode ...`` command changes two YANG leaves at the
+ same time.
+
+* Part of the command should be hidden when the ``show_defaults`` parameter is
+ set to false.
This is the behavior we want to implement:
@@ -1841,19 +1865,27 @@ As mentioned in the fourth step, the northbound retrofitting process can
happen gradually over time, since both “old” and “new” commands can
coexist without problems. Once all commands from a given daemon were
converted, we can proceed to the consolidation step, which consists of
-the following: \* Remove the vty configuration lock, which is enabled by
-default in all daemons. Now multiple users should be able to edit the
-configuration concurrently, using either shared or private candidate
-configurations. \* Reference commit:
-`57dccdb1 <https://github.com/opensourcerouting/frr/commit/57dccdb18b799556214dcfb8943e248c0bf1f6a6>`__.
-\* Stop using the qobj infrastructure to keep track of configuration
-objects. This is not necessary anymore, the northbound uses a similar
-mechanism to keep track of YANG data nodes in the candidate
-configuration. \* Reference commit:
-`4e6d63ce <https://github.com/opensourcerouting/frr/commit/4e6d63cebd988af650c1c29d0f2e5a251c8d2e7a>`__.
-\* Make the daemon SIGHUP handler re-read the configuration file (and
-ensure it’s not doing anything other than that). \* Reference commit:
-`5e57edb4 <https://github.com/opensourcerouting/frr/commit/5e57edb4b71ff03f9a22d9ec1412c3c5167f90cf>`__.
+the following:
+
+* Remove the vty configuration lock, which is enabled by default in all daemons.
+ Now multiple users should be able to edit the configuration concurrently,
+ using either shared or private candidate configurations.
+
+* Reference commit: `57dccdb1
+ <https://github.com/opensourcerouting/frr/commit/57dccdb18b799556214dcfb8943e248c0bf1f6a6>`__.
+
+* Stop using the qobj infrastructure to keep track of configuration objects.
+ This is not necessary anymore, the northbound uses a similar mechanism to keep
+ track of YANG data nodes in the candidate configuration.
+
+* Reference commit: `4e6d63ce
+ <https://github.com/opensourcerouting/frr/commit/4e6d63cebd988af650c1c29d0f2e5a251c8d2e7a>`__.
+
+* Make the daemon SIGHUP handler re-read the configuration file (and ensure it’s
+ not doing anything other than that).
+
+* Reference commit: `5e57edb4
+ <https://github.com/opensourcerouting/frr/commit/5e57edb4b71ff03f9a22d9ec1412c3c5167f90cf>`__.
Final Considerations
--------------------
diff --git a/doc/developer/northbound/transactional-cli.rst b/doc/developer/northbound/transactional-cli.rst
index 439bb6afce..5c495d3a89 100644
--- a/doc/developer/northbound/transactional-cli.rst
+++ b/doc/developer/northbound/transactional-cli.rst
@@ -1,25 +1,10 @@
-Table of Contents
------------------
-
-- `Introduction <#introduction>`__
-- `Configuration modes <#config-modes>`__
-- `New commands <#retrofitting-process>`__
-
- - `commit check <#cmd1>`__
- - `commit <#cmd2>`__
- - `discard <#cmd3>`__
- - `configuration database max-transactions <#cmd4>`__
- - `configuration load <#cmd5>`__
- - `rollback configuration <#cmd6>`__
- - `show configuration candidate <#cmd7>`__
- - `show configuration compare <#cmd8>`__
- - `show configuration running <#cmd9>`__
- - `show configuration transaction <#cmd10>`__
- - `show yang module <#cmd11>`__
- - `show yang module-translator <#cmd12>`__
- - `update <#cmd13>`__
- - `yang module-translator load <#cmd14>`__
- - `yang module-translator unload <#cmd15>`__
+Transactional CLI
+=================
+
+.. contents:: Table of contents
+ :local:
+ :backlinks: entry
+ :depth: 1
Introduction
~~~~~~~~~~~~
@@ -70,18 +55,21 @@ Configuration modes
~~~~~~~~~~~~~~~~~~~
When using the transactional CLI (``--tcli``), FRR supports three
-different forms of the ``configure`` command: \* ``configure terminal``:
-in this mode, a single candidate configuration is shared by all users.
-This means that one user might delete a configuration object that’s
-being edited by another user, in which case the CLI will detect and
-report the problem. If one user issues the ``commit`` command, all
-changes done by all users are committed. \* ``configure private``: users
-have a private candidate configuration that is edited separately from
-the other users. The ``commit`` command commits only the changes done by
-the user. \* ``configure exclusive``: similar to ``configure private``,
-but also locks the running configuration to prevent other users from
-changing it. The configuration lock is released when the user exits the
-configuration mode.
+different forms of the ``configure`` command:
+
+* ``configure terminal``: in this mode, a single candidate configuration is
+ shared by all users. This means that one user might delete a configuration
+ object that’s being edited by another user, in which case the CLI will detect
+ and report the problem. If one user issues the ``commit`` command, all changes
+ done by all users are committed.
+
+* ``configure private``: users have a private candidate configuration that is
+ edited separately from the other users. The ``commit`` command commits only
+ the changes done by the user.
+
+* ``configure exclusive``: similar to ``configure private``, but also locks the
+ running configuration to prevent other users from changing it. The
+ configuration lock is released when the user exits the configuration mode.
When using ``configure terminal`` or ``configure private``, the
candidate configuration being edited might become outdated if another
@@ -112,12 +100,14 @@ Check if the candidate configuration is valid or not.
Commit the changes done in the candidate configuration into the running
configuration.
-Options: \* ``force``: commit even if the candidate configuration is
-outdated. It’s usually a better option to use the ``update`` command
-instead. \* ``comment LINE...``: assign a comment to the configuration
-transaction. This comment is displayed when viewing the recorded
-transactions in the output of the ``show configuration transaction``
-command.
+Options:
+
+* ``force``: commit even if the candidate configuration is outdated. It’s
+ usually a better option to use the ``update`` command instead.
+
+* ``comment LINE...``: assign a comment to the configuration transaction. This
+ comment is displayed when viewing the recorded transactions in the output of
+ the ``show configuration transaction`` command.
``discard``
'''''''''''
@@ -140,10 +130,13 @@ respectively. It’s also possible to load a configuration from a previous
transaction by specifying the desired transaction ID
(``(1-4294967296)``).
-Options: \* ``translate WORD``: translate the JSON/XML configuration
-file using the YANG module translator. \* ``replace``: replace the
-candidate by the loaded configuration. The default is to merge the
-loaded configuration into the candidate configuration.
+Options:
+
+* ``translate WORD``: translate the JSON/XML configuration file using the YANG
+ module translator.
+
+* ``replace``: replace the candidate by the loaded configuration. The default is
+ to merge the loaded configuration into the candidate configuration.
``rollback configuration (1-4294967296)``
'''''''''''''''''''''''''''''''''''''''''
@@ -156,39 +149,42 @@ identified by its transaction ID (``(1-4294967296)``).
Show the candidate configuration.
-Options: \* ``json``: show the configuration in the JSON format. \*
-``xml``: show the configuration in the XML format. \*
-``translate WORD``: translate the JSON/XML output using the YANG module
-translator. \* ``with-defaults``: show default values that are hidden by
-default. \* ``changes``: show only the changes done in the candidate
-configuration.
+Options:
+
+* ``json``: show the configuration in the JSON format.
+* ``xml``: show the configuration in the XML format.
+* ``translate WORD``: translate the JSON/XML output using the YANG module translator.
+* ``with-defaults``: show default values that are hidden by default.
+* ``changes``: show only the changes done in the candidate configuration.
``show configuration compare <candidate|running|transaction (1-4294967296)> <candidate|running|transaction (1-4294967296)> [<json|xml> [translate WORD]]``
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Show the difference between two different configurations.
-Options: \* ``json``: show the configuration differences in the JSON
-format. \* ``xml``: show the configuration differences in the XML
-format. \* ``translate WORD``: translate the JSON/XML output using the
-YANG module translator.
+Options:
+
+* ``json``: show the configuration differences in the JSON format.
+* ``xml``: show the configuration differences in the XML format.
+* ``translate WORD``: translate the JSON/XML output using the YANG module translator.
``show configuration running [<json|xml> [translate WORD]] [with-defaults]``
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Show the running configuration.
-Options: \* ``json``: show the configuration in the JSON format. \*
-``xml``: show the configuration in the XML format. \*
-``translate WORD``: translate the JSON/XML output using the YANG module
-translator. \* ``with-defaults``: show default values that are hidden by
-default.
+Options:
- NOTE: ``show configuration running`` shows only the running
- configuration as known by the northbound layer. Configuration
- commands not converted to the new northbound model will not be
- displayed. To show the full running configuration, the legacy
- ``show running-config`` command must be used.
+* ``json``: show the configuration in the JSON format.
+* ``xml``: show the configuration in the XML format.
+* ``translate WORD``: translate the JSON/XML output using the YANG module translator.
+* ``with-defaults``: show default values that are hidden by default.
+
+NOTE: ``show configuration running`` shows only the running
+configuration as known by the northbound layer. Configuration
+commands not converted to the new northbound model will not be
+displayed. To show the full running configuration, the legacy
+``show running-config`` command must be used.
``show configuration transaction [(1-4294967296) [<json|xml> [translate WORD]] [changes]]``
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
@@ -199,12 +195,13 @@ configuration associated to the previously committed transaction.
When a transaction ID is not given, show all recorded transactions in
the rollback log.
-Options: \* ``json``: show the configuration in the JSON format. \*
-``xml``: show the configuration in the XML format. \*
-``translate WORD``: translate the JSON/XML output using the YANG module
-translator. \* ``with-defaults``: show default values that are hidden by
-default. \* ``changes``: show changes compared to the previous
-transaction.
+Options:
+
+* ``json``: show the configuration in the JSON format.
+* ``xml``: show the configuration in the XML format.
+* ``translate WORD``: translate the JSON/XML output using the YANG module translator.
+* ``with-defaults``: show default values that are hidden by default.
+* ``changes``: show changes compared to the previous transaction.
``show yang module [module-translator WORD] [WORD <summary|tree|yang|yin>]``
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
@@ -212,11 +209,14 @@ transaction.
When a YANG module is not given, show all loaded YANG modules.
Otherwise, show detailed information about the given module.
-Options: \* ``module-translator WORD``: change the context to modules
-loaded by the specified YANG module translator. \* ``summary``: display
-summary information about the module. \* ``tree``: display module in the
-tree (RFC 8340) format. \* ``yang``: display module in the YANG format.
-\* ``yin``: display module in the YIN format.
+Options:
+
+* ``module-translator WORD``: change the context to modules loaded by the
+ specified YANG module translator.
+* ``summary``: display summary information about the module.
+* ``tree``: display module in the tree (RFC 8340) format.
+* ``yang``: display module in the YANG format.
+* ``yin``: display module in the YIN format.
``show yang module-translator``
'''''''''''''''''''''''''''''''
diff --git a/doc/developer/northbound/yang-module-translator.rst b/doc/developer/northbound/yang-module-translator.rst
index aa527ce6b2..17ae160f07 100644
--- a/doc/developer/northbound/yang-module-translator.rst
+++ b/doc/developer/northbound/yang-module-translator.rst
@@ -1,11 +1,10 @@
-Table of Contents
------------------
+YANG Module Translation
+=======================
-- `Introduction <#introduction>`__
-- `Deviation Modules <#deviation-modules>`__
-- `Translation Tables <#translation-tables>`__
-- `CLI Demonstration <#cli-demonstration>`__
-- `Implementation Details <#implementation-details>`__
+.. contents:: Table of contents
+ :local:
+ :backlinks: entry
+ :depth: 1
Introduction
------------
@@ -421,15 +420,20 @@ this shortcoming and make it possible to create more powerful YANG
module translators.
YANG module translators can be evaluated based on the following metrics:
-\* Translation potential: is it possible to make complex translations,
-taking several variables into account? \* Complexity: measure of how
-easy or hard it is to write a module translator. \* Speed: measure of
-how fast the translation can be achieved. Translation speed is of
-fundamental importance, especially for operational data. \* Robustness:
-can the translator be checked for inconsistencies at load time? A module
-translator based on scripts wouldn’t fare well on this metric. \*
-Round-trip conversions: can the translated data be translated back to
-the original format without information loss?
+
+* Translation potential: is it possible to make complex translations, taking
+ several variables into account?
+
+* Complexity: measure of how easy or hard it is to write a module translator.
+
+* Speed: measure of how fast the translation can be achieved. Translation speed
+ is of fundamental importance, especially for operational data.
+
+* Robustness: can the translator be checked for inconsistencies at load time? A
+ module translator based on scripts wouldn’t fare well on this metric.
+
+* Round-trip conversions: can the translated data be translated back to the
+ original format without information loss?
CLI Demonstration
-----------------
diff --git a/doc/developer/northbound/yang-tools.rst b/doc/developer/northbound/yang-tools.rst
index 346efcaaee..fb5a287245 100644
--- a/doc/developer/northbound/yang-tools.rst
+++ b/doc/developer/northbound/yang-tools.rst
@@ -1,5 +1,5 @@
Yang Tools
-~~~~~~~~~~
+==========
Here's some information about various tools for working with yang
models.
@@ -83,17 +83,19 @@ Indent a YANG file:
--keep-comments -f yang --yang-canonical \
module.yang -o module.yang
-Generate skeleton instance data: \* XML:
+Generate skeleton instance data:
-.. code:: sh
+* XML:
+
+ .. code:: sh
$ pyang -p <yang-search-path> \
-f sample-xml-skeleton --sample-xml-skeleton-defaults \
module.yang [augmented-module1.yang ...] -o module.xml
-- JSON:
+* JSON:
-.. code:: sh
+ .. code:: sh
$ pyang -p <yang-search-path> \
-f jsonxsl module.yang -o module.xsl
diff --git a/lib/filter.c b/lib/filter.c
index f86adab5d6..a0adff0e35 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -885,7 +885,7 @@ static void access_list_init_ipv6(void)
install_element(ENABLE_NODE, &show_ipv6_access_list_name_cmd);
}
-void access_list_init(void)
+void access_list_init_new(bool in_backend)
{
cmd_variable_handler_register(access_list_handlers);
@@ -893,7 +893,15 @@ void access_list_init(void)
access_list_init_ipv6();
access_list_init_mac();
- filter_cli_init();
+ if (!in_backend) {
+ /* we do not want to handle config commands in the backend */
+ filter_cli_init();
+ }
+}
+
+void access_list_init(void)
+{
+ access_list_init_new(false);
}
void access_list_reset(void)
diff --git a/lib/filter.h b/lib/filter.h
index e092f0771a..bd9e22d384 100644
--- a/lib/filter.h
+++ b/lib/filter.h
@@ -114,6 +114,7 @@ struct access_master {
/* Prototypes for access-list. */
extern void access_list_init(void);
+extern void access_list_init_new(bool in_backend);
extern void access_list_reset(void);
extern void access_list_add_hook(void (*func)(struct access_list *));
extern void access_list_delete_hook(void (*func)(struct access_list *));
@@ -124,13 +125,13 @@ extern enum filter_type access_list_apply(struct access_list *access,
struct access_list *access_list_get(afi_t afi, const char *name);
void access_list_delete(struct access_list *access);
struct filter *filter_new(void);
-void access_list_filter_add(struct access_list *access,
- struct filter *filter);
+void access_list_filter_add(struct access_list *access, struct filter *filter);
void access_list_filter_delete(struct access_list *access,
struct filter *filter);
int64_t filter_new_seq_get(struct access_list *access);
extern const struct frr_yang_module_info frr_filter_info;
+extern const struct frr_yang_module_info frr_filter_cli_info;
/* filter_nb.c */
diff --git a/lib/filter_cli.c b/lib/filter_cli.c
index 529b46b6ad..28790f69e7 100644
--- a/lib/filter_cli.c
+++ b/lib/filter_cli.c
@@ -69,53 +69,60 @@ static int64_t acl_get_seq(struct vty *vty, const char *xpath, bool is_remove)
return seq;
}
-static int acl_remove_if_empty(struct vty *vty, const char *iptype,
- const char *name)
+/**
+ * Remove main data structure filter list if there are no more entries or
+ * remark. This fixes compatibility with old CLI and tests.
+ */
+static int filter_remove_check_empty(struct vty *vty, const char *ftype,
+ const char *iptype, const char *name,
+ uint32_t del_seq, bool del_remark)
{
+ const struct lyd_node *remark_dnode = NULL;
+ const struct lyd_node *entry_dnode = NULL;
char xpath[XPATH_MAXLEN];
+ uint32_t count;
+
+ /* Count existing entries */
+ count = yang_dnode_count(vty->candidate_config->dnode,
+ "/frr-filter:lib/%s-list[type='%s'][name='%s']/entry",
+ ftype, iptype, name);
+
+ /* Check entry-to-delete actually exists */
+ if (del_seq) {
+ snprintf(xpath, sizeof(xpath),
+ "/frr-filter:lib/%s-list[type='%s'][name='%s']/entry[sequence='%u']",
+ ftype, iptype, name, del_seq);
+ entry_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ xpath);
+
+ /* If exists, delete and don't count it, we need only remaining entries */
+ if (entry_dnode) {
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ count--;
+ }
+ }
+ /* Delete the remark, or check whether it exists if we're keeping it */
snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/access-list[type='%s'][name='%s']/remark",
+ "/frr-filter:lib/%s-list[type='%s'][name='%s']/remark", ftype,
iptype, name);
- /* List is not empty if there is a remark, check that: */
- if (yang_dnode_exists(vty->candidate_config->dnode, xpath))
- return CMD_SUCCESS;
-
- /* Check if we have any entries: */
- snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/access-list[type='%s'][name='%s']", iptype,
- name);
- /*
- * NOTE: if the list is empty it will return the first sequence
- * number: 5.
- */
- if (acl_get_seq(vty, xpath, true) != 5)
- return CMD_SUCCESS;
+ if (del_remark)
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ else
+ remark_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ xpath);
+
+ /* If there are no entries left and no remark, delete the whole list */
+ if (count == 0 && !remark_dnode) {
+ snprintf(xpath, sizeof(xpath),
+ "/frr-filter:lib/%s-list[type='%s'][name='%s']", ftype,
+ iptype, name);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ }
- /* Nobody is using this list, lets remove it. */
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
-static int acl_remove(struct vty *vty, const char *iptype, const char *name,
- int64_t sseq)
-{
- char xpath[XPATH_MAXLEN];
- int rv;
-
- snprintfrr(
- xpath, sizeof(xpath),
- "/frr-filter:lib/access-list[type='%s'][name='%s']/entry[sequence='%" PRId64 "']",
- iptype, name, sseq);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- rv = nb_cli_apply_changes(vty, NULL);
- if (rv == CMD_SUCCESS)
- return acl_remove_if_empty(vty, iptype, name);
-
- return rv;
-}
-
/*
* Cisco (legacy) access lists.
*/
@@ -213,7 +220,8 @@ DEFPY_YANG(
/* If the user provided sequence number, then just go for it. */
if (seq_str != NULL)
- return acl_remove(vty, "ipv4", name, seq);
+ return filter_remove_check_empty(vty, "access", "ipv4", name,
+ seq, false);
/* Otherwise, to keep compatibility, we need to figure it out. */
ada.ada_type = "ipv4";
@@ -237,7 +245,8 @@ DEFPY_YANG(
else
return CMD_WARNING_CONFIG_FAILED;
- return acl_remove(vty, "ipv4", name, sseq);
+ return filter_remove_check_empty(vty, "access", "ipv4", name, sseq,
+ false);
}
DEFPY_YANG(
@@ -384,7 +393,8 @@ DEFPY_YANG(
/* If the user provided sequence number, then just go for it. */
if (seq_str != NULL)
- return acl_remove(vty, "ipv4", name, seq);
+ return filter_remove_check_empty(vty, "access", "ipv4", name,
+ seq, false);
/* Otherwise, to keep compatibility, we need to figure it out. */
ada.ada_type = "ipv4";
@@ -429,7 +439,8 @@ DEFPY_YANG(
else
return CMD_WARNING_CONFIG_FAILED;
- return acl_remove(vty, "ipv4", name, sseq);
+ return filter_remove_check_empty(vty, "access", "ipv4", name, sseq,
+ false);
}
/*
@@ -525,7 +536,8 @@ DEFPY_YANG(
/* If the user provided sequence number, then just go for it. */
if (seq_str != NULL)
- return acl_remove(vty, "ipv4", name, seq);
+ return filter_remove_check_empty(vty, "access", "ipv4", name,
+ seq, false);
/* Otherwise, to keep compatibility, we need to figure it out. */
ada.ada_type = "ipv4";
@@ -549,7 +561,8 @@ DEFPY_YANG(
else
return CMD_WARNING_CONFIG_FAILED;
- return acl_remove(vty, "ipv4", name, sseq);
+ return filter_remove_check_empty(vty, "access", "ipv4", name, sseq,
+ false);
}
DEFPY_YANG(
@@ -600,19 +613,7 @@ DEFPY_YANG(
ACCESS_LIST_ZEBRA_STR
ACCESS_LIST_REMARK_STR)
{
- char xpath[XPATH_MAXLEN];
- int rv;
-
- snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/access-list[type='ipv4'][name='%s']/remark",
- name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- rv = nb_cli_apply_changes(vty, NULL);
- if (rv == CMD_SUCCESS)
- return acl_remove_if_empty(vty, "ipv4", name);
-
- return rv;
+ return filter_remove_check_empty(vty, "access", "ipv4", name, 0, true);
}
ALIAS(
@@ -716,7 +717,8 @@ DEFPY_YANG(
/* If the user provided sequence number, then just go for it. */
if (seq_str != NULL)
- return acl_remove(vty, "ipv6", name, seq);
+ return filter_remove_check_empty(vty, "access", "ipv6", name,
+ seq, false);
/* Otherwise, to keep compatibility, we need to figure it out. */
ada.ada_type = "ipv6";
@@ -740,7 +742,8 @@ DEFPY_YANG(
else
return CMD_WARNING_CONFIG_FAILED;
- return acl_remove(vty, "ipv6", name, sseq);
+ return filter_remove_check_empty(vty, "access", "ipv6", name, sseq,
+ false);
}
DEFPY_YANG(
@@ -794,19 +797,7 @@ DEFPY_YANG(
ACCESS_LIST_ZEBRA_STR
ACCESS_LIST_REMARK_STR)
{
- char xpath[XPATH_MAXLEN];
- int rv;
-
- snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/access-list[type='ipv6'][name='%s']/remark",
- name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- rv = nb_cli_apply_changes(vty, NULL);
- if (rv == CMD_SUCCESS)
- return acl_remove_if_empty(vty, "ipv6", name);
-
- return rv;
+ return filter_remove_check_empty(vty, "access", "ipv6", name, 0, true);
}
ALIAS(
@@ -902,7 +893,8 @@ DEFPY_YANG(
/* If the user provided sequence number, then just go for it. */
if (seq_str != NULL)
- return acl_remove(vty, "mac", name, seq);
+ return filter_remove_check_empty(vty, "access", "mac", name,
+ seq, false);
/* Otherwise, to keep compatibility, we need to figure it out. */
ada.ada_type = "mac";
@@ -922,7 +914,8 @@ DEFPY_YANG(
else
return CMD_WARNING_CONFIG_FAILED;
- return acl_remove(vty, "mac", name, sseq);
+ return filter_remove_check_empty(vty, "access", "mac", name, sseq,
+ false);
}
DEFPY_YANG(
@@ -976,19 +969,7 @@ DEFPY_YANG(
ACCESS_LIST_ZEBRA_STR
ACCESS_LIST_REMARK_STR)
{
- char xpath[XPATH_MAXLEN];
- int rv;
-
- snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/access-list[type='mac'][name='%s']/remark",
- name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- rv = nb_cli_apply_changes(vty, NULL);
- if (rv == CMD_SUCCESS)
- return acl_remove_if_empty(vty, "mac", name);
-
- return rv;
+ return filter_remove_check_empty(vty, "access", "mac", name, 0, true);
}
ALIAS(
@@ -1149,62 +1130,17 @@ void access_list_remark_show(struct vty *vty, const struct lyd_node *dnode,
* Prefix lists.
*/
-/**
- * Remove main data structure prefix list if there are no more entries or
- * remark. This fixes compatibility with old CLI and tests.
- */
-static int plist_remove_if_empty(struct vty *vty, const char *iptype,
- const char *name)
-{
- char xpath[XPATH_MAXLEN];
-
- snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/prefix-list[type='%s'][name='%s']/remark",
- iptype, name);
- /* List is not empty if there is a remark, check that: */
- if (yang_dnode_exists(vty->candidate_config->dnode, xpath))
- return CMD_SUCCESS;
-
- /* Check if we have any entries: */
- snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/prefix-list[type='%s'][name='%s']", iptype,
- name);
- /*
- * NOTE: if the list is empty it will return the first sequence
- * number: 5.
- */
- if (acl_get_seq(vty, xpath, true) != 5)
- return CMD_SUCCESS;
-
- /* Nobody is using this list, lets remove it. */
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
- return nb_cli_apply_changes(vty, NULL);
-}
-
static int plist_remove(struct vty *vty, const char *iptype, const char *name,
- const char *seq, const char *action,
+ uint32_t seq, const char *action,
union prefixconstptr prefix, int ge, int le)
{
int64_t sseq;
struct plist_dup_args pda = {};
- char xpath[XPATH_MAXLEN];
- char xpath_entry[XPATH_MAXLEN + 32];
- int rv;
/* If the user provided sequence number, then just go for it. */
- if (seq != NULL) {
- snprintf(
- xpath, sizeof(xpath),
- "/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry[sequence='%s']",
- iptype, name, seq);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- rv = nb_cli_apply_changes(vty, NULL);
- if (rv == CMD_SUCCESS)
- return plist_remove_if_empty(vty, iptype, name);
-
- return rv;
- }
+ if (seq != 0)
+ return filter_remove_check_empty(vty, "prefix", iptype, name,
+ seq, false);
/* Otherwise, to keep compatibility, we need to figure it out. */
pda.pda_type = iptype;
@@ -1224,17 +1160,8 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name,
else
return CMD_WARNING_CONFIG_FAILED;
- snprintfrr(
- xpath_entry, sizeof(xpath_entry),
- "/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry[sequence='%" PRId64 "']",
- iptype, name, sseq);
- nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
-
- rv = nb_cli_apply_changes(vty, NULL);
- if (rv == CMD_SUCCESS)
- return plist_remove_if_empty(vty, iptype, name);
-
- return rv;
+ return filter_remove_check_empty(vty, "prefix", iptype, name, sseq,
+ false);
}
DEFPY_YANG(
@@ -1347,7 +1274,7 @@ DEFPY_YANG(
"Maximum prefix length to be matched\n"
"Maximum prefix length\n")
{
- return plist_remove(vty, "ipv4", name, seq_str, action,
+ return plist_remove(vty, "ipv4", name, seq, action,
prefix_str ? prefix : NULL, ge, le);
}
@@ -1360,7 +1287,7 @@ DEFPY_YANG(
PREFIX_LIST_NAME_STR
ACCESS_LIST_SEQ_STR)
{
- return plist_remove(vty, "ipv4", name, seq_str, NULL, NULL, 0, 0);
+ return plist_remove(vty, "ipv4", name, seq, NULL, NULL, 0, 0);
}
DEFPY_YANG(
@@ -1414,19 +1341,7 @@ DEFPY_YANG(
PREFIX_LIST_NAME_STR
ACCESS_LIST_REMARK_STR)
{
- char xpath[XPATH_MAXLEN];
- int rv;
-
- snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']/remark",
- name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- rv = nb_cli_apply_changes(vty, NULL);
- if (rv == CMD_SUCCESS)
- return plist_remove_if_empty(vty, "ipv4", name);
-
- return rv;
+ return filter_remove_check_empty(vty, "prefix", "ipv4", name, 0, true);
}
ALIAS(
@@ -1549,7 +1464,7 @@ DEFPY_YANG(
"Minimum prefix length to be matched\n"
"Minimum prefix length\n")
{
- return plist_remove(vty, "ipv6", name, seq_str, action,
+ return plist_remove(vty, "ipv6", name, seq, action,
prefix_str ? prefix : NULL, ge, le);
}
@@ -1562,7 +1477,7 @@ DEFPY_YANG(
PREFIX_LIST_NAME_STR
ACCESS_LIST_SEQ_STR)
{
- return plist_remove(vty, "ipv6", name, seq_str, NULL, NULL, 0, 0);
+ return plist_remove(vty, "ipv6", name, seq, NULL, NULL, 0, 0);
}
DEFPY_YANG(
@@ -1616,19 +1531,7 @@ DEFPY_YANG(
PREFIX_LIST_NAME_STR
ACCESS_LIST_REMARK_STR)
{
- char xpath[XPATH_MAXLEN];
- int rv;
-
- snprintf(xpath, sizeof(xpath),
- "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']/remark",
- name);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- rv = nb_cli_apply_changes(vty, NULL);
- if (rv == CMD_SUCCESS)
- return plist_remove_if_empty(vty, "ipv6", name);
-
- return rv;
+ return filter_remove_check_empty(vty, "prefix", "ipv6", name, 0, true);
}
ALIAS(
diff --git a/lib/filter_nb.c b/lib/filter_nb.c
index 1c436cc6f1..eba4e421c0 100644
--- a/lib/filter_nb.c
+++ b/lib/filter_nb.c
@@ -1785,3 +1785,35 @@ const struct frr_yang_module_info frr_filter_info = {
},
}
};
+
+const struct frr_yang_module_info frr_filter_cli_info = {
+ .name = "frr-filter",
+ .ignore_cfg_cbs = true,
+ .nodes = {
+ {
+ .xpath = "/frr-filter:lib/access-list/remark",
+ .cbs.cli_show = access_list_remark_show,
+ },
+ {
+ .xpath = "/frr-filter:lib/access-list/entry",
+ .cbs = {
+ .cli_cmp = access_list_cmp,
+ .cli_show = access_list_show,
+ }
+ },
+ {
+ .xpath = "/frr-filter:lib/prefix-list/remark",
+ .cbs.cli_show = prefix_list_remark_show,
+ },
+ {
+ .xpath = "/frr-filter:lib/prefix-list/entry",
+ .cbs = {
+ .cli_cmp = prefix_list_cmp,
+ .cli_show = prefix_list_show,
+ }
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/lib/routemap.c b/lib/routemap.c
index e8a92cda0b..6b3f81b4d4 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -3409,7 +3409,7 @@ DEFUN_HIDDEN(show_route_map_pfx_tbl, show_route_map_pfx_tbl_cmd,
}
/* Initialization of route map vector. */
-void route_map_init(void)
+void route_map_init_new(bool in_backend)
{
int i;
@@ -3424,7 +3424,10 @@ void route_map_init(void)
UNSET_FLAG(rmap_debug, DEBUG_ROUTEMAP);
- route_map_cli_init();
+ if (!in_backend) {
+ /* we do not want to handle config commands in the backend */
+ route_map_cli_init();
+ }
/* Install route map top node. */
install_node(&rmap_debug_node);
@@ -3444,3 +3447,8 @@ void route_map_init(void)
install_element(ENABLE_NODE, &show_route_map_pfx_tbl_cmd);
}
+
+void route_map_init(void)
+{
+ route_map_init_new(false);
+}
diff --git a/lib/routemap.h b/lib/routemap.h
index 08e341221d..dfb84ced5b 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -401,6 +401,7 @@ enum ecommunity_lb_type {
/* Prototypes. */
extern void route_map_init(void);
+extern void route_map_init_new(bool in_backend);
/*
* This should only be called on shutdown
@@ -1024,6 +1025,7 @@ routemap_hook_context_insert(struct route_map_index *rmi);
void routemap_hook_context_free(struct routemap_hook_context *rhc);
extern const struct frr_yang_module_info frr_route_map_info;
+extern const struct frr_yang_module_info frr_route_map_cli_info;
/* routemap_cli.c */
extern int route_map_instance_cmp(const struct lyd_node *dnode1,
diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c
index a7a77cc23b..1bba4dad47 100644
--- a/lib/routemap_northbound.c
+++ b/lib/routemap_northbound.c
@@ -1550,3 +1550,45 @@ const struct frr_yang_module_info frr_route_map_info = {
},
}
};
+
+const struct frr_yang_module_info frr_route_map_cli_info = {
+ .name = "frr-route-map",
+ .ignore_cfg_cbs = true,
+ .nodes = {
+ {
+ .xpath = "/frr-route-map:lib/route-map/optimization-disabled",
+ .cbs.cli_show = route_map_optimization_disabled_show,
+ },
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry",
+ .cbs = {
+ .cli_cmp = route_map_instance_cmp,
+ .cli_show = route_map_instance_show,
+ .cli_show_end = route_map_instance_show_end,
+ }
+ },
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/description",
+ .cbs.cli_show = route_map_description_show,
+ },
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/call",
+ .cbs.cli_show = route_map_call_show,
+ },
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/exit-policy",
+ .cbs.cli_show = route_map_exit_policy_show,
+ },
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/match-condition",
+ .cbs.cli_show = route_map_condition_show,
+ },
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/set-action",
+ .cbs.cli_show = route_map_action_show,
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/lib/vty.c b/lib/vty.c
index 3fc7c38083..a8d90d901b 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -124,6 +124,12 @@ bool vty_log_commands;
static bool vty_log_commands_perm;
char const *const mgmt_daemons[] = {
+#ifdef HAVE_RIPD
+ "ripd",
+#endif
+#ifdef HAVE_RIPNGD
+ "ripngd",
+#endif
#ifdef HAVE_STATICD
"staticd",
#endif
diff --git a/lib/yang.c b/lib/yang.c
index 7d35fb0d3d..ed855c8498 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -508,6 +508,30 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg,
ly_set_free(set, NULL);
}
+uint32_t yang_dnode_count(const struct lyd_node *dnode, const char *xpath_fmt,
+ ...)
+{
+ va_list ap;
+ char xpath[XPATH_MAXLEN];
+ struct ly_set *set;
+ uint32_t count;
+
+ va_start(ap, xpath_fmt);
+ vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+ va_end(ap);
+
+ if (lyd_find_xpath(dnode, xpath, &set)) {
+ assert(0);
+ return 0;
+ }
+
+ count = set->count;
+
+ ly_set_free(set, NULL);
+
+ return count;
+}
+
bool yang_dnode_is_default(const struct lyd_node *dnode, const char *xpath)
{
const struct lysc_node *snode;
diff --git a/lib/yang.h b/lib/yang.h
index dbb7f7163b..1235125f26 100644
--- a/lib/yang.h
+++ b/lib/yang.h
@@ -421,6 +421,21 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg,
...) PRINTFRR(4, 5);
/*
+ * Count the number of data nodes that satisfy an XPath query.
+ *
+ * dnode
+ * Base libyang data node to operate on.
+ *
+ * xpath_fmt
+ * XPath expression (absolute or relative).
+ *
+ * ...
+ * any parameters for xpath_fmt.
+ */
+uint32_t yang_dnode_count(const struct lyd_node *dnode, const char *xpath_fmt,
+ ...) PRINTFRR(2, 3);
+
+/*
* Check if the libyang data node contains a default value. Non-presence
* containers are assumed to always contain a default value.
*
diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c
index c8f52a101c..2ebbe255d0 100644
--- a/mgmtd/mgmt_be_adapter.c
+++ b/mgmtd/mgmt_be_adapter.c
@@ -36,6 +36,12 @@
const char *mgmt_be_client_names[MGMTD_BE_CLIENT_ID_MAX + 1] = {
[MGMTD_BE_CLIENT_ID_ZEBRA] = "zebra",
+#ifdef HAVE_RIPD
+ [MGMTD_BE_CLIENT_ID_RIPD] = "ripd",
+#endif
+#ifdef HAVE_RIPNGD
+ [MGMTD_BE_CLIENT_ID_RIPNGD] = "ripngd",
+#endif
#ifdef HAVE_STATICD
[MGMTD_BE_CLIENT_ID_STATICD] = "staticd",
#endif
@@ -58,6 +64,37 @@ struct mgmt_be_xpath_map {
* Each client gets their own map, but also union all the strings into the
* above map as well.
*/
+
+#if HAVE_RIPD
+static const char *const ripd_config_xpaths[] = {
+ "/frr-filter:lib",
+ "/frr-interface:lib/interface",
+ "/frr-ripd:ripd",
+ "/frr-route-map:lib",
+ "/frr-vrf:lib",
+ NULL,
+};
+static const char *const ripd_oper_xpaths[] = {
+ "/frr-ripd:ripd",
+ NULL,
+};
+#endif
+
+#if HAVE_RIPNGD
+static const char *const ripngd_config_xpaths[] = {
+ "/frr-filter:lib",
+ "/frr-interface:lib/interface",
+ "/frr-ripngd:ripngd",
+ "/frr-route-map:lib",
+ "/frr-vrf:lib",
+ NULL,
+};
+static const char *const ripngd_oper_xpaths[] = {
+ "/frr-ripngd:ripngd",
+ NULL,
+};
+#endif
+
#if HAVE_STATICD
static const char *const staticd_config_xpaths[] = {
"/frr-vrf:lib",
@@ -68,6 +105,12 @@ static const char *const staticd_config_xpaths[] = {
#endif
static const char *const *be_client_config_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
+#ifdef HAVE_RIPD
+ [MGMTD_BE_CLIENT_ID_RIPD] = ripd_config_xpaths,
+#endif
+#ifdef HAVE_RIPNGD
+ [MGMTD_BE_CLIENT_ID_RIPNGD] = ripngd_config_xpaths,
+#endif
#ifdef HAVE_STATICD
[MGMTD_BE_CLIENT_ID_STATICD] = staticd_config_xpaths,
#endif
@@ -81,6 +124,12 @@ static const char *const zebra_oper_xpaths[] = {
};
static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
+#ifdef HAVE_RIPD
+ [MGMTD_BE_CLIENT_ID_RIPD] = ripd_oper_xpaths,
+#endif
+#ifdef HAVE_RIPNGD
+ [MGMTD_BE_CLIENT_ID_RIPNGD] = ripngd_oper_xpaths,
+#endif
[MGMTD_BE_CLIENT_ID_ZEBRA] = zebra_oper_xpaths,
};
@@ -318,7 +367,7 @@ static int mgmt_be_send_subscr_reply(struct mgmt_be_client_adapter *adapter,
be_msg.message_case = MGMTD__BE_MESSAGE__MESSAGE_SUBSCR_REPLY;
be_msg.subscr_reply = &reply;
- MGMTD_FE_CLIENT_DBG("Sending SUBSCR_REPLY client: %s sucess: %u",
+ MGMTD_BE_CLIENT_DBG("Sending SUBSCR_REPLY client: %s sucess: %u",
adapter->name, success);
return mgmt_be_adapter_send_msg(adapter, &be_msg);
@@ -608,27 +657,16 @@ static void mgmt_be_adapter_conn_init(struct event *thread)
assert(adapter && adapter->conn->fd >= 0);
/*
- * Check first if the current session can run a CONFIG
- * transaction or not. Reschedule if a CONFIG transaction
- * from another session is already in progress.
- */
- if (mgmt_config_txn_in_progress() != MGMTD_SESSION_ID_NONE) {
- zlog_err("XXX txn in progress, retry init");
- mgmt_be_adapter_sched_init_event(adapter);
- return;
- }
-
- /*
* Notify TXN module to create a CONFIG transaction and
* download the CONFIGs identified for this new client.
* If the TXN module fails to initiate the CONFIG transaction
- * disconnect from the client forcing a reconnect later.
- * That should also take care of destroying the adapter.
+ * retry a bit later. It only fails if there's an existing config
+ * transaction in progress.
*/
if (mgmt_txn_notify_be_adapter_conn(adapter, true) != 0) {
- zlog_err("XXX notify be adapter conn fail");
- msg_conn_disconnect(adapter->conn, false);
- adapter = NULL;
+ zlog_err("XXX txn in progress, retry init");
+ mgmt_be_adapter_sched_init_event(adapter);
+ return;
}
}
diff --git a/mgmtd/mgmt_be_adapter.h b/mgmtd/mgmt_be_adapter.h
index 3407d4c6a7..955291b7c8 100644
--- a/mgmtd/mgmt_be_adapter.h
+++ b/mgmtd/mgmt_be_adapter.h
@@ -17,7 +17,7 @@
#define MGMTD_BE_CONN_INIT_DELAY_MSEC 50
-#define MGMTD_FIND_ADAPTER_BY_INDEX(adapter_index) \
+#define MGMTD_FIND_ADAPTER_BY_INDEX(adapter_index) \
mgmt_adaptr_ref[adapter_index]
/**
@@ -27,6 +27,12 @@
* #ifdef HAVE_COMPONENT
*/
enum mgmt_be_client_id {
+#ifdef HAVE_RIPD
+ MGMTD_BE_CLIENT_ID_RIPD,
+#endif
+#ifdef HAVE_RIPNGD
+ MGMTD_BE_CLIENT_ID_RIPNGD,
+#endif
#ifdef HAVE_STATICD
MGMTD_BE_CLIENT_ID_STATICD,
#endif
diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c
index d91987d888..ff85f56e3e 100644
--- a/mgmtd/mgmt_fe_adapter.c
+++ b/mgmtd/mgmt_fe_adapter.c
@@ -724,7 +724,7 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
if (session->cfg_txn_id == MGMTD_TXN_ID_NONE) {
/* as we have the lock no-one else should have a config txn */
- assert(mgmt_config_txn_in_progress() == MGMTD_SESSION_ID_NONE);
+ assert(!mgmt_config_txn_in_progress());
/* Start a CONFIG Transaction (if not started already) */
session->cfg_txn_id = mgmt_create_txn(session->session_id,
@@ -890,6 +890,9 @@ static int mgmt_fe_session_handle_commit_config_req_msg(
}
if (session->cfg_txn_id == MGMTD_TXN_ID_NONE) {
+ /* as we have the lock no-one else should have a config txn */
+ assert(!mgmt_config_txn_in_progress());
+
/*
* Start a CONFIG Transaction (if not started already)
*/
diff --git a/mgmtd/mgmt_main.c b/mgmtd/mgmt_main.c
index 743091e5c4..1bb1299444 100644
--- a/mgmtd/mgmt_main.c
+++ b/mgmtd/mgmt_main.c
@@ -14,6 +14,8 @@
#include "frr_pthread.h"
#include "mgmtd/mgmt.h"
#include "mgmtd/mgmt_ds.h"
+#include "ripd/rip_nb.h"
+#include "ripngd/ripng_nb.h"
#include "routing_nb.h"
@@ -138,7 +140,7 @@ static struct frr_signal_t mgmt_signals[] = {
};
#ifdef HAVE_STATICD
-extern const struct frr_yang_module_info frr_staticd_info;
+extern const struct frr_yang_module_info frr_staticd_cli_info;
#endif
@@ -170,9 +172,9 @@ const struct frr_yang_module_info zebra_route_map_info = {
* MGMTd.
*/
static const struct frr_yang_module_info *const mgmt_yang_modules[] = {
- &frr_filter_info,
+ &frr_filter_cli_info,
&frr_interface_info,
- &frr_route_map_info,
+ &frr_route_map_cli_info,
&frr_routing_info,
&frr_vrf_info,
@@ -184,8 +186,14 @@ static const struct frr_yang_module_info *const mgmt_yang_modules[] = {
&affinity_map_info,
&zebra_route_map_info,
+#ifdef HAVE_RIPD
+ &frr_ripd_cli_info,
+#endif
+#ifdef HAVE_RIPNGD
+ &frr_ripngd_cli_info,
+#endif
#ifdef HAVE_STATICD
- &frr_staticd_info,
+ &frr_staticd_cli_info,
#endif
};
diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c
index c19b39c696..7f88524e85 100644
--- a/mgmtd/mgmt_txn.c
+++ b/mgmtd/mgmt_txn.c
@@ -32,7 +32,6 @@ enum mgmt_txn_event {
MGMTD_TXN_PROC_GETTREE,
MGMTD_TXN_COMMITCFG_TIMEOUT,
MGMTD_TXN_GETTREE_TIMEOUT,
- MGMTD_TXN_CLEANUP
};
PREDECL_LIST(mgmt_txn_reqs);
@@ -281,6 +280,8 @@ static struct mgmt_master *mgmt_txn_mm;
static void mgmt_txn_register_event(struct mgmt_txn_ctx *txn,
enum mgmt_txn_event event);
+static void mgmt_txn_cleanup_txn(struct mgmt_txn_ctx **txn);
+
static struct mgmt_txn_be_cfg_batch *
mgmt_txn_cfg_batch_alloc(struct mgmt_txn_ctx *txn, enum mgmt_be_client_id id,
struct mgmt_be_client_adapter *be_adapter)
@@ -409,7 +410,6 @@ static struct mgmt_txn_req *mgmt_txn_req_alloc(struct mgmt_txn_ctx *txn,
break;
case MGMTD_TXN_COMMITCFG_TIMEOUT:
case MGMTD_TXN_GETTREE_TIMEOUT:
- case MGMTD_TXN_CLEANUP:
break;
}
@@ -518,7 +518,6 @@ static void mgmt_txn_req_free(struct mgmt_txn_req **txn_req)
break;
case MGMTD_TXN_COMMITCFG_TIMEOUT:
case MGMTD_TXN_GETTREE_TIMEOUT:
- case MGMTD_TXN_CLEANUP:
break;
}
@@ -781,7 +780,7 @@ static int mgmt_txn_send_commit_cfg_reply(struct mgmt_txn_ctx *txn,
* we need to cleanup by itself.
*/
if (!txn->session_id)
- mgmt_txn_register_event(txn, MGMTD_TXN_CLEANUP);
+ mgmt_txn_cleanup_txn(&txn);
return 0;
}
@@ -925,7 +924,6 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
MGMTD__YANG_DATA_VALUE__VALUE_ENCODED_STR_VAL;
batch->value[batch->num_cfg_data].encoded_str_val =
value;
- value = NULL;
MGMTD_TXN_DBG(" -- %s, batch item:%d", adapter->name,
(int)batch->num_cfg_data);
@@ -1456,11 +1454,6 @@ static void mgmt_txn_process_commit_cfg(struct event *thread)
case MGMTD_COMMIT_PHASE_MAX:
break;
}
-
- MGMTD_TXN_DBG("txn-id:%" PRIu64 " session-id: %" PRIu64
- " phase updated to '%s'",
- txn->txn_id, txn->session_id,
- mgmt_txn_commit_phase_str(txn));
}
static void mgmt_init_get_data_reply(struct mgmt_get_data_reply *get_reply)
@@ -1540,7 +1533,6 @@ static void mgmt_txn_send_getcfg_reply_data(struct mgmt_txn_req *txn_req,
case MGMTD_TXN_PROC_GETTREE:
case MGMTD_TXN_GETTREE_TIMEOUT:
case MGMTD_TXN_COMMITCFG_TIMEOUT:
- case MGMTD_TXN_CLEANUP:
MGMTD_TXN_ERR("Invalid Txn-Req-Event %u", txn_req->req_event);
break;
}
@@ -1731,15 +1723,9 @@ static struct mgmt_txn_ctx *mgmt_txn_create_new(uint64_t session_id,
{
struct mgmt_txn_ctx *txn = NULL;
- /*
- * For 'CONFIG' transaction check if one is already created
- * or not. TODO: figure out what code counts on this and fix it.
- */
- if (type == MGMTD_TXN_TYPE_CONFIG && mgmt_txn_mm->cfg_txn) {
- if (mgmt_config_txn_in_progress() == session_id)
- txn = mgmt_txn_mm->cfg_txn;
- goto mgmt_create_txn_done;
- }
+ /* Do not allow multiple config transactions */
+ if (type == MGMTD_TXN_TYPE_CONFIG && mgmt_config_txn_in_progress())
+ return NULL;
txn = mgmt_fe_find_txn_by_session_id(mgmt_txn_mm, session_id, type);
if (!txn) {
@@ -1769,7 +1755,6 @@ static struct mgmt_txn_ctx *mgmt_txn_create_new(uint64_t session_id,
MGMTD_TXN_LOCK(txn);
}
-mgmt_create_txn_done:
return txn;
}
@@ -1899,16 +1884,6 @@ static void mgmt_txn_cleanup_all_txns(void)
mgmt_txn_cleanup_txn(&txn);
}
-static void mgmt_txn_cleanup(struct event *thread)
-{
- struct mgmt_txn_ctx *txn;
-
- txn = (struct mgmt_txn_ctx *)EVENT_ARG(thread);
- assert(txn);
-
- mgmt_txn_cleanup_txn(&txn);
-}
-
static void mgmt_txn_register_event(struct mgmt_txn_ctx *txn,
enum mgmt_txn_event event)
{
@@ -1940,11 +1915,6 @@ static void mgmt_txn_register_event(struct mgmt_txn_ctx *txn,
MGMTD_TXN_GET_TREE_MAX_DELAY_SEC,
&txn->get_tree_timeout);
break;
- case MGMTD_TXN_CLEANUP:
- tv.tv_usec = MGMTD_TXN_CLEANUP_DELAY_USEC;
- event_add_timer_tv(mgmt_txn_tm, mgmt_txn_cleanup, txn, &tv,
- &txn->clnup);
- break;
case MGMTD_TXN_PROC_GETTREE:
assert(!"code bug do not register this event");
break;
@@ -1972,12 +1942,12 @@ void mgmt_txn_destroy(void)
mgmt_txn_hash_destroy();
}
-uint64_t mgmt_config_txn_in_progress(void)
+bool mgmt_config_txn_in_progress(void)
{
if (mgmt_txn_mm && mgmt_txn_mm->cfg_txn)
- return mgmt_txn_mm->cfg_txn->session_id;
+ return true;
- return MGMTD_SESSION_ID_NONE;
+ return false;
}
uint64_t mgmt_create_txn(uint64_t session_id, enum mgmt_txn_type type)
@@ -2161,6 +2131,7 @@ int mgmt_txn_notify_be_adapter_conn(struct mgmt_be_client_adapter *adapter,
if (!txn) {
MGMTD_TXN_ERR("Failed to create CONFIG Transaction for downloading CONFIGs for client '%s'",
adapter->name);
+ nb_config_diff_del_changes(adapter_cfgs);
return -1;
}
@@ -2470,6 +2441,10 @@ state:
mgmt_msg_native_free_msg(msg);
+ /* Return if we didn't send any messages to backends */
+ if (!get_tree->sent_clients)
+ return txn_get_tree_data_done(txn, txn_req);
+
/* Start timeout timer - pulled out of register event code so we can
* pass a different arg
*/
@@ -2529,7 +2504,6 @@ int mgmt_txn_notify_error(struct mgmt_be_client_adapter *adapter,
case MGMTD_TXN_PROC_GETCFG:
case MGMTD_TXN_COMMITCFG_TIMEOUT:
case MGMTD_TXN_GETTREE_TIMEOUT:
- case MGMTD_TXN_CLEANUP:
default:
assert(!"non-native req event in native erorr path");
return -1;
diff --git a/mgmtd/mgmt_txn.h b/mgmtd/mgmt_txn.h
index 3f27f2f07b..02b2baa95f 100644
--- a/mgmtd/mgmt_txn.h
+++ b/mgmtd/mgmt_txn.h
@@ -71,12 +71,12 @@ extern int mgmt_txn_init(struct mgmt_master *cm, struct event_loop *tm);
extern void mgmt_txn_destroy(void);
/*
- * Check if transaction is in progress.
+ * Check if configuration transaction is in progress.
*
* Returns:
- * session ID if in-progress, MGMTD_SESSION_ID_NONE otherwise.
+ * true if in-progress, false otherwise.
*/
-extern uint64_t mgmt_config_txn_in_progress(void);
+extern bool mgmt_config_txn_in_progress(void);
/**
* Get the session ID associated with the given ``txn-id``.
diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c
index f4b24acf3a..194af13f1e 100644
--- a/mgmtd/mgmt_vty.c
+++ b/mgmtd/mgmt_vty.c
@@ -9,9 +9,11 @@
#include <zebra.h>
#include "command.h"
+#include "filter.h"
#include "json.h"
#include "network.h"
#include "northbound_cli.h"
+#include "routemap.h"
#include "mgmtd/mgmt.h"
#include "mgmtd/mgmt_be_adapter.h"
@@ -20,6 +22,9 @@
#include "mgmtd/mgmt_history.h"
#include "mgmtd/mgmt_vty_clippy.c"
+#include "ripd/rip_nb.h"
+#include "ripngd/ripng_nb.h"
+#include "staticd/static_vty.h"
extern struct frr_daemon_info *mgmt_daemon_info;
@@ -561,13 +566,24 @@ static struct cmd_node mgmtd_node = {
void mgmt_vty_init(void)
{
/*
+ * Library based CLI handlers
+ */
+ filter_cli_init();
+ route_map_cli_init();
+
+ /*
* Initialize command handling from VTYSH connection.
* Call command initialization routines defined by
* backend components that are moved to new MGMTD infra
* here one by one.
*/
+#if HAVE_RIPD
+ rip_cli_init();
+#endif
+#if HAVE_RIPNGD
+ ripng_cli_init();
+#endif
#if HAVE_STATICD
- extern void static_vty_init(void);
static_vty_init();
#endif
diff --git a/mgmtd/subdir.am b/mgmtd/subdir.am
index 89a6596f49..3d1dafabd4 100644
--- a/mgmtd/subdir.am
+++ b/mgmtd/subdir.am
@@ -15,6 +15,8 @@ clippy_scan += \
# end
lib_LTLIBRARIES += mgmtd/libmgmt_be_nb.la
+mgmtd_libmgmt_be_nb_la_SOURCES = \
+ # end
nodist_mgmtd_libmgmt_be_nb_la_SOURCES = \
# end
mgmtd_libmgmt_be_nb_la_CFLAGS = $(AM_CFLAGS) -DINCLUDE_MGMTD_CMDDEFS_ONLY
@@ -54,10 +56,39 @@ mgmtd_mgmtd_CFLAGS = $(AM_CFLAGS) -I ./
mgmtd_mgmtd_LDADD = mgmtd/libmgmtd.a lib/libfrr.la $(LIBCAP) $(LIBM) $(LIBYANG_LIBS) $(UST_LIBS)
mgmtd_mgmtd_LDADD += mgmtd/libmgmt_be_nb.la
+
+if STATICD
+nodist_mgmtd_mgmtd_SOURCES += yang/frr-bfdd.yang.c
+else
+if RIPD
+nodist_mgmtd_mgmtd_SOURCES += yang/frr-bfdd.yang.c
+endif
+endif
+
+if RIPD
+nodist_mgmtd_mgmtd_SOURCES += \
+ yang/frr-ripd.yang.c \
+ # end
+mgmtd_libmgmt_be_nb_la_SOURCES += \
+ ripd/rip_cli.c \
+ # end
+endif
+
+if RIPNGD
+nodist_mgmtd_mgmtd_SOURCES += \
+ yang/frr-ripngd.yang.c \
+ # end
+mgmtd_libmgmt_be_nb_la_SOURCES += \
+ ripngd/ripng_cli.c \
+ # end
+endif
+
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
+nodist_mgmtd_libmgmt_be_nb_la_SOURCES += \
+ staticd/static_vty.c \
+ # end
endif
+
diff --git a/python/xref2vtysh.py b/python/xref2vtysh.py
index 75fff8ddd9..1760588ca8 100644
--- a/python/xref2vtysh.py
+++ b/python/xref2vtysh.py
@@ -33,18 +33,18 @@ frr_top_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
daemon_flags = {
"lib/agentx.c": "VTYSH_ISISD|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA",
- "lib/filter.c": "VTYSH_ACL",
- "lib/filter_cli.c": "VTYSH_ACL",
+ "lib/filter.c": "VTYSH_ACL_SHOW",
+ "lib/filter_cli.c": "VTYSH_ACL_CONFIG",
"lib/if.c": "VTYSH_INTERFACE",
"lib/keychain.c": "VTYSH_KEYS",
- "lib/mgmt_be_client.c": "VTYSH_STATICD|VTYSH_ZEBRA",
- "lib/mgmt_fe_client.c": "VTYSH_MGMTD",
+ "lib/mgmt_be_client.c": "VTYSH_MGMT_BACKEND",
+ "lib/mgmt_fe_client.c": "VTYSH_MGMT_FRONTEND",
"lib/lib_vty.c": "VTYSH_ALL",
"lib/log_vty.c": "VTYSH_ALL",
"lib/nexthop_group.c": "VTYSH_NH_GROUP",
"lib/resolver.c": "VTYSH_NHRPD|VTYSH_BGPD",
- "lib/routemap.c": "VTYSH_RMAP",
- "lib/routemap_cli.c": "VTYSH_RMAP",
+ "lib/routemap.c": "VTYSH_RMAP_SHOW",
+ "lib/routemap_cli.c": "VTYSH_RMAP_CONFIG",
"lib/spf_backoff.c": "VTYSH_ISISD",
"lib/event.c": "VTYSH_ALL",
"lib/vrf.c": "VTYSH_VRF",
@@ -206,10 +206,7 @@ class CommandEntry:
}
if defun_file == "lib/if_rmap.c":
- if v6_cmd:
- return {"VTYSH_RIPNGD"}
- else:
- return {"VTYSH_RIPD"}
+ return {"VTYSH_MGMTD"}
return {}
diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c
index fbe647c5ca..29db1b232d 100644
--- a/ripd/rip_cli.c
+++ b/ripd/rip_cli.c
@@ -8,6 +8,7 @@
#include <zebra.h>
#include "if.h"
+#include "if_rmap.h"
#include "vrf.h"
#include "log.h"
#include "prefix.h"
@@ -1257,8 +1258,19 @@ DEFPY_YANG(no_rip_distribute_list_prefix,
return nb_cli_apply_changes(vty, NULL);
}
+/* RIP node structure. */
+static struct cmd_node rip_node = {
+ .name = "rip",
+ .node = RIP_NODE,
+ .parent_node = CONFIG_NODE,
+ .prompt = "%s(config-router)# ",
+ // .config_write = config_write_rip,
+};
+
void rip_cli_init(void)
{
+ install_node(&rip_node);
+
install_element(CONFIG_NODE, &router_rip_cmd);
install_element(CONFIG_NODE, &no_router_rip_cmd);
@@ -1289,6 +1301,7 @@ void rip_cli_init(void)
install_element(RIP_NODE, &no_rip_version_cmd);
install_element(RIP_NODE, &rip_bfd_default_profile_cmd);
install_element(RIP_NODE, &no_rip_bfd_default_profile_cmd);
+ install_default(RIP_NODE);
install_element(INTERFACE_NODE, &ip_rip_split_horizon_cmd);
install_element(INTERFACE_NODE, &ip_rip_v2_broadcast_cmd);
@@ -1308,4 +1321,128 @@ void rip_cli_init(void)
install_element(INTERFACE_NODE, &no_ip_rip_bfd_profile_cmd);
install_element(ENABLE_NODE, &clear_ip_rip_cmd);
-}
+
+ if_rmap_init(RIP_NODE);
+}
+/* clang-format off */
+const struct frr_yang_module_info frr_ripd_cli_info = {
+ .name = "frr-ripd",
+ .ignore_cfg_cbs = true,
+ .nodes = {
+ {
+ .xpath = "/frr-ripd:ripd/instance",
+ .cbs.cli_show = cli_show_router_rip,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/allow-ecmp",
+ .cbs.cli_show = cli_show_rip_allow_ecmp,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/default-information-originate",
+ .cbs.cli_show = cli_show_rip_default_information_originate,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/default-metric",
+ .cbs.cli_show = cli_show_rip_default_metric,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/distance/default",
+ .cbs.cli_show = cli_show_rip_distance,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/distance/source",
+ .cbs.cli_show = cli_show_rip_distance_source,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/explicit-neighbor",
+ .cbs.cli_show = cli_show_rip_neighbor,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/network",
+ .cbs.cli_show = cli_show_rip_network_prefix,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/interface",
+ .cbs.cli_show = cli_show_rip_network_interface,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/offset-list",
+ .cbs.cli_show = cli_show_rip_offset_list,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/passive-default",
+ .cbs.cli_show = cli_show_rip_passive_default,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/passive-interface",
+ .cbs.cli_show = cli_show_rip_passive_interface,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/non-passive-interface",
+ .cbs.cli_show = cli_show_rip_non_passive_interface,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/redistribute",
+ .cbs.cli_show = cli_show_rip_redistribute,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/if-route-maps/if-route-map",
+ .cbs.cli_show = cli_show_if_route_map,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/static-route",
+ .cbs.cli_show = cli_show_rip_route,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/timers",
+ .cbs.cli_show = cli_show_rip_timers,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/version",
+ .cbs.cli_show = cli_show_rip_version,
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/default-bfd-profile",
+ .cbs.cli_show = cli_show_ripd_instance_default_bfd_profile,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripd:rip/split-horizon",
+ .cbs.cli_show = cli_show_ip_rip_split_horizon,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripd:rip/v2-broadcast",
+ .cbs.cli_show = cli_show_ip_rip_v2_broadcast,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-receive",
+ .cbs.cli_show = cli_show_ip_rip_receive_version,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-send",
+ .cbs.cli_show = cli_show_ip_rip_send_version,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme",
+ .cbs.cli_show = cli_show_ip_rip_authentication_scheme,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-password",
+ .cbs.cli_show = cli_show_ip_rip_authentication_string,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain",
+ .cbs.cli_show = cli_show_ip_rip_authentication_key_chain,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripd:rip/bfd-monitoring/enable",
+ .cbs.cli_show = cli_show_ip_rip_bfd_enable,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripd:rip/bfd-monitoring/profile",
+ .cbs.cli_show = cli_show_ip_rip_bfd_profile,
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 65afce8cb7..486d7b05c2 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -1109,7 +1109,6 @@ void rip_if_init(void)
hook_register_prio(if_del, 0, rip_interface_delete_hook);
/* Install interface node. */
- if_cmd_init_default();
hook_register_prio(if_real, 0, rip_ifp_create);
hook_register_prio(if_up, 0, rip_ifp_up);
hook_register_prio(if_down, 0, rip_ifp_down);
diff --git a/ripd/rip_main.c b/ripd/rip_main.c
index cb23098a7e..c86caabaf1 100644
--- a/ripd/rip_main.c
+++ b/ripd/rip_main.c
@@ -22,6 +22,7 @@
#include "libfrr.h"
#include "routemap.h"
#include "bfd.h"
+#include "mgmt_be_client.h"
#include "ripd/ripd.h"
#include "ripd/rip_bfd.h"
@@ -53,6 +54,8 @@ struct zebra_privs_t ripd_privs = {
/* Master of threads. */
struct event_loop *master;
+struct mgmt_be_client *mgmt_be_client;
+
static struct frr_daemon_info ripd_di;
/* SIGHUP handler. */
@@ -73,6 +76,11 @@ static void sigint(void)
bfd_protocol_integration_set_shutdown(true);
+
+ nb_oper_cancel_all_walks();
+ mgmt_be_client_destroy(mgmt_be_client);
+ mgmt_be_client = NULL;
+
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if (!vrf->info)
continue;
@@ -133,6 +141,9 @@ FRR_DAEMON_INFO(ripd, RIP, .vty_port = RIP_VTY_PORT,
.privs = &ripd_privs, .yang_modules = ripd_yang_modules,
.n_yang_modules = array_size(ripd_yang_modules),
+
+ /* mgmtd will load the per-daemon config file now */
+ .flags = FRR_NO_SPLIT_CONFIG,
);
#define DEPRECATED_OPTIONS ""
@@ -179,7 +190,9 @@ int main(int argc, char **argv)
/* RIP related initialization. */
rip_init();
rip_if_init();
- rip_cli_init();
+
+ mgmt_be_client = mgmt_be_client_create("ripd", NULL, 0, master);
+
rip_zclient_init(master);
rip_bfd_init(master);
diff --git a/ripd/rip_nb.c b/ripd/rip_nb.c
index 7167be124a..d5df5916ad 100644
--- a/ripd/rip_nb.c
+++ b/ripd/rip_nb.c
@@ -20,7 +20,6 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance",
.cbs = {
- .cli_show = cli_show_router_rip,
.create = ripd_instance_create,
.destroy = ripd_instance_destroy,
.get_keys = ripd_instance_get_keys,
@@ -31,35 +30,30 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/allow-ecmp",
.cbs = {
- .cli_show = cli_show_rip_allow_ecmp,
.modify = ripd_instance_allow_ecmp_modify,
},
},
{
.xpath = "/frr-ripd:ripd/instance/default-information-originate",
.cbs = {
- .cli_show = cli_show_rip_default_information_originate,
.modify = ripd_instance_default_information_originate_modify,
},
},
{
.xpath = "/frr-ripd:ripd/instance/default-metric",
.cbs = {
- .cli_show = cli_show_rip_default_metric,
.modify = ripd_instance_default_metric_modify,
},
},
{
.xpath = "/frr-ripd:ripd/instance/distance/default",
.cbs = {
- .cli_show = cli_show_rip_distance,
.modify = ripd_instance_distance_default_modify,
},
},
{
.xpath = "/frr-ripd:ripd/instance/distance/source",
.cbs = {
- .cli_show = cli_show_rip_distance_source,
.create = ripd_instance_distance_source_create,
.destroy = ripd_instance_distance_source_destroy,
},
@@ -80,7 +74,6 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/explicit-neighbor",
.cbs = {
- .cli_show = cli_show_rip_neighbor,
.create = ripd_instance_explicit_neighbor_create,
.destroy = ripd_instance_explicit_neighbor_destroy,
},
@@ -88,7 +81,6 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/network",
.cbs = {
- .cli_show = cli_show_rip_network_prefix,
.create = ripd_instance_network_create,
.destroy = ripd_instance_network_destroy,
},
@@ -96,7 +88,6 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/interface",
.cbs = {
- .cli_show = cli_show_rip_network_interface,
.create = ripd_instance_interface_create,
.destroy = ripd_instance_interface_destroy,
},
@@ -104,7 +95,6 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/offset-list",
.cbs = {
- .cli_show = cli_show_rip_offset_list,
.create = ripd_instance_offset_list_create,
.destroy = ripd_instance_offset_list_destroy,
},
@@ -124,14 +114,12 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/passive-default",
.cbs = {
- .cli_show = cli_show_rip_passive_default,
.modify = ripd_instance_passive_default_modify,
},
},
{
.xpath = "/frr-ripd:ripd/instance/passive-interface",
.cbs = {
- .cli_show = cli_show_rip_passive_interface,
.create = ripd_instance_passive_interface_create,
.destroy = ripd_instance_passive_interface_destroy,
},
@@ -139,7 +127,6 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/non-passive-interface",
.cbs = {
- .cli_show = cli_show_rip_non_passive_interface,
.create = ripd_instance_non_passive_interface_create,
.destroy = ripd_instance_non_passive_interface_destroy,
},
@@ -187,7 +174,6 @@ const struct frr_yang_module_info frr_ripd_info = {
.xpath = "/frr-ripd:ripd/instance/redistribute",
.cbs = {
.apply_finish = ripd_instance_redistribute_apply_finish,
- .cli_show = cli_show_rip_redistribute,
.create = ripd_instance_redistribute_create,
.destroy = ripd_instance_redistribute_destroy,
},
@@ -211,7 +197,6 @@ const struct frr_yang_module_info frr_ripd_info = {
.cbs = {
.create = ripd_instance_if_route_maps_if_route_map_create,
.destroy = ripd_instance_if_route_maps_if_route_map_destroy,
- .cli_show = cli_show_if_route_map,
}
},
{
@@ -231,7 +216,6 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-ripd:ripd/instance/static-route",
.cbs = {
- .cli_show = cli_show_rip_route,
.create = ripd_instance_static_route_create,
.destroy = ripd_instance_static_route_destroy,
},
@@ -240,7 +224,6 @@ const struct frr_yang_module_info frr_ripd_info = {
.xpath = "/frr-ripd:ripd/instance/timers",
.cbs = {
.apply_finish = ripd_instance_timers_apply_finish,
- .cli_show = cli_show_rip_timers,
},
},
{
@@ -262,12 +245,6 @@ const struct frr_yang_module_info frr_ripd_info = {
},
},
{
- .xpath = "/frr-ripd:ripd/instance/version",
- .cbs = {
- .cli_show = cli_show_rip_version,
- },
- },
- {
.xpath = "/frr-ripd:ripd/instance/version/receive",
.cbs = {
.modify = ripd_instance_version_receive_modify,
@@ -284,44 +261,33 @@ const struct frr_yang_module_info frr_ripd_info = {
.cbs = {
.modify = ripd_instance_default_bfd_profile_modify,
.destroy = ripd_instance_default_bfd_profile_destroy,
- .cli_show = cli_show_ripd_instance_default_bfd_profile,
},
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/split-horizon",
.cbs = {
- .cli_show = cli_show_ip_rip_split_horizon,
.modify = lib_interface_rip_split_horizon_modify,
},
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/v2-broadcast",
.cbs = {
- .cli_show = cli_show_ip_rip_v2_broadcast,
.modify = lib_interface_rip_v2_broadcast_modify,
},
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-receive",
.cbs = {
- .cli_show = cli_show_ip_rip_receive_version,
.modify = lib_interface_rip_version_receive_modify,
},
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-send",
.cbs = {
- .cli_show = cli_show_ip_rip_send_version,
.modify = lib_interface_rip_version_send_modify,
},
},
{
- .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme",
- .cbs = {
- .cli_show = cli_show_ip_rip_authentication_scheme,
- },
- },
- {
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/mode",
.cbs = {
.modify = lib_interface_rip_authentication_scheme_mode_modify,
@@ -337,7 +303,6 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-password",
.cbs = {
- .cli_show = cli_show_ip_rip_authentication_string,
.destroy = lib_interface_rip_authentication_password_destroy,
.modify = lib_interface_rip_authentication_password_modify,
},
@@ -345,7 +310,6 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain",
.cbs = {
- .cli_show = cli_show_ip_rip_authentication_key_chain,
.destroy = lib_interface_rip_authentication_key_chain_destroy,
.modify = lib_interface_rip_authentication_key_chain_modify,
},
@@ -360,14 +324,12 @@ const struct frr_yang_module_info frr_ripd_info = {
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/bfd-monitoring/enable",
.cbs = {
- .cli_show = cli_show_ip_rip_bfd_enable,
.modify = lib_interface_rip_bfd_enable_modify,
},
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/bfd-monitoring/profile",
.cbs = {
- .cli_show = cli_show_ip_rip_bfd_profile,
.modify = lib_interface_rip_bfd_profile_modify,
.destroy = lib_interface_rip_bfd_profile_destroy,
},
diff --git a/ripd/rip_nb.h b/ripd/rip_nb.h
index 811fee55ec..d07273af80 100644
--- a/ripd/rip_nb.h
+++ b/ripd/rip_nb.h
@@ -10,6 +10,7 @@
#include "northbound.h"
extern const struct frr_yang_module_info frr_ripd_info;
+extern const struct frr_yang_module_info frr_ripd_cli_info;
/* Mandatory callbacks. */
int ripd_instance_create(struct nb_cb_create_args *args);
@@ -239,4 +240,6 @@ void cli_show_ip_rip_bfd_profile(struct vty *vty, const struct lyd_node *dnode,
extern void ripd_notif_send_auth_type_failure(const char *ifname);
extern void ripd_notif_send_auth_failure(const char *ifname);
+extern void rip_cli_init(void);
+
#endif /* _FRR_RIP_NB_H_ */
diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c
index 2ae8857e3f..be17277449 100644
--- a/ripd/rip_routemap.c
+++ b/ripd/rip_routemap.c
@@ -531,7 +531,7 @@ static const struct route_map_rule_cmd route_set_tag_cmd = {
/* Route-map init */
void rip_route_map_init(void)
{
- route_map_init();
+ route_map_init_new(true);
route_map_match_interface_hook(generic_match_add);
route_map_no_match_interface_hook(generic_match_delete);
diff --git a/ripd/ripd.c b/ripd/ripd.c
index a744e081d1..b8a140c9ca 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -34,6 +34,7 @@
#include "privs.h"
#include "lib_errors.h"
#include "northbound_cli.h"
+#include "mgmt_be_client.h"
#include "network.h"
#include "lib/printfrr.h"
#include "frrdistance.h"
@@ -3253,42 +3254,6 @@ DEFUN (show_ip_rip_status,
return CMD_SUCCESS;
}
-/* RIP configuration write function. */
-static int config_write_rip(struct vty *vty)
-{
- struct rip *rip;
- int write = 0;
-
- RB_FOREACH(rip, rip_instance_head, &rip_instances) {
- char xpath[XPATH_MAXLEN];
- struct lyd_node *dnode;
-
- snprintf(xpath, sizeof(xpath),
- "/frr-ripd:ripd/instance[vrf='%s']", rip->vrf_name);
-
- dnode = yang_dnode_get(running_config->dnode, xpath);
- assert(dnode);
-
- nb_cli_show_dnode_cmds(vty, dnode, false);
-
- vty_out(vty, "exit\n");
-
- write = 1;
- }
-
- return write;
-}
-
-static int config_write_rip(struct vty *vty);
-/* RIP node structure. */
-static struct cmd_node rip_node = {
- .name = "rip",
- .node = RIP_NODE,
- .parent_node = CONFIG_NODE,
- .prompt = "%s(config-router)# ",
- .config_write = config_write_rip,
-};
-
/* Distribute-list update functions. */
static void rip_distribute_update(struct distribute_ctx *ctx,
struct distribute *dist)
@@ -3650,8 +3615,6 @@ static int rip_vrf_disable(struct vrf *vrf)
void rip_vrf_init(void)
{
vrf_init(rip_vrf_new, rip_vrf_enable, rip_vrf_disable, rip_vrf_delete);
-
- vrf_cmd_init(NULL);
}
void rip_vrf_terminate(void)
@@ -3662,20 +3625,17 @@ void rip_vrf_terminate(void)
/* Allocate new rip structure and set default value. */
void rip_init(void)
{
- /* Install top nodes. */
- install_node(&rip_node);
-
/* Install rip commands. */
install_element(VIEW_NODE, &show_ip_rip_cmd);
install_element(VIEW_NODE, &show_ip_rip_status_cmd);
- install_default(RIP_NODE);
-
/* Debug related init. */
rip_debug_init();
+ /* Enable mgmt be debug */
+ mgmt_be_client_lib_vty_init();
/* Access list install. */
- access_list_init();
+ access_list_init_new(true);
access_list_add_hook(rip_distribute_update_all_wrapper);
access_list_delete_hook(rip_distribute_update_all_wrapper);
@@ -3689,6 +3649,4 @@ void rip_init(void)
route_map_add_hook(rip_routemap_update);
route_map_delete_hook(rip_routemap_update);
-
- if_rmap_init(RIP_NODE);
}
diff --git a/ripd/ripd.h b/ripd/ripd.h
index ac4a51f586..b7e79332fe 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -526,7 +526,6 @@ extern int offset_list_cmp(struct rip_offset_list *o1,
extern void rip_vrf_init(void);
extern void rip_vrf_terminate(void);
-extern void rip_cli_init(void);
extern struct zebra_privs_t ripd_privs;
extern struct rip_instance_head rip_instances;
diff --git a/ripd/subdir.am b/ripd/subdir.am
index c793a6d685..aed8d249fe 100644
--- a/ripd/subdir.am
+++ b/ripd/subdir.am
@@ -14,7 +14,6 @@ endif
ripd_ripd_SOURCES = \
ripd/rip_bfd.c \
- ripd/rip_cli.c \
ripd/rip_debug.c \
ripd/rip_errors.c \
ripd/rip_interface.c \
diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c
index ee561087c9..a4a0f5a2cb 100644
--- a/ripngd/ripng_cli.c
+++ b/ripngd/ripng_cli.c
@@ -8,6 +8,7 @@
#include <zebra.h>
#include "if.h"
+#include "if_rmap.h"
#include "vrf.h"
#include "log.h"
#include "prefix.h"
@@ -648,8 +649,20 @@ DEFPY_YANG(no_ripng_ipv6_distribute_list_prefix,
return nb_cli_apply_changes(vty, NULL);
}
+/* RIPng node structure. */
+static struct cmd_node cmd_ripng_node = {
+ .name = "ripng",
+ .node = RIPNG_NODE,
+ .parent_node = CONFIG_NODE,
+ .prompt = "%s(config-router)# ",
+};
+
void ripng_cli_init(void)
{
+ /* Install RIPNG_NODE. */
+ install_node(&cmd_ripng_node);
+ install_default(RIPNG_NODE);
+
install_element(CONFIG_NODE, &router_ripng_cmd);
install_element(CONFIG_NODE, &no_router_ripng_cmd);
@@ -676,4 +689,91 @@ void ripng_cli_init(void)
install_element(INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
install_element(ENABLE_NODE, &clear_ipv6_rip_cmd);
-}
+
+ if_rmap_init(RIPNG_NODE);
+}
+
+/* clang-format off */
+const struct frr_yang_module_info frr_ripngd_cli_info = {
+ .name = "frr-ripngd",
+ .ignore_cfg_cbs = true,
+ .nodes = {
+ {
+ .xpath = "/frr-ripngd:ripngd/instance",
+ .cbs.cli_show = cli_show_router_ripng,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
+ .cbs.cli_show = cli_show_ripng_allow_ecmp,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
+ .cbs.cli_show = cli_show_ripng_default_information_originate,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/default-metric",
+ .cbs.cli_show = cli_show_ripng_default_metric,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/network",
+ .cbs.cli_show = cli_show_ripng_network_prefix,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/interface",
+ .cbs.cli_show = cli_show_ripng_network_interface,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/offset-list",
+ .cbs.cli_show = cli_show_ripng_offset_list,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/passive-interface",
+ .cbs.cli_show = cli_show_ripng_passive_interface,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/distribute-list/in/access-list",
+ .cbs.cli_show = group_distribute_list_ipv6_cli_show,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/distribute-list/out/access-list",
+ .cbs.cli_show = group_distribute_list_ipv6_cli_show,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/distribute-list/in/prefix-list",
+ .cbs.cli_show = group_distribute_list_ipv6_cli_show,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/distribute-list/out/prefix-list",
+ .cbs.cli_show = group_distribute_list_ipv6_cli_show,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/redistribute",
+ .cbs.cli_show = cli_show_ripng_redistribute,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/if-route-maps/if-route-map",
+ .cbs.cli_show = cli_show_if_route_map,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/static-route",
+ .cbs.cli_show = cli_show_ripng_route,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
+ .cbs.cli_show = cli_show_ripng_aggregate_address,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/timers",
+ .cbs.cli_show = cli_show_ripng_timers,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon",
+ .cbs = {
+ .cli_show = cli_show_ipv6_ripng_split_horizon,
+ },
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c
index 35d92632a0..9ef9f89005 100644
--- a/ripngd/ripng_interface.c
+++ b/ripngd/ripng_interface.c
@@ -873,7 +873,6 @@ void ripng_if_init(void)
hook_register_prio(if_del, 0, ripng_if_delete_hook);
/* Install interface node. */
- if_cmd_init_default();
hook_register_prio(if_real, 0, ripng_ifp_create);
hook_register_prio(if_up, 0, ripng_ifp_up);
hook_register_prio(if_down, 0, ripng_ifp_down);
diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c
index a799943be1..80b78a150a 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -22,6 +22,7 @@
#include "if_rmap.h"
#include "libfrr.h"
#include "routemap.h"
+#include "mgmt_be_client.h"
#include "ripngd/ripngd.h"
#include "ripngd/ripng_nb.h"
@@ -52,6 +53,8 @@ struct zebra_privs_t ripngd_privs = {
/* Master of threads. */
struct event_loop *master;
+struct mgmt_be_client *mgmt_be_client;
+
static struct frr_daemon_info ripngd_di;
/* SIGHUP handler. */
@@ -70,6 +73,10 @@ 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;
+
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if (!vrf->info)
continue;
@@ -131,6 +138,9 @@ FRR_DAEMON_INFO(ripngd, RIPNG, .vty_port = RIPNG_VTY_PORT,
.yang_modules = ripngd_yang_modules,
.n_yang_modules = array_size(ripngd_yang_modules),
+
+ /* mgmtd will load the per-daemon config file now */
+ .flags = FRR_NO_SPLIT_CONFIG,
);
#define DEPRECATED_OPTIONS ""
@@ -172,7 +182,9 @@ int main(int argc, char **argv)
/* RIPngd inits. */
ripng_init();
- ripng_cli_init();
+
+ mgmt_be_client = mgmt_be_client_create("ripngd", NULL, 0, master);
+
zebra_init(master);
frr_config_fork();
diff --git a/ripngd/ripng_nb.c b/ripngd/ripng_nb.c
index 583a4d08d0..8e20541733 100644
--- a/ripngd/ripng_nb.c
+++ b/ripngd/ripng_nb.c
@@ -20,7 +20,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-ripngd:ripngd/instance",
.cbs = {
- .cli_show = cli_show_router_ripng,
.create = ripngd_instance_create,
.destroy = ripngd_instance_destroy,
.get_keys = ripngd_instance_get_keys,
@@ -31,28 +30,24 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
.cbs = {
- .cli_show = cli_show_ripng_allow_ecmp,
.modify = ripngd_instance_allow_ecmp_modify,
},
},
{
.xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
.cbs = {
- .cli_show = cli_show_ripng_default_information_originate,
.modify = ripngd_instance_default_information_originate_modify,
},
},
{
.xpath = "/frr-ripngd:ripngd/instance/default-metric",
.cbs = {
- .cli_show = cli_show_ripng_default_metric,
.modify = ripngd_instance_default_metric_modify,
},
},
{
.xpath = "/frr-ripngd:ripngd/instance/network",
.cbs = {
- .cli_show = cli_show_ripng_network_prefix,
.create = ripngd_instance_network_create,
.destroy = ripngd_instance_network_destroy,
},
@@ -60,7 +55,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-ripngd:ripngd/instance/interface",
.cbs = {
- .cli_show = cli_show_ripng_network_interface,
.create = ripngd_instance_interface_create,
.destroy = ripngd_instance_interface_destroy,
},
@@ -68,7 +62,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-ripngd:ripngd/instance/offset-list",
.cbs = {
- .cli_show = cli_show_ripng_offset_list,
.create = ripngd_instance_offset_list_create,
.destroy = ripngd_instance_offset_list_destroy,
},
@@ -88,7 +81,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-ripngd:ripngd/instance/passive-interface",
.cbs = {
- .cli_show = cli_show_ripng_passive_interface,
.create = ripngd_instance_passive_interface_create,
.destroy = ripngd_instance_passive_interface_destroy,
},
@@ -105,7 +97,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
.cbs = {
.modify = group_distribute_list_ipv6_modify,
.destroy = group_distribute_list_ipv6_destroy,
- .cli_show = group_distribute_list_ipv6_cli_show,
}
},
{
@@ -113,7 +104,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
.cbs = {
.modify = group_distribute_list_ipv6_modify,
.destroy = group_distribute_list_ipv6_destroy,
- .cli_show = group_distribute_list_ipv6_cli_show,
}
},
{
@@ -121,7 +111,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
.cbs = {
.modify = group_distribute_list_ipv6_modify,
.destroy = group_distribute_list_ipv6_destroy,
- .cli_show = group_distribute_list_ipv6_cli_show,
}
},
{
@@ -129,14 +118,12 @@ const struct frr_yang_module_info frr_ripngd_info = {
.cbs = {
.modify = group_distribute_list_ipv6_modify,
.destroy = group_distribute_list_ipv6_destroy,
- .cli_show = group_distribute_list_ipv6_cli_show,
}
},
{
.xpath = "/frr-ripngd:ripngd/instance/redistribute",
.cbs = {
.apply_finish = ripngd_instance_redistribute_apply_finish,
- .cli_show = cli_show_ripng_redistribute,
.create = ripngd_instance_redistribute_create,
.destroy = ripngd_instance_redistribute_destroy,
},
@@ -160,7 +147,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
.cbs = {
.create = ripngd_instance_if_route_maps_if_route_map_create,
.destroy = ripngd_instance_if_route_maps_if_route_map_destroy,
- .cli_show = cli_show_if_route_map,
}
},
{
@@ -180,7 +166,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-ripngd:ripngd/instance/static-route",
.cbs = {
- .cli_show = cli_show_ripng_route,
.create = ripngd_instance_static_route_create,
.destroy = ripngd_instance_static_route_destroy,
},
@@ -188,7 +173,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
.cbs = {
- .cli_show = cli_show_ripng_aggregate_address,
.create = ripngd_instance_aggregate_address_create,
.destroy = ripngd_instance_aggregate_address_destroy,
},
@@ -197,7 +181,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
.xpath = "/frr-ripngd:ripngd/instance/timers",
.cbs = {
.apply_finish = ripngd_instance_timers_apply_finish,
- .cli_show = cli_show_ripng_timers,
},
},
{
@@ -291,7 +274,6 @@ const struct frr_yang_module_info frr_ripngd_info = {
{
.xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon",
.cbs = {
- .cli_show = cli_show_ipv6_ripng_split_horizon,
.modify = lib_interface_ripng_split_horizon_modify,
},
},
diff --git a/ripngd/ripng_nb.h b/ripngd/ripng_nb.h
index 12d3cd5129..a6ac1fba07 100644
--- a/ripngd/ripng_nb.h
+++ b/ripngd/ripng_nb.h
@@ -10,6 +10,7 @@
#include "northbound.h"
extern const struct frr_yang_module_info frr_ripngd_info;
+extern const struct frr_yang_module_info frr_ripngd_cli_info;
/* Mandatory callbacks. */
int ripngd_instance_create(struct nb_cb_create_args *args);
@@ -138,4 +139,6 @@ void cli_show_ipv6_ripng_split_horizon(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
+extern void ripng_cli_init(void);
+
#endif /* _FRR_RIPNG_NB_H_ */
diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c
index b5f74be3f6..3370546d5c 100644
--- a/ripngd/ripng_routemap.c
+++ b/ripngd/ripng_routemap.c
@@ -386,7 +386,7 @@ static const struct route_map_rule_cmd route_set_tag_cmd = {
void ripng_route_map_init(void)
{
- route_map_init();
+ route_map_init_new(true);
route_map_match_interface_hook(generic_match_add);
route_map_no_match_interface_hook(generic_match_delete);
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 4c3405d7dd..f4dadf377d 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -23,6 +23,7 @@
#include "lib_errors.h"
#include "northbound_cli.h"
#include "network.h"
+#include "mgmt_be_client.h"
#include "ripngd/ripngd.h"
#include "ripngd/ripng_route.h"
@@ -2267,43 +2268,6 @@ void ripng_ecmp_disable(struct ripng *ripng)
}
}
-/* RIPng configuration write function. */
-static int ripng_config_write(struct vty *vty)
-{
- struct ripng *ripng;
- int write = 0;
-
- RB_FOREACH(ripng, ripng_instance_head, &ripng_instances) {
- char xpath[XPATH_MAXLEN];
- struct lyd_node *dnode;
-
- snprintf(xpath, sizeof(xpath),
- "/frr-ripngd:ripngd/instance[vrf='%s']",
- ripng->vrf_name);
-
- dnode = yang_dnode_get(running_config->dnode, xpath);
- assert(dnode);
-
- nb_cli_show_dnode_cmds(vty, dnode, false);
-
- vty_out(vty, "exit\n");
-
- write = 1;
- }
-
- return write;
-}
-
-static int ripng_config_write(struct vty *vty);
-/* RIPng node structure. */
-static struct cmd_node cmd_ripng_node = {
- .name = "ripng",
- .node = RIPNG_NODE,
- .parent_node = CONFIG_NODE,
- .prompt = "%s(config-router)# ",
- .config_write = ripng_config_write,
-};
-
static void ripng_distribute_update(struct distribute_ctx *ctx,
struct distribute *dist)
{
@@ -2671,8 +2635,6 @@ void ripng_vrf_init(void)
{
vrf_init(ripng_vrf_new, ripng_vrf_enable, ripng_vrf_disable,
ripng_vrf_delete);
-
- vrf_cmd_init(NULL);
}
void ripng_vrf_terminate(void)
@@ -2683,20 +2645,18 @@ void ripng_vrf_terminate(void)
/* Initialize ripng structure and set commands. */
void ripng_init(void)
{
- /* Install RIPNG_NODE. */
- install_node(&cmd_ripng_node);
-
/* Install ripng commands. */
install_element(VIEW_NODE, &show_ipv6_ripng_cmd);
install_element(VIEW_NODE, &show_ipv6_ripng_status_cmd);
- install_default(RIPNG_NODE);
-
ripng_if_init();
ripng_debug_init();
+ /* Enable mgmt be debug */
+ mgmt_be_client_lib_vty_init();
+
/* Access list install. */
- access_list_init();
+ access_list_init_new(true);
access_list_add_hook(ripng_distribute_update_all_wrapper);
access_list_delete_hook(ripng_distribute_update_all_wrapper);
@@ -2710,6 +2670,4 @@ void ripng_init(void)
route_map_add_hook(ripng_routemap_update);
route_map_delete_hook(ripng_routemap_update);
-
- if_rmap_init(RIPNG_NODE);
}
diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h
index 3a2bc0c9d3..b4f7b4e52d 100644
--- a/ripngd/ripngd.h
+++ b/ripngd/ripngd.h
@@ -432,7 +432,6 @@ extern void ripng_ecmp_change(struct ripng *ripng);
extern void ripng_vrf_init(void);
extern void ripng_vrf_terminate(void);
-extern void ripng_cli_init(void);
extern uint32_t zebra_ecmp_count;
diff --git a/ripngd/subdir.am b/ripngd/subdir.am
index 162426c58c..83e376b555 100644
--- a/ripngd/subdir.am
+++ b/ripngd/subdir.am
@@ -9,7 +9,6 @@ man8 += $(MANBUILD)/frr-ripngd.8
endif
ripngd_ripngd_SOURCES = \
- ripngd/ripng_cli.c \
ripngd/ripng_debug.c \
ripngd/ripng_interface.c \
ripngd/ripng_nexthop.c \
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 1df7656144..07050ab93b 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -54,7 +54,8 @@ DEFPY(watch_neighbor, watch_neighbor_cmd,
DEFPY(watch_redistribute, watch_redistribute_cmd,
- "sharp watch [vrf NAME$vrf_name] redistribute " FRR_REDIST_STR_SHARPD,
+ "[no] sharp watch [vrf NAME$vrf_name] redistribute " FRR_REDIST_STR_SHARPD,
+ NO_STR
"Sharp routing Protocol\n"
"Watch for changes\n"
"The vrf we would like to watch if non-default\n"
@@ -75,7 +76,7 @@ DEFPY(watch_redistribute, watch_redistribute_cmd,
}
source = proto_redistnum(AFI_IP, argv[argc-1]->text);
- sharp_redistribute_vrf(vrf, source);
+ sharp_redistribute_vrf(vrf, source, !no);
return CMD_SUCCESS;
}
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index f4947540d2..133da918fa 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -704,10 +704,11 @@ static int sharp_redistribute_route(ZAPI_CALLBACK_ARGS)
return 0;
}
-void sharp_redistribute_vrf(struct vrf *vrf, int type)
+void sharp_redistribute_vrf(struct vrf *vrf, int type, bool turn_on)
{
- zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type,
- 0, vrf->vrf_id);
+ zebra_redistribute_send(turn_on ? ZEBRA_REDISTRIBUTE_ADD
+ : ZEBRA_REDISTRIBUTE_DELETE,
+ zclient, AFI_IP, type, 0, vrf->vrf_id);
}
static zclient_handler *const sharp_opaque_handlers[] = {
diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h
index df80ce77a1..5cbcc14665 100644
--- a/sharpd/sharp_zebra.h
+++ b/sharpd/sharp_zebra.h
@@ -55,7 +55,7 @@ extern void sharp_zebra_send_arp(const struct interface *ifp,
/* Register Link State Opaque messages */
extern void sharp_zebra_register_te(void);
-extern void sharp_redistribute_vrf(struct vrf *vrf, int source);
+extern void sharp_redistribute_vrf(struct vrf *vrf, int source, bool turn_on);
extern int sharp_zebra_srv6_manager_get_locator_chunk(const char *lname);
extern int sharp_zebra_srv6_manager_release_locator_chunk(const char *lname);
diff --git a/staticd/static_nb.h b/staticd/static_nb.h
index 9f80653b76..f929997a78 100644
--- a/staticd/static_nb.h
+++ b/staticd/static_nb.h
@@ -11,6 +11,7 @@ extern "C" {
#endif
extern const struct frr_yang_module_info frr_staticd_info;
+extern const struct frr_yang_module_info frr_staticd_cli_info;
/* Mandatory callbacks. */
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create(
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index a641d1a09f..95f79564af 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -1578,7 +1578,7 @@ static int static_path_list_cli_cmp(const struct lyd_node *dnode1,
return (int)distance1 - (int)distance2;
}
-const struct frr_yang_module_info frr_staticd_info = {
+const struct frr_yang_module_info frr_staticd_cli_info = {
.name = "frr-staticd",
.ignore_cfg_cbs = true,
.nodes = {
@@ -1714,5 +1714,7 @@ void static_vty_init(void)
install_element(CONFIG_NODE, &ipv6_route_cmd);
install_element(VRF_NODE, &ipv6_route_vrf_cmd);
+#ifndef INCLUDE_MGMTD_CMDDEFS_ONLY
mgmt_be_client_lib_vty_init();
+#endif
}
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
index 0ac5350308..23ab90794c 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
@@ -161,6 +161,15 @@ def ltemplatePreRouterStartHook():
logger.info(
"setup {0} vrf {0}-cust1, {0}-eth4. enabled mpls input.".format(rtr)
)
+ # configure cust4 VRFs & MPLS
+ cmds = [
+ "ip link add {0}-cust4 type vrf table 30",
+ "ip link set dev {0}-cust4 up",
+ ]
+ rtr = "r1"
+ for cmd in cmds:
+ cc.doCmd(tgen, rtr, cmd.format(rtr))
+ logger.info("setup {0} vrf {0}-cust3 and{0}-cust4.".format(rtr))
# configure cust2 VRFs & MPLS
rtrs = ["r4"]
cmds = [
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf
index 72211fee7f..b389eb1013 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf
@@ -50,6 +50,19 @@ router bgp 5227 vrf r1-cust1
export vpn
exit-address-family
+router bgp 5227 vrf r1-cust4
+ no bgp network import-check
+ bgp router-id 192.168.1.1
+
+ address-family ipv4 unicast
+ network 172.16.0.0/24
+
+ rd vpn export 10:14
+ rt vpn export 52:100
+
+ import vpn
+ export vpn
+ exit-address-family
!
end
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
index 1e2758c1c9..3ab9b3f46e 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
@@ -59,12 +59,20 @@ want_r1_cust1_routes = [
{"p": "5.1.1.0/24", "n": "99.0.0.1"},
{"p": "6.0.1.0/24", "n": "99.0.0.1"},
{"p": "6.0.2.0/24", "n": "99.0.0.1"},
+ {"p": "172.16.0.0/24", "n": "0.0.0.0", "bp": True},
{"p": "99.0.0.1/32", "n": "192.168.1.2"},
]
bgpribRequireUnicastRoutes(
"r1", "ipv4", "r1-cust1", "Customer 1 routes in r1 vrf", want_r1_cust1_routes
)
+want_r1_cust4_routes = [
+ {"p": "172.16.0.0/24", "n": "0.0.0.0", "bp": True},
+]
+bgpribRequireUnicastRoutes(
+ "r1", "ipv4", "r1-cust4", "Customer 4 routes in r1 vrf", want_r1_cust4_routes
+)
+
want_r3_cust1_routes = [
{"p": "5.1.0.0/24", "n": "99.0.0.2"},
{"p": "5.1.1.0/24", "n": "99.0.0.2"},
@@ -667,7 +675,7 @@ bgpribRequireUnicastRoutes(
luCommand(
"ce1",
'vtysh -c "show bgp ipv4 uni"',
- "12 routes and 12",
+ "13 routes and 13",
"wait",
"Local and remote routes",
10,
@@ -689,7 +697,7 @@ bgpribRequireUnicastRoutes(
luCommand(
"ce2",
'vtysh -c "show bgp ipv4 uni"',
- "12 routes and 15",
+ "13 routes and 16",
"wait",
"Local and remote routes",
10,
@@ -721,7 +729,7 @@ luCommand("r4", 'vtysh -c "show ip route vrf r4-cust2"')
luCommand(
"ce3",
'vtysh -c "show bgp ipv4 uni"',
- "12 routes and 13",
+ "13 routes and 14",
"wait",
"Local and remote routes",
10,
@@ -743,7 +751,7 @@ bgpribRequireUnicastRoutes(
luCommand(
"ce4",
'vtysh -c "show bgp vrf ce4-cust2 ipv4 uni"',
- "12 routes and 14",
+ "13 routes and 15",
"wait",
"Local and remote routes",
10,
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py
index 36be926227..43a5245d0f 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py
@@ -49,7 +49,7 @@ if ret != False and found != None:
luCommand(
rtr,
'vtysh -c "show bgp ipv4 uni" | grep Display',
- " 12 route",
+ " 13 route",
"wait",
"BGP routes removed",
wait,
diff --git a/tests/topotests/srv6_locator_custom_bits_length/test_srv6_locator.py b/tests/topotests/srv6_locator_custom_bits_length/test_srv6_locator_custom_bits_length.py
index 92980d3b17..92980d3b17 100755
--- a/tests/topotests/srv6_locator_custom_bits_length/test_srv6_locator.py
+++ b/tests/topotests/srv6_locator_custom_bits_length/test_srv6_locator_custom_bits_length.py
diff --git a/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py b/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py
index 4b462a51e5..f872f7a258 100755
--- a/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py
+++ b/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py
@@ -59,11 +59,11 @@ def teardown_module(_mod):
tgen.stop_topology()
-def test_zebra_seg6local_routes():
+def test_zebra_seg6_routes():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- logger.info("Test for seg6local route install via ZAPI was start.")
+ logger.info("Test for seg6 route install via ZAPI was start.")
r1 = tgen.gears["r1"]
def check(router, dest, expected):
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 3109f1510d..b1a53965cd 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -2006,7 +2006,7 @@ DEFUNSH(VTYSH_KEYS, key, key_cmd, "key (0-2147483647)",
}
#ifdef HAVE_RIPD
-DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]",
+DEFUNSH(VTYSH_MGMTD, router_rip, router_rip_cmd, "router rip [vrf NAME]",
ROUTER_STR "RIP\n" VRF_CMD_HELP_STR)
{
vty->node = RIP_NODE;
@@ -2015,7 +2015,7 @@ DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]",
#endif /* HAVE_RIPD */
#ifdef HAVE_RIPNGD
-DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng [vrf NAME]",
+DEFUNSH(VTYSH_MGMTD, router_ripng, router_ripng_cmd, "router ripng [vrf NAME]",
ROUTER_STR "RIPng\n" VRF_CMD_HELP_STR)
{
vty->node = RIPNG_NODE;
@@ -2303,7 +2303,7 @@ DEFUNSH(VTYSH_AFFMAP, no_affinity_map, vtysh_no_affinity_map_cmd,
return CMD_SUCCESS;
}
-DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd,
+DEFUNSH(VTYSH_RMAP_CONFIG, vtysh_route_map, vtysh_route_map_cmd,
"route-map RMAP_NAME <deny|permit> (1-65535)",
"Create route-map or enter route-map command mode\n"
"Route map tag\n"
@@ -2545,13 +2545,13 @@ DEFUNSH(VTYSH_ZEBRA, exit_srv6_encap, exit_srv6_encap_cmd, "exit",
}
#ifdef HAVE_RIPD
-DEFUNSH(VTYSH_RIPD, vtysh_exit_ripd, vtysh_exit_ripd_cmd, "exit",
+DEFUNSH(VTYSH_MGMTD, vtysh_exit_ripd, vtysh_exit_ripd_cmd, "exit",
"Exit current mode and down to previous mode\n")
{
return vtysh_exit(vty);
}
-DEFUNSH(VTYSH_RIPD, vtysh_quit_ripd, vtysh_quit_ripd_cmd, "quit",
+DEFUNSH(VTYSH_MGMTD, vtysh_quit_ripd, vtysh_quit_ripd_cmd, "quit",
"Exit current mode and down to previous mode\n")
{
return vtysh_exit_ripd(self, vty, argc, argv);
@@ -2559,26 +2559,26 @@ DEFUNSH(VTYSH_RIPD, vtysh_quit_ripd, vtysh_quit_ripd_cmd, "quit",
#endif /* HAVE_RIPD */
#ifdef HAVE_RIPNGD
-DEFUNSH(VTYSH_RIPNGD, vtysh_exit_ripngd, vtysh_exit_ripngd_cmd, "exit",
+DEFUNSH(VTYSH_MGMTD, vtysh_exit_ripngd, vtysh_exit_ripngd_cmd, "exit",
"Exit current mode and down to previous mode\n")
{
return vtysh_exit(vty);
}
-DEFUNSH(VTYSH_RIPNGD, vtysh_quit_ripngd, vtysh_quit_ripngd_cmd, "quit",
+DEFUNSH(VTYSH_MGMTD, vtysh_quit_ripngd, vtysh_quit_ripngd_cmd, "quit",
"Exit current mode and down to previous mode\n")
{
return vtysh_exit_ripngd(self, vty, argc, argv);
}
#endif /* HAVE_RIPNGD */
-DEFUNSH(VTYSH_RMAP, vtysh_exit_rmap, vtysh_exit_rmap_cmd, "exit",
+DEFUNSH(VTYSH_RMAP_CONFIG, vtysh_exit_rmap, vtysh_exit_rmap_cmd, "exit",
"Exit current mode and down to previous mode\n")
{
return vtysh_exit(vty);
}
-DEFUNSH(VTYSH_RMAP, vtysh_quit_rmap, vtysh_quit_rmap_cmd, "quit",
+DEFUNSH(VTYSH_RMAP_CONFIG, vtysh_quit_rmap, vtysh_quit_rmap_cmd, "quit",
"Exit current mode and down to previous mode\n")
{
return vtysh_exit_rmap(self, vty, argc, argv);
@@ -3455,7 +3455,7 @@ static void show_route_map_send(const char *route_map, bool json)
const struct vtysh_client *client = &vtysh_client[i];
bool is_connected = true;
- if (!CHECK_FLAG(client->flag, VTYSH_RMAP))
+ if (!CHECK_FLAG(client->flag, VTYSH_RMAP_SHOW))
continue;
for (; client; client = client->next)
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index 6bc0c5e2c5..b1e914ebf7 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -49,11 +49,27 @@ extern struct event_loop *master;
VTYSH_PIM6D | VTYSH_NHRPD | VTYSH_EIGRPD | VTYSH_BABELD | \
VTYSH_SHARPD | VTYSH_PBRD | VTYSH_STATICD | VTYSH_BFDD | \
VTYSH_FABRICD | VTYSH_VRRPD | VTYSH_PATHD | VTYSH_MGMTD
-#define VTYSH_ACL VTYSH_BFDD|VTYSH_BABELD|VTYSH_BGPD|VTYSH_EIGRPD|VTYSH_ISISD|VTYSH_FABRICD|VTYSH_LDPD|VTYSH_NHRPD|VTYSH_OSPF6D|VTYSH_OSPFD|VTYSH_PBRD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_VRRPD|VTYSH_ZEBRA
+#define VTYSH_ACL_CONFIG \
+ VTYSH_BFDD | VTYSH_BABELD | VTYSH_BGPD | VTYSH_EIGRPD | VTYSH_ISISD | \
+ VTYSH_FABRICD | VTYSH_LDPD | VTYSH_NHRPD | VTYSH_OSPF6D | \
+ VTYSH_OSPFD | VTYSH_PBRD | VTYSH_PIMD | VTYSH_PIM6D | \
+ VTYSH_VRRPD | VTYSH_ZEBRA | VTYSH_MGMTD
+#define VTYSH_ACL_SHOW \
+ VTYSH_BFDD | VTYSH_BABELD | VTYSH_BGPD | VTYSH_EIGRPD | VTYSH_ISISD | \
+ VTYSH_FABRICD | VTYSH_LDPD | VTYSH_NHRPD | VTYSH_OSPF6D | \
+ VTYSH_OSPFD | VTYSH_PBRD | VTYSH_PIMD | VTYSH_PIM6D | \
+ VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_VRRPD | VTYSH_ZEBRA
+
#define VTYSH_AFFMAP VTYSH_ZEBRA | VTYSH_ISISD
-#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_FABRICD
-#define VTYSH_INTERFACE_SUBSET \
+#define VTYSH_RMAP_CONFIG \
+ VTYSH_ZEBRA | VTYSH_OSPFD | VTYSH_OSPF6D | VTYSH_BGPD | VTYSH_ISISD | \
+ VTYSH_PIMD | VTYSH_EIGRPD | VTYSH_FABRICD | VTYSH_MGMTD
+#define VTYSH_RMAP_SHOW \
VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D | \
+ VTYSH_BGPD | VTYSH_ISISD | VTYSH_PIMD | VTYSH_EIGRPD | \
+ VTYSH_FABRICD
+#define VTYSH_INTERFACE_SUBSET \
+ VTYSH_ZEBRA | VTYSH_OSPFD | VTYSH_OSPF6D | \
VTYSH_ISISD | VTYSH_PIMD | VTYSH_PIM6D | VTYSH_NHRPD | \
VTYSH_EIGRPD | VTYSH_BABELD | VTYSH_PBRD | VTYSH_FABRICD | \
VTYSH_VRRPD | VTYSH_MGMTD
@@ -64,6 +80,9 @@ extern struct event_loop *master;
#define VTYSH_NH_GROUP VTYSH_PBRD|VTYSH_SHARPD
#define VTYSH_SR VTYSH_ZEBRA|VTYSH_PATHD
#define VTYSH_DPDK VTYSH_ZEBRA
+#define VTYSH_MGMT_BACKEND \
+ VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_STATICD | VTYSH_ZEBRA
+#define VTYSH_MGMT_FRONTEND VTYSH_MGMTD
enum vtysh_write_integrated {
WRITE_INTEGRATED_UNSPECIFIED,