diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 04:24:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 04:24:34 +0000 |
commit | 137ce8dd46d313f15ee93ddbb5428d702aa61ed8 (patch) | |
tree | a49f76849019651842962dff2197b705e33831e7 /doc | |
parent | Releasing progress-linux version 9.1-0.1~progress7.99u1. (diff) | |
download | frr-137ce8dd46d313f15ee93ddbb5428d702aa61ed8.tar.xz frr-137ce8dd46d313f15ee93ddbb5428d702aa61ed8.zip |
Merging upstream version 10.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
88 files changed, 2091 insertions, 826 deletions
diff --git a/doc/developer/.readthedocs.yaml b/doc/developer/.readthedocs.yaml index 113672f..90ee5c7 100644 --- a/doc/developer/.readthedocs.yaml +++ b/doc/developer/.readthedocs.yaml @@ -6,6 +6,12 @@ build: os: ubuntu-22.04 tools: python: "3.11" + apt_packages: + - graphviz + +python: + install: + - requirements: doc/developer/requirements.txt # Build documentation in the docs/ directory with Sphinx sphinx: diff --git a/doc/developer/bmp.rst b/doc/developer/bmp.rst new file mode 100644 index 0000000..1c0e4b0 --- /dev/null +++ b/doc/developer/bmp.rst @@ -0,0 +1,49 @@ +.. _bmp: + +*** +BMP +*** + +RFC 7854 +======== +Missing features (non exhaustive): + - Per-Peer Header + + - Peer Type Flag + - Peer Distingsher + + - Peer Up + + - Reason codes (according to TODO comments in code) + +Peer Type Flag and Peer Distinguisher can be implemented easily using RFC 9069's base code. + +RFC 9069 +======== +Everything that isn't listed here is implemented and should be working. +Missing features (should be exhaustive): + +- Per-Peer Header + + - Timestamp + + - set to 0 + - value is now saved `struct bgp_path_info -> locrib_uptime` + - needs testing + +- Peer Up/Down + + - VRF/Table Name TLV + + - code for TLV exists + - need better RFC understanding + +- Peer Down Only + + - Reason code (bc not supported in RFC 7854 either) + +- Statistics Report + + - Stat Type = 8: (64-bit Gauge) Number of routes in Loc-RIB. + - Stat Type = 10: Number of routes in per-AFI/SAFI Loc-RIB. The value is + structured as: 2-byte AFI, 1-byte SAFI, followed by a 64-bit Gauge. diff --git a/doc/developer/building-docker.rst b/doc/developer/building-docker.rst index 9d42784..644e02b 100644 --- a/doc/developer/building-docker.rst +++ b/doc/developer/building-docker.rst @@ -14,7 +14,7 @@ source-built FRR on the following base platforms: The following platform images are used to support Travis CI and can also be used to reproduce topotest failures when the docker host is Ubuntu -(tested on 18.04 and 20.04): +(tested on 20.04 and 22.04): * Ubuntu 20.04 * Ubuntu 22.04 @@ -139,12 +139,12 @@ Build image (from project root directory):: Running Full Topotest:: - docker run --init -it --privileged --name frr -v /lib/modules:/lib/modules \ + docker run --init -it --privileged --name frr-ubuntu20 -v /lib/modules:/lib/modules \ frr-ubuntu20:latest bash -c 'cd ~/frr/tests/topotests ; sudo pytest -nauto --dist=loadfile' Extract results from the above run into `run-results` dir and analyze:: - tests/topotest/analyze.py -C frr -Ar run-results + tests/topotests/analyze.py -C frr-ubuntu20 -Ar run-results Start the container:: @@ -176,12 +176,12 @@ Build image (from project root directory):: Running Full Topotest:: - docker run --init -it --privileged --name frr -v /lib/modules:/lib/modules \ + docker run --init -it --privileged --name frr-ubuntu22 -v /lib/modules:/lib/modules \ frr-ubuntu22:latest bash -c 'cd ~/frr/tests/topotests ; sudo pytest -nauto --dist=loadfile' Extract results from the above run into `run-results` dir and analyze:: - tests/topotest/analyze.py -C frr -Ar run-results + tests/topotests/analyze.py -C frr-ubuntu22 -Ar run-results Start the container:: diff --git a/doc/developer/building-frr-for-archlinux.rst b/doc/developer/building-frr-for-archlinux.rst index 406d22d..8b0df21 100644 --- a/doc/developer/building-frr-for-archlinux.rst +++ b/doc/developer/building-frr-for-archlinux.rst @@ -11,18 +11,12 @@ Installing Dependencies git autoconf automake libtool make cmake pcre readline texinfo \ pkg-config pam json-c bison flex python-pytest \ c-ares python python2-ipaddress python-sphinx \ - net-snmp perl libcap libelf libunwind + net-snmp perl libcap libelf libunwind protobuf-c .. include:: building-libunwind-note.rst .. include:: building-libyang.rst -Protobuf -^^^^^^^^ - -.. code-block:: console - - sudo pacman -S protobuf-c ZeroMQ ^^^^^^ diff --git a/doc/developer/building-frr-for-centos6.rst b/doc/developer/building-frr-for-centos6.rst index 233d089..3531162 100644 --- a/doc/developer/building-frr-for-centos6.rst +++ b/doc/developer/building-frr-for-centos6.rst @@ -124,7 +124,7 @@ Install libyang and its dependencies: sudo yum install pcre-devel doxygen cmake git clone https://github.com/CESNET/libyang.git cd libyang - git checkout 090926a89d59a3c4000719505d563aaf6ac60f2 + git checkout v2.1.128 mkdir build ; cd build cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr -D CMAKE_BUILD_TYPE:String="Release" .. make build-rpm @@ -161,10 +161,8 @@ an example.) ./configure \ --bindir=/usr/bin \ --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ --libdir=/usr/lib/frr \ --libexecdir=/usr/lib/frr \ - --localstatedir=/var/run/frr \ --with-moduledir=/usr/lib/frr/modules \ --disable-pimd \ --enable-snmp=agentx \ diff --git a/doc/developer/building-frr-for-centos7.rst b/doc/developer/building-frr-for-centos7.rst index e6da830..eabf515 100644 --- a/doc/developer/building-frr-for-centos7.rst +++ b/doc/developer/building-frr-for-centos7.rst @@ -58,10 +58,8 @@ an example.) ./configure \ --bindir=/usr/bin \ --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ --libdir=/usr/lib/frr \ --libexecdir=/usr/lib/frr \ - --localstatedir=/var/run/frr \ --with-moduledir=/usr/lib/frr/modules \ --enable-snmp=agentx \ --enable-multipath=64 \ diff --git a/doc/developer/building-frr-for-centos8.rst b/doc/developer/building-frr-for-centos8.rst index 6d18e7b..2d514ea 100644 --- a/doc/developer/building-frr-for-centos8.rst +++ b/doc/developer/building-frr-for-centos8.rst @@ -52,10 +52,8 @@ an example.) ./configure \ --bindir=/usr/bin \ --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ --libdir=/usr/lib/frr \ --libexecdir=/usr/lib/frr \ - --localstatedir=/var/run/frr \ --with-moduledir=/usr/lib/frr/modules \ --enable-snmp=agentx \ --enable-multipath=64 \ diff --git a/doc/developer/building-frr-for-debian12.rst b/doc/developer/building-frr-for-debian12.rst index ca882ee..06bc18c 100644 --- a/doc/developer/building-frr-for-debian12.rst +++ b/doc/developer/building-frr-for-debian12.rst @@ -47,9 +47,9 @@ an example.) cd frr ./bootstrap.sh ./configure \ - --localstatedir=/var/opt/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ diff --git a/doc/developer/building-frr-for-debian8.rst b/doc/developer/building-frr-for-debian8.rst index 7071cb6..fe4eeea 100644 --- a/doc/developer/building-frr-for-debian8.rst +++ b/doc/developer/building-frr-for-debian8.rst @@ -57,9 +57,9 @@ an example.) cd frr ./bootstrap.sh ./configure \ - --localstatedir=/var/run/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ @@ -118,9 +118,9 @@ Troubleshooting The local state directory must exist and have the correct permissions applied for the frrouting daemons to start. In the above ./configure -example the local state directory is set to /var/run/frr -(--localstatedir=/var/run/frr) Debian considers /var/run/frr to be -temporary and this is removed after a reboot. +example the local state directory is set to ``/var`` such that ``/var/run/frr`` +is used. Debian considers ``/var/run/frr`` to be temporary and this is removed +after a reboot. When using a different local state directory you need to create the new directory and change the ownership to the frr user, for example: diff --git a/doc/developer/building-frr-for-debian9.rst b/doc/developer/building-frr-for-debian9.rst index 1b2f1b9..a590cf7 100644 --- a/doc/developer/building-frr-for-debian9.rst +++ b/doc/developer/building-frr-for-debian9.rst @@ -47,9 +47,9 @@ an example.) cd frr ./bootstrap.sh ./configure \ - --localstatedir=/var/opt/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ diff --git a/doc/developer/building-frr-for-freebsd10.rst b/doc/developer/building-frr-for-freebsd10.rst index 707f1e7..beefb59 100644 --- a/doc/developer/building-frr-for-freebsd10.rst +++ b/doc/developer/building-frr-for-freebsd10.rst @@ -60,9 +60,9 @@ an example) export LDFLAGS="-L/usr/local/lib" export CPPFLAGS="-I/usr/local/include" ./configure \ - --sysconfdir=/usr/local/etc/frr \ + --sysconfdir=/usr/local/etc \ + --localstatedir=/var \ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ - --localstatedir=/var/run/frr \ --prefix=/usr/local \ --enable-multipath=64 \ --enable-user=frr \ diff --git a/doc/developer/building-frr-for-freebsd11.rst b/doc/developer/building-frr-for-freebsd11.rst index af0b72b..7c8fb83 100644 --- a/doc/developer/building-frr-for-freebsd11.rst +++ b/doc/developer/building-frr-for-freebsd11.rst @@ -65,9 +65,9 @@ an example) setenv CPPFLAGS -I/usr/local/include ln -s /usr/local/bin/sphinx-build-3.6 /usr/local/bin/sphinx-build ./configure \ - --sysconfdir=/usr/local/etc/frr \ + --sysconfdir=/usr/local/etc \ + --localstatedir=/var \ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ - --localstatedir=/var/run/frr \ --prefix=/usr/local \ --enable-multipath=64 \ --enable-user=frr \ diff --git a/doc/developer/building-frr-for-freebsd13.rst b/doc/developer/building-frr-for-freebsd13.rst index 0bc8277..86506a9 100644 --- a/doc/developer/building-frr-for-freebsd13.rst +++ b/doc/developer/building-frr-for-freebsd13.rst @@ -52,9 +52,9 @@ an example) ./bootstrap.sh export MAKE=gmake LDFLAGS=-L/usr/local/lib CPPFLAGS=-I/usr/local/include ./configure \ - --sysconfdir=/usr/local/etc/frr \ + --sysconfdir=/usr/local/etc \ + --localstatedir=/var \ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ - --localstatedir=/var/run/frr \ --prefix=/usr/local \ --enable-multipath=64 \ --enable-user=frr \ diff --git a/doc/developer/building-frr-for-freebsd14.rst b/doc/developer/building-frr-for-freebsd14.rst new file mode 100644 index 0000000..b3fd37a --- /dev/null +++ b/doc/developer/building-frr-for-freebsd14.rst @@ -0,0 +1,122 @@ +FreeBSD 14 +========== + +FreeBSD 14 restrictions: +------------------------ + +- MPLS is not supported on ``FreeBSD``. MPLS requires a Linux Kernel + (4.5 or higher). LDP can be built, but may have limited use without + MPLS +- PIM for IPv6 is not currently supported on ``FreeBSD``. + +Install required packages +------------------------- + +Add packages: (Allow the install of the package management tool if this +is first package install and asked) + +.. code-block:: shell + + pkg install autoconf automake bison c-ares git gmake json-c libtool \ + libunwind libyang2 pkgconf protobuf-c py39-pytest py39-sphinx texinfo + +.. include:: building-libunwind-note.rst + +Get FRR, compile it and install it (from Git) +--------------------------------------------- + +**This assumes you want to build and install FRR from source and not using any +packages** + +Add frr group and user +^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: shell + + pw groupadd frr -g 101 + pw groupadd frrvty -g 102 + pw adduser frr -g 101 -u 101 -G 102 -c "FRR suite" \ + -d /usr/local/etc/frr -s /usr/sbin/nologin + + +Download Source, configure and compile it +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +(You may prefer different options on configure statement. These are just +an example) + +.. code-block:: shell + + git clone https://github.com/frrouting/frr.git frr + cd frr + ./bootstrap.sh + export MAKE=gmake LDFLAGS=-L/usr/local/lib CPPFLAGS=-I/usr/local/include + ./configure \ + --sysconfdir=/usr/local/etc \ + --localstatedir=/var \ + --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ + --prefix=/usr/local \ + --enable-multipath=64 \ + --enable-user=frr \ + --enable-group=frr \ + --enable-vty-group=frrvty \ + --enable-configfile-mask=0640 \ + --enable-logfile-mask=0640 \ + --enable-fpm \ + --with-pkg-git-version \ + --with-pkg-extra-version=-MyOwnFRRVersion + gmake + gmake check + sudo gmake install + +Create empty FRR configuration files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: shell + + sudo mkdir /usr/local/etc/frr + +For integrated config file: + +.. code-block:: shell + + sudo touch /usr/local/etc/frr/frr.conf + +For individual config files: + +.. note:: Integrated config is preferred to individual config. + +.. code-block:: shell + + sudo touch /usr/local/etc/frr/babeld.conf + sudo touch /usr/local/etc/frr/bfdd.conf + sudo touch /usr/local/etc/frr/bgpd.conf + sudo touch /usr/local/etc/frr/eigrpd.conf + sudo touch /usr/local/etc/frr/isisd.conf + sudo touch /usr/local/etc/frr/ldpd.conf + sudo touch /usr/local/etc/frr/nhrpd.conf + sudo touch /usr/local/etc/frr/ospf6d.conf + sudo touch /usr/local/etc/frr/ospfd.conf + sudo touch /usr/local/etc/frr/pbrd.conf + sudo touch /usr/local/etc/frr/pimd.conf + sudo touch /usr/local/etc/frr/ripd.conf + sudo touch /usr/local/etc/frr/ripngd.conf + sudo touch /usr/local/etc/frr/staticd.conf + sudo touch /usr/local/etc/frr/zebra.conf + sudo chown -R frr:frr /usr/local/etc/frr/ + sudo touch /usr/local/etc/frr/vtysh.conf + sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf + sudo chmod 640 /usr/local/etc/frr/*.conf + +Enable IP & IPv6 forwarding +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Add the following lines to the end of ``/etc/sysctl.conf``: + +:: + + # Routing: We need to forward packets + net.inet.ip.forwarding=1 + net.inet6.ip6.forwarding=1 + +**Reboot** or use ``sysctl`` to apply the same config to the running system. diff --git a/doc/developer/building-frr-for-freebsd9.rst b/doc/developer/building-frr-for-freebsd9.rst index 3033287..9f9073d 100644 --- a/doc/developer/building-frr-for-freebsd9.rst +++ b/doc/developer/building-frr-for-freebsd9.rst @@ -70,9 +70,9 @@ an example) export LDFLAGS="-L/usr/local/lib" export CPPFLAGS="-I/usr/local/include" ./configure \ - --sysconfdir=/usr/local/etc/frr \ + --sysconfdir=/usr/local/etc \ + --localstatedir=/var \ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ - --localstatedir=/var/run/frr \ --prefix=/usr/local \ --enable-multipath=64 \ --enable-user=frr \ diff --git a/doc/developer/building-frr-for-netbsd6.rst b/doc/developer/building-frr-for-netbsd6.rst index 8958862..77c0e00 100644 --- a/doc/developer/building-frr-for-netbsd6.rst +++ b/doc/developer/building-frr-for-netbsd6.rst @@ -64,9 +64,9 @@ an example) export LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib" export CPPFLAGS="-I/usr/pkg/include" ./configure \ - --sysconfdir=/usr/pkg/etc/frr \ + --sysconfdir=/usr/pkg/etc \ + --localstatedir=/var \ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ - --localstatedir=/var/run/frr \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ diff --git a/doc/developer/building-frr-for-netbsd7.rst b/doc/developer/building-frr-for-netbsd7.rst index e751ba3..abb04a0 100644 --- a/doc/developer/building-frr-for-netbsd7.rst +++ b/doc/developer/building-frr-for-netbsd7.rst @@ -55,9 +55,9 @@ an example) export LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib" export CPPFLAGS="-I/usr/pkg/include" ./configure \ - --sysconfdir=/usr/pkg/etc/frr \ + --sysconfdir=/usr/pkg/etc \ + --localstatedir=/var \ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ - --localstatedir=/var/run/frr \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ diff --git a/doc/developer/building-frr-for-openbsd6.rst b/doc/developer/building-frr-for-openbsd6.rst index 00bc2e5..6d7f346 100644 --- a/doc/developer/building-frr-for-openbsd6.rst +++ b/doc/developer/building-frr-for-openbsd6.rst @@ -71,8 +71,8 @@ an example) export LDFLAGS="-L/usr/local/lib" export CPPFLAGS="-I/usr/local/include" ./configure \ - --sysconfdir=/etc/frr \ - --localstatedir=/var/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --enable-multipath=64 \ --enable-user=_frr \ --enable-group=_frr \ diff --git a/doc/developer/building-frr-for-opensuse.rst b/doc/developer/building-frr-for-opensuse.rst index 3ff445b..6e9913d 100644 --- a/doc/developer/building-frr-for-opensuse.rst +++ b/doc/developer/building-frr-for-opensuse.rst @@ -13,11 +13,13 @@ Installing Dependencies zypper in git autoconf automake libtool make \ readline-devel texinfo net-snmp-devel groff pkgconfig libjson-c-devel\ pam-devel python3-pytest bison flex c-ares-devel python3-devel\ - python3-Sphinx perl patch libcap-devel libyang-devel \ + python3-Sphinx perl patch libcap-devel \ libelf-devel libunwind-devel protobuf-c .. include:: building-libunwind-note.rst +.. include:: building-libyang.rst + Building & Installing FRR ------------------------- diff --git a/doc/developer/building-frr-for-ubuntu1404.rst b/doc/developer/building-frr-for-ubuntu1404.rst index cc6c3c0..dd3f98a 100644 --- a/doc/developer/building-frr-for-ubuntu1404.rst +++ b/doc/developer/building-frr-for-ubuntu1404.rst @@ -14,16 +14,11 @@ Installing Dependencies git autoconf automake libtool make libreadline-dev texinfo \ pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \ libc-ares-dev python3-dev python3-sphinx install-info build-essential \ + protobuf-c-compiler libprotobuf-c-dev \ libsnmp-dev perl libcap-dev libelf-dev .. include:: building-libyang.rst -Protobuf -^^^^^^^^ - -.. code-block:: console - - sudo apt-get install protobuf-c-compiler libprotobuf-c-dev Building & Installing FRR ------------------------- diff --git a/doc/developer/building-frr-for-ubuntu1604.rst b/doc/developer/building-frr-for-ubuntu1604.rst index e5c2389..f3b6aa0 100644 --- a/doc/developer/building-frr-for-ubuntu1604.rst +++ b/doc/developer/building-frr-for-ubuntu1604.rst @@ -19,12 +19,6 @@ Installing Dependencies .. include:: building-libyang.rst -Protobuf -^^^^^^^^ - -.. code-block:: console - - sudo apt-get install protobuf-c-compiler libprotobuf-c-dev Building & Installing FRR ------------------------- diff --git a/doc/developer/building-frr-for-ubuntu1804.rst b/doc/developer/building-frr-for-ubuntu1804.rst index fcfd94e..b4880e2 100644 --- a/doc/developer/building-frr-for-ubuntu1804.rst +++ b/doc/developer/building-frr-for-ubuntu1804.rst @@ -15,18 +15,13 @@ Installing Dependencies pkg-config libpam0g-dev libjson-c-dev bison flex \ libc-ares-dev python3-dev python3-sphinx \ install-info build-essential libsnmp-dev perl libcap-dev \ + protobuf-c-compiler libprotobuf-c-dev \ libelf-dev libunwind-dev .. include:: building-libunwind-note.rst .. include:: building-libyang.rst -Protobuf -^^^^^^^^ - -.. code-block:: console - - sudo apt-get install protobuf-c-compiler libprotobuf-c-dev ZeroMQ ^^^^^^ diff --git a/doc/developer/building-frr-for-ubuntu2004.rst b/doc/developer/building-frr-for-ubuntu2004.rst index fdfc25d..3db97c4 100644 --- a/doc/developer/building-frr-for-ubuntu2004.rst +++ b/doc/developer/building-frr-for-ubuntu2004.rst @@ -15,34 +15,33 @@ Installing Dependencies pkg-config libpam0g-dev libjson-c-dev bison flex \ libc-ares-dev python3-dev python3-sphinx \ install-info build-essential libsnmp-dev perl \ - libcap-dev python2 libelf-dev libunwind-dev + protobuf-c-compiler libprotobuf-c-dev \ + libcap-dev libelf-dev libunwind-dev .. include:: building-libunwind-note.rst -Note that Ubuntu 20 no longer installs python 2.x, so it must be -installed explicitly. Ensure that your system has a symlink named -``/usr/bin/python`` pointing at ``/usr/bin/python3``. +.. include:: building-libyang.rst -In addition, ``pip`` for python2 must be installed if you wish to run -the FRR topotests. That version of ``pip`` is not available from the -ubuntu apt repositories; in order to install it: +GRPC +^^^^ +If GRPC is enabled using ``--enable-grpc`` the following packages should be +installed. -.. code-block:: shell +.. code-block:: console - curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py - sudo python2 ./get-pip.py + sudo apt-get install libgrpc++-dev protobuf-compiler-grpc - # And verify the installation - pip2 --version -.. include:: building-libyang.rst +Config Rollbacks +^^^^^^^^^^^^^^^^ -Protobuf -^^^^^^^^ +If config rollbacks are enabled using ``--enable-config-rollbacks`` +the sqlite3 developer package also should be installed. .. code-block:: console - sudo apt-get install protobuf-c-compiler libprotobuf-c-dev + sudo apt install libsqlite3-dev + ZeroMQ ^^^^^^ diff --git a/doc/developer/building-frr-for-ubuntu2204.rst b/doc/developer/building-frr-for-ubuntu2204.rst index 97bdf88..c898c3c 100644 --- a/doc/developer/building-frr-for-ubuntu2204.rst +++ b/doc/developer/building-frr-for-ubuntu2204.rst @@ -15,40 +15,21 @@ Installing Dependencies pkg-config libpam0g-dev libjson-c-dev bison flex \ libc-ares-dev python3-dev python3-sphinx \ install-info build-essential libsnmp-dev perl \ - libcap-dev python2 libelf-dev libunwind-dev \ - libyang2 libyang2-dev + libcap-dev libelf-dev libunwind-dev \ + protobuf-c-compiler libprotobuf-c-dev .. include:: building-libunwind-note.rst -Note that Ubuntu >= 20 no longer installs python 2.x, so it must be -installed explicitly. Ensure that your system has a symlink named -``/usr/bin/python`` pointing at ``/usr/bin/python3``. +.. include:: building-libyang.rst -.. code-block:: shell - - sudo ln -s /usr/bin/python3 /usr/bin/python - python --version - -In addition, ``pip`` for python2 must be installed if you wish to run -the FRR topotests. That version of ``pip`` is not available from the -ubuntu apt repositories; in order to install it: - -.. code-block:: shell - - curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py - sudo python2 ./get-pip.py - - # And verify the installation - pip2 --version - - -Protobuf -^^^^^^^^ -This is optional +GRPC +^^^^ +If GRPC is enabled using ``--enable-grpc`` the following packages should be +installed. .. code-block:: console - sudo apt-get install protobuf-c-compiler libprotobuf-c-dev + sudo apt-get install libgrpc++-dev protobuf-compiler-grpc Config Rollbacks diff --git a/doc/developer/building-libyang.rst b/doc/developer/building-libyang.rst index c36cd34..a46c793 100644 --- a/doc/developer/building-libyang.rst +++ b/doc/developer/building-libyang.rst @@ -10,11 +10,11 @@ The FRR project builds some binary ``libyang`` packages. RPM packages are at our `RPM repository <https://rpm.frrouting.org>`_. DEB packages are available as CI artifacts `here -<https://ci1.netdef.org/browse/LIBYANG-LIBYANGV2/latestSuccessful/artifact>`_. +<https://ci1.netdef.org/browse/LIBYANG-LIBYANG21/latestSuccessful/artifact>`_. .. warning:: - ``libyang`` version 2.0.0 or newer is required to build FRR. + ``libyang`` version 2.1.128 or newer is required to build FRR. .. note:: @@ -39,7 +39,7 @@ DEB packages are available as CI artifacts `here git clone https://github.com/CESNET/libyang.git cd libyang - git checkout v2.0.0 + git checkout v2.1.128 mkdir build; cd build cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr \ -D CMAKE_BUILD_TYPE:String="Release" .. diff --git a/doc/developer/building.rst b/doc/developer/building.rst index 8ca0c13..6762604 100644 --- a/doc/developer/building.rst +++ b/doc/developer/building.rst @@ -21,6 +21,7 @@ Building FRR building-frr-for-freebsd10 building-frr-for-freebsd11 building-frr-for-freebsd13 + building-frr-for-freebsd14 building-frr-for-netbsd6 building-frr-for-netbsd7 building-frr-for-openbsd6 diff --git a/doc/developer/cross-compiling.rst b/doc/developer/cross-compiling.rst index 3bf78f7..af99262 100644 --- a/doc/developer/cross-compiling.rst +++ b/doc/developer/cross-compiling.rst @@ -239,9 +239,9 @@ the last thing to actually build is FRR itself: --host=${HOST_ARCH} \ --with-sysroot=/usr/${HOST_ARCH} \ --with-clippy=./build-clippy/lib/clippy \ - --sysconfdir=/etc/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --sbindir="\${prefix}/lib/frr" \ - --localstatedir=/var/run/frr \ --prefix=/usr \ --enable-user=frr \ --enable-group=frr \ diff --git a/doc/developer/frr-release-procedure.rst b/doc/developer/frr-release-procedure.rst index 9378637..9dbc9b4 100644 --- a/doc/developer/frr-release-procedure.rst +++ b/doc/developer/frr-release-procedure.rst @@ -13,6 +13,13 @@ Stage 1 - Preparation Note: use ``tools/release_notes.py`` to help draft release notes changelog + .. code-block:: console + + ./tools/release_notes.py -b dev/9.1 -t frr-9.0.1 + + dev/9.1 is the branch to be renamed to stable/9.1, and frr-9.0.1 in this + example is the latest tag from which to generate the logs. + #. Checkout the existing ``dev/<version>`` branch. .. code-block:: console diff --git a/doc/developer/include-compile.rst b/doc/developer/include-compile.rst index b98d237..49fd6c8 100644 --- a/doc/developer/include-compile.rst +++ b/doc/developer/include-compile.rst @@ -14,8 +14,8 @@ obtained by running ``./configure -h``. The options shown below are examples. --sbindir=\${prefix}/lib/frr \ --libdir=\${prefix}/lib/frr \ --libexecdir=\${prefix}/lib/frr \ - --localstatedir=/var/run/frr \ - --sysconfdir=/etc/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --with-moduledir=\${prefix}/lib/frr/modules \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ diff --git a/doc/developer/mgmtd-dev.rst b/doc/developer/mgmtd-dev.rst index 9839aa8..2404ffe 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,18 +33,64 @@ each daemon. ``mgmtd`` currently provides the CLI interface for each daemon that has been converted to it, but in the future RESTCONF and NETCONF servers can easily be added as *front-ends* to mgmtd to support those protocols as well. +Conversion Status +^^^^^^^^^^^^^^^^^ + +Fully Converted To MGMTD +"""""""""""""""""""""""" + +- lib/distribute +- lib/filter +- lib/if_rmap +- lib/routemap +- lib/affinitymap +- lib/if +- lib/vrf +- ripd +- ripngd +- staticd +- zebra (* - partial) + +Converted To Northbound +""""""""""""""""""""""" +- bfdd +- pathd +- pbrd +- pimd + +Converted To Northbound With Issues +""""""""""""""""""""""""""""""""""" +- eigrp +- isisd + +Unconverted +""""""""""" +- babel +- bgpd +- ldpd +- lib/event +- lib/keychain +- lib/log_vty +- lib/nexthop_group +- lib/zlog_5424_cli +- nhrpd +- ospfd +- ospf6d +- pceplib +- qdb +- sharpd +- vrrpd Converting A Daemon to MGMTD -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +---------------------------- -A daemon must first be transitioned to the new *northbound* interface if that -has not already been done (see `this northbound conversion documentation -<https://github.com/opensourcerouting/frr/wiki/Retrofitting-Configuration-Commands>`_ -for how to do this). Once this is done a few simple steps are all that is -required move the daemon over to ``mgmtd`` control. +A daemon must first be transitioned to the new :ref:`northbound` interface if that +has not already been done (see :ref:`nb-retrofit` for how to do this). Once this +is done a few simple steps are all that is required move the daemon over to +``mgmtd`` control. Overview of Changes -------------------- +^^^^^^^^^^^^^^^^^^^ Adding support for a *northbound* converted daemon involves very little work. It requires enabling *frontend* (CLI and YANG) and *backend* (YANG) support. @@ -52,64 +98,126 @@ 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.c``) -2. Add YANG module description into array defined in ``mgmtd/mgmt_main.c`` -3. Add CLI handler file[s] to ``mgmtd/subdir.am`` (e.g., ``staticd/static_vty.c``) -4. [if needed] Exclude (#ifndef) non-configuration CLI handlers from CLI source - file (e.g., inside ``staticd/static_vty.c``) +#. 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: -5. Add XPATHs mappings to a couple arrays to direct ``mgmtd`` at your daemon in - ``mgmtd/mgmt_be_adapter.c`` - +#. In the daemon's main file initialize the BE client library. You add a global + `struct mgmt_be_client *mgmt_be_client` near the daemons `event_loop *master` + variable. Then where the daemon used to initialize it's CLI/VTY code replace + that with the client initialization by calling `mgmt_be_client_create`. + Likewise in the daemon's sigint cleanup code, operational walks should be + canceled with a call to `nb_oper_cancel_all_walks`, and then the BE client + should be destroyed with a call to `mgmt_be_client_destroy` and to be safe + NULL out the global `mgmt_be_client` variable. + +#. In ``mgmtd/mgmt_be_adapter.c`` add xpath prefix mappings to a one or both + mapping arrays (``be_client_config_xpaths`` and ``be_client_oper_xpaths``) to + direct ``mgmtd`` to send config and oper-state requests to your daemon. NOTE: + make sure to include library supported xpaths prefixes as well (e.g., + "/frr-interface:lib"). A good way to figure these paths out are to look in + each of the YANG modules that the daemon uses and include each of their paths + in the array. Add YANG and CLI into MGMTD ---------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ As an example here is the addition made to ``mgmtd/subdir.am`` for adding ``staticd`` support. .. code-block:: make - if STATICD - nodist_mgmtd_mgmtd_SOURCES += \ + if STATICD + nodist_mgmtd_mgmtd_SOURCES += \ yang/frr-staticd.yang.c \ yang/frr-bfdd.yang.c \ # end - nodist_mgmtd_libmgmt_be_nb_la_SOURCES += staticd/static_vty.c - endif + nodist_mgmtd_libmgmt_be_nb_la_SOURCES += staticd/static_vty.c + endif An here is the addition to the modules array in ``mgmtd/mgmt_main.c``: .. code-block:: c - static const struct frr_yang_module_info *const mgmt_yang_modules[] = { + #ifdef HAVE_STATICD + extern const struct frr_yang_module_info frr_staticd_info; + #endif + + static const struct frr_yang_module_info *const mgmt_yang_modules[] = { &frr_filter_info, ... - #ifdef HAVE_STATICD - &(struct frr_yang_module_info){.name = "frr-staticd", - .ignore_cbs = true}, - #endif - } + #ifdef HAVE_STATICD + &frr_staticd_info, + #endif + } -CLI Handlers ------------- +CLI Config and Show Handlers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The daemon's CLI handlers for configuration (which having been converted to -*northbound* now simply generate YANG changes) will be linked directly into +The daemon's CLI handlers for configuration (which having been converted to the +:ref:`northbound` now simply generate YANG changes) will be linked directly into ``mgmtd``. If the operational and debug CLI commands are kept in files separate from the daemon's configuration CLI commands then no extra work is required. Otherwise some CPP #ifndef's will be required. -Currently ``mgmtd`` supports configuration CLI but not operational -state so if both types of CLI handlers are present in a single file (e.g. a -``xxx_vty.c`` or ``xxx_cli.c`` file ) then #ifndef will be used to exclude these -non-configuration CLI handlers from ``mgmtd``. The same goes for *debug* CLI -handlers. For example: +``mgmtd`` supports both config and operational state. However, many +daemons have not had their operational state CLI commands converted over to the +new YANG based methods. If that is the case and if both types of CLI handlers +are present in a single file (e.g. a ``xxx_vty.c`` or ``xxx_cli.c`` file) then +:code:`#ifndef` will need to be used to exclude the non-config CLI handlers from +``mgmtd``. The same goes for unconverted *debug* CLI handlers. For example: .. code-block:: c @@ -121,7 +229,7 @@ handlers. For example: } #ifndef INCLUDE_MGMTD_CMDDEFS_ONLY - DEFPY(daemon_show_oepr, daemon_show_oepr_cmd, + DEFPY(daemon_show_oper, daemon_show_oper_cmd, "show daemon oper [all]" ... { @@ -140,83 +248,136 @@ handlers. For example: } +.. _mgmtd-config-write: + +CLI Config Write Handlers (:code:`cli_show`) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To support writing out the CLI configuration file the northbound API defines a +2 callbacks (:code:`cli_show` and :code:`cli_show_end`). Pointers to these +callbacks used to live side-by-side in a daemons :code:`struct frr_yang_module_info`, +with the daemons back-end configuration and operational state callbacks +(normally in a file named `<daemon>_nb.c`). + +However, these 2 functionalities need to be split up now. The *frontend* config +writing callbacks (:code:`cli_show`) should now be linked into ``mgmtd`` while +the *backend* config and oper-state callbacks (e.g., :code:`create`, +:code:`modify`, etc) should continue to be linked into the daemon. + +So you will need to define 2 :code:`struct frr_yang_module_info` arrays. + +#. The existing array remains in the same place in the daemon, but with all the + :code:`cli_show` handlers removed. + +#. The removed :code:`cli_show` handlers should be added to a new + :code:`struct frr_yang_module_info` array. This second array should be + included in the same file that includes that actual function pointed to by + the the :code:`cli_show` callbacks (i.e., the file is compiled into + ``mgmtd``). + + This new :code:`struct frr_yang_module_info` array is the one to be included + in mgmtd in `mgmt_yang_modules` inside ``mgmtd/mgmt_main.c``. + +Back-End Client Connection +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In order for your daemon to communicate with mgmtd you need to initialize the +backend client library. You normally do this where you used to initialize your +CLI/VTY code. + +.. code-block:: c + + ... + struct event_loop *master; -Add Back-End XPATH mappings ---------------------------- + static struct mgmt_be_client *mgmt_be_client; + ... + + int main(int argc, char **argv) + { + ... + rip_init(); + rip_if_init(); + mgmt_be_client = mgmt_be_client_create("ripd", NULL, 0, master); + +Likewise the client should be cleaned up in the daemon cleanup routine. + +.. code-block:: c + + /* SIGINT handler. */ + static void sigint(void) + { + zlog_notice("Terminating on signal"); + ... + nb_oper_cancel_all_walks(); + mgmt_be_client_destroy(mgmt_be_client); + mgmt_be_client = NULL; + + +Back-End XPATH mappings +^^^^^^^^^^^^^^^^^^^^^^^ In order for ``mgmtd`` to direct configuration to your daemon you need to add some XPATH mappings to ``mgmtd/mgmt_be_adapter.c``. These XPATHs determine which configuration changes get sent over the *back-end* interface to your daemon. +There are 2 arrays to update the first for config support and the second for +operational state. -Below are the strings added for staticd support: +Below are the strings added for staticd config support: .. code-block:: c - static const struct mgmt_be_xpath_map_init mgmt_xpath_map_init[] = { - { - .xpath_regexp = "/frr-vrf:lib/*", - .subscr_info = - { - #if HAVE_STATICD - [MGMTD_BE_CLIENT_ID_STATICD] = - MGMT_SUBSCR_VALIDATE_CFG | - MGMT_SUBSCR_NOTIFY_CFG, - #endif - }, - }, - ... - { - .xpath_regexp = - "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/*", - .subscr_info = - { - #if HAVE_STATICD - [MGMTD_BE_CLIENT_ID_STATICD] = - MGMT_SUBSCR_VALIDATE_CFG | - MGMT_SUBSCR_NOTIFY_CFG, - #endif - }, - }, - }; - - #if HAVE_STATICD - static struct mgmt_be_client_xpath staticd_xpaths[] = { - { - .xpath = "/frr-vrf:lib/*", - .subscribed = MGMT_SUBSCR_VALIDATE_CFG | MGMT_SUBSCR_NOTIFY_CFG, - }, - ... - { - .xpath = - "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/*", - .subscribed = MGMT_SUBSCR_VALIDATE_CFG | MGMT_SUBSCR_NOTIFY_CFG, - }, - }; - #endif - - static struct mgmt_be_client_xpath_map - mgmt_client_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { - #ifdef HAVE_STATICD - [MGMTD_BE_CLIENT_ID_STATICD] = {staticd_xpaths, - array_size(staticd_xpaths)}, - #endif - }; + #if HAVE_STATICD + static const char *const staticd_xpaths[] = { + "/frr-vrf:lib", + "/frr-interface:lib", + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd", + NULL, + }; + #endif + + static const char *const *be_client_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { + #ifdef HAVE_STATICD + [MGMTD_BE_CLIENT_ID_STATICD] = staticd_xpaths, + #endif + }; +Below are the strings added for zebra operational state support (note zebra is +not conditionalized b/c it should always be present): + +.. code-block:: c + + static const char *const zebra_oper_xpaths[] = { + "/frr-interface:lib/interface", + "/frr-vrf:lib/vrf/frr-zebra:zebra", + "/frr-zebra:zebra", + NULL, + }; + + static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { + [MGMTD_BE_CLIENT_ID_ZEBRA] = zebra_oper_xpaths, + }; MGMTD Internals -^^^^^^^^^^^^^^^ +--------------- This section will describe the internal functioning of ``mgmtd``, for now a couple diagrams are included to aide in source code perusal. -The client side of a CLI change +The client side of a CLI configuration change .. figure:: ../figures/cli-change-client.svg :align: center -The server (mgmtd) side of a CLI change +The server (mgmtd) side of a CLI configuration change .. figure:: ../figures/cli-change-mgmtd.svg :align: center + + +The client and server sides of oper-state query + +.. figure:: ../figures/cli-oper-state.svg + :align: center diff --git a/doc/developer/northbound/advanced-topics.rst b/doc/developer/northbound/advanced-topics.rst index bee29a9..edfc10b 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 e571971..5fd89c3 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 876bd25..8a0f6ad 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 e80374c..6cec176 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 7dddf06..c5f4e2f 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 554bc17..5cb70ca 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 186c3a0..0cfdb82 100644 --- a/doc/developer/northbound/plugins-sysrepo.rst +++ b/doc/developer/northbound/plugins-sysrepo.rst @@ -1,137 +1,193 @@ +Plugins Sysrepo +=============== + Installation ------------ Required dependencies ^^^^^^^^^^^^^^^^^^^^^ +Install FRR build required dependencies, check `Building FRR +<https://docs.frrouting.org/projects/dev-guide/en/latest/building.html>`_ document for specific platform required packages. +Below are debian systems required packages: -:: +.. code-block:: console - # apt-get install git cmake build-essential bison flex libpcre3-dev libev-dev \ - libavl-dev libprotobuf-c-dev protobuf-c-compiler libcmocka0 \ - libcmocka-dev doxygen libssl-dev libssl-dev libssh-dev + sudo apt-get install git autoconf automake libtool make \ + libprotobuf-c-dev protobuf-c-compiler build-essential \ + python3-dev python3-pytest python3-sphinx libjson-c-dev \ + libelf-dev libreadline-dev cmake libcap-dev bison flex \ + pkg-config texinfo gdb libgrpc-dev python3-grpc-tools libpcre2-dev libyang ^^^^^^^ -:: +.. note:: - # apt-get install libyang0.16 libyang-dev + FRR requires version 2.1.128 or newer, in this document we will + be compiling and installing libyang version 2.1.148. -Sysrepo -^^^^^^^ +.. code-block:: console -:: + git clone https://github.com/CESNET/libyang.git + cd libyang + git checkout v2.1.148 + mkdir build; cd build + cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + -DCMAKE_BUILD_TYPE:String="Release" .. + make + sudo make install - $ git clone https://github.com/sysrepo/sysrepo.git - $ cd sysrepo/ - $ mkdir build; cd build - $ cmake -DCMAKE_BUILD_TYPE=Release -DGEN_LANGUAGE_BINDINGS=OFF .. && make - # make install +Sysrepo +^^^^^^^ -libnetconf2 -^^^^^^^^^^^ +.. note:: -:: + The following code block assumes you have installed libyang v2.1.148, if you have + libyang v2.1.128 change sysrepo version to 2.2.105. - $ git clone https://github.com/CESNET/libnetconf2.git - $ cd libnetconf2/ - $ mkdir build; cd build - $ cmake .. && make - # make install +.. code-block:: console -netopeer2 -^^^^^^^^^ + git clone https://github.com/sysrepo/sysrepo.git + cd sysrepo/ + git checkout v2.2.150 + mkdir build; cd build + cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + -DCMAKE_BUILD_TYPE:String="Release" .. + make + sudo make install -:: +Verify that sysrepo is installed correctly: - $ git clone https://github.com/CESNET/Netopeer2.git - $ cd Netopeer2 - $ cd server - $ mkdir build; cd build - $ cmake .. && make - # make install +.. code-block:: console -**Note:** If ``make install`` fails as it can’t find -``libsysrepo.so.0.7``, then run ``ldconfig`` and try again as it might -not have updated the lib search path + sudo sysrepoctl -l FRR ^^^ -Build and install FRR using the ``--enable-sysrepo`` configure-time -option. +Follow the steps of `Building FRR +<https://docs.frrouting.org/projects/dev-guide/en/latest/building.html>`_ + + +Make sure to use ``--enable-sysrepo`` configure-time option while building FRR. + +Below is an example of frr configure-time options, your options +might vary, however in order to allow sysrepo plugin you have +to keep ``--enable-sysrepo`` option: + +.. code-block:: console + + ./bootstrap.sh + ./configure \ + --localstatedir=/var/opt/frr \ + --sbindir=/usr/lib/frr \ + --sysconfdir=/etc/frr \ + --enable-multipath=64 \ + --enable-user=frr \ + --enable-group=frr \ + --enable-vty-group=frrvty \ + --enable-configfile-mask=0640 \ + --enable-logfile-mask=0640 \ + --enable-fpm \ + --enable-sysrepo \ + --with-pkg-git-version \ + --with-pkg-extra-version=-MyOwnFRRVersion + make + make check + sudo make install + Initialization -------------- -Install the FRR YANG modules in the Sysrepo datastore: +Install FRR YANG modules in Sysrepo datastore: -:: +.. code-block:: console - # sysrepoctl --install /usr/local/share/yang/ietf-interfaces@2018-01-09.yang - # sysrepoctl --install /usr/local/share/yang/frr-vrf.yang - # sysrepoctl --install /usr/local/share/yang/frr-interface.yang - # sysrepoctl --install /usr/local/share/yang/frr-route-types.yang - # sysrepoctl --install /usr/local/share/yang/frr-filter.yang - # sysrepoctl --install /usr/local/share/yang/frr-route-map.yang - # sysrepoctl --install /usr/local/share/yang/frr-isisd.yang - # sysrepoctl --install /usr/local/share/yang/frr-ripd.yang - # sysrepoctl --install /usr/local/share/yang/frr-ripngd.yang - # sysrepoctl -c frr-vrf --owner frr --group frr - # sysrepoctl -c frr-interface --owner frr --group frr - # sysrepoctl -c frr-route-types --owner frr --group frr - # sysrepoctl -c frr-filter --owner frr --group frr - # sysrepoctl -c frr-route-map --owner frr --group frr - # sysrepoctl -c frr-isisd --owner frr --group frr - # sysrepoctl -c frr-ripd --owner frr --group frr - # sysrepoctl -c frr-ripngd --owner frr --group frr + cd frr/yang/ + sudo sysrepoctl -i ./ietf/ietf-interfaces.yang -o frr -g frr + sudo sysrepoctl -i frr-vrf.yang -o frr -g frr + sudo sysrepoctl -i frr-interface.yang -o frr -g frr + sudo sysrepoctl -i frr-route-types.yang -o frr -g frr + sudo sysrepoctl -i frr-filter.yang -o frr -g frr + sudo sysrepoctl -i frr-route-map.yang -o frr -g frr + sudo sysrepoctl -i frr-isisd.yang -o frr -g frr + sudo sysrepoctl -i frr-bfdd.yang -o frr -g frr + sudo sysrepoctl -i ./ietf/ietf-routing-types.yang -o frr -g frr + sudo sysrepoctl -i frr-nexthop.yang -o frr -g frr + sudo sysrepoctl -i frr-if-rmap.yang -o frr -g frr + sudo sysrepoctl -i frr-ripd.yang -o frr -g frr + sudo sysrepoctl -i frr-ripngd.yang -o frr -g frr + sudo sysrepoctl -i frr-affinity-map.yang -o frr -g frr + sudo sysrepoctl -i ./ietf/frr-deviations-ietf-interfaces.yang -o frr -g frr -Start netopeer2-server: -:: +Start FRR daemons with sysrepo plugin: - # netopeer2-server -d & +.. code-block:: console -Start the FRR daemons with the sysrepo module: + sudo /usr/lib/frr/isisd -M sysrepo --log stdout -:: - - # isisd -M sysrepo --log=stdout +Any daemon running with ``-M sysrepo`` will subscribe to its frr yang moduels +on sysrepo and you be able to configure it by editing module configuration on sysrepo. Managing the configuration -------------------------- -The following NETCONF scripts can be used to show and edit the FRR -configuration: -https://github.com/rzalamena/ietf-hackathon-brazil-201907/tree/master/netconf-scripts +Testing +^^^^^^^ -Example: +To test FRR intergartion with sysrepo, ``sysrepocfg`` tool can be used +to edit frr configuration on sysrepo -:: +Example: - # ./netconf-edit.py 127.0.0.1 - # ./netconf-get-config.py 127.0.0.1 - <?xml version="1.0" encoding="UTF-8"?><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"><isis xmlns="http://frrouting.org/yang/isisd"><instance><area-tag>testnet</area-tag><is-type>level-1</is-type></instance></isis></data> +Edit sysrepo running datastore configuration for the desiged frr module: -.. +.. code-block:: console - NOTE: the ncclient library needs to be installed first: - ``apt install -y python3-ncclient`` + sudo sysrepocfg -E nano -d running -m frr-isisd -f json -The *sysrepocfg* tool can also be used to show/edit the FRR -configuration. Example: +Paste the following json configuration: -:: +.. code-block:: console - # sysrepocfg --format=json --import=frr-isisd.json --datastore=running frr-isisd - # sysrepocfg --format=json --export --datastore=running frr-isisd { "frr-isisd:isis": { "instance": [ { "area-tag": "testnet", + "vrf": "default", "is-type": "level-1" } ] } } + +Exit and save config to the same file. + +After that, this configuration should get reflected to vtysh: + +.. code-block:: console + + show run + Building configuration... + + Current configuration: + ! + frr version 9.2-dev-MyOwnFRRVersion + frr defaults traditional + hostname bullseye + ! + router isis testnet + is-type level-1 + exit + ! + end + +NETCONF +^^^^^^^ + +To manage sysrepo configuration through netconf +you can use `netopeer2 <https://github.com/CESNET/netopeer2>`_ as a netfconf server that can +be easily integrated with sysrepo. diff --git a/doc/developer/northbound/ppr-basic-test-topology.rst b/doc/developer/northbound/ppr-basic-test-topology.rst index a680ed7..4929c9b 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 cedb795..aceec5f 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 b407246..d328be9 100644 --- a/doc/developer/northbound/retrofitting-configuration-commands.rst +++ b/doc/developer/northbound/retrofitting-configuration-commands.rst @@ -1,5 +1,16 @@ + +.. _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 @@ -7,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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -30,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. @@ -726,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 @@ -965,34 +982,30 @@ future. For libfrr commands, it’s not possible to centralize all commands in a single file because the *extract.pl* script from *vtysh* treats commands differently depending on the file in which they are defined (e.g. DEFUNs -from *lib/routemap.c* are installed using the ``VTYSH_RMAP`` constant, +from *lib/routemap.c* are installed using the ``VTYSH_RMAP_SHOW`` constant, which identifies the daemons that support route-maps). In this case, the CLI commands should be rewritten but maintained in the same file. Since all CLI configuration commands from FRR will need to be rewritten, this is an excellent opportunity to rework this part of the code to make the commands easier to maintain and extend. These are the three main -recommendations: 1. Always use DEFPY instead of DEFUN to improve code -readability. 2. Always try to join multiple DEFUNs into a single DEFPY -whenever possible. As an example, there’s no need to have both -``distance (1-255) A.B.C.D/M`` and ``distance (1-255) A.B.C.D/M WORD`` -when a single ``distance (1-255) A.B.C.D/M [WORD]`` would suffice. 3. -When necessary, create a separate DEFPY for ``no`` commands so that part -of the configuration command can be made optional for convenience. -Example: -``no timers basic [(5-2147483647) (5-2147483647) (5-2147483647)]``. In -this example, everything after ``no timers basic`` is ignored by FRR, so -it makes sense to accept ``no timers basic`` as a valid command. But it -also makes sense to accept all parameters -(``no timers basic (5-2147483647) (5-2147483647) (5-2147483647)``) to -make it easier to remove the command just by prefixing a “no” to it. +recommendations: + +#. Always use DEFPY instead of DEFUN to improve code readability +#. Always try to join multiple DEFUNs into a single DEFPY whenever possible. As + an example, there’s no need to have both ``distance (1-255) A.B.C.D/M`` and + ``distance (1-255) A.B.C.D/M WORD`` when a single ``distance (1-255) + A.B.C.D/M [WORD]`` would suffice. +#. When making a negative form of a command, put ``[no]`` in the positive form + and use ``![...]`` to mark portions of the command that should be optional + only in the ``no`` version. To rewrite a CLI command as a dumb wrapper around the northbound callbacks, use the ``nb_cli_cfg_change()`` function. This function accepts as a parameter an array of ``cli_config_change`` structures that specify the changes that need to performed on the candidate configuration. Here’s the declaration of this structure (taken from the -*lib/northbound_cli.h* file): +``lib/northbound_cli.h`` file): .. code:: c @@ -1005,7 +1018,7 @@ configuration. Here’s the declaration of this structure (taken from the /* * Operation to apply (either NB_OP_CREATE, NB_OP_MODIFY or - * NB_OP_DELETE). + * NB_OP_DESTROY). */ enum nb_operation operation; @@ -1034,16 +1047,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. @@ -1205,7 +1225,7 @@ This example shows how to create a list entry: }, { .xpath = "./access-list", - .operation = acl ? NB_OP_MODIFY : NB_OP_DELETE, + .operation = acl ? NB_OP_MODIFY : NB_OP_DESTROY, .value = acl, }, }; @@ -1242,7 +1262,7 @@ When deleting a list entry, all non-key leaves can be ignored: struct cli_config_change changes[] = { { .xpath = ".", - .operation = NB_OP_DELETE, + .operation = NB_OP_DESTROY, }, }; @@ -1785,10 +1805,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: @@ -1838,19 +1861,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 439bb6a..5c495d3 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 aa527ce..17ae160 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 346efca..fb5a287 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/doc/developer/process-architecture.rst b/doc/developer/process-architecture.rst index 06ee6a3..85126ca 100644 --- a/doc/developer/process-architecture.rst +++ b/doc/developer/process-architecture.rst @@ -87,7 +87,7 @@ are given by integer macros in :file:`frrevent.h` and are: ``EVENT_EXECUTE`` Just before a task is run its type is changed to this. This is used to show - ``X`` as the type in the output of :clicmd:`show thread cpu`. + ``X`` as the type in the output of :clicmd:`show event cpu`. The programmer never has to work with these types explicitly. Each type of task is created and queued via special-purpose functions (actually macros, but @@ -238,16 +238,16 @@ proceeding. In addition, the existing commands to show statistics and other information for tasks within the event driven model have been expanded to handle multiple -pthreads; running :clicmd:`show thread cpu` will display the usual event +pthreads; running :clicmd:`show event cpu` will display the usual event breakdown, but it will do so for each pthread running in the program. For example, :ref:`bgpd` runs a dedicated I/O pthread and shows the following -output for :clicmd:`show thread cpu`: +output for :clicmd:`show event cpu`: :: - frr# show thread cpu + frr# show event cpu - Thread statistics for bgpd: + Event statistics for bgpd: Showing statistics for pthread main ------------------------------------ diff --git a/doc/developer/rcu.rst b/doc/developer/rcu.rst index 4fd5658..2335e8f 100644 --- a/doc/developer/rcu.rst +++ b/doc/developer/rcu.rst @@ -232,6 +232,15 @@ Internals that case, either all of the library's threads must be registered for RCU, or the code must instead pass a (non-RCU) copy of the data to the library. +.. c:function:: int frr_pthread_non_controlled_startup(pthread_t thread, const char *name, const char *os_name) + + If a pthread is started outside the control of normal pthreads in frr + then frr_pthread_non_controlled_startup should be called. This will + properly setup both the pthread with rcu usage as well as some data + structures pertaining to the name of the pthread. This is especially + important if the pthread created ends up calling back into FRR and + one of the various zlog_XXX functions is called. + .. c:function:: void rcu_shutdown(void) Stop the RCU sweeper thread and make sure all cleanup has finished. diff --git a/doc/developer/requirements.txt b/doc/developer/requirements.txt new file mode 100644 index 0000000..483a4e9 --- /dev/null +++ b/doc/developer/requirements.txt @@ -0,0 +1 @@ +sphinx_rtd_theme diff --git a/doc/developer/scripting.rst b/doc/developer/scripting.rst index 202f003..7a43314 100644 --- a/doc/developer/scripting.rst +++ b/doc/developer/scripting.rst @@ -488,12 +488,6 @@ match *exactly*. In the above example, we defined encoders/decoders for a value of ``struct prefix *``, but not ``struct prefix`` or ``const struct prefix *``. -``const`` values are a special case. We want to use them in our Lua scripts -but not modify them, so creating a decoder for them would be meaningless. -But we still need a decoder for the type of value so that the compiler will be -satisfied. -For that, use ``lua_decode_noop``: - .. code-block:: diff #define DECODE_ARGS_WITH_STATE(L, value) \ diff --git a/doc/developer/subdir.am b/doc/developer/subdir.am index 0deb0f5..652ee4e 100644 --- a/doc/developer/subdir.am +++ b/doc/developer/subdir.am @@ -5,6 +5,7 @@ dev_RSTFILES = \ doc/developer/bgp-typecodes.rst \ doc/developer/bgpd.rst \ + doc/developer/bmp.rst \ doc/developer/building-frr-for-alpine.rst \ doc/developer/building-frr-for-archlinux.rst \ doc/developer/building-frr-for-centos6.rst \ diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst index b8f213b..9b9058b 100644 --- a/doc/developer/topotests.rst +++ b/doc/developer/topotests.rst @@ -8,14 +8,15 @@ Topotests is a suite of topology tests for FRR built on top of micronet. Installation and Setup ---------------------- -Topotests run under python3. Additionally, for ExaBGP (which is used -in some of the BGP tests) an older python2 version (and the python2 -version of ``pip``) must be installed. +Topotests run under python3. -Tested with Ubuntu 20.04,Ubuntu 18.04, and Debian 11. +Tested with Ubuntu 22.04,Ubuntu 20.04, and Debian 12. -Instructions are the same for all setups (i.e. ExaBGP is only used for -BGP tests). +Python protobuf version < 4 is required b/c python protobuf >= 4 requires a +protoc >= 3.19, and older package versions are shipped by in the above distros. + +Instructions are the same for all setups. However, ExaBGP is only used for +BGP tests. Tshark is only required if you enable any packet captures on test runs. @@ -35,15 +36,23 @@ Installing Topotest Requirements tshark \ valgrind python3 -m pip install wheel - python3 -m pip install 'pytest>=6.2.4' - python3 -m pip install 'pytest-xdist>=2.3.0' + python3 -m pip install 'pytest>=6.2.4' 'pytest-xdist>=2.3.0' python3 -m pip install 'scapy>=2.4.5' python3 -m pip install xmltodict - # Use python2 pip to install older ExaBGP - python2 -m pip install 'exabgp<4.0.0' + python3 -m pip install git+https://github.com/Exa-Networks/exabgp@0659057837cd6c6351579e9f0fa47e9fb7de7311 useradd -d /var/run/exabgp/ -s /bin/false exabgp - # To enable the gRPC topotest install: +The version of protobuf package that is installed on your system will determine +which versions of the python protobuf packages you need to install. + +.. code:: shell + # - Either - For protobuf version <= 3.12 + python3 -m pip install 'protobuf<4' + + # - OR- for protobuf version >= 3.21 + python3 -m pip install 'protobuf>=4' + + # To enable the gRPC topotest also install: python3 -m pip install grpcio grpcio-tools @@ -116,9 +125,9 @@ If you prefer to manually build FRR, then use the following suggested config: ./configure \ --prefix=/usr \ - --localstatedir=/var/run/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ --enable-vtysh \ --enable-pimd \ --enable-pim6d \ @@ -230,8 +239,8 @@ the number of the test we are interested in along with ``--errmsg`` option. ~/frr/tests/topotests# ./analyze.py -Ar run-save -T0 --errmsg bgp_multiview_topo1/test_bgp_multiview_topo1.py::test_bgp_converge: AssertionError: BGP did not converge: - IPv4 Unicast Summary (VIEW 1): - BGP router identifier 172.30.1.1, local AS number 100 vrf-id -1 + IPv4 Unicast Summary: + BGP router identifier 172.30.1.1, local AS number 100 VIEW 1 vrf-id -1 BGP table version 1 RIB entries 1, using 184 bytes of memory Peers 3, using 2169 KiB of memory @@ -266,8 +275,8 @@ select the first failed test case. > assert False, "BGP did not converge:\n%s" % bgpStatus E AssertionError: BGP did not converge: E - E IPv4 Unicast Summary (VIEW 1): - E BGP router identifier 172.30.1.1, local AS number 100 vrf-id -1 + E IPv4 Unicast Summary: + E BGP router identifier 172.30.1.1, local AS number 100 VIEW 1 vrf-id -1 [...] E Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc E 172.16.1.1 4 65001 0 0 0 0 0 never Connect 0 N/A @@ -386,8 +395,9 @@ for ``master`` branch: ./bootstrap.sh ./configure \ --enable-address-sanitizer \ - --prefix=/usr/lib/frr --sysconfdir=/etc/frr \ - --localstatedir=/var/run/frr \ + --prefix=/usr/lib/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --sbindir=/usr/lib/frr --bindir=/usr/lib/frr \ --with-moduledir=/usr/lib/frr/modules \ --enable-multipath=0 --enable-rtadv \ @@ -559,6 +569,8 @@ Here's an example of launching ``vtysh`` on routers ``rt1`` and ``rt2``. sudo -E pytest --vtysh=rt1,rt2 all-protocol-startup +.. _debug_with_gdb: + Debugging with GDB """""""""""""""""" @@ -583,6 +595,12 @@ Here's an example of launching ``zebra`` and ``bgpd`` inside ``gdb`` on router --gdb-breakpoints=nb_config_diff \ all-protocol-startup +Finally, for Emacs users, you can specify ``--gdb-use-emacs``. When specified +the first router and daemon to be launched in gdb will be launched and run with +Emacs gdb functionality by using `emacsclient --eval` commands. This provides an +IDE debugging experience for Emacs users. This functionality works best when +using password-less sudo. + Reporting Memleaks with FRR Memory Statistics """"""""""""""""""""""""""""""""""""""""""""" @@ -631,16 +649,26 @@ Detecting Memleaks with Valgrind """""""""""""""""""""""""""""""" Topotest can automatically launch all daemons with ``valgrind`` to check for -memleaks. This is enabled by specifying 1 or 2 CLI arguments. -``--valgrind-memleaks`` will enable general memleak detection, and -``--valgrind-extra`` enables extra functionality including generating a -suppression file. The suppression file ``tools/valgrind.supp`` is used when -memleak detection is enabled. +memleaks. This is enabled by specifying 1 to 3 CLI arguments. +``--valgrind-memleaks`` enables memleak detection. ``--valgrind-extra`` enables +extra functionality including generating a suppression file. The suppression +file ``tools/valgrind.supp`` is used when memleak detection is enabled. Finally, +``--valgrind-leak-kinds=KINDS`` can be used to modify what types of links are +reported. This corresponds to valgrind's ``--show-link-kinds`` arg. The value is +either ``all`` or a comma-separated list of types: +``definite,indirect,possible,reachable``. The default is ``definite,possible``. .. code:: shell sudo -E pytest --valgrind-memleaks all-protocol-startup +.. note:: GDB can be used in conjection with valgrind. + + When you enable ``--valgrind-memleaks`` and you also launch various daemons + under GDB (debug_with_gdb_) topotest will connect the two utilities using + ``--vgdb-error=0`` and attaching to a ``vgdb`` process. This is very + useful for debugging bugs with use of uninitialized errors, et al. + Collecting Performance Data using perf(1) """"""""""""""""""""""""""""""""""""""""" @@ -662,6 +690,28 @@ during the config_timing test. To specify different arguments for ``perf record``, one can use the ``--perf-options`` this will replace the ``-g`` used by default. +Running Daemons under RR Debug (``rr record``) +"""""""""""""""""""""""""""""""""""""""""""""" + +Topotest can automatically launch any daemon under ``rr(1)`` to collect +execution state. The daemon is run in the foreground with ``rr record``. + +The execution state will be saved in the router specific directory +(in a `rr` subdir that rr creates) under the test's run directoy. + +Here's an example of collecting ``rr`` execution state from ``mgmtd`` on router +``r1`` during the ``config_timing`` test. + +.. code:: console + + $ sudo -E pytest --rr-routers=r1 --rr-daemons=mgmtd config_timing + ... + $ find /tmp/topotests/ -name '*perf.data*' + /tmp/topotests/config_timing.test_config_timing/r1/perf.data + +To specify additional arguments for ``rr record``, one can use the +``--rr-options``. + .. _topotests_docker: Running Tests with Docker diff --git a/doc/figures/cli-oper-state.drawio b/doc/figures/cli-oper-state.drawio new file mode 100644 index 0000000..4b86b58 --- /dev/null +++ b/doc/figures/cli-oper-state.drawio @@ -0,0 +1,377 @@ +<mxfile host="Electron" modified="2024-01-04T05:29:53.817Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.16 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="qF0825mlH7rzndmYEIdj" version="22.1.16" type="device"> + <diagram name="Page-1" id="58cdce13-f638-feb5-8d6f-7d28b1aa9fa0"> + <mxGraphModel dx="1398" dy="842" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" background="none" math="0" shadow="1"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="kVfNefTpehhSeJQHV--9-92" value="<div style="font-size: 12px;">Frontend CLI (mgmtd)</div>" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#dae8fc;strokeColor=#6c8ebf;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=12;align=center;verticalAlign=top;fontStyle=1" parent="1" vertex="1"> + <mxGeometry x="10" y="61.42000000000001" width="425" height="312.17" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-30" value="<div style="font-size: 12px;">MGMTD</div>" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#dae8fc;strokeColor=#6c8ebf;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=12;align=center;verticalAlign=top;fontStyle=1" parent="1" vertex="1"> + <mxGeometry x="50" y="400" width="730" height="410" as="geometry" /> + </mxCell> + <mxCell id="lldLKuc6OoWEgdetZcLS-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="lldLKuc6OoWEgdetZcLS-3" target="lldLKuc6OoWEgdetZcLS-4" edge="1"> + <mxGeometry relative="1" as="geometry"> + <Array as="points"> + <mxPoint x="115" y="645" /> + <mxPoint x="115" y="645" /> + </Array> + <mxPoint x="385.0031707317075" y="605" as="sourcePoint" /> + <mxPoint x="385.93" y="695" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="lldLKuc6OoWEgdetZcLS-10" value="xpath" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=none;fontSize=8;" parent="lldLKuc6OoWEgdetZcLS-6" vertex="1" connectable="0"> + <mxGeometry x="0.062" y="2" relative="1" as="geometry"> + <mxPoint x="-22" y="4" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;startArrow=classic;startFill=1;" parent="1" source="lldLKuc6OoWEgdetZcLS-3" target="kVfNefTpehhSeJQHV--9-3" edge="1"> + <mxGeometry relative="1" as="geometry"> + <Array as="points"> + <mxPoint x="215" y="695" /> + <mxPoint x="215" y="695" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-6" value="txn" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=8;labelBackgroundColor=none;" parent="kVfNefTpehhSeJQHV--9-4" vertex="1" connectable="0"> + <mxGeometry x="-0.1676" y="-2" relative="1" as="geometry"> + <mxPoint x="12" y="-26" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Helvetica;fontSize=8;fontColor=default;" parent="1" source="lldLKuc6OoWEgdetZcLS-3" target="kVfNefTpehhSeJQHV--9-7" edge="1"> + <mxGeometry relative="1" as="geometry"> + <Array as="points"> + <mxPoint x="255" y="595" /> + <mxPoint x="255" y="742" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-10" value="clients (bitmask)" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=8;fontFamily=Helvetica;fontColor=default;labelBackgroundColor=none;" parent="kVfNefTpehhSeJQHV--9-8" vertex="1" connectable="0"> + <mxGeometry x="-0.1299" y="1" relative="1" as="geometry"> + <mxPoint x="29" y="58" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="lldLKuc6OoWEgdetZcLS-3" value="fe_adapter_handle_get_tree" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="75" y="575" width="160" height="30" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-73" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Helvetica;fontSize=8;fontColor=default;endArrow=doubleBlock;endFill=1;" parent="1" source="kVfNefTpehhSeJQHV--9-46" target="kVfNefTpehhSeJQHV--9-72" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="530.037037037037" y="571" as="sourcePoint" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-77" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Helvetica;fontSize=8;fontColor=default;" parent="1" source="kVfNefTpehhSeJQHV--9-72" target="kVfNefTpehhSeJQHV--9-76" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-72" value="be_adapter_handle_get_tree<br>mgmt_txn_notify_tree_data_reply<br>------------------------------------<br>merge tree data<br>when all clients respond or timeout" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="550" y="530" width="160" height="60" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Helvetica;fontSize=8;fontColor=default;endArrow=doubleBlock;endFill=1;" parent="1" source="kVfNefTpehhSeJQHV--9-7" target="kVfNefTpehhSeJQHV--9-11" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-7" value="mgmt_txn_send_get_tree_oper" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="320" y="725" width="160" height="30" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-11" value="mgmt_be_send_native" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="565" y="725" width="130" height="30" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-83" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Verdana;fontSize=12;fontColor=default;labelBackgroundColor=none;endArrow=open;strokeColor=#C73500;startSize=8;endSize=8;dashed=1;dashPattern=1 4;strokeWidth=2;fillColor=#fa6800;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="kVfNefTpehhSeJQHV--9-76" target="kVfNefTpehhSeJQHV--9-82" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="320" y="543.75" as="sourcePoint" /> + <mxPoint x="300.03703703703695" y="326.25" as="targetPoint" /> + <Array as="points" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-84" value="<i style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;">socket connection<br style="border-color: var(--border-color);"></i><font style="font-size: 10px;">FE adapter -&gt; FE client<br style="border-color: var(--border-color); font-family: Verdana;"></font><span style="font-family: Verdana; font-size: 10px;">MGMT_MSG_CODE_TREE_DATA</span><br style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;"><i style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;">struct mgmt_msg_tree_data</i>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=8;fontFamily=Helvetica;fontColor=default;labelBackgroundColor=none;" parent="kVfNefTpehhSeJQHV--9-83" vertex="1" connectable="0"> + <mxGeometry x="0.5" relative="1" as="geometry"> + <mxPoint x="80" y="84" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-76" value="txn_get_tree_data_done<br>fe_adapter_send_tree_data" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="320" y="545" width="160" height="30" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-88" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Helvetica;fontSize=8;fontColor=default;" parent="1" source="kVfNefTpehhSeJQHV--9-85" target="kVfNefTpehhSeJQHV--9-86" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-85" value="session-&gt;get_tree_notify" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="235" y="256.79999999999995" width="160" height="30" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-90" value="vty_mgmt_resume_response" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="235" y="118.92000000000002" width="160" height="30" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-91" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Helvetica;fontSize=8;fontColor=default;" parent="1" source="kVfNefTpehhSeJQHV--9-86" target="kVfNefTpehhSeJQHV--9-90" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-86" value="<b>vty_mgmt_get_tree_result_notified<br></b>displays result<br>" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="225" y="174.03" width="180" height="64.93" as="geometry" /> + </mxCell> + <mxCell id="lldLKuc6OoWEgdetZcLS-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="lldLKuc6OoWEgdetZcLS-4" target="lldLKuc6OoWEgdetZcLS-3" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="445" y="392.21000000000004" as="sourcePoint" /> + <mxPoint x="445" y="485" as="targetPoint" /> + <Array as="points"> + <mxPoint x="145" y="645" /> + <mxPoint x="145" y="645" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="lldLKuc6OoWEgdetZcLS-11" value="clients (bitmask)" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=8;fontFamily=Helvetica;fontColor=default;labelBackgroundColor=none;" parent="lldLKuc6OoWEgdetZcLS-9" vertex="1" connectable="0"> + <mxGeometry x="-0.1435" y="-1" relative="1" as="geometry"> + <mxPoint x="29" y="-9" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="lldLKuc6OoWEgdetZcLS-4" value="mgmt_be_interested_clients" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="75" y="665" width="120" height="30" as="geometry" /> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-90" value="" style="edgeStyle=orthogonalEdgeStyle;shape=connector;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;labelBackgroundColor=default;strokeColor=default;fontFamily=Helvetica;fontSize=11;fontColor=default;endArrow=classic;startSize=8;endSize=8;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endFill=1;" parent="1" source="nUYlmBzm2YxJIW5L2hvB-78" target="nUYlmBzm2YxJIW5L2hvB-84" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-78" value="vty_mgmt_send_get_tree_req" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;fontColor=#000000;align=center;" parent="1" vertex="1"> + <mxGeometry x="45.01999999999998" y="255.79999999999998" width="140" height="31" as="geometry" /> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-88" value="" style="edgeStyle=orthogonalEdgeStyle;shape=connector;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;labelBackgroundColor=none;strokeColor=#C73500;fontFamily=Verdana;fontSize=12;fontColor=default;endArrow=open;startSize=8;endSize=8;dashed=1;dashPattern=1 4;strokeWidth=2;fillColor=#fa6800;" parent="1" source="nUYlmBzm2YxJIW5L2hvB-84" target="nUYlmBzm2YxJIW5L2hvB-87" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="540" y="715" as="targetPoint" /> + <Array as="points"> + <mxPoint x="115" y="470" /> + <mxPoint x="115" y="470" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-89" value="<i style="font-size: 10px;">socket connection<br style="font-size: 10px;"></i>FE client -&gt; FE adapter<br>MGMT_MSG_CODE_GET_TREE<br><i>struct mgmt_msg_get_tree</i>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontFamily=Verdana;fontColor=default;labelBackgroundColor=none;" parent="nUYlmBzm2YxJIW5L2hvB-88" vertex="1" connectable="0"> + <mxGeometry x="-0.0463" y="1" relative="1" as="geometry"> + <mxPoint x="89" y="34" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-84" value="mgmt_fe_send_get_tree_req" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;fontColor=#000000;align=center;" parent="1" vertex="1"> + <mxGeometry x="45.01999999999998" y="320.79999999999995" width="140" height="30" as="geometry" /> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-93" value="" style="edgeStyle=orthogonalEdgeStyle;shape=connector;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;labelBackgroundColor=default;strokeColor=default;fontFamily=Helvetica;fontSize=11;fontColor=default;endArrow=classic;startSize=8;endSize=8;endFill=1;" parent="1" source="nUYlmBzm2YxJIW5L2hvB-87" target="lldLKuc6OoWEgdetZcLS-3" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="532.8049999999998" y="542.2400000000002" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="lldLKuc6OoWEgdetZcLS-5" value="xpath" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=8;labelBackgroundColor=none;" parent="nUYlmBzm2YxJIW5L2hvB-93" vertex="1" connectable="0"> + <mxGeometry x="-0.2901" y="1" relative="1" as="geometry"> + <mxPoint x="-21" y="15" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-87" value="fe_adapter_handle_native_msg" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#b1ddf0;strokeColor=#10739e;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=7;fontColor=default;align=center;" parent="1" vertex="1"> + <mxGeometry x="75" y="487.5" width="160" height="35" as="geometry" /> + </mxCell> + <mxCell id="lldLKuc6OoWEgdetZcLS-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;labelBackgroundColor=default;endArrow=classic;fontSize=11;fontFamily=Helvetica;strokeColor=default;startSize=8;endSize=8;endFill=1;" parent="1" source="nUYlmBzm2YxJIW5L2hvB-245" target="nUYlmBzm2YxJIW5L2hvB-78" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-245" value=""show mgmt get-data-tree WORD$path [json|xml]"" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=default;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;fontColor=#000000;align=center;strokeWidth=1;" parent="1" vertex="1"> + <mxGeometry x="55.01999999999999" y="198.27999999999997" width="120" height="35" as="geometry" /> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-252" style="edgeStyle=orthogonalEdgeStyle;shape=connector;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;labelBackgroundColor=default;strokeColor=default;fontFamily=Helvetica;fontSize=11;fontColor=default;endArrow=classic;startSize=8;endSize=8;endFill=1;" parent="1" source="nUYlmBzm2YxJIW5L2hvB-251" target="nUYlmBzm2YxJIW5L2hvB-245" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-251" value="EVENT: VTYSH_READ" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Verdana;fontSize=7;fillColor=#b1ddf0;strokeColor=#10739e;" parent="1" vertex="1"> + <mxGeometry x="55.01999999999999" y="93.92000000000004" width="120" height="80" as="geometry" /> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-275" style="edgeStyle=orthogonalEdgeStyle;shape=connector;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;labelBackgroundColor=default;strokeColor=default;fontFamily=Helvetica;fontSize=11;fontColor=default;endArrow=classic;startSize=8;endSize=8;endFill=1;" parent="1" source="kVfNefTpehhSeJQHV--9-90" target="nUYlmBzm2YxJIW5L2hvB-268" edge="1"> + <mxGeometry relative="1" as="geometry"> + <Array as="points"> + <mxPoint x="320" y="30" /> + </Array> + <mxPoint x="320.03703703703695" y="134.71000000000004" as="sourcePoint" /> + <mxPoint x="158.76" y="20" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-269" style="edgeStyle=orthogonalEdgeStyle;shape=connector;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;labelBackgroundColor=default;strokeColor=default;fontFamily=Helvetica;fontSize=11;fontColor=default;endArrow=classic;startSize=8;endSize=8;jumpStyle=gap;endFill=1;" parent="1" source="nUYlmBzm2YxJIW5L2hvB-268" target="nUYlmBzm2YxJIW5L2hvB-251" edge="1"> + <mxGeometry relative="1" as="geometry"> + <Array as="points"> + <mxPoint x="120" y="95" /> + <mxPoint x="120" y="95" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-268" value="<div>VTYSH</div>" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#cdeb8b;strokeColor=#36393d;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;" parent="1" vertex="1"> + <mxGeometry x="81.28" y="10" width="77.48" height="40" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-3" value="mgmt_create_txn" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="115" y="725" width="120" height="30" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-12" value="mgmt_txn_req_alloc" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="340" y="647.83" width="120" height="30" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;startArrow=classic;startFill=1;" parent="1" source="kVfNefTpehhSeJQHV--9-12" target="kVfNefTpehhSeJQHV--9-7" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="374.78" y="645" as="sourcePoint" /> + <mxPoint x="374.78" y="755" as="targetPoint" /> + <Array as="points" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-14" value="txn_req<br>MGMTD_TXN_PROC_GETTREE" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=8;labelBackgroundColor=none;" parent="kVfNefTpehhSeJQHV--9-13" vertex="1" connectable="0"> + <mxGeometry x="-0.1676" y="-2" relative="1" as="geometry"> + <mxPoint x="37" y="-2" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-18" value="<div style="text-align: center;"><span style="background-color: initial;">for each of the clients</span></div><div style="text-align: center;"><span style="background-color: initial;">in bitmask</span></div>" style="verticalLabelPosition=middle;html=1;verticalAlign=middle;strokeWidth=2;shape=mxgraph.lean_mapping.physical_pull;pointerEvents=1;fontFamily=Verdana;fontSize=10;fontColor=default;labelPosition=right;align=left;horizontal=1;" parent="1" vertex="1"> + <mxGeometry x="525" y="687.83" width="30" height="30" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-41" value="be_client_send_native_msg" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="660" y="186.42000000000002" width="130" height="25" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-46" value="be_adapter_handle_native_msg" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#b1ddf0;strokeColor=#10739e;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=7;fontColor=default;align=center;" parent="1" vertex="1"> + <mxGeometry x="550" y="437.83" width="160" height="35" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-50" value="<i style="font-size: 10px;">socket connection<br style="font-size: 10px;"></i>BE client -&gt; BE adapter<br>MGMT_MSG_CODE_TREE_DATA<br><i>struct mgmt_msg_tree_data</i>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontFamily=Verdana;fontColor=default;labelBackgroundColor=none;" parent="1" vertex="1" connectable="0"> + <mxGeometry x="529.997037037037" y="360.00370370370393" as="geometry"> + <mxPoint x="21" y="1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-59" value="be_client_send_native_msg" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="670" y="196.42000000000002" width="130" height="25" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-60" value="<div style="font-size: 12px;">Backend Client (ospfd, staticd, ...)</div>" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#E6FFCC;strokeColor=#36393d;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=12;align=center;verticalAlign=top;fontStyle=1" parent="1" vertex="1"> + <mxGeometry x="480" y="102.02000000000001" width="380" height="207.57" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-61" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Helvetica;fontSize=8;fontColor=default;startArrow=classic;startFill=1;" parent="1" source="kVfNefTpehhSeJQHV--9-64" target="kVfNefTpehhSeJQHV--9-65" edge="1"> + <mxGeometry relative="1" as="geometry"> + <Array as="points"> + <mxPoint x="720" y="186.2" /> + <mxPoint x="720" y="186.2" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-62" value="<span style="font-style: normal;">(1) build oper state tree<br></span>struct mgmt_msg_tree_data" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontFamily=Helvetica;fontColor=default;labelBackgroundColor=none;fontStyle=2" parent="kVfNefTpehhSeJQHV--9-61" vertex="1" connectable="0"> + <mxGeometry x="0.038" y="1" relative="1" as="geometry"> + <mxPoint x="71" y="-1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Helvetica;fontSize=8;fontColor=default;" parent="1" source="kVfNefTpehhSeJQHV--9-64" target="kVfNefTpehhSeJQHV--9-68" edge="1"> + <mxGeometry relative="1" as="geometry"> + <Array as="points"> + <mxPoint x="670" y="213.63" /> + <mxPoint x="670" y="213.63" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="eMqbX30VPKpUhST_t5Pw-11" value="(2)" style="edgeLabel;html=1;align=center;verticalAlign=bottom;resizable=0;points=[];labelBackgroundColor=none;" vertex="1" connectable="0" parent="kVfNefTpehhSeJQHV--9-63"> + <mxGeometry x="0.1063" y="-1" relative="1" as="geometry"> + <mxPoint x="3" y="1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-64" value="be_client_handle_get_tree" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="690" y="201.2" width="140" height="25" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-65" value="nb_oper_data_iterate" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="690" y="131.13" width="110" height="25" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-66" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Helvetica;fontSize=8;fontColor=default;" parent="1" source="kVfNefTpehhSeJQHV--9-67" target="kVfNefTpehhSeJQHV--9-64" edge="1"> + <mxGeometry relative="1" as="geometry"> + <Array as="points"> + <mxPoint x="760" y="238.63" /> + <mxPoint x="760" y="238.63" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-67" value="be_client_handle_native_msg" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#b1ddf0;strokeColor=#10739e;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=7;fontColor=default;align=center;" parent="1" vertex="1"> + <mxGeometry x="670" y="251.79999999999998" width="160" height="35" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-70" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Verdana;fontSize=12;fontColor=default;labelBackgroundColor=none;endArrow=open;strokeColor=#C73500;startSize=8;endSize=8;dashed=1;dashPattern=1 4;strokeWidth=2;fillColor=#fa6800;" parent="1" source="kVfNefTpehhSeJQHV--9-68" edge="1" target="kVfNefTpehhSeJQHV--9-46"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="624.257037037037" y="257.56999999999994" as="sourcePoint" /> + <mxPoint x="624.257037037037" y="482.1700000000001" as="targetPoint" /> + <Array as="points" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-68" value="be_client_send_native_msg" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#ffffc0;strokeColor=#ff0000;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=8;align=center;fontColor=#000000;" parent="1" vertex="1"> + <mxGeometry x="500" y="201.2" width="130" height="25" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-74" value="<div style="text-align: center;"><span style="background-color: initial;">for each of the</span></div>queried&nbsp;<span style="background-color: initial; text-align: center;">BE clients</span>" style="verticalLabelPosition=middle;html=1;verticalAlign=middle;strokeWidth=2;shape=mxgraph.lean_mapping.physical_pull;pointerEvents=1;fontFamily=Verdana;fontSize=10;fontColor=default;labelPosition=right;align=left;horizontal=1;" parent="1" vertex="1"> + <mxGeometry x="635" y="487.8299999999999" width="30" height="32.83" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-69" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Verdana;fontSize=12;fontColor=default;labelBackgroundColor=none;endArrow=none;strokeColor=#C73500;startSize=8;endSize=8;dashed=1;dashPattern=1 4;strokeWidth=2;fillColor=#fa6800;endFill=0;startArrow=open;startFill=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="kVfNefTpehhSeJQHV--9-67" target="kVfNefTpehhSeJQHV--9-11" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="740.037037037037" y="312.21000000000004" as="sourcePoint" /> + <mxPoint x="570" y="775.037037037037" as="targetPoint" /> + <Array as="points"> + <mxPoint x="750" y="740" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-81" value="<i style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;">socket connection<br style="border-color: var(--border-color);"></i>BE adapter -&gt; BE client<br style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;"><span style="font-family: Verdana; font-size: 10px;">MGMT_MSG_CODE_GET_TREE</span><br style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;"><i style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;">struct mgmt_msg_get_tree</i>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontFamily=Verdana;fontColor=default;labelBackgroundColor=none;" parent="kVfNefTpehhSeJQHV--9-69" vertex="1" connectable="0"> + <mxGeometry x="-0.7023" y="-3" relative="1" as="geometry"> + <mxPoint x="93" y="-4" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-87" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Helvetica;fontSize=8;fontColor=default;" parent="1" source="kVfNefTpehhSeJQHV--9-82" target="kVfNefTpehhSeJQHV--9-85" edge="1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="kVfNefTpehhSeJQHV--9-82" value="fe_client_handle_native_msg" style="rounded=1;whiteSpace=wrap;html=1;arcSize=24;fillColor=#b1ddf0;strokeColor=#10739e;shadow=0;comic=0;labelBackgroundColor=none;fontFamily=Verdana;fontSize=7;fontColor=default;align=center;" parent="1" vertex="1"> + <mxGeometry x="235" y="315.8" width="160" height="35" as="geometry" /> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-284" value="" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Verdana;fontSize=12;fontColor=default;" parent="1" vertex="1"> + <mxGeometry x="930" y="20" width="130" height="100" as="geometry" /> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-278" value="" style="edgeStyle=orthogonalEdgeStyle;shape=connector;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;labelBackgroundColor=none;strokeColor=#C73500;fontFamily=Verdana;fontSize=12;fontColor=default;endArrow=open;startSize=8;endSize=8;dashed=1;dashPattern=1 4;strokeWidth=2;fillColor=#fa6800;" parent="1" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="950" y="50" as="sourcePoint" /> + <mxPoint x="1040.02" y="50" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-279" value="<i style="font-size: 10px;">socket&nbsp;</i>async" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontFamily=Verdana;fontColor=default;labelBackgroundColor=none;" parent="nUYlmBzm2YxJIW5L2hvB-278" vertex="1" connectable="0"> + <mxGeometry x="-0.0463" y="1" relative="1" as="geometry"> + <mxPoint x="-8" y="-9" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-282" style="edgeStyle=orthogonalEdgeStyle;shape=connector;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;labelBackgroundColor=none;strokeColor=#001DBC;fontFamily=Verdana;fontSize=12;fontColor=default;endArrow=open;startSize=8;endSize=8;dashed=1;dashPattern=1 4;strokeWidth=2;fillColor=#0050ef;" parent="1" edge="1"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="950" y="80" as="sourcePoint" /> + <mxPoint x="1040" y="80" as="targetPoint" /> + <Array as="points"> + <mxPoint x="980" y="79.76999999999998" /> + <mxPoint x="980" y="79.76999999999998" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-283" value="<span style="font-size: 10px;"><font style="font-size: 10px;">timer/event&nbsp;</font>async<br style="font-size: 10px;"></span>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontFamily=Verdana;fontColor=default;labelBackgroundColor=none;" parent="nUYlmBzm2YxJIW5L2hvB-282" vertex="1" connectable="0"> + <mxGeometry x="0.2852" y="-1" relative="1" as="geometry"> + <mxPoint x="-28" y="-11" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-287" value="" style="endArrow=classic;html=1;rounded=1;labelBackgroundColor=none;strokeColor=#330000;fontFamily=Verdana;fontSize=12;fontColor=default;startSize=8;endSize=8;shape=connector;endFill=1;" parent="1" edge="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="950" y="110" as="sourcePoint" /> + <mxPoint x="1035" y="109.20000000000005" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="nUYlmBzm2YxJIW5L2hvB-288" value="function sync" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=9;fontFamily=Verdana;fontColor=default;labelBackgroundColor=none;" parent="nUYlmBzm2YxJIW5L2hvB-287" vertex="1" connectable="0"> + <mxGeometry x="-0.26" y="2" relative="1" as="geometry"> + <mxPoint x="6" y="-8" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="eMqbX30VPKpUhST_t5Pw-6" value="" style="endArrow=none;dashed=1;html=1;strokeWidth=2;rounded=0;entryX=0.323;entryY=0.002;entryDx=0;entryDy=0;entryPerimeter=0;fillColor=#f5f5f5;strokeColor=#B3B3B3;" edge="1" parent="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="290" y="800" as="sourcePoint" /> + <mxPoint x="290" y="410" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="eMqbX30VPKpUhST_t5Pw-7" value="<i><font color="#999999">mgmt_fe_adapter.c</font></i>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontFamily=Verdana;fontColor=default;labelBackgroundColor=none;" vertex="1" connectable="0" parent="1"> + <mxGeometry x="169.99999999999977" y="570" as="geometry"> + <mxPoint x="29" y="212" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="eMqbX30VPKpUhST_t5Pw-8" value="<i><font color="#999999">mgmt_txn.c</font></i>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontFamily=Verdana;fontColor=default;labelBackgroundColor=none;" vertex="1" connectable="0" parent="1"> + <mxGeometry x="369.9999999999998" y="570" as="geometry"> + <mxPoint x="29" y="212" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="eMqbX30VPKpUhST_t5Pw-9" value="<i><font color="#999999">mgmt_be_adapter.c</font></i>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontFamily=Verdana;fontColor=default;labelBackgroundColor=none;" vertex="1" connectable="0" parent="1"> + <mxGeometry x="604.9999999999998" y="570" as="geometry"> + <mxPoint x="29" y="212" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="eMqbX30VPKpUhST_t5Pw-10" value="z" style="endArrow=none;dashed=1;html=1;strokeWidth=2;rounded=0;entryX=0.323;entryY=0.002;entryDx=0;entryDy=0;entryPerimeter=0;fillColor=#f5f5f5;strokeColor=#B3B3B3;" edge="1" parent="1"> + <mxGeometry width="50" height="50" relative="1" as="geometry"> + <mxPoint x="510" y="800" as="sourcePoint" /> + <mxPoint x="510" y="410" as="targetPoint" /> + </mxGeometry> + </mxCell> + </root> + </mxGraphModel> + </diagram> +</mxfile> diff --git a/doc/figures/cli-oper-state.svg b/doc/figures/cli-oper-state.svg new file mode 100644 index 0000000..bda7d7b --- /dev/null +++ b/doc/figures/cli-oper-state.svg @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1057" height="807" viewBox="-0.5 -0.5 1057 807" style="background-color: rgb(255, 255, 255);"><defs><filter id="dropShadow"><feGaussianBlur in="SourceAlpha" stdDeviation="1.7" result="blur"/><feOffset in="blur" dx="3" dy="3" result="offsetBlur"/><feFlood flood-color="#3D4574" flood-opacity="0.4" result="offsetColor"/><feComposite in="offsetColor" in2="offsetBlur" operator="in" result="offsetBlur"/><feBlend in="SourceGraphic" in2="offsetBlur"/></filter></defs><g filter="url(#dropShadow)"><rect x="0" y="51.42" width="425" height="312.17" rx="74.92" ry="74.92" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 423px; height: 1px; padding-top: 58px; margin-left: 1px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><div style="font-size: 12px;">Frontend CLI (mgmtd)</div></div></div></div></foreignObject><text x="213" y="70" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="12px" text-anchor="middle" font-weight="bold">Frontend CLI (mgmtd)</text></switch></g><rect x="40" y="390" width="730" height="410" rx="98.4" ry="98.4" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 728px; height: 1px; padding-top: 397px; margin-left: 41px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><div style="font-size: 12px;">MGMTD</div></div></div></div></foreignObject><text x="405" y="409" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="12px" text-anchor="middle" font-weight="bold">MGMTD</text></switch></g><path d="M 105 595 L 105 635 L 105 648.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 105 653.88 L 101.5 646.88 L 105 648.63 L 108.5 646.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 631px; margin-left: 85px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">xpath</div></div></div></foreignObject><text x="85" y="633" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="8px" text-anchor="middle">xpath</text></switch></g><path d="M 205 601.37 L 205 685 L 205 708.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 205 596.12 L 208.5 603.12 L 205 601.37 L 201.5 603.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 205 713.88 L 201.5 706.88 L 205 708.63 L 208.5 706.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 619px; margin-left: 215px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">txn</div></div></div></foreignObject><text x="215" y="622" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="8px" text-anchor="middle">txn</text></switch></g><path d="M 225 585 L 245 585 L 245 732 L 303.63 732" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 308.88 732 L 301.88 735.5 L 303.63 732 L 301.88 728.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 724px; margin-left: 275px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">clients (bitmask)</div></div></div></foreignObject><text x="275" y="727" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="8px" text-anchor="middle">clients (bitmask)</text></switch></g><rect x="65" y="565" width="160" height="30" rx="7.2" ry="7.2" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 580px; margin-left: 66px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">fe_adapter_handle_get_tree</div></div></div></foreignObject><text x="145" y="582" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">fe_adapter_handle_get_tree</text></switch></g><path d="M 620 462.83 L 620 504.88" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 620 518.88 L 616.5 511.88 L 623.5 511.88 Z M 620 511.88 L 616.5 504.88 L 623.5 504.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 540 550 L 476.37 550" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 471.12 550 L 478.12 546.5 L 476.37 550 L 478.12 553.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="540" y="520" width="160" height="60" rx="14.4" ry="14.4" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 550px; margin-left: 541px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">be_adapter_handle_get_tree<br />mgmt_txn_notify_tree_data_reply<br />------------------------------------<br />merge tree data<br />when all clients respond or timeout</div></div></div></foreignObject><text x="620" y="552" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">be_adapter_handle_get_tree...</text></switch></g><path d="M 470 730 L 539.88 730" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 553.88 730 L 546.88 733.5 L 546.88 726.5 Z M 546.88 730 L 539.88 733.5 L 539.88 726.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="310" y="715" width="160" height="30" rx="7.2" ry="7.2" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 730px; margin-left: 311px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">mgmt_txn_send_get_tree_oper</div></div></div></foreignObject><text x="390" y="732" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">mgmt_txn_send_get_tree_oper</text></switch></g><rect x="555" y="715" width="130" height="30" rx="7.2" ry="7.2" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 730px; margin-left: 556px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">mgmt_be_send_native</div></div></div></foreignObject><text x="620" y="732" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">mgmt_be_send_native</text></switch></g><path d="M 390 535 L 390 447.92 Q 390 437.92 380 437.92 L 315 437.92 Q 305 437.92 305 427.92 L 305 345.27" fill="none" stroke="#c73500" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="2 8" pointer-events="stroke"/><path d="M 310 353.04 L 305 343.04 L 300 353.04" fill="none" stroke="#c73500" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 495px; margin-left: 385px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><i style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;">socket connection<br style="border-color: var(--border-color);" /></i><font style="font-size: 10px;">FE adapter -> FE client<br style="border-color: var(--border-color); font-family: Verdana;" /></font><span style="font-family: Verdana; font-size: 10px;">MGMT_MSG_CODE_TREE_DATA</span><br style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;" /><i style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;">struct mgmt_msg_tree_data</i></div></div></div></foreignObject><text x="385" y="498" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="8px" text-anchor="middle">socket connection...</text></switch></g><rect x="310" y="535" width="160" height="30" rx="7.2" ry="7.2" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 550px; margin-left: 311px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">txn_get_tree_data_done<br />fe_adapter_send_tree_data</div></div></div></foreignObject><text x="390" y="552" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">txn_get_tree_data_done...</text></switch></g><path d="M 305 246.8 L 305 226.77 L 305 248.92 L 305 235.33" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 305 230.08 L 308.5 237.08 L 305 235.33 L 301.5 237.08 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="225" y="246.8" width="160" height="30" rx="7.2" ry="7.2" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 262px; margin-left: 226px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">session->get_tree_notify</div></div></div></foreignObject><text x="305" y="264" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">session->get_tree_notify</text></switch></g><rect x="225" y="108.92" width="160" height="30" rx="7.2" ry="7.2" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 124px; margin-left: 226px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">vty_mgmt_resume_response</div></div></div></foreignObject><text x="305" y="126" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">vty_mgmt_resume_response</text></switch></g><path d="M 305 164.03 L 305 144 L 305 158.92 L 305 145.29" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 305 140.04 L 308.5 147.04 L 305 145.29 L 301.5 147.04 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="215" y="164.03" width="180" height="64.93" rx="15.58" ry="15.58" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 196px; margin-left: 216px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><b>vty_mgmt_get_tree_result_notified<br /></b>displays result<br /></div></div></div></foreignObject><text x="305" y="199" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">vty_mgmt_get_tree_result_notified...</text></switch></g><path d="M 135 655 L 135 635 L 135 601.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 135 596.12 L 138.5 603.12 L 135 601.37 L 131.5 603.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 621px; margin-left: 165px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">clients (bitmask)</div></div></div></foreignObject><text x="165" y="623" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="8px" text-anchor="middle">clients (bitmask)</text></switch></g><rect x="65" y="655" width="120" height="30" rx="7.2" ry="7.2" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 670px; margin-left: 66px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">mgmt_be_interested_clients</div></div></div></foreignObject><text x="125" y="672" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">mgmt_be_interested_clients</text></switch></g><path d="M 105 276.8 L 105 296.77 L 105 290.77 L 105.01 302.93" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 105.02 309.68 L 100.51 300.69 L 105.01 302.93 L 109.51 300.68 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="35.02" y="245.8" width="140" height="31" rx="7.44" ry="7.44" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 261px; margin-left: 36px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">vty_mgmt_send_get_tree_req</div></div></div></foreignObject><text x="105" y="264" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">vty_mgmt_send_get_tree_req</text></switch></g><path d="M 105 340.8 L 105 450 Q 105 460 105 466.51 L 105 473.03" fill="none" stroke="#c73500" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="2 8" pointer-events="stroke"/><path d="M 100 465.26 L 105 475.26 L 110 465.26" fill="none" stroke="#c73500" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 441px; margin-left: 195px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 10px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><i style="font-size: 10px;">socket connection<br style="font-size: 10px;" /></i>FE client -> FE adapter<br />MGMT_MSG_CODE_GET_TREE<br /><i>struct mgmt_msg_get_tree</i></div></div></div></foreignObject><text x="195" y="444" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="10px" text-anchor="middle">socket connection...</text></switch></g><rect x="35.02" y="310.8" width="140" height="30" rx="7.2" ry="7.2" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 326px; margin-left: 36px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">mgmt_fe_send_get_tree_req</div></div></div></foreignObject><text x="105" y="328" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">mgmt_fe_send_get_tree_req</text></switch></g><path d="M 145 512.5 L 145 557.13" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 145 563.88 L 140.5 554.88 L 145 557.13 L 149.5 554.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 546px; margin-left: 125px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">xpath</div></div></div></foreignObject><text x="125" y="549" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="8px" text-anchor="middle">xpath</text></switch></g><rect x="65" y="477.5" width="160" height="35" rx="8.4" ry="8.4" fill="#b1ddf0" stroke="#10739e" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 495px; margin-left: 66px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 7px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">fe_adapter_handle_native_msg</div></div></div></foreignObject><text x="145" y="497" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="7px" text-anchor="middle">fe_adapter_handle_native_msg</text></switch></g><path d="M 105 223.28 L 105 243.31 L 105 225.77 L 105 237.93" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 105 244.68 L 100.5 235.68 L 105 237.93 L 109.5 235.68 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="45.02" y="188.28" width="120" height="35" rx="8.4" ry="8.4" fill="#ffffc0" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 206px; margin-left: 46px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">"show mgmt get-data-tree WORD$path [json|xml]"</div></div></div></foreignObject><text x="105" y="208" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">"show mgmt get-data-tree WORD...</text></switch></g><path d="M 105.02 163.92 L 105 183.92 L 105 168.31 L 105 180.41" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 105 187.16 L 100.5 178.16 L 105 180.41 L 109.5 178.16 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="105.02" cy="123.92" rx="60" ry="40" fill="#b1ddf0" stroke="#10739e" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 124px; margin-left: 46px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 7px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">EVENT: VTYSH_READ</div></div></div></foreignObject><text x="105" y="126" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="7px" text-anchor="middle">EVENT: VTYSH_READ</text></switch></g><path d="M 310 108.92 L 310 20 L 156.63 20" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 149.88 20 L 158.88 15.5 L 156.63 20 L 158.88 24.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 110.02 40 L 110.02 76.19" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 110.02 82.94 L 105.52 73.94 L 110.02 76.19 L 114.52 73.94 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="71.28" y="0" width="77.48" height="40" rx="9.6" ry="9.6" fill="#cdeb8b" stroke="#36393d" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 75px; height: 1px; padding-top: 20px; margin-left: 72px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>VTYSH</div></div></div></div></foreignObject><text x="110" y="22" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="8px" text-anchor="middle">VTYSH</text></switch></g><rect x="105" y="715" width="120" height="30" rx="7.2" ry="7.2" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 730px; margin-left: 106px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">mgmt_create_txn</div></div></div></foreignObject><text x="165" y="732" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">mgmt_create_txn</text></switch></g><rect x="330" y="637.83" width="120" height="30" rx="7.2" ry="7.2" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 653px; margin-left: 331px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">mgmt_txn_req_alloc</div></div></div></foreignObject><text x="390" y="655" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">mgmt_txn_req_alloc</text></switch></g><path d="M 390 674.2 L 390 708.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 390 668.95 L 393.5 675.95 L 390 674.2 L 386.5 675.95 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 390 713.88 L 386.5 706.88 L 390 708.63 L 393.5 706.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 686px; margin-left: 425px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">txn_req<br />MGMTD_TXN_PROC_GETTREE</div></div></div></foreignObject><text x="425" y="689" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="8px" text-anchor="middle">txn_req...</text></switch></g><path d="M 536.96 680.04 C 531.58 676.78 524.78 677.42 520.07 681.64 C 515.37 685.86 513.83 692.7 516.25 698.62 C 518.67 704.53 524.51 708.18 530.73 707.68 C 536.96 707.18 542.17 702.63 543.66 696.4" fill="none" stroke="rgb(0, 0, 0)" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 542.21 696.4 L 544.38 692.68 L 545 697.14 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 693px; margin-left: 547px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 10px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><div style="text-align: center;"><span style="background-color: initial;">for each of the clients</span></div><div style="text-align: center;"><span style="background-color: initial;">in bitmask</span></div></div></div></div></foreignObject><text x="547" y="696" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="10px">for ea...</text></switch></g><rect x="650" y="176.42" width="130" height="25" rx="6" ry="6" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 189px; margin-left: 651px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">be_client_send_native_msg</div></div></div></foreignObject><text x="715" y="191" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">be_client_send_native_msg</text></switch></g><rect x="540" y="427.83" width="160" height="35" rx="8.4" ry="8.4" fill="#b1ddf0" stroke="#10739e" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 445px; margin-left: 541px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 7px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">be_adapter_handle_native_msg</div></div></div></foreignObject><text x="620" y="447" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="7px" text-anchor="middle">be_adapter_handle_native_msg</text></switch></g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 351px; margin-left: 541px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 10px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><i style="font-size: 10px;">socket connection<br style="font-size: 10px;" /></i>BE client -> BE adapter<br />MGMT_MSG_CODE_TREE_DATA<br /><i>struct mgmt_msg_tree_data</i></div></div></div></foreignObject><text x="541" y="354" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="10px" text-anchor="middle">socket connection...</text></switch></g><rect x="660" y="186.42" width="130" height="25" rx="6" ry="6" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 199px; margin-left: 661px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">be_client_send_native_msg</div></div></div></foreignObject><text x="725" y="201" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">be_client_send_native_msg</text></switch></g><rect x="470" y="92.02" width="380" height="207.57" rx="49.82" ry="49.82" fill="#e6ffcc" stroke="#36393d" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 378px; height: 1px; padding-top: 99px; margin-left: 471px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><div style="font-size: 12px;">Backend Client (ospfd, staticd, ...)</div></div></div></div></foreignObject><text x="660" y="111" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="12px" text-anchor="middle" font-weight="bold">Backend Client (ospfd, staticd, ...)</text></switch></g><path d="M 710 184.83 L 710 176.23 L 710 152.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 710 190.08 L 706.5 183.08 L 710 184.83 L 713.5 183.08 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 710 147.25 L 713.5 154.25 L 710 152.5 L 706.5 154.25 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 168px; margin-left: 780px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-style: italic; white-space: nowrap;"><span style="font-style: normal;">(1) build oper state tree<br /></span>struct mgmt_msg_tree_data</div></div></div></foreignObject><text x="780" y="171" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="10px" text-anchor="middle" font-style="italic">(1) build oper state tree...</text></switch></g><path d="M 680 203.69 L 660 203.69 L 626.37 203.69" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 621.12 203.69 L 628.12 200.19 L 626.37 203.69 L 628.12 207.19 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 201px; margin-left: 650px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">(2)</div></div></div></foreignObject><text x="650" y="201" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">(2)</text></switch></g><rect x="680" y="191.2" width="140" height="25" rx="6" ry="6" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 204px; margin-left: 681px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">be_client_handle_get_tree</div></div></div></foreignObject><text x="750" y="206" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">be_client_handle_get_tree</text></switch></g><rect x="680" y="121.13" width="110" height="25" rx="6" ry="6" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 134px; margin-left: 681px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">nb_oper_data_iterate</div></div></div></foreignObject><text x="735" y="136" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">nb_oper_data_iterate</text></switch></g><path d="M 750 241.8 L 750 228.62 L 750 222.57" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 750 217.32 L 753.5 224.32 L 750 222.57 L 746.5 224.32 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="660" y="241.8" width="160" height="35" rx="8.4" ry="8.4" fill="#b1ddf0" stroke="#10739e" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 259px; margin-left: 661px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 7px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">be_client_handle_native_msg</div></div></div></foreignObject><text x="740" y="261" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="7px" text-anchor="middle">be_client_handle_native_msg</text></switch></g><path d="M 555 216.2 L 555 312 Q 555 322 565 322 L 610 322 Q 620 322 620 332 L 620 423.36" fill="none" stroke="#c73500" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="2 8" pointer-events="stroke"/><path d="M 615 415.59 L 620 425.59 L 625 415.59" fill="none" stroke="#c73500" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><rect x="490" y="191.2" width="130" height="25" rx="6" ry="6" fill="#ffffc0" stroke="#ff0000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 204px; margin-left: 491px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 8px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">be_client_send_native_msg</div></div></div></foreignObject><text x="555" y="206" fill="#000000" font-family="Verdana" font-size="8px" text-anchor="middle">be_client_send_native_msg</text></switch></g><path d="M 646.96 480.25 C 641.58 476.68 634.78 477.38 630.07 482 C 625.37 486.62 623.83 494.11 626.25 500.58 C 628.67 507.05 634.51 511.05 640.73 510.5 C 646.96 509.95 652.17 504.97 653.66 498.16" fill="none" stroke="rgb(0, 0, 0)" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 652.21 498.16 L 654.38 494.08 L 655 498.97 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 494px; margin-left: 657px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 10px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><div style="text-align: center;"><span style="background-color: initial;">for each of the</span></div>queried <span style="background-color: initial; text-align: center;">BE clients</span></div></div></div></foreignObject><text x="657" y="497" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="10px">for ea...</text></switch></g><path d="M 740 281.27 L 740 720 Q 740 730 730 730 L 685 730" fill="none" stroke="#c73500" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="2 8" pointer-events="stroke"/><path d="M 745 289.04 L 740 279.04 L 735 289.04" fill="none" stroke="#c73500" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 349px; margin-left: 830px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 10px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><i style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;">socket connection<br style="border-color: var(--border-color);" /></i>BE adapter -> BE client<br style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;" /><span style="font-family: Verdana; font-size: 10px;">MGMT_MSG_CODE_GET_TREE</span><br style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;" /><i style="border-color: var(--border-color); font-family: Verdana; font-size: 10px;">struct mgmt_msg_get_tree</i></div></div></div></foreignObject><text x="830" y="352" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="10px" text-anchor="middle">socket connection...</text></switch></g><path d="M 305 305.8 L 305 285.77 L 305 296.77 L 305 283.17" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 305 277.92 L 308.5 284.92 L 305 283.17 L 301.5 284.92 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="225" y="305.8" width="160" height="35" rx="8.4" ry="8.4" fill="#b1ddf0" stroke="#10739e" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 323px; margin-left: 226px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 7px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">fe_client_handle_native_msg</div></div></div></foreignObject><text x="305" y="325" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="7px" text-anchor="middle">fe_client_handle_native_msg</text></switch></g><rect x="920" y="10" width="130" height="100" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 940 40 L 1025.55 40" fill="none" stroke="#c73500" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="2 8" pointer-events="stroke"/><path d="M 1017.78 45 L 1027.78 40 L 1017.78 35" fill="none" stroke="#c73500" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 30px; margin-left: 975px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 10px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><i style="font-size: 10px;">socket </i>async</div></div></div></foreignObject><text x="975" y="33" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="10px" text-anchor="middle">socket async</text></switch></g><path d="M 940 70 L 960 70 Q 970 70 980 70 L 1025.53 70" fill="none" stroke="#001dbc" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="2 8" pointer-events="stroke"/><path d="M 1017.76 75 L 1027.76 70 L 1017.76 65" fill="none" stroke="#001dbc" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 60px; margin-left: 970px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 10px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><span style="font-size: 10px;"><font style="font-size: 10px;">timer/event </font>async<br style="font-size: 10px;" /></span></div></div></div></foreignObject><text x="970" y="63" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="10px" text-anchor="middle">timer/event async
</text></switch></g><path d="M 940 100 L 1017.13 99.27" fill="none" stroke="#330000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 1023.88 99.21 L 1014.92 103.8 L 1017.13 99.27 L 1014.84 94.8 Z" fill="#330000" stroke="#330000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 90px; margin-left: 978px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 9px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">function sync</div></div></div></foreignObject><text x="978" y="93" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="9px" text-anchor="middle">function sync</text></switch></g><path d="M 280 790 L 280 400" fill="none" stroke="#b3b3b3" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="6 6" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 772px; margin-left: 189px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 10px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><i><font color="#999999">mgmt_fe_adapter.c</font></i></div></div></div></foreignObject><text x="189" y="775" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="10px" text-anchor="middle">mgmt_fe_adapter.c</text></switch></g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 772px; margin-left: 389px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 10px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><i><font color="#999999">mgmt_txn.c</font></i></div></div></div></foreignObject><text x="389" y="775" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="10px" text-anchor="middle">mgmt_txn.c</text></switch></g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 772px; margin-left: 624px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 10px; font-family: Verdana; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><i><font color="#999999">mgmt_be_adapter.c</font></i></div></div></div></foreignObject><text x="624" y="775" fill="rgb(0, 0, 0)" font-family="Verdana" font-size="10px" text-anchor="middle">mgmt_be_adapter.c</text></switch></g><path d="M 500 790 L 500 400" fill="none" stroke="#b3b3b3" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="6 6" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 595px; margin-left: 500px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">z</div></div></div></foreignObject><text x="500" y="599" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">z</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg>
\ No newline at end of file diff --git a/doc/user/.readthedocs.yaml b/doc/user/.readthedocs.yaml index c5a11da..ba5698c 100644 --- a/doc/user/.readthedocs.yaml +++ b/doc/user/.readthedocs.yaml @@ -7,6 +7,9 @@ build: tools: python: "3.11" +python: + install: + - requirements: doc/user/requirements.txt # Build documentation in the docs/ directory with Sphinx sphinx: configuration: doc/user/conf.py diff --git a/doc/user/babeld.rst b/doc/user/babeld.rst index bda0045..b7b7c1f 100644 --- a/doc/user/babeld.rst +++ b/doc/user/babeld.rst @@ -26,8 +26,7 @@ The *zebra* daemon must be running before *babeld* is invoked. Also, if *zebra* is restarted then *babeld* must be too. -Configuration of *babeld* is done in its configuration file -:file:`babeld.conf`. +.. include:: config-include.rst .. _babel-configuration: diff --git a/doc/user/basic.rst b/doc/user/basic.rst index bbf24c5..5fdd188 100644 --- a/doc/user/basic.rst +++ b/doc/user/basic.rst @@ -11,45 +11,22 @@ The following sections discuss commands common to all the routing daemons. Config Commands =============== - - - - -In a config file, you can write the debugging options, a vty's password, +In the config file, you can write the debugging options, a vty's password, routing daemon configurations, a log file name, and so forth. This information forms the initial command set for a routing beast as it is starting. -Config files are generally found in |INSTALL_PREFIX_ETC|. - -Config Methods --------------- - -There are two ways of configuring FRR. - -Traditionally each of the daemons had its own config file. The daemon name plus -``.conf`` was the default config file name. For example, zebra's default config -file was :file:`zebra.conf`. This method is deprecated. - -Because of the amount of config files this creates, and the tendency of one -daemon to rely on others for certain functionality, most deployments now use -"integrated" configuration. In this setup all configuration goes into a single -file, typically :file:`/etc/frr/frr.conf`. When starting up FRR using an init -script or systemd, ``vtysh`` is invoked to read the config file and send the -appropriate portions to only the daemons interested in them. Running -configuration updates are persisted back to this single file using ``vtysh``. -This is the recommended method. To use this method, add the following line to -:file:`/etc/frr/vtysh.conf`: - -.. code-block:: frr - - service integrated-vtysh-config +.. _config-file: -If you installed from source or used a package, this is probably already -present. +Integrated Config File +---------------------- -If desired, you can specify a config file using the :option:`-f` or -:option:`--config_file` options when starting a daemon. +FRR uses a single configuration file located in |INSTALL_PREFIX_ETC|/frr.conf. +When FRR is started using an init script or ``systemd``, ``vtysh`` is invoked to +read the config file and send the appropriate portions to only the daemons +interested in them. Running configuration updates are persisted back to this +single file using ``vtysh`` as well. +.. include:: prior-config-files.rst .. _basic-config-commands: @@ -152,6 +129,20 @@ Basic Config Commands deprecated ``log trap`` command) will be used. The ``no`` form of the command disables logging to a file. +.. clicmd:: log daemon DAEMON file [FILENAME [LEVEL]] + + Configure file logging for a single FRR daemon. If you want to log + into a file, please specify ``filename`` as in this example: + + :: + + log daemon bgpd file /var/log/frr/bgpd.log informational + + If the optional second argument specifying the logging level is not present, + the default logging level (typically debugging, but can be changed using the + deprecated ``log trap`` command) will be used. The ``no`` form of the command + disables logging to a file for a single FRR daemon. + .. clicmd:: log syslog [LEVEL] Enable logging output to syslog. If the optional second argument specifying @@ -215,7 +206,7 @@ Basic Config Commands enabled log destinations. The note that logging includes full command lines, including passwords. If the daemon startup option `--command-log-always` is used to start the daemon then this command is turned on by default - and cannot be turned off and the [no] form of the command is dissallowed. + and cannot be turned off and the [no] form of the command is disallowed. .. clicmd:: log filtered-file [FILENAME [LEVEL]] @@ -673,24 +664,29 @@ Terminal Mode Commands .. _common-show-commands: -.. clicmd:: show thread cpu [r|w|t|e|x] +.. clicmd:: show event cpu [r|w|t|e|x] This command displays system run statistics for all the different event types. If no options is specified all different run types are displayed together. Additionally you can ask to look at (r)ead, (w)rite, (t)imer, (e)vent and e(x)ecute thread event types. -.. clicmd:: show thread poll +.. clicmd:: show event poll This command displays FRR's poll data. It allows a glimpse into how we are setting each individual fd for the poll command at that point in time. -.. clicmd:: show thread timers +.. clicmd:: show event timers This command displays FRR's timer data for timers that will pop in the future. +.. clicmd:: show configuration running [<json|xml> [translate WORD]] [with-defaults] DAEMON + + This command displays the northbound/YANG configuration data for a + daemon in text/vty, json, or xml format. + .. clicmd:: show yang operational-data XPATH [{format <json|xml>|translate TRANSLATOR|with-config}] DAEMON Display the YANG operational data starting from XPATH. The default @@ -773,7 +769,7 @@ These options apply to all |PACKAGE_NAME| daemons. .. option:: --command-log-always Cause the daemon to always log commands entered to the specified log file. - This also makes the `no log commands` command dissallowed. Enabling this + This also makes the `no log commands` command disallowed. Enabling this is suggested if you have need to track what the operator is doing on this router. diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst index 6c57822..3ca104a 100644 --- a/doc/user/bfd.rst +++ b/doc/user/bfd.rst @@ -27,6 +27,8 @@ This document will focus on the later implementation: *bfdd*. Starting BFD ============ +.. include:: config-include.rst + *bfdd* default configuration file is :file:`bfdd.conf`. *bfdd* searches the current directory first then |INSTALL_PREFIX_ETC|/bfdd.conf. All of *bfdd*'s command must be configured in :file:`bfdd.conf`. @@ -44,9 +46,7 @@ may also be specified (:ref:`common-invocation-options`). /usr/lib/frr/bfdd --bfdctl /tmp/bfdd.sock - The default UNIX socket location is: - - #define BFDD_CONTROL_SOCKET "|INSTALL_PREFIX_STATE|/bfdd.sock" + The default UNIX socket location is |INSTALL_PREFIX_STATE|/bfdd.sock This option overrides the location addition that the -N option provides to the bfdd.sock diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 5b8ec11..53dc551 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -14,10 +14,7 @@ interdomain routing protocol. BGP-4 is described in :rfc:`1771` and updated by Starting BGP ============ -The default configuration file of *bgpd* is :file:`bgpd.conf`. *bgpd* searches -the current directory first, followed by |INSTALL_PREFIX_ETC|/bgpd.conf. All of -*bgpd*'s commands must be configured in :file:`bgpd.conf` when the integrated -config is not being used. +.. include:: config-include.rst *bgpd* specific invocation options are described below. Common options may also be specified (:ref:`common-invocation-options`). @@ -494,8 +491,8 @@ Require policy on EBGP exit1# show bgp summary - IPv4 Unicast Summary (VRF default): - BGP router identifier 10.10.10.1, local AS number 65001 vrf-id 0 + IPv4 Unicast Summary: + BGP router identifier 10.10.10.1, local AS number 65001 VRF default vrf-id 0 BGP table version 4 RIB entries 7, using 1344 bytes of memory Peers 2, using 43 KiB of memory @@ -527,6 +524,27 @@ Reject routes with AS_SET or AS_CONFED_SET types This command enables rejection of incoming and outgoing routes having AS_SET or AS_CONFED_SET type. +Enforce first AS +---------------- + +.. clicmd:: bgp enforce-first-as + + To configure a router to deny an update received from an external BGP (eBGP) + peer that does not list its autonomous system number at the beginning of + the `AS_PATH` in the incoming update, use the ``bgp enforce-first-as`` command + in router configuration mode. + + In order to exclude an arbitrary neighbor from this enforcement, use the + command ``no neighbor NAME enforce-first-as``. And vice-versa if a global + enforcement is disabled, you can override this behavior per neighbor too. + + Default: enabled. + +.. note:: + + If you have a peering to RS (Route-Server), most likely you MUST disable the + first AS enforcement. + Suppress duplicate updates -------------------------- @@ -1309,10 +1327,31 @@ section for the specific AF to redistribute into. Protocol availability for redistribution is determined by BGP AF; for example, you cannot redistribute OSPFv3 into ``address-family ipv4 unicast`` as OSPFv3 supports IPv6. -.. clicmd:: redistribute <babel|connected|eigrp|isis|kernel|openfabric|ospf|ospf6|rip|ripng|sharp|static|table> [metric (0-4294967295)] [route-map WORD] +.. clicmd:: redistribute <babel|connected|eigrp|isis|kernel|openfabric|ospf|ospf6|rip|ripng|sharp|static> [metric (0-4294967295)] [route-map WORD] Redistribute routes from other protocols into BGP. +.. clicmd:: redistribute <table|table-direct> (1-65535)] [metric (0-4294967295)] [route-map WORD] + + Redistribute routes from a routing table ID into BGP. There are two + techniques for redistribution: + + - Standard Table Redistribution ``table (1-65535)``: + - Routes from the specified routing table ID are imported into the + default routing table using the ``ip import-table ID`` command. + - These routes are identified by the protocol type "T[ID]" when + displayed with ``show (ip|ipv6) route``. + - The ``redistribute table ID`` command then integrates these routes + into BGP. + + - Direct Table Redistribution ``table-direct (1-65535)``: + - This method directly imports routes from the designated routing table + ID into BGP, omitting the step of adding to the default routing table. + - This method is especially relevant when the specified table ID is + checked against routing by appending the appropriate `ip rules`. + +Redistribute routes from a routing table number into BGP. + .. clicmd:: redistribute vnc-direct Redistribute VNC direct (not via zebra) routes to BGP process. @@ -1432,6 +1471,23 @@ Defining Peers peers ASN is the same as mine as specified under the :clicmd:`router bgp ASN` command the connection will be denied. +.. clicmd:: neighbor PEER oad + + Mark a peer belonging to the One Administrative Domain. + + Some networks span more than one autonomous system and require more + flexibility in the propagation of path attributes.It is worth noting that + these multi-AS networks have a common or single administrative entity. + These networks are said to belong to One Administrative Domain (OAD). + It is desirable to carry IBGP-only attributes across EBGP peerings when + the peers belong to an OAD. + + Enabling this peering sub-type will allow the propagation of non-transitive + attributes across EBGP peerings (e.g. local-preference). Make sure to + turn this peering type on for all peers in the OAD. + + Disabled by default. + .. clicmd:: bgp listen range <A.B.C.D/M|X:X::X:X/M> peer-group PGNAME Accept connections from any peers in the specified prefix. Configuration @@ -1509,7 +1565,10 @@ Configuring Peers Discard updates received from the specified (eBGP) peer if the AS_PATH attribute does not contain the PEER's ASN as the first AS_PATH segment. - Default: disabled. + You can enable or disable this enforcement globally too using + ``bgp enforce-first-as`` command. + + Default: enabled. .. clicmd:: neighbor PEER extended-optional-parameters @@ -1545,7 +1604,10 @@ Configuring Peers Configure an unnumbered BGP peer. ``PEER`` should be an interface name. The session will be established via IPv6 link locals. Use ``internal`` for iBGP - and ``external`` for eBGP sessions, or specify an ASN if you wish. + and ``external`` for eBGP sessions, or specify an ASN if you wish. Finally + this connection type is meant for point to point connections. If you are + on an ethernet segment and attempt to use this with more than one bgp + neighbor, only one neighbor will come up, due to how this feature works. .. clicmd:: neighbor PEER next-hop-self [force] @@ -1564,10 +1626,12 @@ Configuring Peers .. clicmd:: neighbor PEER update-source <IFNAME|ADDRESS> - Specify the IPv4 source address to use for the :abbr:`BGP` session to this - neighbour, may be specified as either an IPv4 address directly or as an + Specify the IPv4 or IPv6 source address to use for the :abbr:`BGP` session to this + neighbour, may be specified as either an IP address directly or as an interface name (in which case the *zebra* daemon MUST be running in order - for *bgpd* to be able to retrieve interface state). + for *bgpd* to be able to retrieve interface state). When there are multiple + addresses on the choosen IFNAME then BGP will use the address that matches + the most number of bits in comparison to the destination peer address. .. code-block:: frr @@ -1610,7 +1674,18 @@ Configuring Peers modifying the `net.core.optmem_max` sysctl to a larger value to avoid out of memory errors from the linux kernel. -.. clicmd:: neighbor PEER send-community +.. clicmd:: neighbor PEER send-community <both|all|extended|standard|large> + + Send the communities to the peer. + + Default: enabled. + +.. clicmd:: neighbor PEER send-community extended rpki + + Send the extended RPKI communities to the peer. RPKI extended community + can be send only to iBGP and eBGP-OAD peers. + + Default: enabled. .. clicmd:: neighbor PEER weight WEIGHT @@ -1730,6 +1805,18 @@ Configuring Peers This includes changing graceful-restart (LLGR also) timers, enabling/disabling add-path, and other supported capabilities. +.. clicmd:: neighbor PEER capability fqdn + + Allow BGP to negotiate the FQDN Capability with its peers. + + FQDN Capability defines a new BGP message (CAPABILITY) allowing the + use of peer's name and domain name. + + This capability is activated by default. The ``no neighbor PEER capability + fqdn`` avoid negotiation of that capability. This is useful for peers who + are not supporting this capability or supporting BGP Capabilities + Negotiation RFC 2842. + .. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> accept-own Enable handling of self-originated VPN routes containing ``accept-own`` community. @@ -1860,8 +1947,8 @@ Configuring Peers .. code-block:: frr - IPv4 Unicast Summary (VRF default): - BGP router identifier 10.0.0.6, local AS number 65001 vrf-id 0 + IPv4 Unicast Summary: + BGP router identifier 10.0.0.6, local AS number 65001 VRF default vrf-id 0 BGP table version 12 RIB entries 23, using 4600 bytes of memory Peers 3, using 2174 KiB of memory @@ -2059,7 +2146,6 @@ Capability Negotiation .. clicmd:: neighbor PEER strict-capability-match - Strictly compares remote capabilities and local capabilities. If capabilities are different, send Unsupported Capability error then reset connection. @@ -2986,7 +3072,33 @@ address-family: Specifies the route-target list to be attached to a route (export) or the route-target list to match against (import) when exporting/importing between - the current unicast VRF and VPN. + the current unicast VRF and VPN. The `rt vpn export RTLIST` command is not + mandatory and can be replaced or completed by the `set extcommunity rt` + command in the route-map attached with the `route-map vpn export`. The below + configuration illustrates how the route target is selected based on the + prefixes, and not solely on vrf criterium: + + .. code-block:: frr + + access-list acl1 permit 192.0.2.0/24 + access-list acl2 permit 192.0.3.0/24 + route-map rmap permit 10 + match address acl1 + set extcommunity rt 65001:10 + ! + route-map rmap permit 20 + match address acl1 + set extcommunity rt 65001:20 + ! + router bgp 65001 vrf vrf1 + ! + address-family ipv4 unicast + rd vpn export 65001:1 + import vpn + export vpn + rt vpn import 65001:1 + route-map vpn export rmap + The RTLIST is a space-separated list of route-targets, which are BGP extended community values as described in @@ -3374,7 +3486,7 @@ The import filtering described in item (2) is constrained just to Type-2 The EVPN MAC-VRF Site-of-Origin can be configured using a single CLI command under ``address-family l2vpn evpn`` of the EVPN underlay BGP instance. -.. clicmd:: [no] mac-vrf soo <site-of-origin-string> +.. clicmd:: mac-vrf soo <site-of-origin-string> Example configuration: @@ -3520,7 +3632,7 @@ route maybe fragmented. The number of EVIs per-EAD route can be configured via the following BGP command - -.. clicmd:: [no] ead-es-frag evi-limit (1-1000) +.. clicmd:: ead-es-frag evi-limit (1-1000) Sample Configuration ^^^^^^^^^^^^^^^^^^^^^ @@ -3698,7 +3810,7 @@ When default route is present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2.1/3 *> 192.0.2.1/32 10.10.10.1 0 0 1 i *> 192.0.2.5/32 10.10.10.1 0 0 1 i - Displayed 4 routes and 4 total paths + Displayed 4 routes and 4 total paths Router2# show ip bgp neighbors 10.10.20.3 !--- Output suppressed. @@ -3746,7 +3858,7 @@ When default route is not present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2 *> 192.0.2.1/32 10.10.10.1 0 0 1 i *> 192.0.2.5/32 10.10.10.1 0 0 1 i - Displayed 3 routes and 3 total paths + Displayed 3 routes and 3 total paths Router2# show ip bgp neighbors 10.10.20.3 @@ -3815,12 +3927,20 @@ Debugging information on BGP events such as peer connection / disconnection, session establishment / teardown, and capability negotiation. -.. clicmd:: debug bgp updates +.. clicmd:: debug bgp updates [detail] Enable or disable debugging for BGP updates. This provides information on BGP UPDATE messages transmitted and received between local and remote instances. + If ``detail`` is specified, the output will include the full BGP UPDATE with + detailed information such as attribute length, withdraw length, and more. + +.. clicmd:: debug bgp updates <in|out> [<A.B.C.D|X:X::X:X|WORD> [prefix-list WORD]] + + Enable or disable debugging for BGP updates. Optionally, you can specify + a prefix-list to filter the updates for an arbitrary neighbor. + .. clicmd:: debug bgp keepalives Enable or disable debugging for BGP keepalives. This provides information on @@ -3921,6 +4041,26 @@ The following are available in the top level *enable* mode: Clear BGP message statistics for a specified peer or for all peers, optionally filtered by activated address-family and sub-address-family. +.. clicmd:: clear bgp [ipv4|ipv6] [unicast] PEER|\* capabilities + + Clear specific BGP capabilities for a specified peer or for all peers. This + includes such capabilities like FQDN capability, that can't be controlled by + any other configuration knob. + + For example, if you want to change the FQDN, you MUST reset the BGP session + in order to send a new FQDN capability to the peer. This command allows you + to resend FQDN capability without resetting the session. + + .. code-block:: frr + + hostname bgp-new.example.com + clear bgp 10.10.10.1 capabilities + +.. note:: + + Changing the hostname is possible only when connected to the specific daemon. + If you change the hostname via ``vtysh``, it won't be changed. + The following are available in the ``router bgp`` mode: .. clicmd:: write-quanta (1-64) @@ -4044,8 +4184,8 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`. exit1# show ip bgp summary wide - IPv4 Unicast Summary (VRF default): - BGP router identifier 192.168.100.1, local AS number 65534 vrf-id 0 + IPv4 Unicast Summary: + BGP router identifier 192.168.100.1, local AS number 65534 VRF default vrf-id 0 BGP table version 3 RIB entries 5, using 920 bytes of memory Peers 1, using 27 KiB of memory @@ -4339,7 +4479,7 @@ incoming/outgoing directions. Origin incomplete, metric 0, weight 32768, valid, sourced, bestpath-from-AS Local, best (First path received) Last update: Wed May 8 12:54:41 2023 - Displayed 2 routes and 2 total paths + Displayed 2 routes and 2 total paths .. code-block:: frr @@ -4364,7 +4504,7 @@ incoming/outgoing directions. Origin incomplete, metric 0, weight 32768, valid, sourced, bestpath-from-AS Local, best (First path received) Last update: Wed May 8 12:45:01 2023 - Displayed 2 routes and 2 total paths + Displayed 2 routes and 2 total paths Instance vrf3: @@ -4389,7 +4529,7 @@ incoming/outgoing directions. Extended Community: RT:65000:1009 ET:8 Rmac:00:02:00:00:00:58 Last update: Fri May 8 02:41:55 2023 - Displayed 2 routes and 2 total paths + Displayed 2 routes and 2 total paths .. code-block:: frr @@ -4417,7 +4557,7 @@ incoming/outgoing directions. Extended Community: RT:65000:1009 ET:8 Rmac:00:02:00:00:00:58 Last update: Fri May 8 02:23:55 2023 - Displayed 2 routes and 2 total paths + Displayed 2 routes and 2 total paths .. _bgp-display-routes-by-community: diff --git a/doc/user/bmp.rst b/doc/user/bmp.rst index 1983995..0f46832 100644 --- a/doc/user/bmp.rst +++ b/doc/user/bmp.rst @@ -36,8 +36,8 @@ The `BMP` implementation in FRR has the following properties: successfully. OPEN messages for failed sessions cannot currently be mirrored. -- **route monitoring** is available for IPv4 and IPv6 AFIs, unicast and - multicast SAFIs. Other SAFIs (VPN, Labeled-Unicast, Flowspec, etc.) are not +- **route monitoring** is available for IPv4 and IPv6 AFIs, unicast, multicast, + EVPN and VPN SAFIs. Other SAFIs (VPN, Labeled-Unicast, Flowspec, etc.) are not currently supported. - monitoring peers that have BGP **add-path** enabled on the session will @@ -146,10 +146,10 @@ associated with a particular ``bmp targets``: Send BMP Statistics (counter) messages at the specified interval (in milliseconds.) -.. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy> +.. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy|loc-rib> Perform Route Monitoring for the specified AFI and SAFI. Only IPv4 and - IPv6 are currently valid for AFI. SAFI valid values are currently + IPv6 are currently valid for AFI. SAFI valid values are currently unicast, multicast, evpn and vpn. Other AFI/SAFI combinations may be added in the future. diff --git a/doc/user/config-include.rst b/doc/user/config-include.rst new file mode 100644 index 0000000..3a34151 --- /dev/null +++ b/doc/user/config-include.rst @@ -0,0 +1,12 @@ +.. +.. January 12 2024, Christian Hopps <chopps@labn.net> +.. +.. Copyright (c) 2024, LabN Consulting, L.L.C. +.. +.. + +Configuration for the daemon should be saved in the FRR integrated configuration +file located in |INSTALL_PREFIX_ETC|/frr.conf, see :ref:`config-file` for more +information on system configuration. + +.. include:: prior-config-files.rst diff --git a/doc/user/eigrpd.rst b/doc/user/eigrpd.rst index fa157c4..58a2957 100644 --- a/doc/user/eigrpd.rst +++ b/doc/user/eigrpd.rst @@ -24,21 +24,17 @@ known topology. Starting and Stopping eigrpd ============================ -The default configuration file name of *eigrpd*'s is :file:`eigrpd.conf`. When -invocation *eigrpd* searches directory |INSTALL_PREFIX_ETC|. If -:file:`eigrpd.conf` is not there next search current directory. If an -integrated config is specified configuration is written into :file:`frr.conf`. +.. include:: config-include.rst -The EIGRP protocol requires interface information maintained by *zebra* daemon. -So running *zebra* is mandatory to run *eigrpd*. Thus minimum sequence for -running EIGRP is: +If starting daemons by hand then please note, the EIGRP protocol requires +interface information maintained by *zebra* daemon. So running *zebra* is +mandatory to run *eigrpd*. Thus minimum sequence for running EIGRP is: :: # zebra -d # eigrpd -d - Please note that *zebra* must be invoked before *eigrpd*. To stop *eigrpd*, please use:: diff --git a/doc/user/installation.rst b/doc/user/installation.rst index 24c6c22..fb9e23d 100644 --- a/doc/user/installation.rst +++ b/doc/user/installation.rst @@ -234,10 +234,9 @@ options from the list below. assigned to the realm. See the tc man page. This option is currently not compatible with the usage of nexthop groups in the linux kernel itself. -.. option:: --disable-irdp +.. option:: --enable-irdp - Disable IRDP server support. This is enabled by default if we have - both `struct in_pktinfo` and `struct icmphdr` available to us. + Enable IRDP server support. This is deprecated. .. option:: --disable-rtadv @@ -394,13 +393,20 @@ options to the configuration script. .. option:: --sysconfdir <dir> - Look for configuration files in `dir` [`prefix`/etc]. Note that sample - configuration files will be installed here. + Look for configuration files in `dir`/frr [`prefix`/etc]. Note that sample + configuration files will be installed here. Should be ``/etc`` unless + your platform splits package configuration locations. .. option:: --localstatedir <dir> - Configure zebra to use `dir` for local state files, such as pid files and - unix sockets. + Configure base directory for local state. Indirectly controls + ``--runstatedir``. Should be ``/var`` in most cases. + +.. option:: --runstatedir <dir> + + Configure FRR to use `dir`/frr for local state files, such as pid files and + unix sockets. Should be ``/var/run`` (default through ``--localstatedir``) + or ``/run`` in most cases. .. option:: --with-scriptdir <dir> @@ -579,9 +585,9 @@ the options you chose: ./configure \ --prefix=/usr \ - --localstatedir=/var/run/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ --enable-pimd \ --enable-watchfrr \ ... diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index 63c9213..d37dfa6 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -22,8 +22,7 @@ interface information from *zebra* in order to function. Therefore *zebra* must be running before invoking *isisd*. Also, if *zebra* is restarted then *isisd* must be too. -Like other daemons, *isisd* configuration is done in :abbr:`ISIS` specific -configuration file :file:`isisd.conf`. +.. include:: config-include.rst .. _isis-router: diff --git a/doc/user/ldpd.rst b/doc/user/ldpd.rst index 682443a..cbed734 100644 --- a/doc/user/ldpd.rst +++ b/doc/user/ldpd.rst @@ -32,9 +32,7 @@ options (:ref:`common-invocation-options`). The *zebra* daemon must be running before *ldpd* is invoked. -Configuration of *ldpd* is done in its configuration file -:file:`ldpd.conf`. - +.. include:: config-include.rst .. _understanding-ldp: diff --git a/doc/user/mgmtd.rst b/doc/user/mgmtd.rst index 42bc860..aa7ccaa 100644 --- a/doc/user/mgmtd.rst +++ b/doc/user/mgmtd.rst @@ -371,22 +371,22 @@ MGMT Daemon debug commands The following debug commands enable debugging within the management daemon: -.. clicmd:: [no] debug mgmt backend +.. clicmd:: debug mgmt backend Enable[/Disable] debugging messages related to backend operations within the management daemon. -.. clicmd:: [no] debug mgmt datastore +.. clicmd:: debug mgmt datastore Enable[/Disable] debugging messages related to YANG datastore operations within the management daemon. -.. clicmd:: [no] debug mgmt frontend +.. clicmd:: debug mgmt frontend Enable[/Disable] debugging messages related to frontend operations within the management daemon. -.. clicmd:: [no] debug mgmt transaction +.. clicmd:: debug mgmt transaction Enable[/Disable] debugging messages related to transactions within the management daemon. @@ -398,12 +398,12 @@ MGMT Client debug commands The following debug commands enable debugging within the management front and backend clients: -.. clicmd:: [no] debug mgmt client backend +.. clicmd:: debug mgmt client backend Enable[/Disable] debugging messages related to backend operations inside the backend mgmtd clients. -.. clicmd:: [no] debug mgmt client frontend +.. clicmd:: debug mgmt client frontend Enable[/Disable] debugging messages related to frontend operations inside the frontend mgmtd clients. diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index 2f4c956..ad58610 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -9,8 +9,13 @@ described in :rfc:`2740`. .. _ospf6-router: -OSPF6 router -============ +Configuring OSPF6 +***************** + +.. include:: config-include.rst + +Configuration Commands +====================== .. clicmd:: router ospf6 [vrf NAME] @@ -312,10 +317,135 @@ OSPF6 interface Sets interface's Inf-Trans-Delay. Default value is 1. -.. clicmd:: ipv6 ospf6 network (broadcast|point-to-point) +.. clicmd:: ipv6 ospf6 network (broadcast|point-to-point|point-to-multipoint) Set explicitly network type for specified interface. + The only functional difference between ``point-to-point`` (PtP) and + ``point-to-multipoint`` (PtMP) mode is the packet addressing for database + flooding and updates. PtP will use multicast packets while PtMP will + unicast them. Apart from this, + :clicmd:`ipv6 ospf6 p2p-p2mp connected-prefixes <include|exclude>` has a + different default for PtP and PtMP. There are no other differences, in + particular FRR does not impose a limit of one neighbor in PtP mode. + + FRR does not support NBMA mode for IPv6 and likely never will, as NBMA is + considered deprecated for IPv6. Refer to `this IETF OSPF working group + discussion + <https://mailarchive.ietf.org/arch/msg/ospf/8GAbr4qSMMt5J7SvAcZQ1H7ARhk/>`_ + for context. + +OSPF6 point-to-point and point-to-multipoint operation +====================================================== + +OSPFv3, by default, operates in broadcast mode where it elects a DR and BDR +for each network segment. This can be changed to point-to-point (PtP) / +point-to-multipoint (PtMP) mode by configuration. The actual physical +interface characteristics do not matter for this setting, all interfaces can +be configured for all modes. However, routers must be configured for the same +mode to form adjacencies. + +The main advantages of PtP/PtMP mode are: + +- no DR/BDR election +- adjacencies can be suppressed in a pairwise manner for any two routers, e.g. + to represent the underlying topology if it isn't a true full mesh +- distinct costs can be set for each pair of routers and direction + +The main downside is less efficient flooding on networks with a large number +of OSPFv3 routers. + +.. warning:: + + All options in this section should be considered "advanced" configuration + options. Inconsistent or nonsensical combinations can easily result in a + non-functional setup. + +.. clicmd:: ipv6 ospf6 p2p-p2mp disable-multicast-hello + + Disables sending normal multicast hellos when in PtP/PtMP mode. Some + vendors do this automatically for PtMP mode while others have a separate + ``no-broadcast`` option matching this. + + If this setting is used, you must issue + :clicmd:`ipv6 ospf6 neighbor X:X::X:X poll-interval (1-65535)` for each + neighbor to send unicast hello packets. + +.. clicmd:: ipv6 ospf6 p2p-p2mp config-neighbors-only + + Only form adjacencies with neighbors that are explicitly configured with + the :clicmd:`ipv6 ospf6 neighbor X:X::X:X` command. Hellos from other + routers are ignored. + + .. warning:: + + This setting is not intended to provide any security benefit. Do not + run OSPFv3 over untrusted links without additional security measures + (e.g. IPsec.) + +.. clicmd:: ipv6 ospf6 p2p-p2mp connected-prefixes <include|exclude> + + For global/ULA prefixes configured on this interfaces, do (not) advertise + the full prefix to the area. Regardless of this setting, the router's own + address, as a /128 host route with the "LA" (Local Address) bit set, will + always be advertised. + + The default is to include connected prefixes for PtP mode and exclude them + for PtMP mode. Since these prefixes will cover other router's addresses, + these addresses can become unreachable if the link is partitioned if the + other router does not advertise the address as a /128. However, conversely, + if all routers have this flag set, the overall prefix will not be advertised + anywhere. End hosts on this link will therefore be unreachable (and + blackholing best-practices for non-existing prefixes apply.) It may be + preferable to have only one router announce the connected prefix. + + The Link LSA (which is not propagated into the area) always includes all + prefixes on the interface. This setting only affects the Router LSA that + is visible to all routers in the area. + + .. note:: + + Before interacting with this setting, consider either not configuring + any global/ULA IPv6 address on the interface, or directly configuring a + /128 if needed. OSPFv3 relies exclusively on link-local addresses to do + its signaling and there is absolutely no reason to configure global/ULA + addresses as far as OSPFv3 is concerned. + +.. clicmd:: ipv6 ospf6 neighbor X:X::X:X + + Explicitly configure a neighbor by its link-local address on this interface. + This statement has no effect other than allowing an adjacency when + :clicmd:`ipv6 ospf6 p2p-p2mp config-neighbors-only` is set. This command + does **not** cause unicast hellos to be sent. + + Only link-local addresses can be used to establish explicit neighbors. + When using this command, you should probably assign static IPv6 link-local + addresses to all routers on this link. It would technically be possible to + use the neighbor's Router ID (IPv4 address) here to ease working with + changing link-local addresses but this is not planned as a feature at the + time of writing. Global/ULA IPv6 addresses cannot be supported here due to + the way OSPFv3 works. + +.. clicmd:: ipv6 ospf6 neighbor X:X::X:X poll-interval (1-65535) + + Send unicast hellos to this neighbor at the specified interval (in seconds.) + The interval is only used while there is no adjacency with this neighbor. + As soon as an adjacency is formed, the interface's + :clicmd:`ipv6 ospf6 hello-interval HELLOINTERVAL` value is used. + (``hello-interval`` must be the same on all routers on this link.) + + :rfc:`2328` recommends a "much larger" value than ``hello-interval`` for + this setting, but this is a legacy of ATM and X.25 networks and nowadays you + should probably just use the same value as for ``hello-interval``. + +.. clicmd:: ipv6 ospf6 neighbor X:X::X:X cost (1-65535) + + Use a distinct cost for paths traversing this neighbor. The default is + to use the interface's cost value (which may be automatically calculated + based on link bandwidth.) Note that costs are directional in OSPF and the + reverse direction must be set on the other router. + + OSPF6 route-map =============== diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index d61522b..3bc4487 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -32,8 +32,7 @@ Configuring OSPF Therefore *zebra* must be running before invoking *ospfd*. Also, if *zebra* is restarted then *ospfd* must be too. -Like other daemons, *ospfd* configuration is done in :abbr:`OSPF` specific -configuration file :file:`ospfd.conf` when the integrated config is not used. +.. include:: config-include.rst .. _ospf-multi-instance: @@ -853,7 +852,7 @@ Graceful Restart affects the restarting router. By default 'strict-lsa-checking' is enabled" -.. clicmd:: graceful-restart helper supported-grace-time +.. clicmd:: graceful-restart helper supported-grace-time (10-1800) Supports as HELPER for configured grace period. diff --git a/doc/user/overview.rst b/doc/user/overview.rst index a1cb0cc..2ef88ac 100644 --- a/doc/user/overview.rst +++ b/doc/user/overview.rst @@ -428,6 +428,8 @@ BGP :t:`Route Leak Prevention and Detection Using Roles in UPDATE and OPEN Messages. A. Azimov, E. Bogomazov, R. Bush, K. Patel, K. Sriram. May 2022.` - :rfc:`9384` :t:`A BGP Cease NOTIFICATION Subcode for Bidirectional Forwarding Detection (BFD). J. Haas. March 2023.` +- :rfc:`9494` + :t:`Long-Lived Graceful Restart for BGP. J. Uttaro, E. Chen, B. Decraene, J. Scudder. November 2023.` OSPF ---- diff --git a/doc/user/pathd.rst b/doc/user/pathd.rst index ec107fb..2519ac4 100644 --- a/doc/user/pathd.rst +++ b/doc/user/pathd.rst @@ -327,7 +327,7 @@ Configuration Commands Delete or specify a bandwidth constraint for a dynamic candidate path. -.. clicmd:: metric [bound] METRIC VALUE [required] +.. clicmd:: metric [bound] METRIC VALUE [required] [computed] Delete or specify a metric constraint for a dynamic candidate path. @@ -475,6 +475,9 @@ Configuration Commands Specify the maximum SID depth in a PCC definition. +.. clicmd:: no msd [(1-32)] + + Default the maximum SID depth to 4. .. clicmd:: peer WORD [precedence (1-255)] @@ -531,7 +534,7 @@ retrieved via PCEP a random number based name is generated. Display PCC information. -.. clicmd:: show sr-te pcep session [NAME] +.. clicmd:: show sr-te pcep session [NAME] [json] Display the information of a PCEP session, if not name is specified all the sessions will be displayed. diff --git a/doc/user/pbr.rst b/doc/user/pbr.rst index 7a4effd..6ea153c 100644 --- a/doc/user/pbr.rst +++ b/doc/user/pbr.rst @@ -15,11 +15,7 @@ the default Linux kernel dataplane provider. Starting PBR ============ -Default configuration file for *pbrd* is :file:`pbrd.conf`. The typical -location of :file:`pbrd.conf` is |INSTALL_PREFIX_ETC|/pbrd.conf. - -If FRR is using integrated config, then :file:`pbrd.conf` need not be -present and the :file:`frr.conf` is read instead. +.. include:: config-include.rst .. program:: pbrd diff --git a/doc/user/pim.rst b/doc/user/pim.rst index d70c3c0..80a6a27 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -23,12 +23,11 @@ network for optimizing forwarding of overlay BUM traffic. Starting and Stopping pimd ========================== -The default configuration file name of *pimd*'s is :file:`pimd.conf`. When -invoked *pimd* searches directory |INSTALL_PREFIX_ETC|. If -:file:`pimd.conf` is not there then next search current directory. +.. include:: config-include.rst -*pimd* requires zebra for proper operation. Additionally *pimd* depends on -routing properly setup and working in the network that it is working on. +If starting daemons by hand then please note, *pimd* requires zebra for proper +operation. Additionally *pimd* depends on routing properly setup and working in +the network that it is working on. :: diff --git a/doc/user/pimv6.rst b/doc/user/pimv6.rst index 8569390..d550c8e 100644 --- a/doc/user/pimv6.rst +++ b/doc/user/pimv6.rst @@ -15,12 +15,11 @@ do S,G mrouting. Starting and Stopping pim6d =========================== -The default configuration file name of *pim6d*'s is :file:`pim6d.conf`. When -invoked *pim6d* searches directory |INSTALL_PREFIX_ETC|. If -:file:`pim6d.conf` is not there then next search current directory. +.. include:: config-include.rst -*pim6d* requires zebra for proper operation. Additionally *pim6d* depends on -routing properly setup and working in the network that it is working on. +If starting daemons by hand then please note, *pim6d* requires zebra for proper +operation. Additionally *pim6d* depends on routing properly setup and working in +the network that it is working on. :: diff --git a/doc/user/prior-config-files.rst b/doc/user/prior-config-files.rst new file mode 100644 index 0000000..a01b688 --- /dev/null +++ b/doc/user/prior-config-files.rst @@ -0,0 +1,23 @@ +.. +.. January 12 2024, Christian Hopps <chopps@labn.net> +.. +.. Copyright (c) 2024, LabN Consulting, L.L.C. +.. +.. + +Prior versions of FRR supported reading and writing per-daemon config files; +however, with the introduction of the centralized management daemon ``mgmtd`` +this could no longer be supported. + +In order to allow for an orderly transition from per-daemon config files to the +integrated config file, FRR daemons will continue to try and **read** their +specific per-daemon configuration file as before. Additionally the config can +still be loaded directly using the ``-f`` or ``--config-file`` CLI options; +however, these files will **not** be updated when the configuration is written +(e.g., with the ``write mem`` command). + +.. warning:: + + Per-daemon files will **no longer** be updated when the user issues a ``write + memory`` command. Therefore these per-daemon config files should only be used + as a mechanism for transitioning to the integrated config, and then removed. diff --git a/doc/user/requirements.txt b/doc/user/requirements.txt new file mode 100644 index 0000000..483a4e9 --- /dev/null +++ b/doc/user/requirements.txt @@ -0,0 +1 @@ +sphinx_rtd_theme diff --git a/doc/user/ripd.rst b/doc/user/ripd.rst index f9c7724..ea13dc9 100644 --- a/doc/user/ripd.rst +++ b/doc/user/ripd.rst @@ -21,15 +21,15 @@ version 1 as described in RFC1058. Starting and Stopping ripd ========================== -The default configuration file name of *ripd*'s is :file:`ripd.conf`. When -invocation *ripd* searches directory |INSTALL_PREFIX_ETC|. If :file:`ripd.conf` -is not there next search current directory. +.. include:: config-include.rst RIP uses UDP port 520 to send and receive RIP packets. So the user must have the capability to bind the port, generally this means that the user must have -superuser privileges. RIP protocol requires interface information maintained by -*zebra* daemon. So running *zebra* is mandatory to run *ripd*. Thus minimum -sequence for running RIP is like below: +superuser privileges. + +If starting daemons by hand then please note, RIP protocol requires interface +information maintained by *zebra* daemon. So running *zebra* is mandatory to run +*ripd*. Thus minimum sequence for running RIP is like below: :: diff --git a/doc/user/ripngd.rst b/doc/user/ripngd.rst index 1e78294..f898bed 100644 --- a/doc/user/ripngd.rst +++ b/doc/user/ripngd.rst @@ -12,6 +12,8 @@ reincarnation of the RIP protocol. Invoking ripngd =============== +.. include:: config-include.rst + There are no `ripngd` specific invocation options. Common options can be specified (:ref:`common-invocation-options`). diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst index 3d43e74..791762a 100644 --- a/doc/user/routemap.rst +++ b/doc/user/routemap.rst @@ -185,9 +185,11 @@ Route Map Match Command Matches the specified `local-preference`. -.. clicmd:: match community COMMUNITY_LIST +.. clicmd:: match community COMMUNITY_LIST [<exact-match|any>] - Matches the specified `community_list` + Matches the specified `community_list`. ``exact-match`` specifies to + do the exact matching of the communities, while ``any`` - can match any + community specified in COMMUNITY_LIST. .. clicmd:: match peer IPV4_ADDR @@ -378,13 +380,13 @@ Route Map Exit Action Command .. clicmd:: on-match next -.. clicmd:: continue - Proceed on to the next entry in the route-map. -.. clicmd:: on-match goto N +.. clicmd:: continue (1-65535) -.. clicmd:: continue N + Proceed to the specified sequence in the route-map. + +.. clicmd:: on-match goto N Proceed processing the route-map at the first entry whose order is >= N diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst index 4053536..76910ee 100644 --- a/doc/user/rpki.rst +++ b/doc/user/rpki.rst @@ -62,8 +62,9 @@ otherwise ``bgpd`` daemon won't startup. This command enables the RPKI configuration mode. Most commands that start with *rpki* can only be used in this mode. - When it is used in a telnet session, leaving of this mode cause rpki to be - initialized. + This command is available either in *configure node* for default *vrf* or + in *vrf node* for specific *vrf*. When it is used in a telnet session, + leaving of this mode cause rpki to be initialized. Executing this command alone does not activate prefix validation. You need to configure at least one reachable cache server. See section @@ -90,6 +91,9 @@ Examples of the error:: router(config)# rpki % [BGP] Unknown command: rpki + router(config-vrf)# rpki + % [BGP] Unknown command: rpki + Note that the RPKI commands will be available in vtysh when running ``find rpki`` regardless of whether the module is loaded. @@ -98,7 +102,14 @@ Note that the RPKI commands will be available in vtysh when running Configuring RPKI/RTR Cache Servers ---------------------------------- -The following commands are independent of a specific cache server. +RPKI/RTR can be configured independently, either in configure node, or in *vrf* +sub context. If configured in configure node, the core *bgp* instance of default +*vrf* is impacted by the configuration. + +Each RPKI/RTR context is mapped to a *vrf* and can be made up of a specific list +of cache-servers, and specific settings. + +The following commands are available for independent of a specific cache server. .. clicmd:: rpki polling_period (1-3600) @@ -166,7 +177,7 @@ Validating BGP Updates .. code-block:: frr ! Allow for invalid routes in route selection process - route bgp 60001 + route bgp 65001 ! ! Set local preference of invalid prefixes to 10 route-map rpki permit 10 @@ -200,35 +211,39 @@ Debugging Displaying RPKI --------------- -.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)] [json] +.. clicmd:: show rpki configuration [vrf NAME] [json] + + Display RPKI configuration state including timers values. + +.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)] [vrf NAME] [json] Display validated prefixes received from the cache servers filtered by the specified prefix. -.. clicmd:: show rpki as-number ASN [json] +.. clicmd:: show rpki as-number ASN [vrf NAME] [json] Display validated prefixes received from the cache servers filtered by ASN. -.. clicmd:: show rpki prefix-table [json] +.. clicmd:: show rpki prefix-table [vrf NAME] [json] Display all validated prefix to origin AS mappings/records which have been received from the cache servers and stored in the router. Based on this data, the router validates BGP Updates. -.. clicmd:: show rpki cache-server [json] +.. clicmd:: show rpki cache-server [vrf NAME] [json] Display all configured cache servers, whether active or not. -.. clicmd:: show rpki cache-connection [json] +.. clicmd:: show rpki cache-connection [vrf NAME] [json] Display all cache connections, and show which is connected or not. -.. clicmd:: show bgp [afi] [safi] <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> rpki <valid|invalid|notfound> +.. clicmd:: show bgp [vrf NAME] [afi] [safi] <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> rpki <valid|invalid|notfound> Display for the specified prefix or address the bgp paths that match the given rpki state. -.. clicmd:: show bgp [afi] [safi] rpki <valid|invalid|notfound> +.. clicmd:: show bgp [vrf NAME] [afi] [safi] rpki <valid|invalid|notfound> Display all prefixes that match the given rpki state. @@ -244,25 +259,52 @@ RPKI Configuration Example debug bgp keepalives debug rpki ! + vrf VRF1 + rpki + rpki polling_period 1000 + rpki timeout 10 + ! SSH Example: + rpki cache example.com 22 rtr-ssh ./ssh_key/id_rsa preference 1 + ! TCP Example: + rpki cache rpki-validator.realmv6.org 8282 preference 2 + exit + ! + exit-vrf + ! rpki rpki polling_period 1000 rpki timeout 10 ! SSH Example: - rpki cache example.com source 141.22.28.223 22 rtr-ssh ./ssh_key/id_rsa ./ssh_key/id_rsa.pub preference 1 + rpki cache example.com source 198.51.100.223 22 rtr-ssh ./ssh_key/id_rsa preference 1 ! TCP Example: rpki cache rpki-validator.realmv6.org 8282 preference 2 exit ! - router bgp 60001 - bgp router-id 141.22.28.223 - network 192.168.0.0/16 - neighbor 123.123.123.0 remote-as 60002 - neighbor 123.123.123.0 route-map rpki in - neighbor 123.123.123.0 update-source 141.22.28.223 + router bgp 65001 + bgp router-id 198.51.100.223 + neighbor 203.0.113.1 remote-as 65002 + neighbor 203.0.113.1 update-source 198.51.100.223 + address-family ipv4 + network 192.0.2.0/24 + neighbor 203.0.113.1 route-map rpki in + exit-address-family + ! + address-family ipv6 + neighbor 203.0.113.1 activate + neighbor 203.0.113.1 route-map rpki in + exit-address-family + ! + router bgp 65001 vrf VRF1 + bgp router-id 198.51.100.223 + neighbor 203.0.113.1 remote-as 65002 + address-family ipv4 + network 192.0.2.0/24 + neighbor 203.0.113.1 route-map rpki in + exit-address-family ! address-family ipv6 - neighbor 123.123.123.0 activate - neighbor 123.123.123.0 route-map rpki in + neighbor 203.0.113.1 activate + neighbor 203.0.113.1 route-map rpki in exit-address-family ! route-map rpki permit 10 diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst index 3e73a59..2be38a3 100644 --- a/doc/user/sharp.rst +++ b/doc/user/sharp.rst @@ -13,11 +13,7 @@ labs. Starting SHARP ============== -Default configuration file for *sharpd* is :file:`sharpd.conf`. The typical -location of :file:`sharpd.conf` is |INSTALL_PREFIX_ETC|/sharpd.conf. - -If the user is using integrated config, then :file:`sharpd.conf` need not be -present and the :file:`frr.conf` is read instead. +.. include:: config-include.rst .. program:: sharpd @@ -67,6 +63,11 @@ keyword. At present, no sharp commands will be preserved in the config. Install a label into the kernel that causes the specified vrf NAME table to be used for pop and forward operations when the specified label is seen. +.. clicmd:: sharp watch [vrf VRF_NAME] neighbor + + Instruct zebra to notify sharpd about neighbor events in the specified vrf. + If no vrf is specified then assume default. + .. clicmd:: sharp watch <nexthop <A.B.C.D|X:X::X:X>|import <A.B.C.D/M:X:X::X:X/M> [connected] Instruct zebra to monitor and notify sharp when the specified nexthop is diff --git a/doc/user/snmptrap.rst b/doc/user/snmptrap.rst index 7e306b7..df534e2 100644 --- a/doc/user/snmptrap.rst +++ b/doc/user/snmptrap.rst @@ -4,8 +4,9 @@ Handling SNMP Traps To handle snmp traps make sure your snmp setup of frr works correctly as described in the frr documentation in :ref:`snmp-support`. -The BGP4 mib will send traps on peer up/down events. These should be visible in -your snmp logs with a message similar to: +BGP handles both :rfc:`4273` and [Draft-IETF-idr-bgp4-mibv2-11]_ MIBs. +The BGP4 MIBs will send traps on peer up/down events. These should be +visible in your snmp logs with a message similar to: :: @@ -199,3 +200,18 @@ a siren, have your display flash, etc., be creative ;). # mail the notification echo "$MAIL" | mail -s "$SUBJECT" $EMAILADDR + +.. _traps-mib-selection: + +Traps Mib Selection in BGP +-------------------------- + +Both :rfc:`4273` and [Draft-IETF-idr-bgp4-mibv2-11]_ MIBs define traps for +dealing with up/down events and state transition. The user has the +possibility to select the MIB he wants to receive traps from: + +.. clicmd:: bgp snmp traps <rfc4273|bgp4-mibv2> + +By default, only rfc4273 traps are enabled and sent. + +.. [Draft-IETF-idr-bgp4-mibv2-11] <https://tools.ietf.org/id/draft-ietf-idr-bgp4-mibv2-11.txt> diff --git a/doc/user/static.rst b/doc/user/static.rst index d405276..922c71a 100644 --- a/doc/user/static.rst +++ b/doc/user/static.rst @@ -12,21 +12,13 @@ of static routes. Starting STATIC =============== -Default configuration file for *staticd* is :file:`staticd.conf`. The typical -location of :file:`staticd.conf` is |INSTALL_PREFIX_ETC|/staticd.conf. - -If the user is using integrated config, then :file:`staticd.conf` need not be -present and the :file:`frr.conf` is read instead. - -If the user has not fully upgraded to using the staticd.conf and still has -a non-integrated config with zebra.conf holding the static routes, *staticd* -will read in the :file:`zebrad.conf` as a backup. - .. program:: staticd :abbr:`STATIC` supports all the common FRR daemon start options which are documented elsewhere. +.. include:: config-include.rst + .. _static-route-commands: Static Route Commands diff --git a/doc/user/vrrp.rst b/doc/user/vrrp.rst index ef3aebe..d99fc23 100644 --- a/doc/user/vrrp.rst +++ b/doc/user/vrrp.rst @@ -24,11 +24,7 @@ protocol. Starting VRRP ============= -The configuration file for *vrrpd* is :file:`vrrpd.conf`. The typical location -of :file:`vrrpd.conf` is |INSTALL_PREFIX_ETC|/vrrpd.conf. - -If using integrated config, then :file:`vrrpd.conf` need not be present and -:file:`frr.conf` is read instead. +.. include:: config-include.rst .. program:: vrrpd diff --git a/doc/user/vtysh.rst b/doc/user/vtysh.rst index adbdf34..9722231 100644 --- a/doc/user/vtysh.rst +++ b/doc/user/vtysh.rst @@ -131,14 +131,14 @@ could be made SGID (set group ID) to the |INSTALL_VTY_GROUP| group. at all. -.. _integrated-configuration-mode: +.. _integrated-configuration-file: -Integrated configuration mode +Integrated configuration file ============================= -Integrated configuration mode uses a single configuration file, -:file:`frr.conf`, for all daemons. This replaces the individual files like -:file:`zebra.conf` or :file:`bgpd.conf`. +FRR uses a single configuration file, :file:`frr.conf`, for all daemons. This +replaces the individual files like :file:`zebra.conf` or :file:`bgpd.conf` used +in previous versions of the software. :file:`frr.conf` is located in |INSTALL_PREFIX_ETC|. All daemons check for the existence of this file at startup, and if it exists will not load their diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index ba6e3bf..30b0204 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -50,7 +50,8 @@ Besides the common invocation options (:ref:`common-invocation-options`), the When *Zebra* starts with this option, the VRF backend is based on Linux network namespaces. That implies that all network namespaces discovered by ZEBRA will create an associated VRF. The other daemons will operate on the VRF - VRF defined by *Zebra*, as usual. + VRF defined by *Zebra*, as usual. If this option is specified when running + *Zebra*, one must also specify the same option for *mgmtd*. .. seealso:: :ref:`zebra-vrf` @@ -177,16 +178,15 @@ Standard Commands work on non-linux systems at all. 'enable' and 'disable' will respectively turn on and off mpls on the given interface. -.. clicmd:: multicast +.. clicmd:: multicast <enable|disable> Enable or disable multicast flag for the interface. -.. clicmd:: bandwidth (1-10000000) +.. clicmd:: bandwidth (1-1000000) - - Set bandwidth value of the interface in kilobits/sec. This is for + Set bandwidth value of the interface in Megabits/sec. This is for calculating OSPF cost. This command does not affect the actual device configuration. @@ -213,20 +213,14 @@ Link Parameters Commands .. clicmd:: link-params + Enter into the link parameters sub node. This command activates the link + parameters and allows to configure routing information that could be used + as part of Traffic Engineering on this interface. MPLS-TE must be enabled at + the OSPF (:ref:`ospf-traffic-engineering`) or ISIS + (:ref:`isis-traffic-engineering`) router level in complement to this. To + disable link parameters, use the ``no`` version of this command. - Enter into the link parameters sub node. At least 'enable' must be - set to activate the link parameters, and consequently routing - information that could be used as part of Traffic Engineering on - this interface. MPLS-TE must be enable at the OSPF - (:ref:`ospf-traffic-engineering`) or ISIS - (:ref:`isis-traffic-engineering`) router level in complement to - this. - - Under link parameter statement, the following commands set the different TE values: - -.. clicmd:: enable - - Enable link parameters for this interface. +Under link parameter statement, the following commands set the different TE values: .. clicmd:: metric (0-4294967295) @@ -252,7 +246,7 @@ Link Parameters Commands as specified in RFC3630 (OSPF) or RFC5305 (ISIS). Admin-group is also known as Resource Class/Color in the OSPF protocol. -.. clicmd:: [no] affinity AFFINITY-MAP-NAME +.. clicmd:: affinity AFFINITY-MAP-NAME This commands configures the Traffic Engineering Admin-Group of the interface using the affinity-map definitions (:ref:`affinity-map`). @@ -263,7 +257,7 @@ Link Parameters Commands ``admin-grp`` and ``affinity`` commands provide two ways of setting admin-groups. They cannot be both set on the same interface. -.. clicmd:: [no] affinity-mode [extended|standard|both] +.. clicmd:: affinity-mode [extended|standard|both] This commands configures which admin-group format is set by the affinity command. ``extended`` Admin-Group is the default and uses the RFC7308 format. @@ -783,9 +777,25 @@ presence of the entry. 21 Static 10.125.0.2 IPv4 Explicit Null +MPLS label chunks +----------------- + +MPLS label chunks are handled in the zebra label manager service, +which ensures a same label value or label chunk can not be used by +multiple CP routing daemons at the same time. + +Label requests originate from CP routing daemons, and are resolved +over the default MPLS range (16-1048575). There are two kind of +requests: +- Static label requests request an exact label value or range. For +instance, segment routing label blocks requests originating from +IS-IS are part of it. +- Dynamic label requests only need a range of label values. The +'bgp l3vpn export auto' command uses such requests. + Allocated label chunks table can be dumped using the command -.. clicmd:: show debugging label-table +.. clicmd:: show debugging label-table [json] :: @@ -796,6 +806,15 @@ Allocated label chunks table can be dumped using the command Proto ospf: [20000/21000] Proto isis: [22000/23000] +.. clicmd:: mpls label dynamic-block (16-1048575) (16-1048575) + + Define a range of labels where dynamic label requests will + allocate label chunks from. This command guarantees that + static label values outside that range will not conflict + with the dynamic label requests. When the dynamic-block + range is configured, static label requests that match that + range are not accepted. + .. _zebra-srv6: Segment-Routing IPv6 @@ -813,6 +832,35 @@ FRR's cli or frr.conf or zebra.conf. This section shows how to configure SRv6 on FRR. Of course SRv6 can be used as standalone, and this section also helps that case. +.. clicmd:: show segment-routing srv6 manager [json] + + This command dumps the SRv6 information configured on zebra, including + the encapsulation parameters (e.g., the IPv6 source address used for + the encapsulated packets). + + Example:: + + router# sh segment-routing srv6 manager + Parameters: + Encapsulation: + Source Address: + Configured: fc00:0:1::1 + + + To get the same information in json format, you can use the ``json`` keyword:: + + rose-srv6# sh segment-routing srv6 manager json + { + "parameters":{ + "encapsulation":{ + "sourceAddress":{ + "configured":"fc00:0:1::1" + } + } + } + } + + .. clicmd:: show segment-routing srv6 locator [json] This command dump SRv6-locator configured on zebra. SRv6-locator is used @@ -973,6 +1021,14 @@ and this section also helps that case. ! ... +.. clicmd:: encapsulation + + Configure parameters for SRv6 encapsulation. + +.. clicmd:: source-address X:X::X:X + + Configure the source address of the outer encapsulating IPv6 header. + .. _multicast-rib-commands: Multicast RIB Commands @@ -1434,8 +1490,6 @@ zebra Terminal Mode Commands .. clicmd:: show ip prefix-list [NAME] -.. clicmd:: show route-map [NAME] - .. clicmd:: show ip protocol .. clicmd:: show ip forward diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile index 98e8407..1cff06f 100644 --- a/docker/alpine/Dockerfile +++ b/docker/alpine/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 # Create a basic stage set up to build APKs -FROM alpine:3.18 as alpine-builder +FROM alpine:3.19 as alpine-builder RUN apk add \ --update-cache \ abuild \ @@ -24,7 +24,7 @@ RUN cd /src/libyang \ && abuild -r -P /pkgs/apk # This stage builds a dist tarball from the source -FROM alpine:3.18 as source-builder +FROM alpine:3.19 as source-builder RUN mkdir -p /src/alpine /pkgs/apk COPY alpine/APKBUILD.in /src/alpine COPY --from=alpine-apk-builder-libyang /pkgs/apk/src /pkgs/apk @@ -33,8 +33,7 @@ RUN source /src/alpine/APKBUILD.in \ && apk add \ --no-cache \ --update-cache \ - $makedepends \ - && pip install pytest + $makedepends COPY . /src ARG PKGVER RUN cd /src \ @@ -58,7 +57,7 @@ RUN cd /dist \ && abuild -r -P /pkgs/apk # This stage installs frr from the apk -FROM alpine:3.18 +FROM alpine:3.19 RUN mkdir -p /pkgs/apk COPY --from=alpine-apk-builder /pkgs/apk/ /pkgs/apk/ RUN apk add \ diff --git a/docker/alpine/libyang/APKBUILD b/docker/alpine/libyang/APKBUILD index 04e943f..6973fd6 100755 --- a/docker/alpine/libyang/APKBUILD +++ b/docker/alpine/libyang/APKBUILD @@ -1,7 +1,7 @@ # Contributor: Sören Tempel <soeren+alpine@soeren-tempel.net> # Maintainer: Christian Franke <nobody@nowhere.ws> pkgname=libyang -pkgver=2.1.80 +pkgver=2.1.128 pkgrel=0 pkgdesc="YANG data modelling language parser and toolkit" url="https://github.com/CESNET/libyang" diff --git a/docker/ubi8-minimal/Dockerfile b/docker/ubi8-minimal/Dockerfile index 53f8d25..14a5cdd 100644 --- a/docker/ubi8-minimal/Dockerfile +++ b/docker/ubi8-minimal/Dockerfile @@ -10,6 +10,7 @@ ADD docker/ubi8-minimal/almalinux.repo /etc/yum.repos.d/almalinux.repo # and later reinstall it again: https://bugzilla.redhat.com/show_bug.cgi?id=1668185 RUN rpm --quiet -e --nodeps tzdata >/dev/null 2>&1 +# Keep the list of dependencies alphabetically sorted for easier maintenance RUN microdnf --disableplugin=subscription-manager --setopt=install_weak_deps=0 install \ autoconf \ automake \ @@ -29,6 +30,7 @@ RUN microdnf --disableplugin=subscription-manager --setopt=install_weak_deps=0 i pcre-devel \ pkgconfig \ platform-python-devel \ + protobuf-c-devel \ python3-devel \ python3-pytest \ python3-sphinx \ @@ -37,7 +39,6 @@ RUN microdnf --disableplugin=subscription-manager --setopt=install_weak_deps=0 i systemd-devel \ texinfo \ tzdata \ - protobuf-c-devel \ && microdnf --disableplugin=subscription-manager clean all RUN curl -sSL -o /tmp/libyang2.rpm https://ci1.netdef.org/artifact/LIBYANG-LIBYANG2/shared/build-181/RedHat-8-x86_64-Packages/libyang-2.1.80-1.el8.x86_64.rpm \ @@ -92,12 +93,14 @@ ADD docker/ubi8-minimal/almalinux.repo /etc/yum.repos.d/almalinux.repo RUN rpm --import https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-8 +# Keep the list of dependencies alphabetically sorted for easier maintenance RUN microdnf --disableplugin=subscription-manager --setopt=install_weak_deps=0 install \ c-ares \ initscripts \ net-snmp-agent-libs \ net-snmp-libs \ openssl \ + protobuf-c \ python3 \ shadow-utils \ systemd \ diff --git a/docker/ubuntu-ci/Dockerfile b/docker/ubuntu-ci/Dockerfile index 939a43e..5a49806 100644 --- a/docker/ubuntu-ci/Dockerfile +++ b/docker/ubuntu-ci/Dockerfile @@ -41,17 +41,24 @@ RUN apt update && apt upgrade -y && \ cmake \ libpcre2-dev \ && \ + # GRPC extra build requirements + apt-get install -y \ + libgrpc-dev \ + libgrpc++-dev \ + protobuf-compiler-grpc \ + && \ # Runtime/triage/testing requirements apt-get install -y \ curl \ gdb \ + kmod \ iproute2 \ iputils-ping \ liblua5.3-dev \ libssl-dev \ lua5.3 \ net-tools \ - python2 \ + python3 \ python3-pip \ snmp \ snmp-mibs-downloader \ @@ -66,17 +73,12 @@ RUN apt update && apt upgrade -y && \ wget https://raw.githubusercontent.com/FRRouting/frr-mibs/main/iana/IANA-IPPM-METRICS-REGISTRY-MIB -O /usr/share/snmp/mibs/iana/IANA-IPPM-METRICS-REGISTRY-MIB && \ wget https://raw.githubusercontent.com/FRRouting/frr-mibs/main/ietf/SNMPv2-PDU -O /usr/share/snmp/mibs/ietf/SNMPv2-PDU && \ wget https://raw.githubusercontent.com/FRRouting/frr-mibs/main/ietf/IPATM-IPMC-MIB -O /usr/share/snmp/mibs/ietf/IPATM-IPMC-MIB && \ - curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output /tmp/get-pip.py && \ - python2 /tmp/get-pip.py && \ - rm -f /tmp/get-pip.py && \ python3 -m pip install wheel && \ - python3 -m pip install pytest && \ - python3 -m pip install pytest-sugar && \ - python3 -m pip install pytest-xdist && \ - python3 -m pip install "scapy>=2.4.2" && \ + python3 -m pip install 'protobuf<4' grpcio grpcio-tools && \ + python3 -m pip install 'pytest>=6.2.4' 'pytest-xdist>=2.3.0' && \ + python3 -m pip install 'scapy>=2.4.5' && \ python3 -m pip install xmltodict && \ - python3 -m pip install grpcio grpcio-tools && \ - python2 -m pip install 'exabgp<4.0.0' + python3 -m pip install git+https://github.com/Exa-Networks/exabgp@0659057837cd6c6351579e9f0fa47e9fb7de7311 RUN groupadd -r -g 92 frr && \ groupadd -r -g 85 frrvty && \ @@ -93,7 +95,7 @@ USER frr:frr RUN cd && pwd && ls -al && \ git clone https://github.com/CESNET/libyang.git && \ cd libyang && \ - git checkout v2.1.80 && \ + git checkout v2.1.128 && \ mkdir build; cd build && \ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \ -DCMAKE_BUILD_TYPE:String="Release" .. && \ @@ -106,14 +108,15 @@ RUN cd ~/frr && \ ./bootstrap.sh && \ ./configure \ --prefix=/usr \ - --localstatedir=/var/run/frr \ + --sysconfdir=/etc \ + --localstatedir=/var \ --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ --enable-sharpd \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-config-rollbacks \ + --enable-grpc \ --enable-vty-group=frrvty \ --enable-snmp=agentx \ --enable-scripting \ diff --git a/docker/ubuntu20-ci/README.md b/docker/ubuntu20-ci/README.md index 536f8e2..6c0ff44 100644 --- a/docker/ubuntu20-ci/README.md +++ b/docker/ubuntu20-ci/README.md @@ -11,13 +11,13 @@ docker build -t frr-ubuntu20:latest --build-arg=UBUNTU_VERSION=20.04 -f docker/u # Running Full Topotest ``` -docker run --init -it --privileged --name frr -v /lib/modules:/lib/modules frr-ubuntu22:latest bash -c 'cd ~/frr/tests/topotests ; sudo pytest -nauto --dist=loadfile' +docker run --init -it --privileged --name frr-ubuntu20 -v /lib/modules:/lib/modules frr-ubuntu20:latest bash -c 'cd ~/frr/tests/topotests ; sudo pytest -nauto --dist=loadfile' ``` # Extract results from the above run into `run-results` dir and analyze ``` -tests/topotest/analyze.py -C frr -Ar run-results +tests/topotests/analyze.py -C frr-ubuntu20 -Ar run-results ``` # Running @@ -41,13 +41,13 @@ docker exec -it frr-ubuntu20 bash # topotest -- when Host O/S is Ubuntu only ``` -docker exec frr-ubuntu20 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py' +docker exec frr-ubuntu20 bash -c 'cd ~/frr/tests/topotests/ospf_topo1 ; sudo pytest test_ospf_topo1.py' ``` # stop & remove container ``` -docker stop frr-ubuntu20 ; docker rm frr-ubuntu18 +docker stop frr-ubuntu20 ; docker rm frr-ubuntu20 ``` # remove image diff --git a/docker/ubuntu22-ci/README.md b/docker/ubuntu22-ci/README.md index 403abbf..73f4a10 100644 --- a/docker/ubuntu22-ci/README.md +++ b/docker/ubuntu22-ci/README.md @@ -11,43 +11,43 @@ docker build -t frr-ubuntu22:latest -f docker/ubuntu-ci/Dockerfile . # Running Full Topotest ``` -docker run --init -it --privileged --name frr -v /lib/modules:/lib/modules frr-ubuntu22:latest bash -c 'cd ~/frr/tests/topotests ; sudo pytest -nauto --dist=loadfile' +docker run --init -it --privileged --name frr-ubuntu22 -v /lib/modules:/lib/modules frr-ubuntu22:latest bash -c 'cd ~/frr/tests/topotests ; sudo pytest -nauto --dist=loadfile' ``` # Extract results from the above run into `run-results` dir and analyze ``` -tests/topotest/analyze.py -C frr -Ar run-results +tests/topotests/analyze.py -C frr-ubuntu22 -Ar run-results ``` # Running ``` -docker run -d --init --privileged --name frr --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu22:latest +docker run -d --init --privileged --name frr-ubuntu22 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu22:latest ``` # make check ``` -docker exec frr bash -c 'cd ~/frr ; make check' +docker exec frr-ubuntu22 bash -c 'cd ~/frr ; make check' ``` # interactive bash ``` -docker exec -it frr bash +docker exec -it frr-ubuntu22 bash ``` # topotest -- when Host O/S is Ubuntu only ``` -docker exec frr bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py' +docker exec frr-ubuntu22 bash -c 'cd ~/frr/tests/topotests/ospf_topo1 ; sudo pytest test_ospf_topo1.py' ``` # stop & remove container ``` -docker stop frr ; docker rm frr +docker stop frr-ubuntu22 ; docker rm frr-ubuntu22 ``` # remove image |