+++ /dev/null
-Building FRR for OpenWRT/LEDE from Git Source
-===============================================
-
-- for the moment because of cross compile problems, master is not supported,
- only upto 3.0
-- LDP can't be built because of missing Perl-XML-LibXML in OpenWRT/LEDE tree
-
-Prepare build environment
--------------------------
-
-https://lede-project.org/docs/guide-developer/install-buildsystem
-
-for
-
-Ubuntu 12.04LTS:
-
- sudo apt-get install build-essential subversion git-core \
- libncurses5-dev zlib1g-dev gawk flex quilt libssl-dev xsltproc \
- libxml-parser-perl mercurial bzr ecj cvs unzip
-
-Ubuntu 64bit:
-
- sudo apt-get install build-essential subversion libncurses5-dev zlib1g-dev \
- gawk gcc-multilib flex git-core gettext libssl-dev
-
-Debian 8 Jessie:
-
- sudo apt-get install build-essential libncurses5-dev gawk git subversion \
- libssl-dev gettext unzip zlib1g-dev file python
-
-Debian 9 Stretch:
-
- sudo apt-get install build-essential libncurses5-dev gawk git subversion \
- libssl-dev gettext zlib1g-dev
-
-Centos x86-64 (some packages require EPEL):
-
- yum install subversion binutils bzip2 gcc gcc-c++ gawk gettext flex \
- ncurses-devel zlib-devel zlib-static make patch unzip glibc glibc-devel \
- perl-ExtUtils-MakeMaker glibc-static quilt ncurses-libs sed sdcc bison \
- intltool sharutils wget git-core openssl-devel xz
-
-Fedora 24 - 64Bit:
-
- dnf install -y subversion binutils bzip2 gcc gcc-c++ gawk gettext git-core \
- unzip ncurses-devel ncurses-compat-libs zlib-devel zlib-static make \
- flex patch perl-ExtUtils-MakeMaker perl-Thread-Queue glibc glibc-devel \
- glibc-static quilt sed sdcc intltool sharutils bison wget openssl-devel
-
-
-Get LEDE Sources (from Git)
----------------------------
-
-LEDE and OpenWRT is planned to remerge and won't cover the similar OpenWRT build
-As normal user:
- git clone https://git.lede-project.org/source.git lede
- cd lede
- ./scripts/feeds update -a
- ./scripts/feeds install -a
- cd feeds/routing
- git pull origin pull/319/head
- ln -s ../../../feeds/routing/frr/ ../../package/feeds/routing/
- cd ../..
- make menuconfig
-
-Select the needed target then select needed packages in
-Network -> Routing and Redirection -> frr, exit and save
-
- make or make package/frr/compile
-
-It may be possible that on first build `make package/frr/compile` not to work
-and it may be needed to run a `make` for the entire build envronment, add V=s
-for debugging
-
-Work with sources
------------------
-
-To update the rc1 version or add other options, the Makefile is found in
-feeds/routing/frr
-
-edit:
- PKG_VERSION:=
- PKG_SOURCE_VERSION:=<git-hash>
-
-Usage
------
-
-Edit `/usr/sbin/frr.init` and add/remove the daemons name in section DAEMONS=
-or don't install unneded packages
-For example: zebra bgpd ldpd isisd nhrpd ospfd ospf6d pimd ripd ripngd
-
-### Enable the serivce
- - service frr enable
-
-### Start the service
- - service frr start
+++ /dev/null
-Building FRR on CentOS 6 from Git Source
-========================================
-
-(As an alternative to this installation, you may prefer to create a FRR
-rpm package yourself and install that package instead. See instructions
-in redhat/README.rpm_build.md on how to build a rpm package)
-
-Instructions are tested with `CentOS 6.8` on `x86_64` platform
-
-CentOS 6 restrictions:
-----------------------
-
-- PIMd is not supported on `CentOS 6`. Upgrade to `CentOS 7` if PIMd is
- needed
-- MPLS is not supported on `CentOS 6`. MPLS requires Linux Kernel 4.5 or
- higher (LDP can be built, but may have limited use without MPLS)
-- Zebra is unable to detect what bridge/vrf an interface is associcated
- with (IFLA_INFO_SLAVE_KIND does not exist in the kernel headers, you
- can use a newer kernel + headers to get this functionality)
-- frr_reload.py will not work, as this requires Python 2.7, and CentOS 6
- only has 2.6. You can install Python 2.7 via IUS, but it won't work
- properly unless you compile and install the ipaddr package for it.
-
-Install required packages
--------------------------
-
-Add packages:
-
- sudo yum install git autoconf automake libtool make gawk \
- readline-devel texinfo net-snmp-devel groff pkgconfig \
- json-c-devel pam-devel flex epel-release perl-XML-LibXML \
- c-ares-devel
-
-Install newer version of bison (CentOS 6 package source is too old) from
-CentOS 7
-
- sudo yum install rpm-build
- curl -O http://vault.centos.org/7.0.1406/os/Source/SPackages/bison-2.7-4.el7.src.rpm
- rpmbuild --rebuild ./bison-2.7-4.el7.src.rpm
- sudo yum install ./rpmbuild/RPMS/x86_64/bison-2.7-4.el6.x86_64.rpm
- rm -rf rpmbuild
-
-Install newer version of autoconf and automake (Package versions are too old)
-
- curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
- tar xvf autoconf-2.69.tar.gz
- cd autoconf-2.69
- ./configure --prefix=/usr
- make
- sudo make install
- cd ..
-
- curl -O http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz
- tar xvf automake-1.15.tar.gz
- cd automake-1.15
- ./configure --prefix=/usr
- make
- sudo make install
- cd ..
-
-Install `Python 2.7` in parallel to default 2.6.
-Make sure you've install EPEL (`epel-release` as above). Then install current
-`python27`, `python27-devel` and `pytest`
-
- sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
- sudo rpm -ivh https://centos6.iuscommunity.org/ius-release.rpm
- sudo yum install python27 python27-pip python27-devel
- sudo pip2.7 install pytest
-
-Please note that `CentOS 6` needs to keep python pointing to version 2.6
-for `yum` to keep working, so don't create a symlink for python2.7 to python
-
-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 groups and user
-
- sudo groupadd -g 92 frr
- sudo groupadd -r -g 85 frrvt
- sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
- -c "FRR FRRouting suite" -d /var/run/frr frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example.)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- ./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 \
- --enable-multipath=64 \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvt \
- --enable-rtadv \
- --disable-exampledir \
- --enable-watchfrr \
- --disable-ldpd \
- --enable-fpm \
- --enable-nhrpd \
- --enable-eigrpd \
- --enable-babeld \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- make
- make check PYTHON=/usr/bin/python2.7
- sudo make install
-
-### Create empty FRR configuration files
- sudo mkdir /var/log/frr
- sudo mkdir /etc/frr
- sudo touch /etc/frr/zebra.conf
- sudo touch /etc/frr/bgpd.conf
- sudo touch /etc/frr/ospfd.conf
- sudo touch /etc/frr/ospf6d.conf
- sudo touch /etc/frr/isisd.conf
- sudo touch /etc/frr/ripd.conf
- sudo touch /etc/frr/ripngd.conf
- sudo touch /etc/frr/nhrpd.conf
- sudo touch /etc/frr/eigrpd.conf
- sudo touch /etc/frr/babeld.conf
- sudo chown -R frr:frr /etc/frr/
- sudo touch /etc/frr/vtysh.conf
- sudo chown frr:frrvt /etc/frr/vtysh.conf
- sudo chmod 640 /etc/frr/*.conf
-
-### Install daemon config file
- sudo install -p -m 644 redhat/daemons /etc/frr/
- sudo chown frr:frr /etc/frr/daemons
-
-### Edit /etc/frr/daemons as needed to select the required daemons
-
-Look for the section with `watchfrr_enable=...` and `zebra=...` etc.
-Enable the daemons as required by changing the value to `yes`
-
-### Enable IP & IPv6 forwarding
-
-Edit `/etc/sysctl.conf` and set the following values (ignore the other
-settings)
-
- # Controls IP packet forwarding
- net.ipv4.ip_forward = 1
- net.ipv6.conf.all.forwarding=1
-
- # Controls source route verification
- net.ipv4.conf.default.rp_filter = 0
-
-Load the modifed sysctl's on the system:
-
- sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
-
-### Add init.d startup files
- sudo install -p -m 755 redhat/frr.init /etc/init.d/frr
- sudo chkconfig --add frr
-
-### Enable frr daemon at startup
- sudo chkconfig frr on
-
-### Start FRR manually (or reboot)
- sudo /etc/init.d/frr start
+++ /dev/null
-Building FRR on CentOS 7 from Git Source
-========================================
-
-(As an alternative to this installation, you may prefer to create a FRR
-rpm package yourself and install that package instead. See instructions
-in redhat/README.rpm_build.md on how to build a rpm package)
-
-CentOS 7 restrictions:
-----------------------
-
-- MPLS is not supported on `CentOS 7` with default kernel. MPLS requires
- Linux Kernel 4.5 or higher (LDP can be built, but may have limited use
- without MPLS)
-
-Install required packages
--------------------------
-
-Add packages:
-
- sudo yum install git autoconf automake libtool make gawk \
- readline-devel texinfo net-snmp-devel groff pkgconfig \
- json-c-devel pam-devel bison flex pytest c-ares-devel \
- perl-XML-LibXML python-devel
-
-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 groups and user
-
- sudo groupadd -g 92 frr
- sudo groupadd -r -g 85 frrvt
- sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
- -c "FRR FRRouting suite" -d /var/run/frr frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example.)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- ./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-pimd \
- --enable-snmp=agentx \
- --enable-multipath=64 \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvt \
- --enable-rtadv \
- --disable-exampledir \
- --enable-watchfrr \
- --disable-ldpd \
- --enable-fpm \
- --enable-nhrpd \
- --enable-eigrpd \
- --enable-babeld \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- make
- make check
- sudo make install
-
-### Create empty FRR configuration files
- sudo mkdir /var/log/frr
- sudo mkdir /etc/frr
- sudo touch /etc/frr/zebra.conf
- sudo touch /etc/frr/bgpd.conf
- sudo touch /etc/frr/ospfd.conf
- sudo touch /etc/frr/ospf6d.conf
- sudo touch /etc/frr/isisd.conf
- sudo touch /etc/frr/ripd.conf
- sudo touch /etc/frr/ripngd.conf
- sudo touch /etc/frr/pimd.conf
- sudo touch /etc/frr/nhrpd.conf
- sudo touch /etc/frr/eigrpd.conf
- sudo touch /etc/frr/babeld.conf
- sudo chown -R frr:frr /etc/frr/
- sudo touch /etc/frr/vtysh.conf
- sudo chown frr:frrvt /etc/frr/vtysh.conf
- sudo chmod 640 /etc/frr/*.conf
-
-### Install daemon config file
- sudo install -p -m 644 redhat/daemons /etc/frr/
- sudo chown frr:frr /etc/frr/daemons
-
-### Edit /etc/frr/daemons as needed to select the required daemons
-
-Look for the section with `watchfrr_enable=...` and `zebra=...` etc.
-Enable the daemons as required by changing the value to `yes`
-
-### Enable IP & IPv6 forwarding
-
-Create a new file `/etc/sysctl.d/90-routing-sysctl.conf` with the
-following content:
-
- # Sysctl for routing
- #
- # Routing: We need to forward packets
- net.ipv4.conf.all.forwarding=1
- net.ipv6.conf.all.forwarding=1
-
-Load the modifed sysctl's on the system:
-
- sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
-
-### Install frr Service and redhat init files
- sudo install -p -m 644 redhat/frr.service /usr/lib/systemd/system/frr.service
- sudo install -p -m 755 redhat/frr.init /usr/lib/frr/frr
-
-### Register the systemd files
- sudo systemctl preset frr.service
-
-### Enable required frr at startup
- sudo systemctl enable frr
-
-### Reboot or start FRR manually
- sudo systemctl start frr
+++ /dev/null
-Building FRR on Debian 8 from Git Source
-========================================
-
-Debian 8 restrictions:
-----------------------
-
-- MPLS is not supported on `Debian 8` with default kernel. MPLS requires
- Linux Kernel 4.5 or higher (LDP can be built, but may have limited use
- without MPLS)
-
-Install required packages
--------------------------
-
-Add packages:
-
- sudo apt-get install git autoconf automake libtool make gawk \
- libreadline-dev texinfo libjson-c-dev pkg-config bison flex \
- python-pip libc-ares-dev python3-dev
-
-Install newer pytest (>3.0) from pip
-
- sudo pip install pytest
-
-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 groups and user
-
- sudo addgroup --system --gid 92 frr
- sudo addgroup --system --gid 85 frrvty
- sudo adduser --system --ingroup frr --home /var/run/frr/ \
- --gecos "FRR suite" --shell /bin/false frr
- sudo usermod -a -G frrvty frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example.)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- ./configure \
- --enable-exampledir=/usr/share/doc/frr/examples/ \
- --localstatedir=/var/run/frr \
- --sbindir=/usr/lib/frr \
- --sysconfdir=/etc/frr \
- --enable-vtysh \
- --enable-isisd \
- --enable-pimd \
- --enable-watchfrr \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --enable-ldpd \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- make
- make check
- sudo make install
-
-### Create empty FRR configuration files
-
- sudo install -m 755 -o frr -g frr -d /var/log/frr
- sudo install -m 775 -o frr -g frrvty -d /etc/frr
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
- sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
-
-### Enable IP & IPv6 forwarding
-
-Edit `/etc/sysctl.conf` and uncomment the following values (ignore the
-other settings)
-
- # Uncomment the next line to enable packet forwarding for IPv4
- net.ipv4.ip_forward=1
-
- # Uncomment the next line to enable packet forwarding for IPv6
- # Enabling this option disables Stateless Address Autoconfiguration
- # based on Router Advertisements for this host
- net.ipv6.conf.all.forwarding=1
-
-**Reboot** or use `sysctl -p` to apply the same config to the running system
-
-### Troubleshooting
-
-**Local state directory**
-
-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.
-
-When using a different local state directory you need to create the new
-directory and change the ownership to the frr user, for example:
-
- mkdir /var/opt/frr
- chown frr /var/opt/frr
-
-**Shared library error**
-
-If you try and start any of the frrouting daemons you may see the below error
-due to the frrouting shared library directory not being found:
-
- ./zebra: error while loading shared libraries: libfrr.so.0: cannot open shared object file: No such file or directory
-
-The fix is to add the following line to /etc/ld.so.conf which will continue to
-reference the library directory after the system reboots. To load the library
-directory path immediately run the ldconfig command after adding the line to
-the file eg:
-
- echo include /usr/local/lib >> /etc/ld.so.conf
- ldconfig
+++ /dev/null
-Building FRR on Debian 9 from Git Source
-========================================
-
-Install required packages
--------------------------
-
-Add packages:
-
- sudo apt-get install git autoconf automake libtool make \
- libreadline-dev texinfo libjson-c-dev pkg-config bison flex \
- python-pip libc-ares-dev python3-dev python-pytest
-
-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 groups and user
-
- sudo addgroup --system --gid 92 frr
- sudo addgroup --system --gid 85 frrvty
- sudo adduser --system --ingroup frr --home /var/run/frr/ \
- --gecos "FRR suite" --shell /bin/false frr
- sudo usermod -a -G frrvty frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example.)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- git checkout stable/3.0
- ./bootstrap.sh
- ./configure \
- --enable-exampledir=/usr/share/doc/frr/examples/ \
- --localstatedir=/var/run/frr \
- --sbindir=/usr/lib/frr \
- --sysconfdir=/etc/frr \
- --enable-vtysh \
- --enable-isisd \
- --enable-pimd \
- --enable-watchfrr \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --enable-ldpd \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- make
- make check
- sudo make install
-
-### Create empty FRR configuration files
-
- sudo install -m 755 -o frr -g frr -d /var/log/frr
- sudo install -m 775 -o frr -g frrvty -d /etc/frr
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
- sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
-
-### Enable IP & IPv6 forwarding
-
-Edit `/etc/sysctl.conf` and uncomment the following values (ignore the
-other settings)
-
- # Uncomment the next line to enable packet forwarding for IPv4
- net.ipv4.ip_forward=1
-
- # Uncomment the next line to enable packet forwarding for IPv6
- # Enabling this option disables Stateless Address Autoconfiguration
- # based on Router Advertisements for this host
- net.ipv6.conf.all.forwarding=1
-
-**Reboot** or use `sysctl -p` to apply the same config to the running system
-
-### Troubleshooting
-
-**Local state directory**
-
-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.
-
-When using a different local state directory you need to create the new
-directory and change the ownership to the frr user, for example:
-
- mkdir /var/opt/frr
- chown frr /var/opt/frr
-
-**Shared library error**
-
-If you try and start any of the frrouting daemons you may see the below error
-due to the frrouting shared library directory not being found:
-
- ./zebra: error while loading shared libraries: libfrr.so.0: cannot open shared object file: No such file or directory
-
-The fix is to add the following line to /etc/ld.so.conf which will continue to
-reference the library directory after the system reboots. To load the library
-directory path immediately run the ldconfig command after adding the line to
-the file eg:
-
- echo include /usr/local/lib >> /etc/ld.so.conf
- ldconfig
+++ /dev/null
-Building FRR on Fedora 24 from Git Source
-=========================================
-
-(As an alternative to this installation, you may prefer to create a FRR
-rpm package yourself and install that package instead. See instructions
-in redhat/README.rpm_build.md on how to build a rpm package)
-
-Install required packages
--------------------------
-
-Add packages:
-
- sudo dnf install git autoconf automake libtool make gawk \
- readline-devel texinfo net-snmp-devel groff pkgconfig \
- json-c-devel pam-devel perl-XML-LibXML pytest bison flex \
- c-ares-devel python3-devel
-
-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 groups and user
-
- sudo groupadd -g 92 frr
- sudo groupadd -r -g 85 frrvt
- sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
- -c "FRR FRRouting suite" -d /var/run/frr frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example.)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- ./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-pimd \
- --enable-snmp=agentx \
- --enable-multipath=64 \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvt \
- --enable-rtadv \
- --disable-exampledir \
- --enable-watchfrr \
- --enable-ldpd \
- --enable-fpm \
- --enable-nhrpd \
- --enable-eigrpd \
- --enable-babeld \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- make
- make check
- sudo make install
-
-### Create empty FRR configuration files
- sudo mkdir /var/log/frr
- sudo mkdir /etc/frr
- sudo touch /etc/frr/zebra.conf
- sudo touch /etc/frr/bgpd.conf
- sudo touch /etc/frr/ospfd.conf
- sudo touch /etc/frr/ospf6d.conf
- sudo touch /etc/frr/isisd.conf
- sudo touch /etc/frr/ripd.conf
- sudo touch /etc/frr/ripngd.conf
- sudo touch /etc/frr/pimd.conf
- sudo touch /etc/frr/ldpd.conf
- sudo touch /etc/frr/nhrpd.conf
- sudo touch /etc/frr/eigrpd.conf
- sudo touch /etc/frr/babeld.conf
- sudo chown -R frr:frr /etc/frr/
- sudo touch /etc/frr/vtysh.conf
- sudo chown frr:frrvt /etc/frr/vtysh.conf
- sudo chmod 640 /etc/frr/*.conf
-
-### Install daemon config file
- sudo install -p -m 644 redhat/daemons /etc/frr/
- sudo chown frr:frr /etc/frr/daemons
-
-### Edit /etc/frr/daemons as needed to select the required daemons
-
-Look for the section with `watchfrr_enable=...` and `zebra=...` etc.
-Enable the daemons as required by changing the value to `yes`
-
-### Enable IP & IPv6 forwarding (and MPLS)
-
-Create a new file `/etc/sysctl.d/90-routing-sysctl.conf` with the
-following content:
-(Please make sure to list all interfaces with required MPLS similar
-to `net.mpls.conf.eth0.input=1`)
-
- # Sysctl for routing
- #
- # Routing: We need to forward packets
- net.ipv4.conf.all.forwarding=1
- net.ipv6.conf.all.forwarding=1
- #
- # Enable MPLS Label processing on all interfaces
- net.mpls.conf.eth0.input=1
- net.mpls.conf.eth1.input=1
- net.mpls.conf.eth2.input=1
- net.mpls.platform_labels=100000
-
-Load the modifed sysctl's on the system:
-
- sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
-
-Create a new file `/etc/modules-load.d/mpls.conf` with the following content:
-
- # Load MPLS Kernel Modules
- mpls-router
- mpls-iptunnel
-
-And load the kernel modules on the running system:
-
- sudo modprobe mpls-router mpls-iptunnel
-
-### Install frr Service and redhat init files
- sudo install -p -m 644 redhat/frr.service /usr/lib/systemd/system/frr.service
- sudo install -p -m 755 redhat/frr.init /usr/lib/frr/frr
-
-### Enable required frr at startup
- sudo systemctl enable frr
-
-### Reboot or start FRR manually
- sudo systemctl start frr
+++ /dev/null
-Building FRR on FreeBSD 10 from Git Source
-==========================================
-
-FreeBSD 10 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
-
-Install required packages
--------------------------
-
-Add packages:
-(Allow the install of the package managment tool if this is first package
-install and asked)
-
- pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
- bison flex py27-pytest c-ares python3
-
-Make sure there is no /usr/bin/flex preinstalled (and use the newly
-installed in /usr/local/bin):
-(FreeBSD frequently provides a older flex as part of the base OS which
-takes preference in path)
-
- rm -f /usr/bin/flex
-
-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
-
- 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
-
-(You may prefer different options on configure statement. These are just
-an example)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- export MAKE=gmake
- export LDFLAGS="-L/usr/local/lib"
- export CPPFLAGS="-I/usr/local/include"
- ./configure \
- --sysconfdir=/usr/local/etc/frr \
- --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
- --localstatedir=/var/run/frr \
- --prefix=/usr/local \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- gmake
- gmake check
- sudo gmake install
-
-### Create empty FRR configuration files
- sudo mkdir /usr/local/etc/frr
- sudo touch /usr/local/etc/frr/zebra.conf
- sudo touch /usr/local/etc/frr/bgpd.conf
- sudo touch /usr/local/etc/frr/ospfd.conf
- sudo touch /usr/local/etc/frr/ospf6d.conf
- sudo touch /usr/local/etc/frr/isisd.conf
- sudo touch /usr/local/etc/frr/ripd.conf
- sudo touch /usr/local/etc/frr/ripngd.conf
- sudo touch /usr/local/etc/frr/pimd.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
+++ /dev/null
-Building FRR on FreeBSD 11 from Git Source
-==========================================
-
-FreeBSD 11 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
-
-Install required packages
--------------------------
-
-Add packages:
-(Allow the install of the package managment tool if this is first package
-install and asked)
-
- pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
- bison flex py27-pytest c-ares python3
-
-Make sure there is no /usr/bin/flex preinstalled (and use the newly
-installed in /usr/local/bin):
-(FreeBSD frequently provides a older flex as part of the base OS which
-takes preference in path)
-
- rm -f /usr/bin/flex
-
-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
-
- 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
-
-(You may prefer different options on configure statement. These are just
-an example)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- export MAKE=gmake
- export LDFLAGS="-L/usr/local/lib"
- export CPPFLAGS="-I/usr/local/include"
- ./configure \
- --sysconfdir=/usr/local/etc/frr \
- --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
- --localstatedir=/var/run/frr \
- --prefix=/usr/local \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- gmake
- gmake check
- sudo gmake install
-
-### Create empty FRR configuration files
- sudo mkdir /usr/local/etc/frr
- sudo touch /usr/local/etc/frr/zebra.conf
- sudo touch /usr/local/etc/frr/bgpd.conf
- sudo touch /usr/local/etc/frr/ospfd.conf
- sudo touch /usr/local/etc/frr/ospf6d.conf
- sudo touch /usr/local/etc/frr/isisd.conf
- sudo touch /usr/local/etc/frr/ripd.conf
- sudo touch /usr/local/etc/frr/ripngd.conf
- sudo touch /usr/local/etc/frr/pimd.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
+++ /dev/null
-Building FRR on FreeBSD 9 from Git Source
-=========================================
-
-FreeBSD 9 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
-
-Install required packages
--------------------------
-
-Add packages:
-(Allow the install of the package managment tool if this is first package
-install and asked)
-
- pkg install -y git autoconf automake libtool gmake gawk \
- pkgconf texinfo json-c bison flex py27-pytest c-ares \
- python3
-
-Make sure there is no /usr/bin/flex preinstalled (and use the newly
-installed in /usr/local/bin):
-(FreeBSD frequently provides a older flex as part of the base OS which
-takes preference in path)
-
- rm -f /usr/bin/flex
-
-For building with clang (instead of gcc), upgrade clang from 3.4 default to 3.6 *This is needed to build FreeBSD packages as well - for packages clang is default* (Clang 3.4 as shipped with FreeBSD 9 crashes during compile)
-
- pkg install clang36
- pkg delete clang34
- mv /usr/bin/clang /usr/bin/clang34
- ln -s /usr/local/bin/clang36 /usr/bin/clang
-
-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
-
- 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
-
-(You may prefer different options on configure statement. These are just
-an example)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- export MAKE=gmake
- export LDFLAGS="-L/usr/local/lib"
- export CPPFLAGS="-I/usr/local/include"
- ./configure \
- --sysconfdir=/usr/local/etc/frr \
- --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
- --localstatedir=/var/run/frr \
- --prefix=/usr/local \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- gmake
- gmake check
- sudo gmake install
-
-### Create empty FRR configuration files
- sudo mkdir /usr/local/etc/frr
- sudo touch /usr/local/etc/frr/zebra.conf
- sudo touch /usr/local/etc/frr/bgpd.conf
- sudo touch /usr/local/etc/frr/ospfd.conf
- sudo touch /usr/local/etc/frr/ospf6d.conf
- sudo touch /usr/local/etc/frr/isisd.conf
- sudo touch /usr/local/etc/frr/ripd.conf
- sudo touch /usr/local/etc/frr/ripngd.conf
- sudo touch /usr/local/etc/frr/pimd.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
+++ /dev/null
-Building FRR on NetBSD 6 from Git Source
-========================================
-
-NetBSD 6 restrictions:
-----------------------
-
-- MPLS is not supported on `NetBSD`. MPLS requires a Linux Kernel
- (4.5 or higher). LDP can be built, but may have limited use
- without MPLS
-
-Install required packages
--------------------------
-Configure Package location:
-
- PKG_PATH="ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/`uname -m`/`uname -r`/All"
- export PKG_PATH
-
-Add packages:
-
- sudo pkg_add git autoconf automake libtool gmake gawk openssl \
- pkg-config json-c python27 py27-test python35
-
-Install SSL Root Certificates (for git https access):
-
- sudo pkg_add mozilla-rootcerts
- sudo touch /etc/openssl/openssl.cnf
- sudo mozilla-rootcerts install
-
-Select default Python and py.test
-
- sudo ln -s /usr/pkg/bin/python2.7 /usr/bin/python
- sudo ln -s /usr/pkg/bin/py.test-2.7 /usr/bin/py.test
-
-Get FRR, compile it and install it (from Git)
-------------------------------------------------
-
-### Add frr groups and user
-
- sudo groupadd -g 92 frr
- sudo groupadd -g 93 frrvty
- sudo useradd -g 92 -u 92 -G frrvty -c "FRR suite" \
- -d /nonexistent -s /sbin/nologin frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- MAKE=gmake
- export LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib"
- export CPPFLAGS="-I/usr/pkg/include"
- ./configure \
- --sysconfdir=/usr/pkg/etc/frr \
- --enable-exampledir=/usr/pkg/share/examples/frr \
- --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
- --localstatedir=/var/run/frr \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- gmake
- gmake check
- sudo gmake install
-
-### Create empty FRR configuration files
- sudo mkdir /var/log/frr
- sudo mkdir /usr/pkg/etc/frr
- sudo touch /usr/pkg/etc/frr/zebra.conf
- sudo touch /usr/pkg/etc/frr/bgpd.conf
- sudo touch /usr/pkg/etc/frr/ospfd.conf
- sudo touch /usr/pkg/etc/frr/ospf6d.conf
- sudo touch /usr/pkg/etc/frr/isisd.conf
- sudo touch /usr/pkg/etc/frr/ripd.conf
- sudo touch /usr/pkg/etc/frr/ripngd.conf
- sudo touch /usr/pkg/etc/frr/pimd.conf
- sudo chown -R frr:frr /usr/pkg/etc/frr
- sudo touch /usr/local/etc/frr/vtysh.conf
- sudo chown frr:frrvty /usr/pkg/etc/frr/*.conf
- sudo chmod 640 /usr/pkg/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
-
-### Install rc.d init files
- cp pkgsrc/*.sh /etc/rc.d/
- chmod 555 /etc/rc.d/*.sh
-
-### Enable FRR processes
-(Enable the required processes only)
-
- echo "zebra=YES" >> /etc/rc.conf
- echo "bgpd=YES" >> /etc/rc.conf
- echo "ospfd=YES" >> /etc/rc.conf
- echo "ospf6d=YES" >> /etc/rc.conf
- echo "isisd=YES" >> /etc/rc.conf
- echo "ripngd=YES" >> /etc/rc.conf
- echo "ripd=YES" >> /etc/rc.conf
- echo "pimd=YES" >> /etc/rc.conf
+++ /dev/null
-Building FRR on NetBSD 7 from Git Source
-========================================
-
-NetBSD 7 restrictions:
-----------------------
-
-- MPLS is not supported on `NetBSD`. MPLS requires a Linux Kernel
- (4.5 or higher). LDP can be built, but may have limited use
- without MPLS
-
-Install required packages
--------------------------
-
- sudo pkgin install git autoconf automake libtool gmake gawk openssl \
- pkg-config json-c python27 py27-test python35
-
-Install SSL Root Certificates (for git https access):
-
- sudo pkgin install mozilla-rootcerts
- sudo touch /etc/openssl/openssl.cnf
- sudo mozilla-rootcerts install
-
-Select default Python and py.test
-
- sudo ln -s /usr/pkg/bin/python2.7 /usr/bin/python
- sudo ln -s /usr/pkg/bin/py.test-2.7 /usr/bin/py.test
-
-Get FRR, compile it and install it (from Git)
-------------------------------------------------
-
-### Add frr groups and user
-
- sudo groupadd -g 92 frr
- sudo groupadd -g 93 frrvty
- sudo useradd -g 92 -u 92 -G frrvty -c "FRR suite" \
- -d /nonexistent -s /sbin/nologin frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- MAKE=gmake
- export LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib"
- export CPPFLAGS="-I/usr/pkg/include"
- ./configure \
- --sysconfdir=/usr/pkg/etc/frr \
- --enable-exampledir=/usr/pkg/share/examples/frr \
- --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
- --localstatedir=/var/run/frr \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- gmake
- gmake check
- sudo gmake install
-
-### Create empty FRR configuration files
- sudo mkdir /usr/pkg/etc/frr
- sudo touch /usr/pkg/etc/frr/zebra.conf
- sudo touch /usr/pkg/etc/frr/bgpd.conf
- sudo touch /usr/pkg/etc/frr/ospfd.conf
- sudo touch /usr/pkg/etc/frr/ospf6d.conf
- sudo touch /usr/pkg/etc/frr/isisd.conf
- sudo touch /usr/pkg/etc/frr/ripd.conf
- sudo touch /usr/pkg/etc/frr/ripngd.conf
- sudo touch /usr/pkg/etc/frr/pimd.conf
- sudo chown -R frr:frr /usr/pkg/etc/frr
- sudo touch /usr/local/etc/frr/vtysh.conf
- sudo chown frr:frrvty /usr/pkg/etc/frr/*.conf
- sudo chmod 640 /usr/pkg/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
-
-### Install rc.d init files
- cp pkgsrc/*.sh /etc/rc.d/
- chmod 555 /etc/rc.d/*.sh
-
-### Enable FRR processes
-(Enable the required processes only)
-
- echo "zebra=YES" >> /etc/rc.conf
- echo "bgpd=YES" >> /etc/rc.conf
- echo "ospfd=YES" >> /etc/rc.conf
- echo "ospf6d=YES" >> /etc/rc.conf
- echo "isisd=YES" >> /etc/rc.conf
- echo "ripngd=YES" >> /etc/rc.conf
- echo "ripd=YES" >> /etc/rc.conf
- echo "pimd=YES" >> /etc/rc.conf
+++ /dev/null
-Building FRR on OmniOS (OpenSolaris) from Git Source
-====================================================
-
-OmniOS restrictions:
---------------------
-
-- MPLS is not supported on `OmniOS` or `Solaris`. MPLS requires a Linux
- Kernel (4.5 or higher). LDP can be built, but may have limited use
- without MPLS
-
-### Enable IP & IPv6 forwarding
-
- routeadm -e ipv4-forwarding
- routeadm -e ipv6-forwarding
-
-Install required packages
--------------------------
-
-Add packages:
-
- pkg install \
- developer/build/autoconf \
- developer/build/automake \
- developer/lexer/flex \
- developer/parser/bison \
- developer/object-file \
- developer/linker \
- developer/library/lint \
- developer/build/gnu-make \
- developer/gcc51 \
- library/idnkit \
- library/idnkit/header-idnkit \
- system/header \
- system/library/math/header-math \
- git libtool gawk pkg-config
-
-Add additional Solaris packages:
-
- pkgadd -d http://get.opencsw.org/now
- /opt/csw/bin/pkgutil -U
- /opt/csw/bin/pkgutil -y -i texinfo
- /opt/csw/bin/pkgutil -y -i perl
- /opt/csw/bin/pkgutil -y -i libjson_c_dev
- /opt/csw/bin/pkgutil -y -i python27 py_pip python27_dev
-
-Add libjson to Solaris equivalent of ld.so.conf
-
- crle -l /opt/csw/lib -u
-
-Add pytest:
-
- pip install pytest
-
-Select Python 2.7 as default (required for pytest)
-
- rm -f /usr/bin/python
- ln -s /opt/csw/bin/python2.7 /usr/bin/python
-
-Fix PATH for all users and non-interactive sessions. Edit `/etc/default/login`
-and add the following default PATH:
-
- PATH=/usr/gnu/bin:/usr/bin:/usr/sbin:/sbin:/opt/csw/bin
-
-Edit `~/.profile` and add the following default PATH:
-
- PATH=/usr/gnu/bin:/usr/bin:/usr/sbin:/sbin:/opt/csw/bin
-
-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
-
- sudo groupadd -g 93 frr
- sudo groupadd -g 94 frrvty
- sudo useradd -g 93 -u 93 -G frrvty -c "FRR suite" \
- -d /nonexistent -s /bin/false frr
-
-(You may prefer different options on configure statement. These are just
-an example)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- export MAKE=gmake
- export LDFLAGS="-L/opt/csw/lib"
- export CPPFLAGS="-I/opt/csw/include"
- export PKG_CONFIG_PATH=/opt/csw/lib/pkgconfig
- ./configure \
- --sysconfdir=/etc/frr \
- --enable-exampledir=/usr/share/doc/frr/examples/ \
- --localstatedir=/var/run/frr \
- --sbindir=/usr/lib/frr \
- --enable-vtysh \
- --enable-watchfrr \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- gmake
- gmake check
- sudo gmake install
-
-### Enable IP & IPv6 forwarding
-
- routeadm -e ipv4-forwarding
- routeadm -e ipv6-forwarding
+++ /dev/null
-Building FRR on OpenBSD 6 from Git Source
-=========================================
-
-Install required packages
--------------------------
-
-Configure PKG_PATH
-
- export PKG_PATH=http://ftp5.usa.openbsd.org/pub/OpenBSD/$(uname -r)/packages/$(machine -a)/
-
-Add packages:
-
- pkg_add git autoconf-2.69p2 automake-1.15p0 libtool bison
- pkg_add gmake gawk dejagnu openssl json-c py-test
-
-Select Python2.7 as default (required for pytest)
-
- ln -s /usr/local/bin/python2.7 /usr/local/bin/python
-
-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
-
- groupadd -g 525 _frr
- groupadd -g 526 _frrvty
- useradd -g 525 -u 525 -c "FRR suite" -G _frrvty \
- -d /nonexistent -s /sbin/nologin _frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- export AUTOCONF_VERSION="2.69"
- export AUTOMAKE_VERSION="1.15"
- ./bootstrap.sh
- export LDFLAGS="-L/usr/local/lib"
- export CPPFLAGS="-I/usr/local/include"
- ./configure \
- --sysconfdir=/etc/frr \
- --localstatedir=/var/frr \
- --enable-pimd \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=_frr \
- --enable-group=_frr \
- --enable-vty-group=_frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- gmake
- gmake check
- doas gmake install
-
-### Create empty FRR configuration files
-
- doas mkdir /var/frr
- doas chown _frr:_frr /var/frr
- doas chmod 755 /var/frr
- doas mkdir /etc/frr
- doas touch /etc/frr/zebra.conf
- doas touch /etc/frr/bgpd.conf
- doas touch /etc/frr/ospfd.conf
- doas touch /etc/frr/ospf6d.conf
- doas touch /etc/frr/isisd.conf
- doas touch /etc/frr/ripd.conf
- doas touch /etc/frr/ripngd.conf
- doas touch /etc/frr/pimd.conf
- doas touch /etc/frr/ldpd.conf
- doas touch /etc/frr/nhrpd.conf
- doas chown -R _frr:_frr /etc/frr
- doas touch /etc/frr/vtysh.conf
- doas chown -R _frr:_frrvty /etc/frr/vtysh.conf
- doas chmod 750 /etc/frr
- doas chmod 640 /etc/frr/*.conf
-
-### Enable IP & IPv6 forwarding
-
-Add the following lines to the end of `/etc/rc.conf`:
-
- net.inet6.ip6.forwarding=1 # 1=Permit forwarding of IPv6 packets
- net.inet6.ip6.mforwarding=1 # 1=Permit forwarding of IPv6 multicast packets
- net.inet6.ip6.multipath=1 # 1=Enable IPv6 multipath routing
-
-**Reboot** to apply the config to the system
-
-### Enable MPLS Forwarding
-
-To enable MPLS forwarding on a given interface, use the following command:
-
- doas ifconfig em0 mpls
-
-Alternatively, to make MPLS forwarding persistent across reboots, add the "mpls"
-keyword in the hostname.* files of the desired interfaces. Example:
-
- cat /etc/hostname.em0
- inet 10.0.1.1 255.255.255.0 mpls
-
-### Install rc.d init files
-(create them in /etc/rc.d - no example are included at this time with
-FRR source)
-
-Example (for zebra - store as `/etc/rc.d/frr_zebra.sh`)
-
- #!/bin/sh
- #
- # $OpenBSD: frr_zebra.rc,v 1.1 2013/04/18 20:29:08 sthen Exp $
-
- daemon="/usr/local/sbin/zebra -d"
-
- . /etc/rc.d/rc.subr
-
- rc_cmd $1
-
-### Enable FRR processes
-(Enable the required processes only)
-
- echo "frr_zebra=YES" >> /etc/rc.conf
- echo "frr_bgpd=YES" >> /etc/rc.conf
- echo "frr_ospfd=YES" >> /etc/rc.conf
- echo "frr_ospf6d=YES" >> /etc/rc.conf
- echo "frr_isisd=YES" >> /etc/rc.conf
- echo "frr_ripngd=YES" >> /etc/rc.conf
- echo "frr_ripd=YES" >> /etc/rc.conf
- echo "frr_pimd=YES" >> /etc/rc.conf
- echo "frr_ldpd=YES" >> /etc/rc.conf
+++ /dev/null
-Building FRR on Ubuntu 12.04LTS from Git Source
-===============================================
-
-- MPLS is not supported on `Ubuntu 12.04` with default kernel. MPLS requires
- Linux Kernel 4.5 or higher (LDP can be built, but may have limited use
- without MPLS)
- For an updated Ubuntu Kernel, see http://kernel.ubuntu.com/~kernel-ppa/mainline/
-
-Install required packages
--------------------------
-
-Add packages:
-
- apt-get install git autoconf automake libtool make gawk libreadline-dev \
- texinfo libpam0g-dev dejagnu libjson0-dev pkg-config libpam0g-dev \
- libjson0-dev flex python-pip libc-ares-dev python3-dev
-
-Install newer bison from 14.04 package source (Ubuntu 12.04 package source
-is too old)
-
- mkdir builddir
- cd builddir
- wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg-2.dsc
- wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg.orig.tar.bz2
- wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg-2.debian.tar.gz
- tar -jxvf bison_3.0.2.dfsg.orig.tar.bz2
- cd bison-3.0.2.dfsg/
- tar xzf ../bison_3.0.2.dfsg-2.debian.tar.gz
- sudo apt-get build-dep bison
- debuild -b -uc -us
- cd ..
- sudo dpkg -i ./libbison-dev_3.0.2.dfsg-2_amd64.deb ./bison_3.0.2.dfsg-2_amd64.deb
- cd ..
- rm -rf builddir
-
-Install newer version of autoconf and automake:
-
- wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
- tar xvf autoconf-2.69.tar.gz
- cd autoconf-2.69
- ./configure --prefix=/usr
- make
- sudo make install
- cd ..
-
- wget http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz
- tar xvf automake-1.15.tar.gz
- cd automake-1.15
- ./configure --prefix=/usr
- make
- sudo make install
- cd ..
-
-Install pytest:
-
- pip install pytest
-
-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 groups and user
-
- sudo groupadd -g 92 frr
- sudo groupadd -r -g 85 frrvty
- sudo adduser --system --ingroup frr --home /var/run/frr/ \
- --gecos "FRR suite" --shell /sbin/nologin frr
- sudo usermod -a -G frrvty frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example.)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- ./configure \
- --prefix=/usr \
- --enable-exampledir=/usr/share/doc/frr/examples/ \
- --localstatedir=/var/run/frr \
- --sbindir=/usr/lib/frr \
- --sysconfdir=/etc/frr \
- --enable-pimd \
- --enable-watchfrr \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- make
- make check
- sudo make install
-
-### Create empty FRR configuration files
-
- sudo install -m 755 -o frr -g frr -d /var/log/frr
- sudo install -m 775 -o frr -g frrvty -d /etc/frr
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
- sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
-
-### Enable IP & IPv6 forwarding
-
-Edit `/etc/sysctl.conf` and uncomment the following values (ignore the
-other settings)
-
- # Uncomment the next line to enable packet forwarding for IPv4
- net.ipv4.ip_forward=1
-
- # Uncomment the next line to enable packet forwarding for IPv6
- # Enabling this option disables Stateless Address Autoconfiguration
- # based on Router Advertisements for this host
- net.ipv6.conf.all.forwarding=1
-
-**Reboot** or use `sysctl -p` to apply the same config to the running system
-
-### Install the init.d service
-
- sudo install -m 755 tools/frr /etc/init.d/frr
- sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
- sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf
- sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
-
-### Enable daemons
-Edit `/etc/frr/daemons` and change the value from "no" to "yes" for those daemons you want to start by systemd.
-For example.
-
- zebra=yes
- bgpd=yes
- ospfd=yes
- ospf6d=yes
- ripd=yes
- ripngd=yes
- isisd=yes
-
-### Start the init.d service
-- /etc/init.d/frr start
-- use `/etc/init.d/frr status` to check its status.
+++ /dev/null
-Building FRR on Ubuntu 14.04LTS from Git Source
-===============================================
-
-- MPLS is not supported on `Ubuntu 14.04` with default kernel. MPLS requires
- Linux Kernel 4.5 or higher (LDP can be built, but may have limited use
- without MPLS)
- For an updated Ubuntu Kernel, see http://kernel.ubuntu.com/~kernel-ppa/mainline/
-
-Install required packages
--------------------------
-
-Add packages:
-
- apt-get install git autoconf automake libtool make gawk libreadline-dev \
- texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \
- python-pytest libc-ares-dev python3-dev
-
-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 groups and user
-
- sudo groupadd -g 92 frr
- sudo groupadd -r -g 85 frrvty
- sudo adduser --system --ingroup frr --home /var/run/frr/ \
- --gecos "FRR suite" --shell /sbin/nologin frr
- sudo usermod -a -G frrvty frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example.)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- ./configure \
- --prefix=/usr \
- --enable-exampledir=/usr/share/doc/frr/examples/ \
- --localstatedir=/var/run/frr \
- --sbindir=/usr/lib/frr \
- --sysconfdir=/etc/frr \
- --enable-pimd \
- --enable-watchfrr \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --enable-ldpd \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- make
- make check
- sudo make install
-
-### Create empty FRR configuration files
-
- sudo install -m 755 -o frr -g frr -d /var/log/frr
- sudo install -m 775 -o frr -g frrvty -d /etc/frr
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
- sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
-
-### Enable IP & IPv6 forwarding
-
-Edit `/etc/sysctl.conf` and uncomment the following values (ignore the
-other settings)
-
- # Uncomment the next line to enable packet forwarding for IPv4
- net.ipv4.ip_forward=1
-
- # Uncomment the next line to enable packet forwarding for IPv6
- # Enabling this option disables Stateless Address Autoconfiguration
- # based on Router Advertisements for this host
- net.ipv6.conf.all.forwarding=1
-
-**Reboot** or use `sysctl -p` to apply the same config to the running system
-### Install the init.d service
-
- sudo install -m 755 tools/frr /etc/init.d/frr
- sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
- sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf
- sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
-
-
-### Enable daemons
-
-Edit `/etc/frr/daemons` and change the value from "no" to "yes" for those daemons you want to start by systemd.
-For example.
-
- zebra=yes
- bgpd=yes
- ospfd=yes
- ospf6d=yes
- ripd=yes
- ripngd=yes
- isisd=yes
-
-### Start the init.d service
-- /etc/init.d/frr start
-- use `/etc/init.d/frr status` to check its status.
-
-
+++ /dev/null
-Building FRR on Ubuntu 16.04LTS from Git Source
-===============================================
-
-- MPLS is not supported on `Ubuntu 16.04` with default kernel. MPLS requires
- Linux Kernel 4.5 or higher (LDP can be built, but may have limited use
- without MPLS)
- For an updated Ubuntu Kernel, see
- http://kernel.ubuntu.com/~kernel-ppa/mainline/
-
-Install required packages
--------------------------
-
-Add packages:
-
- apt-get install git autoconf automake libtool make gawk libreadline-dev \
- texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \
- python-pytest libc-ares-dev python3-dev libsystemd-dev python-ipaddr
-
-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 groups and user
-
- sudo groupadd -g 92 frr
- sudo groupadd -r -g 85 frrvty
- sudo adduser --system --ingroup frr --home /var/run/frr/ \
- --gecos "FRR suite" --shell /sbin/nologin frr
- sudo usermod -a -G frrvty frr
-
-### Download Source, configure and compile it
-(You may prefer different options on configure statement. These are just
-an example.)
-
- git clone https://github.com/frrouting/frr.git frr
- cd frr
- ./bootstrap.sh
- ./configure \
- --prefix=/usr \
- --enable-exampledir=/usr/share/doc/frr/examples/ \
- --localstatedir=/var/run/frr \
- --sbindir=/usr/lib/frr \
- --sysconfdir=/etc/frr \
- --enable-pimd \
- --enable-watchfrr \
- --enable-ospfclient=yes \
- --enable-ospfapi=yes \
- --enable-multipath=64 \
- --enable-user=frr \
- --enable-group=frr \
- --enable-vty-group=frrvty \
- --enable-configfile-mask=0640 \
- --enable-logfile-mask=0640 \
- --enable-rtadv \
- --enable-fpm \
- --enable-systemd=yes \
- --with-pkg-git-version \
- --with-pkg-extra-version=-MyOwnFRRVersion
- make
- make check
- sudo make install
-
-### Create empty FRR configuration files
-
- sudo install -m 755 -o frr -g frr -d /var/log/frr
- sudo install -m 775 -o frr -g frrvty -d /etc/frr
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
- sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
- sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
-
-### Enable IPv4 & IPv6 forwarding
-
-Edit `/etc/sysctl.conf` and uncomment the following values (ignore the
-other settings)
-
- # Uncomment the next line to enable packet forwarding for IPv4
- net.ipv4.ip_forward=1
-
- # Uncomment the next line to enable packet forwarding for IPv6
- # Enabling this option disables Stateless Address Autoconfiguration
- # based on Router Advertisements for this host
- net.ipv6.conf.all.forwarding=1
-
-### Enable MPLS Forwarding (with Linux Kernel >= 4.5)
-
-Edit `/etc/sysctl.conf` and the following lines. Make sure to add a line
-equal to `net.mpls.conf.eth0.input` or each interface used with MPLS
-
- # Enable MPLS Label processing on all interfaces
- net.mpls.conf.eth0.input=1
- net.mpls.conf.eth1.input=1
- net.mpls.conf.eth2.input=1
- net.mpls.platform_labels=100000
-
-### Add MPLS kernel modules
-
-Add the following lines to `/etc/modules-load.d/modules.conf`:
-
- # Load MPLS Kernel Modules
- mpls-router
- mpls-iptunnel
-
-**Reboot** or use `sysctl -p` to apply the same config to the running system
-
-
-### Install the systemd service (if rebooted from last step, change directory back to frr directory)
-
- sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service
- sudo install -m 644 tools/etc/default/frr /etc/default/frr
- sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
- sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf
- sudo install -m 644 tools/etc/frr/frr.conf /etc/frr/frr.conf
- sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
-
-### Enable daemons
-
-Edit `/etc/frr/daemons` and change the value from "no" to "yes" for those daemons you want to start by systemd.
-For example.
-
- zebra=yes
- bgpd=yes
- ospfd=yes
- ospf6d=yes
- ripd=yes
- ripngd=yes
- isisd=yes
-
-### Enable the systemd service
- - systemctl enable frr
-
-### Start the systemd service
-- systemctl start frr
-- use `systemctl status frr` to check its status.
+++ /dev/null
-FRR Command Line Interface
-==========================
-
-Definition Grammar
-------------------
-
-This is a reference for the syntax used when defining new CLI commands. An
-example definition is:
-
-```
-DEFUN (command_name,
- command_name_cmd,
---> "example <command|line [interface]> DEFINITION...",
- <..doc strings..>)
-```
-
-The arrowed part is the definition string.
-
-Explicit syntax rules in Flex and Bison may be found in lib/command_lex.l and
-lib/command_parse.y, respectively. If you can read BNF and regex those will be
-more useful than this document.
-
-If the parser is throwing syntax or other errors and you can't figure out why,
-it's unlikely to be a bug in the parser. If the error message is not useful,
-please file a bug for a better error message. If all else fails, read the token
-definitions in the lexer source and the Bison BNF in the parser source.
-
-Characters allowed in each token type:
-
-Tokens
-------
-* `WORD` -- A token that begins with +, -, or a lowercase letter. It is
- an unchanging part of the command and will only match itself.
- Example: "show ip bgp", every token is a WORD.
-* `IPV4` -- 'A.B.C.D', matches an IPv4 address.
-* `IPV6` -- 'X:X::X:X', matches an IPv6 address.
-* `IPV4_PREFIX` -- 'A.B.C.D/M', matches an IPv4 prefix in CIDR notation.
-* `IPV6_PREFIX` -- 'X:X::X:X/M', matches an IPv6 prefix in CIDR notation.
-* `MAC` -- 'M:A:C', matches a 48-bit mac address
-* `MAC_PREFIX` -- 'M:A:C/M', matches a 48-bit mac address with a mask
-* `VARIABLE` -- Begins with a capital letter. Matches any input.
-* `RANGE` -- Numeric range delimited by parentheses, e.g. (-100 - 100) or
- (10-20). Will only match numbers in the range.
-
-Rules
------
-* `<angle|brackets>` -- Contain sequences of tokens separated by pipes and
- provide mutual exclusion. Sequences may contain
- `<mutual|exclusion>` but not as the first token.
- Disallowed: `"example <<a|b> c|d>"`
- Allowed: `"example <a c|b c|d>"`
-* `[square brackets]` -- Contains sequences of tokens that are optional (can be
- omitted). `[<a|b>]` can be shortened to `[a|b]`.
-* `{curly|braces}` -- similar to angle brackets, but instead of mutual
- exclusion, curly braces indicate that one or more of the
- pipe-separated sequences may be provided in any order.
-* `VARIADICS...` -- Any token which accepts input (so anything except WORD)
- and that occurs as the last token of a line may be
- followed by an ellipsis, which indicates that input
- matching the token may be repeated an unlimited number
- of times.
-* `$name` -- Specify a variable name for the preceding token. See
- "Variable Names" below.
-
-Some general notes:
-
-* Options are allowed at the beginning of the command. The developer is
- entreated to use these extremely sparingly. They are most useful for
- implementing the 'no' form of configuration commands. Please think carefully
- before using them for anything else. There is usually a better solution, even
- if it is just separating out the command definition into separate ones.
-
-* The developer should judiciously apply separation of concerns when defining
- CLI. CLI definitions for two unrelated or vaguely related commands or
- configuration items should be defined in separate commands. Clarity is
- preferred over LOC (within reason).
-
-* The maximum number of space-separated tokens that can be entered is presently
- limited to 256. Please keep this limit in mind when implementing new CLI.
-
-Variable Names
---------------
-The parser tries to fill the "varname" field on each token. This can happen
-either manually or automatically. Manual specifications work by appending
-`"$name"` after the input specifier:
-
-```
-foo bar$cmd WORD$name A.B.C.D$ip
-```
-
-Note that you can also assign variable names to fixed input tokens, this can
-be useful if multiple commands share code. You can also use "$name" after a
-multiple-choice option:
-
-```
-foo bar <A.B.C.D|X:X::X:X>$addr [optionA|optionB]$mode
-```
-
-The variable name is in this case assigned to the last token in each of the
-branches.
-
-Automatic assignment of variable names works by applying the following rules:
-
-- manual names always have priority
-- a "[no]" at the beginning receives "no" as varname on the "no" token
-- VARIABLE tokens whose text is not "WORD" or "NAME" receive a cleaned lowercase
- version of the token text as varname, e.g. "ROUTE-MAP" becomes "route_map".
-- other variable tokens (i.e. everything except "fixed") receive the text of
- the preceding fixed token as varname, if one can be found. E.g.:
- "ip route A.B.C.D/M INTERFACE" assigns "route" to the "A.B.C.D/M" token.
-
-These rules should make it possible to avoid manual varname assignment in 90%
-of the cases.
-
-DEFPY
------
-
-`DEFPY(...)` is an enhanced version of `DEFUN()` which is preprocessed by
-` python/clidef.py`. The python script parses the command definition string,
-extracts variable names and types, and generates a C wrapper function that
-parses the variables and passes them on. This means that in the CLI function
-body, you will receive additional parameters with appropriate types.
-
-This is best explained by an example:
-
-```
-DEFPY(func, func_cmd, "[no] foo bar A.B.C.D (0-99)$num", "...help...")
-
-=>
-
-func(self, vty, argc, argv, /* standard CLI arguments */
-
- const char *no, /* unparsed "no" */
- struct in_addr bar, /* parsed IP address */
- const char *bar_str, /* unparsed IP address */
- long num, /* parsed num */
- const char *num_str) /* unparsed num */
-```
-
-Note that as documented in the previous section, "bar" is automatically
-applied as variable name for "A.B.C.D". The python code then detects this
-is an IP address argument and generates code to parse it into a
-`struct in_addr`, passing it in `bar`. The raw value is passed in `bar_str`.
-The range/number argument works in the same way with the explicitly given
-variable name.
-
-### Type rules
-
-| Token(s) | Type | Value if omitted by user |
-|--------------------------|-------------|--------------------------|
-| `A.B.C.D` | `struct in_addr` | 0.0.0.0 |
-| `X:X::X:X` | `struct in6_addr` | :: |
-| `A.B.C.D + X:X::X:X` | `const union sockunion *` | NULL |
-| `A.B.C.D/M` | `const struct prefix_ipv4 *` | NULL |
-| `X:X::X:X/M` | `const struct prefix_ipv6 *` | NULL |
-| `A.B.C.D/M + X:X::X:X/M` | `const struct prefix *` | NULL |
-| `(0-9)` | `long` | 0 |
-| `VARIABLE` | `const char *` | NULL |
-| `word` | `const char *` | NULL |
-| _all other_ | `const char *` | NULL |
-
-Note the following details:
-
-* not all parameters are pointers, some are passed as values.
-* when the type is not `const char *`, there will be an extra `_str` argument
- with type `const char *`.
-* you can give a variable name not only to `VARIABLE` tokens but also to
- `word` tokens (e.g. constant words). This is useful if some parts of a
- command are optional. The type will be `const char *`.
-* `[no]` will be passed as `const char *no`.
-* pointers will be NULL when the argument is optional and the user did not
- use it.
-* if a parameter is not a pointer, but is optional and the user didn't use it,
- the default value will be passed. Check the `_str` argument if you need to
- determine whether the parameter was omitted.
-* if the definition contains multiple parameters with the same variable name,
- they will be collapsed into a single function parameter. The python code
- will detect if the types are compatible (i.e. IPv4 + IPv6 variantes) and
- choose a corresponding C type.
-* the standard DEFUN parameters (self, vty, argc, argv) are still present and
- can be used. A DEFUN can simply be **edited into a DEFPY without further
- changes and it will still work**; this allows easy forward migration.
-* a file may contain both DEFUN and DEFPY statements.
-
-### Getting a parameter dump
-
-The clidef.py script can be called to get a list of DEFUNs/DEFPYs with
-the parameter name/type list:
-
-```
-lib/clippy python/clidef.py --all-defun --show lib/plist.c > /dev/null
-```
-
-The generated code is printed to stdout, the info dump to stderr. The
-`--all-defun` argument will make it process DEFUN blocks as well as DEFPYs,
-which is useful prior to converting some DEFUNs. **The dump does not list
-the `_str` arguments** to keep the output shorter.
-
-Note that the clidef.py script cannot be run with python directly, it needs
-to be run with _clippy_ since the latter makes the CLI parser available.
-
-### Include & Makefile requirements
-
-A source file that uses DEFPY needs to include the `_clippy.c` file **before
-all DEFPY statements**:
-
-```
-/* GPL header */
-#include ...
-
-...
-
-#include "daemon/filename_clippy.c"
-
-DEFPY(...)
-DEFPY(...)
-
-install_element(...)
-```
-
-This dependency needs to be marked in Makefile.am: (there is no ordering
-requirement)
-
-```
-include ../common.am
-
-# ...
-
-# if linked into a LTLIBRARY (.la/.so):
-filename.lo: filename_clippy.c
-
-# if linked into an executable or static library (.a):
-filename.o: filename_clippy.c
-```
-
-Doc Strings
------------
-Each token in a command definition should be documented with a brief doc
-string that informs a user of the meaning and/or purpose of the subsequent
-command tree. These strings are provided as the last parameter to DEFUN macros,
-concatenated together and separated by an escaped newline ('\n'). These are
-best explained by example.
-
-```
-DEFUN (config_terminal,
- config_terminal_cmd,
- "configure terminal",
- "Configuration from vty interface\n"
- "Configuration terminal\n")
-```
-
-The last parameter is split into two lines for readability. Two newline
-delimited doc strings are present, one for each token in the command. The
-second string documents the functionality of the 'terminal' command in the
-'configure' tree.
-
-Note that the first string, for 'configure' does not contain documentation for
-'terminal'. This is because the CLI is best envisioned as a tree, with tokens
-defining branches. An imaginary 'start' token is the root of every command in a
-CLI node. Each subsequent written token descends into a subtree, so the
-documentation for that token ideally summarizes all the functionality contained
-in the subtree.
-
-A consequence of this structure is that the developer must be careful to use
-the same doc strings when defining multiple commands that are part of the same
-tree. Commands which share prefixes must share the same doc strings for those
-prefixes. On startup the parser will generate warnings if it notices
-inconsistent doc strings. Behavior is undefined; the same token may show up
-twice in completions, with different doc strings, or it may show up once with a
-random doc string. Parser warnings should be heeded and fixed to avoid
-confusing users.
-
-The number of doc strings provided must be equal to the amount of tokens
-present in the command definition, read left to right, ignoring any special
-constructs.
-
-In the examples below, each arrowed token needs a doc string.
-
-```
- "show ip bgp"
- ^ ^ ^
-
- "command <foo|bar> [example]"
- ^ ^ ^ ^
-```
-
-Data Structures
----------------
-On startup, the CLI parser sequentially parses each command string definition
-and constructs a directed graph with each token forming a node. This graph is
-the basis of the entire CLI system. It is used to match user input in order to
-generate command completions and match commands to functions.
-
-There is one graph per CLI node (not the same as a graph node in the CLI
-graph). The CLI node struct keeps a reference to its graph (see lib/command.h).
-
-While most of the graph maintains the form of a tree, special constructs
-outlined in the Rules section introduce some quirks. <>, [] and {} form
-self-contained 'subgraphs'. Each subgraph is a tree except that all of the
-'leaves' actually share a child node. This helps with minimizing graph size and
-debugging.
-
-As an example, the subgraph generated by <foo|bar> looks like this:
-
- .
- .
- |
- +----+---+
- +--- -+ FORK +----+
- | +--------+ |
- +--v---+ +--v---+
- | foo | | bar |
- +--+---+ +--+---+
- | +------+ |
- +------> JOIN <-----+
- +---+--+
- |
- .
- .
-
-FORK and JOIN nodes are plumbing nodes that don't correspond to user input.
-They're necessary in order to deduplicate these constructs where applicable.
-
-Options follow the same form, except that there is an edge from the FORK node
-to the JOIN node.
-
-Keywords follow the same form, except that there is an edge from JOIN to FORK.
-Because of this the CLI graph cannot be called acyclic. There is special logic
-in the input matching code that keeps a stack of paths already taken through
-the node in order to disallow following the same path more than once.
-
-Variadics are a bit special; they have an edge back to themselves, which allows
-repeating the same input indefinitely.
-
-The leaves of the graph are nodes that have no out edges. These nodes are
-special; their data section does not contain a token, as most nodes do, or
-NULL, as in FORK/JOIN nodes, but instead has a pointer to a cmd_element. All
-paths through the graph that terminate on a leaf are guaranteed to be defined
-by that command. When a user enters a complete command, the command matcher
-tokenizes the input and executes a DFS on the CLI graph. If it is
-simultaneously able to exhaust all input (one input token per graph node), and
-then find exactly one leaf connected to the last node it reaches, then the
-input has matched the corresponding command and the command is executed. If it
-finds more than one node, then the command is ambiguous (more on this in
-deduplication). If it cannot exhaust all input, the command is unknown. If it
-exhausts all input but does not find an edge node, the command is incomplete.
-
-The parser uses an incremental strategy to build the CLI graph for a node. Each
-command is parsed into its own graph, and then this graph is merged into the
-overall graph. During this merge step, the parser makes a best-effort attempt
-to remove duplicate nodes. If it finds a node in the overall graph that is
-equal to a node in the corresponding position in the command graph, it will
-intelligently merge the properties from the node in the command graph into the
-already-existing node. Subgraphs are also checked for isomorphism and merged
-where possible. The definition of whether two nodes are 'equal' is based on the
-equality of some set of token properties; read the parser source for the most
-up-to-date definition of equality.
-
-When the parser is unable to deduplicate some complicated constructs, this
-can result in two identical paths through separate parts of the graph. If
-this occurs and the user enters input that matches these paths, they will
-receive an 'ambiguous command' error and will be unable to execute the command.
-Most of the time the parser can detect and warn about duplicate commands, but
-it will not always be able to do this. Hence care should be taken before
-defining a new command to ensure it is not defined elsewhere.
-
-
-Command handlers
-----------------
-The block that follows a CLI definition is executed when a user enters input
-that matches the definition. Its function signature looks like this:
-
-int (*func) (const struct cmd_element *, struct vty *, int, struct cmd_token *[]);
-
-The first argument is the command definition struct. The last argument is an
-ordered array of tokens that correspond to the path taken through the graph,
-and the argument just prior to that is the length of the array.
-
-The arrangement of the token array has changed from the prior incarnation of
-the CLI system. In the old system, missing arguments were padded with NULLs so
-that the same parts of a command would show up at the same indices regardless
-of what was entered. The new system does not perform such padding and therefore
-it is generally _incorrect_ to assume consistent indices in this array. As a
-simple example:
-
-Command definition:
-```
- command [foo] <bar|baz>
-```
-
-User enters:
-```
- command foo bar
-```
-
-Array:
-```
- [0] -> command
- [1] -> foo
- [2] -> bar
-```
-
-User enters:
-```
- command baz
-```
-
-Array:
-```
- [0] -> command
- [1] -> baz
-```
-
-
-
-Command abbreviation & matching priority
-----------------------------------------
-As in the prior implementation, it is possible for users to elide parts of
-tokens when the CLI matcher does not need them to make an unambiguous match.
-This is best explained by example.
-
-Command definitions:
-```
- command dog cow
- command dog crow
-```
-
-User input:
-```
- c d c -> ambiguous command
- c d co -> match "command dog cow"
-```
-
-In the new implementation, this functionality has improved. Where previously
-the parser would stop at the first ambiguous token, it will now look ahead and
-attempt to disambiguate based on tokens later on in the input string.
-
-Command definitions:
-```
- show ip bgp A.B.C.D
- show ipv6 bgp X:X::X:X
-```
-
-User enters:
-```
- s i b 4.3.2.1 -> match "show ip bgp A.B.C.D"
- s i b ::e0 -> match "show ipv6 bgp X:X::X:X"
-```
-
-Previously both of these commands would be ambiguous since 'i' does not
-explicitly select either 'ip' or 'ipv6'. However, since the user later provides
-a token that matches only one of the commands (an IPv4 or IPv6 address) the
-parser is able to look ahead and select the appropriate command. This has some
-implications for parsing the argv*[] that is passed to the command handler.
-
-Now consider a command definition such as:
-```
- command <foo|VAR>
-```
-
-'foo' only matches the string 'foo', but 'VAR' matches any input, including
-'foo'. Who wins? In situations like this the matcher will always choose the
-'better' match, so 'foo' will win.
-
-Consider also:
-```
- show <ip|ipv6> foo
-```
-
-User input:
-```
- show ip foo
-```
-
-'ip' partially matches 'ipv6' but exactly matches 'ip', so 'ip' will win.
-
-
-struct cmd_token
-----------------
-
-```
-/* Command token struct. */
-struct cmd_token
-{
- enum cmd_token_type type; // token type
- u_char attr; // token attributes
- bool allowrepeat; // matcher allowed to match token repetitively?
-
- char *text; // token text
- char *desc; // token description
- long long min, max; // for ranges
- char *arg; // user input that matches this token
- char *varname; // variable name
-};
-```
-
-This struct is used in the CLI graph to match input against. It is also used to
-pass user input to command handler functions, as it is frequently useful for
-handlers to have access to that information. When a command is matched, the
-sequence of cmd_tokens that form the matching path are duplicated and placed in
-order into argv*[]. Before this happens the ->arg field is set to point at the
-snippet of user input that matched it.
-
-For most nontrivial commands the handler function will need to determine which
-of the possible matching inputs was entered. Previously this was done by
-looking at the first few characters of input. This is now considered an
-anti-pattern and should be avoided. Instead, the ->type or ->text fields for
-this logic. The ->type field can be used when the possible inputs differ in
-type. When the possible types are the same, use the ->text field. This field
-has the full text of the corresponding token in the definition string and using
-it makes for much more readable code. An example is helpful.
-
-Command definition:
-```
- command <(1-10)|foo|BAR>
-```
-
-In this example, the user may enter any one of:
- * an integer between 1 and 10
- * "foo"
- * anything at all
-
-If the user enters "command f", then:
-
-```
-argv[1]->type == WORD_TKN
-argv[1]->arg == "f"
-argv[1]->text == "foo"
-```
-
-Range tokens have some special treatment; a token with ->type == RANGE_TKN will
-have the ->min and ->max fields set to the bounding values of the range.
-
-
-Permutations
-------------
-Finally, it is sometimes useful to check all the possible combinations of input
-that would match an arbitrary definition string. There is a tool in tools/
-called 'permutations' that reads CLI definition strings on stdin and prints out
-all matching input permutations. It also dumps a text representation of the
-graph, which is more useful for debugging than anything else. It looks like
-this:
-
-```
-$ ./permutations "show [ip] bgp [<view|vrf> WORD]"
-
-show ip bgp view WORD
-show ip bgp vrf WORD
-show ip bgp
-show bgp view WORD
-show bgp vrf WORD
-show bgp
-```
-
-This functionality is also built into VTY/VTYSH; the 'list permutations'
-command will list all possible matching input permutations in the current CLI
-node.
+++ /dev/null
-/_templates
-/_build
-!/Makefile
+++ /dev/null
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = _build
-
-# User-friendly check for sphinx-build
-ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
-$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
-endif
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-.PHONY: help
-help:
- @echo "Please use \`make <target>' where <target> is one of"
- @echo " html to make standalone HTML files"
- @echo " dirhtml to make HTML files named index.html in directories"
- @echo " singlehtml to make a single large HTML file"
- @echo " pickle to make pickle files"
- @echo " json to make JSON files"
- @echo " htmlhelp to make HTML files and a HTML help project"
- @echo " qthelp to make HTML files and a qthelp project"
- @echo " applehelp to make an Apple Help Book"
- @echo " devhelp to make HTML files and a Devhelp project"
- @echo " epub to make an epub"
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
- @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
- @echo " text to make text files"
- @echo " man to make manual pages"
- @echo " texinfo to make Texinfo files"
- @echo " info to make Texinfo files and run them through makeinfo"
- @echo " gettext to make PO message catalogs"
- @echo " changes to make an overview of all changed/added/deprecated items"
- @echo " xml to make Docutils-native XML files"
- @echo " pseudoxml to make pseudoxml-XML files for display purposes"
- @echo " linkcheck to check all external links for integrity"
- @echo " doctest to run all doctests embedded in the documentation (if enabled)"
- @echo " coverage to run coverage check of the documentation (if enabled)"
-
-.PHONY: clean
-clean:
- rm -rf $(BUILDDIR)/*
-
-.PHONY: html
-html:
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-.PHONY: dirhtml
-dirhtml:
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-.PHONY: singlehtml
-singlehtml:
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
- @echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-.PHONY: pickle
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-.PHONY: json
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
-.PHONY: htmlhelp
-htmlhelp:
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
- @echo
- @echo "Build finished; now you can run HTML Help Workshop with the" \
- ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-.PHONY: qthelp
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/FRR.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/FRR.qhc"
-
-.PHONY: applehelp
-applehelp:
- $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
- @echo
- @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
- @echo "N.B. You won't be able to view it unless you put it in" \
- "~/Library/Documentation/Help or install it in your application" \
- "bundle."
-
-.PHONY: devhelp
-devhelp:
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
- @echo
- @echo "Build finished."
- @echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/FRR"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/FRR"
- @echo "# devhelp"
-
-.PHONY: epub
-epub:
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
- @echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-.PHONY: latex
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
- "(use \`make latexpdf' here to do that automatically)."
-
-.PHONY: latexpdf
-latexpdf:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through pdflatex..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-.PHONY: latexpdfja
-latexpdfja:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through platex and dvipdfmx..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-.PHONY: text
-text:
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
- @echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-.PHONY: man
-man:
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
- @echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-.PHONY: texinfo
-texinfo:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo
- @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
- @echo "Run \`make' in that directory to run these through makeinfo" \
- "(use \`make info' here to do that automatically)."
-
-.PHONY: info
-info:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo "Running Texinfo files through makeinfo..."
- make -C $(BUILDDIR)/texinfo info
- @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
-
-.PHONY: gettext
-gettext:
- $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
- @echo
- @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
-
-.PHONY: changes
-changes:
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
- @echo
- @echo "The overview file is in $(BUILDDIR)/changes."
-
-.PHONY: linkcheck
-linkcheck:
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
- @echo
- @echo "Link check complete; look for any errors in the above output " \
- "or in $(BUILDDIR)/linkcheck/output.txt."
-
-.PHONY: doctest
-doctest:
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
- @echo "Testing of doctests in the sources finished, look at the " \
- "results in $(BUILDDIR)/doctest/output.txt."
-
-.PHONY: coverage
-coverage:
- $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
- @echo "Testing of coverage in the sources finished, look at the " \
- "results in $(BUILDDIR)/coverage/python.txt."
-
-.PHONY: xml
-xml:
- $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
- @echo
- @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
-
-.PHONY: pseudoxml
-pseudoxml:
- $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
- @echo
- @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# FRR documentation build configuration file, created by
-# sphinx-quickstart on Tue Jan 31 16:00:52 2017.
-#
-# This file is execfile()d with the current directory set to its
-# containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import sys
-import os
-import re
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
-
-# -- General configuration ------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions = ['sphinx.ext.todo']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix(es) of source filenames.
-# You can specify multiple suffix as a list of string:
-# source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'FRR'
-copyright = u'2017, FRR'
-author = u'FRR'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-
-# The short X.Y version.
-version = u'?.?'
-# The full version, including alpha/beta/rc tags.
-release = u'?.?-?'
-
-val = re.compile('^S\["([^"]+)"\]="(.*)"$')
-with open('../../config.status', 'r') as cfgstatus:
- for ln in cfgstatus.readlines():
- m = val.match(ln)
- if m is None: continue
- if m.group(1) == 'PACKAGE_VERSION':
- release = m.group(2)
- version = release.split('-')[0]
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#
-# This is also used if you do content translation via gettext catalogs.
-# Usually you set "language" from the command line for these cases.
-language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
-
-# The reST default role (used for this markup: `text`) to use for all
-# documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-# If true, keep warnings as "system message" paragraphs in the built documents.
-#keep_warnings = False
-
-# If true, `todo` and `todoList` produce output, else they produce nothing.
-todo_include_todos = True
-
-
-# -- Options for HTML output ----------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-html_theme = 'sphinx_rtd_theme'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# Add any extra paths that contain custom files (such as robots.txt or
-# .htaccess) here, relative to this directory. These files are copied
-# directly to the root of the documentation.
-#html_extra_path = []
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
-
-# Language to be used for generating the HTML full-text search index.
-# Sphinx supports the following languages:
-# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
-# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
-#html_search_language = 'en'
-
-# A dictionary with options for the search language support, empty by default.
-# Now only 'ja' uses this config value
-#html_search_options = {'type': 'default'}
-
-# The name of a javascript file (relative to the configuration directory) that
-# implements a search results scorer. If empty, the default will be used.
-#html_search_scorer = 'scorer.js'
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'FRRdoc'
-
-# -- Options for LaTeX output ---------------------------------------------
-
-latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-
-# Latex figure (float) alignment
-#'figure_align': 'htbp',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-# author, documentclass [howto, manual, or own class]).
-latex_documents = [
- (master_doc, 'FRR.tex', u'FRR Documentation',
- u'FRR', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
-
-# -- Options for manual page output ---------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
- (master_doc, 'frr', u'FRR Documentation',
- [author], 1)
-]
-
-# If true, show URL addresses after external links.
-#man_show_urls = False
-
-
-# -- Options for Texinfo output -------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-# dir menu entry, description, category)
-texinfo_documents = [
- (master_doc, 'FRR', u'FRR Documentation',
- author, 'FRR', 'One line description of project.',
- 'Miscellaneous'),
-]
-
-# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
-
-# If false, no module index is generated.
-#texinfo_domain_indices = True
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
-
-# If true, do not generate a @detailmenu in the "Top" node's menu.
-#texinfo_no_detailmenu = False
+++ /dev/null
-.. highlight:: c
-
-Hooks
-=====
-
-Libfrr provides type-safe subscribable hook points where other pieces of
-code can add one or more callback functions. "type-safe" in this case
-applies to the function pointers used for subscriptions. The
-implementations checks (at compile-time) wheter a callback to be added has
-the appropriate function signature (parameters) for the hook.
-
-Example:
-
-.. code-block:: c
- :caption: mydaemon.h
-
- #include "hook.h"
- DECLARE_HOOK(some_update_event, (struct eventinfo *info), (info))
-
-.. code-block:: c
- :caption: mydaemon.c
-
- #include "mydaemon.h"
- DEFINE_HOOK(some_update_event, (struct eventinfo *info), (info))
- ...
- hook_call(some_update_event, info);
-
-.. code-block:: c
- :caption: mymodule.c
-
- #include "mydaemon.h"
- static int event_handler(struct eventinfo *info);
- ...
- hook_register(some_update_event, event_handler);
-
-Do not use parameter names starting with "hook", these can collide with
-names used by the hook code itself.
-
-
-Return values
--------------
-
-Callbacks to be placed on hooks always return "int" for now; hook_call will
-sum up the return values from each called function. (The default is 0 if no
-callbacks are registered.)
-
-There are no pre-defined semantics for the value, in most cases it is
-ignored. For success/failure indication, 0 should be success, and
-handlers should make sure to only return 0 or 1 (not -1 or other values).
-
-There is no built-in way to abort executing a chain after a failure of one
-of the callbacks. If this is needed, the hook can use an extra
-``bool *aborted`` argument.
-
-
-Priorities
-----------
-
-Hooks support a "priority" value for ordering registered calls
-relative to each other. The priority is a signed integer where lower
-values are called earlier. There are also "Koohs", which is hooks with
-reverse priority ordering (for cleanup/deinit hooks, so you can use the
-same priority value).
-
-Recommended priority value ranges are:
-
-======================== ===================================================
-Range Usage
------------------------- ---------------------------------------------------
- -999 ... 0 ... 999 main executable / daemon, or library
-
--1999 ... -1000 modules registering calls that should run before
- the daemon's bits
-
-1000 ... 1999 modules' calls that should run after daemon's
- (includes default value: 1000)
-======================== ===================================================
-
-Note: the default value is 1000, based on the following 2 expectations:
-
-- most hook_register() usage will be in loadable modules
-- usage of hook_register() in the daemon itself may need relative ordering
- to itself, making an explicit value the expected case
-
-The priority value is passed as extra argument on hook_register_prio() /
-hook_register_arg_prio(). Whether a hook runs in reverse is determined
-solely by the code defining / calling the hook. (DECLARE_KOOH is actually
-the same thing as DECLARE_HOOK, it's just there to make it obvious.)
-
-
-Definition
-----------
-
-.. c:macro:: DECLARE_HOOK(name, arglist, passlist)
-.. c:macro:: DECLARE_KOOH(name, arglist, passlist)
-
- :param name: Name of the hook to be defined
- :param arglist: Function definition style parameter list in braces.
- :param passlist: List of the same parameters without their types.
-
- Note: the second and third macro args must be the hook function's
- parameter list, with the same names for each parameter. The second
- macro arg is with types (used for defining things), the third arg is
- just the names (used for passing along parameters).
-
- This macro must be placed in a header file; this header file must be
- included to register a callback on the hook.
-
- Examples:
-
- .. code-block:: c
-
- DECLARE_HOOK(foo, (), ())
- DECLARE_HOOK(bar, (int arg), (arg))
- DECLARE_HOOK(baz, (const void *x, in_addr_t y), (x, y))
-
-.. c:macro:: DEFINE_HOOK(name, arglist, passlist)
-
- Implements an hook. Each ``DECLARE_HOOK`` must have be accompanied by
- exactly one ``DEFINE_HOOK``, which needs to be placed in a source file.
- **The hook can only be called from this source file.** This is intentional
- to avoid overloading and/or misusing hooks for distinct purposes.
-
- The compiled source file will include a global symbol with the name of the
- hook prefixed by `_hook_`. Trying to register a callback for a hook that
- doesn't exist will therefore result in a linker error, or a module
- load-time error for dynamic modules.
-
-.. c:macro:: DEFINE_KOOH(name, arglist, passlist)
-
- Same as ``DEFINE_HOOK``, but the sense of priorities / order of callbacks
- is reversed. This should be used for cleanup hooks.
-
-.. c:function:: int hook_call(name, ...)
-
- Calls the specified named hook. Parameters to the hook are passed right
- after the hook name, e.g.:
-
- .. code-block:: c
-
- hook_call(foo);
- hook_call(bar, 0);
- hook_call(baz, NULL, INADDR_ANY);
-
- Returns the sum of return values from all callbacks. The ``DEFINE_HOOK``
- statement for the hook must be placed in the file before any ``hook_call``
- use of the hook.
-
-
-Callback registration
----------------------
-
-.. c:function:: void hook_register(name, int (*callback)(...))
-.. c:function:: void hook_register_prio(name, int priority, int (*callback)(...))
-.. c:function:: void hook_register_arg(name, int (*callback)(void *arg, ...), void *arg)
-.. c:function:: void hook_register_arg_prio(name, int priority, int (*callback)(void *arg, ...), void *arg)
-
- Register a callback with an hook. If the caller needs to pass an extra
- argument to the callback, the _arg variant can be used and the extra
- parameter will be passed as first argument to the callback. There is no
- typechecking for this argument.
-
- The priority value is used as described above. The variants without a
- priority parameter use 1000 as priority value.
-
-.. c:function:: void hook_unregister(name, int (*callback)(...))
-.. c:function:: void hook_unregister_arg(name, int (*callback)(void *arg, ...), void *arg)
-
- Removes a previously registered callback from a hook. Note that there
- is no _prio variant of these calls. The priority value is only used during
- registration.
+++ /dev/null
-Welcome to FRR's documentation!
-===============================
-
-Contents:
-
-.. toctree::
- :maxdepth: 2
-
- library
-
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-
+++ /dev/null
-libfrr library facilities
-=========================
-
-.. toctree::
- :maxdepth: 2
-
- memtypes
- hooks
-
-
+++ /dev/null
-.. highlight:: c
-
-Memtypes
-========
-
-FRR includes wrappers arround ``malloc()`` and ``free()`` that count the number
-of objects currently allocated, for each of a defined ``MTYPE``.
-
-To this extent, there are `memory groups` and `memory types`. Each memory
-type must belong to a memory group, this is used just to provide some basic
-structure.
-
-Example:
-
-.. code-block:: c
- :caption: mydaemon.h
-
- DECLARE_MGROUP(MYDAEMON)
- DECLARE_MTYPE(MYNEIGHBOR)
-
-.. code-block:: c
- :caption: mydaemon.c
-
- DEFINE_MGROUP( MYDAEMON, "My daemon's memory")
- DEFINE_MTYPE( MYDAEMON, MYNEIGHBOR, "Neighbor entry")
- DEFINE_MTYPE_STATIC(MYDAEMON, MYNEIGHBORNAME, "Neighbor name")
-
- struct neigh *neighbor_new(const char *name)
- {
- struct neigh *n = XMALLOC(MYNEIGHBOR, sizeof(*n));
- n->name = XSTRDUP(MYNEIGHBORNAME, name);
- return n;
- }
-
- void neighbor_free(struct neigh *n)
- {
- XFREE(MYNEIGHBORNAME, n->name);
- XFREE(MYNEIGHBOR, n);
- }
-
-
-Definition
-----------
-
-.. c:macro:: DECLARE_MGROUP(name)
-
- This macro forward-declares a memory group and should be placed in a
- ``.h`` file. It expands to an ``extern struct memgroup`` statement.
-
-.. c:macro:: DEFINE_MGROUP(mname, description)
-
- Defines/implements a memory group. Must be placed into exactly one ``.c``
- file (multiple inclusion will result in a link-time symbol conflict).
-
- Contains additional logic (constructor and destructor) to register the
- memory group in a global list.
-
-.. c:macro:: DECLARE_MTYPE(name)
-
- Forward-declares a memory type and makes ``MTYPE_name`` available for use.
- Note that the ``MTYPE_`` prefix must not be included in the name, it is
- automatically prefixed.
-
- ``MTYPE_name`` is created as a `static const` symbol, i.e. a compile-time
- constant. It refers to an ``extern struct memtype _mt_name``, where `name`
- is replaced with the actual name.
-
-.. c:macro:: DEFINE_MTYPE(group, name, description)
-
- Define/implement a memory type, must be placed into exactly one ``.c``
- file (multiple inclusion will result in a link-time symbol conflict).
-
- Like ``DEFINE_MGROUP``, this contains actual code to register the MTYPE
- under its group.
-
-.. c:macro:: DEFINE_MTYPE_STATIC(group, name, description)
-
- Same as ``DEFINE_MTYPE``, but the ``DEFINE_MTYPE_STATIC`` variant places
- the C ``static`` keyword on the definition, restricting the MTYPE's
- availability to the current source file. This should be appropriate in
- >80% of cases.
-
- .. todo::
-
- Daemons currently have ``daemon_memory.[ch]`` files listing all of
- their MTYPEs. This is not how it should be, most of these types
- should be moved into the appropriate files where they are used.
- Only a few MTYPEs should remain non-static after that.
-
-
-Usage
------
-
-.. c:function:: void *XMALLOC(struct memtype *mtype, size_t size)
-
-.. c:function:: void *XCALLOC(struct memtype *mtype, size_t size)
-
-.. c:function:: void *XSTRDUP(struct memtype *mtype, size_t size)
-
- Allocation wrappers for malloc/calloc/realloc/strdup, taking an extra
- mtype parameter.
-
-.. c:function:: void *XREALLOC(struct memtype *mtype, void *ptr, size_t size)
-
- Wrapper around realloc() with MTYPE tracking. Note that ``ptr`` may
- be NULL, in which case the function does the same as XMALLOC (regardless
- of whether the system realloc() supports this.)
-
-.. c:function:: void XFREE(struct memtype *mtype, void *ptr)
-
- Wrapper around free(), again taking an extra mtype parameter. This is
- actually a macro, with the following additional properties:
-
- - the macro contains ``ptr = NULL``
- - if ptr is NULL, no operation is performed (as is guaranteed by system
- implementations.) Do not surround XFREE with ``if (ptr != NULL)``
- checks.
--- /dev/null
+CentOS 6
+========================================
+
+(As an alternative to this installation, you may prefer to create a FRR
+rpm package yourself and install that package instead. See instructions
+in redhat/README.rpm\_build.md on how to build a rpm package)
+
+Instructions are tested with ``CentOS 6.8`` on ``x86_64`` platform
+
+CentOS 6 restrictions:
+----------------------
+
+- PIMd is not supported on ``CentOS 6``. Upgrade to ``CentOS 7`` if
+ PIMd is needed
+- MPLS is not supported on ``CentOS 6``. MPLS requires Linux Kernel 4.5
+ or higher (LDP can be built, but may have limited use without MPLS)
+- Zebra is unable to detect what bridge/vrf an interface is associcated
+ with (IFLA\_INFO\_SLAVE\_KIND does not exist in the kernel headers,
+ you can use a newer kernel + headers to get this functionality)
+- frr\_reload.py will not work, as this requires Python 2.7, and CentOS
+ 6 only has 2.6. You can install Python 2.7 via IUS, but it won't work
+ properly unless you compile and install the ipaddr package for it.
+
+Install required packages
+-------------------------
+
+Add packages:
+
+::
+
+ sudo yum install git autoconf automake libtool make gawk \
+ readline-devel texinfo net-snmp-devel groff pkgconfig \
+ json-c-devel pam-devel flex epel-release perl-XML-LibXML \
+ c-ares-devel
+
+Install newer version of bison (CentOS 6 package source is too old) from
+CentOS 7
+
+::
+
+ sudo yum install rpm-build
+ curl -O http://vault.centos.org/7.0.1406/os/Source/SPackages/bison-2.7-4.el7.src.rpm
+ rpmbuild --rebuild ./bison-2.7-4.el7.src.rpm
+ sudo yum install ./rpmbuild/RPMS/x86_64/bison-2.7-4.el6.x86_64.rpm
+ rm -rf rpmbuild
+
+Install newer version of autoconf and automake (Package versions are too
+old)
+
+::
+
+ curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
+ tar xvf autoconf-2.69.tar.gz
+ cd autoconf-2.69
+ ./configure --prefix=/usr
+ make
+ sudo make install
+ cd ..
+
+ curl -O http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz
+ tar xvf automake-1.15.tar.gz
+ cd automake-1.15
+ ./configure --prefix=/usr
+ make
+ sudo make install
+ cd ..
+
+Install ``Python 2.7`` in parallel to default 2.6. Make sure you've
+install EPEL (``epel-release`` as above). Then install current
+``python27``, ``python27-devel`` and ``pytest``
+
+::
+
+ sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
+ sudo rpm -ivh https://centos6.iuscommunity.org/ius-release.rpm
+ sudo yum install python27 python27-pip python27-devel
+ sudo pip2.7 install pytest
+
+Please note that ``CentOS 6`` needs to keep python pointing to version
+2.6 for ``yum`` to keep working, so don't create a symlink for python2.7
+to python
+
+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 groups and user
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo groupadd -g 92 frr
+ sudo groupadd -r -g 85 frrvt
+ sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
+ -c "FRR FRRouting suite" -d /var/run/frr frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example.)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ ./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 \
+ --enable-multipath=64 \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvt \
+ --enable-rtadv \
+ --disable-exampledir \
+ --enable-watchfrr \
+ --disable-ldpd \
+ --enable-fpm \
+ --enable-nhrpd \
+ --enable-eigrpd \
+ --enable-babeld \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ make
+ make check PYTHON=/usr/bin/python2.7
+ sudo make install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo mkdir /var/log/frr
+ sudo mkdir /etc/frr
+ sudo touch /etc/frr/zebra.conf
+ sudo touch /etc/frr/bgpd.conf
+ sudo touch /etc/frr/ospfd.conf
+ sudo touch /etc/frr/ospf6d.conf
+ sudo touch /etc/frr/isisd.conf
+ sudo touch /etc/frr/ripd.conf
+ sudo touch /etc/frr/ripngd.conf
+ sudo touch /etc/frr/nhrpd.conf
+ sudo touch /etc/frr/eigrpd.conf
+ sudo touch /etc/frr/babeld.conf
+ sudo chown -R frr:frr /etc/frr/
+ sudo touch /etc/frr/vtysh.conf
+ sudo chown frr:frrvt /etc/frr/vtysh.conf
+ sudo chmod 640 /etc/frr/*.conf
+
+Install daemon config file
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -p -m 644 redhat/daemons /etc/frr/
+ sudo chown frr:frr /etc/frr/daemons
+
+Edit /etc/frr/daemons as needed to select the required daemons
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Look for the section with ``watchfrr_enable=...`` and ``zebra=...`` etc.
+Enable the daemons as required by changing the value to ``yes``
+
+Enable IP & IPv6 forwarding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Edit ``/etc/sysctl.conf`` and set the following values (ignore the other
+settings)
+
+::
+
+ # Controls IP packet forwarding
+ net.ipv4.ip_forward = 1
+ net.ipv6.conf.all.forwarding=1
+
+ # Controls source route verification
+ net.ipv4.conf.default.rp_filter = 0
+
+Load the modifed sysctl's on the system:
+
+::
+
+ sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
+
+Add init.d startup files
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -p -m 755 redhat/frr.init /etc/init.d/frr
+ sudo chkconfig --add frr
+
+Enable frr daemon at startup
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo chkconfig frr on
+
+Start FRR manually (or reboot)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo /etc/init.d/frr start
--- /dev/null
+CentOS 7
+========================================
+
+(As an alternative to this installation, you may prefer to create a FRR
+rpm package yourself and install that package instead. See instructions
+in redhat/README.rpm\_build.md on how to build a rpm package)
+
+CentOS 7 restrictions:
+----------------------
+
+- MPLS is not supported on ``CentOS 7`` with default kernel. MPLS
+ requires Linux Kernel 4.5 or higher (LDP can be built, but may have
+ limited use without MPLS)
+
+Install required packages
+-------------------------
+
+Add packages:
+
+::
+
+ sudo yum install git autoconf automake libtool make gawk \
+ readline-devel texinfo net-snmp-devel groff pkgconfig \
+ json-c-devel pam-devel bison flex pytest c-ares-devel \
+ perl-XML-LibXML python-devel
+
+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 groups and user
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo groupadd -g 92 frr
+ sudo groupadd -r -g 85 frrvt
+ sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
+ -c "FRR FRRouting suite" -d /var/run/frr frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example.)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ ./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-pimd \
+ --enable-snmp=agentx \
+ --enable-multipath=64 \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvt \
+ --enable-rtadv \
+ --disable-exampledir \
+ --enable-watchfrr \
+ --disable-ldpd \
+ --enable-fpm \
+ --enable-nhrpd \
+ --enable-eigrpd \
+ --enable-babeld \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ make
+ make check
+ sudo make install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo mkdir /var/log/frr
+ sudo mkdir /etc/frr
+ sudo touch /etc/frr/zebra.conf
+ sudo touch /etc/frr/bgpd.conf
+ sudo touch /etc/frr/ospfd.conf
+ sudo touch /etc/frr/ospf6d.conf
+ sudo touch /etc/frr/isisd.conf
+ sudo touch /etc/frr/ripd.conf
+ sudo touch /etc/frr/ripngd.conf
+ sudo touch /etc/frr/pimd.conf
+ sudo touch /etc/frr/nhrpd.conf
+ sudo touch /etc/frr/eigrpd.conf
+ sudo touch /etc/frr/babeld.conf
+ sudo chown -R frr:frr /etc/frr/
+ sudo touch /etc/frr/vtysh.conf
+ sudo chown frr:frrvt /etc/frr/vtysh.conf
+ sudo chmod 640 /etc/frr/*.conf
+
+Install daemon config file
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -p -m 644 redhat/daemons /etc/frr/
+ sudo chown frr:frr /etc/frr/daemons
+
+Edit /etc/frr/daemons as needed to select the required daemons
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Look for the section with ``watchfrr_enable=...`` and ``zebra=...`` etc.
+Enable the daemons as required by changing the value to ``yes``
+
+Enable IP & IPv6 forwarding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Create a new file ``/etc/sysctl.d/90-routing-sysctl.conf`` with the
+following content:
+
+::
+
+ # Sysctl for routing
+ #
+ # Routing: We need to forward packets
+ net.ipv4.conf.all.forwarding=1
+ net.ipv6.conf.all.forwarding=1
+
+Load the modifed sysctl's on the system:
+
+::
+
+ sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
+
+Install frr Service and redhat init files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -p -m 644 redhat/frr.service /usr/lib/systemd/system/frr.service
+ sudo install -p -m 755 redhat/frr.init /usr/lib/frr/frr
+
+Register the systemd files
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo systemctl preset frr.service
+
+Enable required frr at startup
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo systemctl enable frr
+
+Reboot or start FRR manually
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo systemctl start frr
--- /dev/null
+Debian 8
+========================================
+
+Debian 8 restrictions:
+----------------------
+
+- MPLS is not supported on ``Debian 8`` with default kernel. MPLS
+ requires Linux Kernel 4.5 or higher (LDP can be built, but may have
+ limited use without MPLS)
+
+Install required packages
+-------------------------
+
+Add packages:
+
+::
+
+ sudo apt-get install git autoconf automake libtool make gawk \
+ libreadline-dev texinfo libjson-c-dev pkg-config bison flex \
+ python-pip libc-ares-dev python3-dev
+
+Install newer pytest (>3.0) from pip
+
+::
+
+ sudo pip install pytest
+
+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 groups and user
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo addgroup --system --gid 92 frr
+ sudo addgroup --system --gid 85 frrvty
+ sudo adduser --system --ingroup frr --home /var/run/frr/ \
+ --gecos "FRR suite" --shell /bin/false frr
+ sudo usermod -a -G frrvty frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example.)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ ./configure \
+ --enable-exampledir=/usr/share/doc/frr/examples/ \
+ --localstatedir=/var/run/frr \
+ --sbindir=/usr/lib/frr \
+ --sysconfdir=/etc/frr \
+ --enable-vtysh \
+ --enable-isisd \
+ --enable-pimd \
+ --enable-watchfrr \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --enable-ldpd \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ make
+ make check
+ sudo make install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -m 755 -o frr -g frr -d /var/log/frr
+ sudo install -m 775 -o frr -g frrvty -d /etc/frr
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
+ sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
+
+Enable IP & IPv6 forwarding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
+other settings)
+
+::
+
+ # Uncomment the next line to enable packet forwarding for IPv4
+ net.ipv4.ip_forward=1
+
+ # Uncomment the next line to enable packet forwarding for IPv6
+ # Enabling this option disables Stateless Address Autoconfiguration
+ # based on Router Advertisements for this host
+ net.ipv6.conf.all.forwarding=1
+
+**Reboot** or use ``sysctl -p`` to apply the same config to the running
+system
+
+Troubleshooting
+~~~~~~~~~~~~~~~
+
+**Local state directory**
+
+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.
+
+When using a different local state directory you need to create the new
+directory and change the ownership to the frr user, for example:
+
+::
+
+ mkdir /var/opt/frr
+ chown frr /var/opt/frr
+
+**Shared library error**
+
+If you try and start any of the frrouting daemons you may see the below
+error due to the frrouting shared library directory not being found:
+
+::
+
+ ./zebra: error while loading shared libraries: libfrr.so.0: cannot open shared object file: No such file or directory
+
+The fix is to add the following line to /etc/ld.so.conf which will
+continue to reference the library directory after the system reboots. To
+load the library directory path immediately run the ldconfig command
+after adding the line to the file eg:
+
+::
+
+ echo include /usr/local/lib >> /etc/ld.so.conf
+ ldconfig
--- /dev/null
+Debian 9
+========================================
+
+Install required packages
+-------------------------
+
+Add packages:
+
+::
+
+ sudo apt-get install git autoconf automake libtool make \
+ libreadline-dev texinfo libjson-c-dev pkg-config bison flex \
+ python-pip libc-ares-dev python3-dev python-pytest
+
+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 groups and user
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo addgroup --system --gid 92 frr
+ sudo addgroup --system --gid 85 frrvty
+ sudo adduser --system --ingroup frr --home /var/run/frr/ \
+ --gecos "FRR suite" --shell /bin/false frr
+ sudo usermod -a -G frrvty frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example.)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ git checkout stable/3.0
+ ./bootstrap.sh
+ ./configure \
+ --enable-exampledir=/usr/share/doc/frr/examples/ \
+ --localstatedir=/var/run/frr \
+ --sbindir=/usr/lib/frr \
+ --sysconfdir=/etc/frr \
+ --enable-vtysh \
+ --enable-isisd \
+ --enable-pimd \
+ --enable-watchfrr \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --enable-ldpd \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ make
+ make check
+ sudo make install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -m 755 -o frr -g frr -d /var/log/frr
+ sudo install -m 775 -o frr -g frrvty -d /etc/frr
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
+ sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
+
+Enable IP & IPv6 forwarding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
+other settings)
+
+::
+
+ # Uncomment the next line to enable packet forwarding for IPv4
+ net.ipv4.ip_forward=1
+
+ # Uncomment the next line to enable packet forwarding for IPv6
+ # Enabling this option disables Stateless Address Autoconfiguration
+ # based on Router Advertisements for this host
+ net.ipv6.conf.all.forwarding=1
+
+**Reboot** or use ``sysctl -p`` to apply the same config to the running
+system
+
+Troubleshooting
+~~~~~~~~~~~~~~~
+
+**Local state directory**
+
+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.
+
+When using a different local state directory you need to create the new
+directory and change the ownership to the frr user, for example:
+
+::
+
+ mkdir /var/opt/frr
+ chown frr /var/opt/frr
+
+**Shared library error**
+
+If you try and start any of the frrouting daemons you may see the below
+error due to the frrouting shared library directory not being found:
+
+::
+
+ ./zebra: error while loading shared libraries: libfrr.so.0: cannot open shared object file: No such file or directory
+
+The fix is to add the following line to /etc/ld.so.conf which will
+continue to reference the library directory after the system reboots. To
+load the library directory path immediately run the ldconfig command
+after adding the line to the file eg:
+
+::
+
+ echo include /usr/local/lib >> /etc/ld.so.conf
+ ldconfig
--- /dev/null
+Fedora 24
+=========================================
+
+(As an alternative to this installation, you may prefer to create a FRR
+rpm package yourself and install that package instead. See instructions
+in redhat/README.rpm\_build.md on how to build a rpm package)
+
+Install required packages
+-------------------------
+
+Add packages:
+
+::
+
+ sudo dnf install git autoconf automake libtool make gawk \
+ readline-devel texinfo net-snmp-devel groff pkgconfig \
+ json-c-devel pam-devel perl-XML-LibXML pytest bison flex \
+ c-ares-devel python3-devel
+
+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 groups and user
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo groupadd -g 92 frr
+ sudo groupadd -r -g 85 frrvt
+ sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
+ -c "FRR FRRouting suite" -d /var/run/frr frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example.)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ ./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-pimd \
+ --enable-snmp=agentx \
+ --enable-multipath=64 \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvt \
+ --enable-rtadv \
+ --disable-exampledir \
+ --enable-watchfrr \
+ --enable-ldpd \
+ --enable-fpm \
+ --enable-nhrpd \
+ --enable-eigrpd \
+ --enable-babeld \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ make
+ make check
+ sudo make install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo mkdir /var/log/frr
+ sudo mkdir /etc/frr
+ sudo touch /etc/frr/zebra.conf
+ sudo touch /etc/frr/bgpd.conf
+ sudo touch /etc/frr/ospfd.conf
+ sudo touch /etc/frr/ospf6d.conf
+ sudo touch /etc/frr/isisd.conf
+ sudo touch /etc/frr/ripd.conf
+ sudo touch /etc/frr/ripngd.conf
+ sudo touch /etc/frr/pimd.conf
+ sudo touch /etc/frr/ldpd.conf
+ sudo touch /etc/frr/nhrpd.conf
+ sudo touch /etc/frr/eigrpd.conf
+ sudo touch /etc/frr/babeld.conf
+ sudo chown -R frr:frr /etc/frr/
+ sudo touch /etc/frr/vtysh.conf
+ sudo chown frr:frrvt /etc/frr/vtysh.conf
+ sudo chmod 640 /etc/frr/*.conf
+
+Install daemon config file
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -p -m 644 redhat/daemons /etc/frr/
+ sudo chown frr:frr /etc/frr/daemons
+
+Edit /etc/frr/daemons as needed to select the required daemons
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Look for the section with ``watchfrr_enable=...`` and ``zebra=...`` etc.
+Enable the daemons as required by changing the value to ``yes``
+
+Enable IP & IPv6 forwarding (and MPLS)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Create a new file ``/etc/sysctl.d/90-routing-sysctl.conf`` with the
+following content: (Please make sure to list all interfaces with
+required MPLS similar to ``net.mpls.conf.eth0.input=1``)
+
+::
+
+ # Sysctl for routing
+ #
+ # Routing: We need to forward packets
+ net.ipv4.conf.all.forwarding=1
+ net.ipv6.conf.all.forwarding=1
+ #
+ # Enable MPLS Label processing on all interfaces
+ net.mpls.conf.eth0.input=1
+ net.mpls.conf.eth1.input=1
+ net.mpls.conf.eth2.input=1
+ net.mpls.platform_labels=100000
+
+Load the modifed sysctl's on the system:
+
+::
+
+ sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
+
+Create a new file ``/etc/modules-load.d/mpls.conf`` with the following
+content:
+
+::
+
+ # Load MPLS Kernel Modules
+ mpls-router
+ mpls-iptunnel
+
+And load the kernel modules on the running system:
+
+::
+
+ sudo modprobe mpls-router mpls-iptunnel
+
+Install frr Service and redhat init files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -p -m 644 redhat/frr.service /usr/lib/systemd/system/frr.service
+ sudo install -p -m 755 redhat/frr.init /usr/lib/frr/frr
+
+Enable required frr at startup
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo systemctl enable frr
+
+Reboot or start FRR manually
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo systemctl start frr
--- /dev/null
+FreeBSD 10
+==========================================
+
+FreeBSD 10 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
+
+Install required packages
+-------------------------
+
+Add packages: (Allow the install of the package managment tool if this
+is first package install and asked)
+
+::
+
+ pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
+ bison flex py27-pytest c-ares python3
+
+Make sure there is no /usr/bin/flex preinstalled (and use the newly
+installed in /usr/local/bin): (FreeBSD frequently provides a older flex
+as part of the base OS which takes preference in path)
+
+::
+
+ rm -f /usr/bin/flex
+
+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
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ 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
+
+(You may prefer different options on configure statement. These are just
+an example)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ export MAKE=gmake
+ export LDFLAGS="-L/usr/local/lib"
+ export CPPFLAGS="-I/usr/local/include"
+ ./configure \
+ --sysconfdir=/usr/local/etc/frr \
+ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
+ --localstatedir=/var/run/frr \
+ --prefix=/usr/local \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ gmake
+ gmake check
+ sudo gmake install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo mkdir /usr/local/etc/frr
+ sudo touch /usr/local/etc/frr/zebra.conf
+ sudo touch /usr/local/etc/frr/bgpd.conf
+ sudo touch /usr/local/etc/frr/ospfd.conf
+ sudo touch /usr/local/etc/frr/ospf6d.conf
+ sudo touch /usr/local/etc/frr/isisd.conf
+ sudo touch /usr/local/etc/frr/ripd.conf
+ sudo touch /usr/local/etc/frr/ripngd.conf
+ sudo touch /usr/local/etc/frr/pimd.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
--- /dev/null
+FreeBSD 11
+==========================================
+
+FreeBSD 11 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
+
+Install required packages
+-------------------------
+
+Add packages: (Allow the install of the package managment tool if this
+is first package install and asked)
+
+::
+
+ pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
+ bison flex py27-pytest c-ares python3
+
+Make sure there is no /usr/bin/flex preinstalled (and use the newly
+installed in /usr/local/bin): (FreeBSD frequently provides a older flex
+as part of the base OS which takes preference in path)
+
+::
+
+ rm -f /usr/bin/flex
+
+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
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ 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
+
+(You may prefer different options on configure statement. These are just
+an example)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ export MAKE=gmake
+ export LDFLAGS="-L/usr/local/lib"
+ export CPPFLAGS="-I/usr/local/include"
+ ./configure \
+ --sysconfdir=/usr/local/etc/frr \
+ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
+ --localstatedir=/var/run/frr \
+ --prefix=/usr/local \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ gmake
+ gmake check
+ sudo gmake install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo mkdir /usr/local/etc/frr
+ sudo touch /usr/local/etc/frr/zebra.conf
+ sudo touch /usr/local/etc/frr/bgpd.conf
+ sudo touch /usr/local/etc/frr/ospfd.conf
+ sudo touch /usr/local/etc/frr/ospf6d.conf
+ sudo touch /usr/local/etc/frr/isisd.conf
+ sudo touch /usr/local/etc/frr/ripd.conf
+ sudo touch /usr/local/etc/frr/ripngd.conf
+ sudo touch /usr/local/etc/frr/pimd.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
--- /dev/null
+FreeBSD 9
+=========================================
+
+FreeBSD 9 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
+
+Install required packages
+-------------------------
+
+Add packages: (Allow the install of the package managment tool if this
+is first package install and asked)
+
+::
+
+ pkg install -y git autoconf automake libtool gmake gawk \
+ pkgconf texinfo json-c bison flex py27-pytest c-ares \
+ python3
+
+Make sure there is no /usr/bin/flex preinstalled (and use the newly
+installed in /usr/local/bin): (FreeBSD frequently provides a older flex
+as part of the base OS which takes preference in path)
+
+::
+
+ rm -f /usr/bin/flex
+
+For building with clang (instead of gcc), upgrade clang from 3.4 default
+to 3.6 *This is needed to build FreeBSD packages as well - for packages
+clang is default* (Clang 3.4 as shipped with FreeBSD 9 crashes during
+compile)
+
+::
+
+ pkg install clang36
+ pkg delete clang34
+ mv /usr/bin/clang /usr/bin/clang34
+ ln -s /usr/local/bin/clang36 /usr/bin/clang
+
+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
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ 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
+
+(You may prefer different options on configure statement. These are just
+an example)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ export MAKE=gmake
+ export LDFLAGS="-L/usr/local/lib"
+ export CPPFLAGS="-I/usr/local/include"
+ ./configure \
+ --sysconfdir=/usr/local/etc/frr \
+ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
+ --localstatedir=/var/run/frr \
+ --prefix=/usr/local \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ gmake
+ gmake check
+ sudo gmake install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo mkdir /usr/local/etc/frr
+ sudo touch /usr/local/etc/frr/zebra.conf
+ sudo touch /usr/local/etc/frr/bgpd.conf
+ sudo touch /usr/local/etc/frr/ospfd.conf
+ sudo touch /usr/local/etc/frr/ospf6d.conf
+ sudo touch /usr/local/etc/frr/isisd.conf
+ sudo touch /usr/local/etc/frr/ripd.conf
+ sudo touch /usr/local/etc/frr/ripngd.conf
+ sudo touch /usr/local/etc/frr/pimd.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
--- /dev/null
+OpenWRT/LEDE
+=============================================
+
+- for the moment because of cross compile problems, master is not
+ supported, only up to 3.0
+- LDP can't be built because of missing Perl-XML-LibXML in OpenWRT/LEDE
+ tree
+
+Prepare build environment
+-------------------------
+
+https://lede-project.org/docs/guide-developer/install-buildsystem
+
+for
+
+Ubuntu 12.04LTS:
+
+::
+
+ sudo apt-get install build-essential subversion git-core \
+ libncurses5-dev zlib1g-dev gawk flex quilt libssl-dev xsltproc \
+ libxml-parser-perl mercurial bzr ecj cvs unzip
+
+Ubuntu 64bit:
+
+::
+
+ sudo apt-get install build-essential subversion libncurses5-dev zlib1g-dev \
+ gawk gcc-multilib flex git-core gettext libssl-dev
+
+Debian 8 Jessie:
+
+::
+
+ sudo apt-get install build-essential libncurses5-dev gawk git subversion \
+ libssl-dev gettext unzip zlib1g-dev file python
+
+Debian 9 Stretch:
+
+::
+
+ sudo apt-get install build-essential libncurses5-dev gawk git subversion \
+ libssl-dev gettext zlib1g-dev
+
+Centos x86-64 (some packages require EPEL):
+
+::
+
+ yum install subversion binutils bzip2 gcc gcc-c++ gawk gettext flex \
+ ncurses-devel zlib-devel zlib-static make patch unzip glibc glibc-devel \
+ perl-ExtUtils-MakeMaker glibc-static quilt ncurses-libs sed sdcc bison \
+ intltool sharutils wget git-core openssl-devel xz
+
+Fedora 24 - 64Bit:
+
+::
+
+ dnf install -y subversion binutils bzip2 gcc gcc-c++ gawk gettext git-core \
+ unzip ncurses-devel ncurses-compat-libs zlib-devel zlib-static make \
+ flex patch perl-ExtUtils-MakeMaker perl-Thread-Queue glibc glibc-devel \
+ glibc-static quilt sed sdcc intltool sharutils bison wget openssl-devel
+
+Get LEDE Sources (from Git)
+---------------------------
+
+LEDE and OpenWRT is planned to remerge and won't cover the similar
+OpenWRT build As normal user: git clone
+https://git.lede-project.org/source.git lede cd lede ./scripts/feeds
+update -a ./scripts/feeds install -a cd feeds/routing git pull origin
+pull/319/head ln -s ../../../feeds/routing/frr/
+../../package/feeds/routing/ cd ../.. make menuconfig
+
+Select the needed target then select needed packages in Network ->
+Routing and Redirection -> frr, exit and save
+
+::
+
+ make or make package/frr/compile
+
+It may be possible that on first build ``make package/frr/compile`` not
+to work and it may be needed to run a ``make`` for the entire build
+envronment, add V=s for debugging
+
+Work with sources
+-----------------
+
+To update the rc1 version or add other options, the Makefile is found in
+feeds/routing/frr
+
+edit: PKG\_VERSION:= PKG\_SOURCE\_VERSION:=
+
+Usage
+-----
+
+Edit ``/usr/sbin/frr.init`` and add/remove the daemons name in section
+DAEMONS= or don't install unneded packages For example: zebra bgpd ldpd
+isisd nhrpd ospfd ospf6d pimd ripd ripngd
+
+Enable the serivce
+~~~~~~~~~~~~~~~~~~
+
+- service frr enable
+
+Start the service
+~~~~~~~~~~~~~~~~~
+
+- service frr start
--- /dev/null
+NetBSD 6
+========================================
+
+NetBSD 6 restrictions:
+----------------------
+
+- MPLS is not supported on ``NetBSD``. MPLS requires a Linux Kernel
+ (4.5 or higher). LDP can be built, but may have limited use without
+ MPLS
+
+Install required packages
+-------------------------
+
+Configure Package location:
+
+::
+
+ PKG_PATH="ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/`uname -m`/`uname -r`/All"
+ export PKG_PATH
+
+Add packages:
+
+::
+
+ sudo pkg_add git autoconf automake libtool gmake gawk openssl \
+ pkg-config json-c python27 py27-test python35
+
+Install SSL Root Certificates (for git https access):
+
+::
+
+ sudo pkg_add mozilla-rootcerts
+ sudo touch /etc/openssl/openssl.cnf
+ sudo mozilla-rootcerts install
+
+Select default Python and py.test
+
+::
+
+ sudo ln -s /usr/pkg/bin/python2.7 /usr/bin/python
+ sudo ln -s /usr/pkg/bin/py.test-2.7 /usr/bin/py.test
+
+Get FRR, compile it and install it (from Git)
+---------------------------------------------
+
+Add frr groups and user
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo groupadd -g 92 frr
+ sudo groupadd -g 93 frrvty
+ sudo useradd -g 92 -u 92 -G frrvty -c "FRR suite" \
+ -d /nonexistent -s /sbin/nologin frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ MAKE=gmake
+ export LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib"
+ export CPPFLAGS="-I/usr/pkg/include"
+ ./configure \
+ --sysconfdir=/usr/pkg/etc/frr \
+ --enable-exampledir=/usr/pkg/share/examples/frr \
+ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
+ --localstatedir=/var/run/frr \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ gmake
+ gmake check
+ sudo gmake install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo mkdir /var/log/frr
+ sudo mkdir /usr/pkg/etc/frr
+ sudo touch /usr/pkg/etc/frr/zebra.conf
+ sudo touch /usr/pkg/etc/frr/bgpd.conf
+ sudo touch /usr/pkg/etc/frr/ospfd.conf
+ sudo touch /usr/pkg/etc/frr/ospf6d.conf
+ sudo touch /usr/pkg/etc/frr/isisd.conf
+ sudo touch /usr/pkg/etc/frr/ripd.conf
+ sudo touch /usr/pkg/etc/frr/ripngd.conf
+ sudo touch /usr/pkg/etc/frr/pimd.conf
+ sudo chown -R frr:frr /usr/pkg/etc/frr
+ sudo touch /usr/local/etc/frr/vtysh.conf
+ sudo chown frr:frrvty /usr/pkg/etc/frr/*.conf
+ sudo chmod 640 /usr/pkg/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
+
+Install rc.d init files
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ cp pkgsrc/*.sh /etc/rc.d/
+ chmod 555 /etc/rc.d/*.sh
+
+Enable FRR processes
+~~~~~~~~~~~~~~~~~~~~
+
+(Enable the required processes only)
+
+::
+
+ echo "zebra=YES" >> /etc/rc.conf
+ echo "bgpd=YES" >> /etc/rc.conf
+ echo "ospfd=YES" >> /etc/rc.conf
+ echo "ospf6d=YES" >> /etc/rc.conf
+ echo "isisd=YES" >> /etc/rc.conf
+ echo "ripngd=YES" >> /etc/rc.conf
+ echo "ripd=YES" >> /etc/rc.conf
+ echo "pimd=YES" >> /etc/rc.conf
--- /dev/null
+NetBSD 7
+========================================
+
+NetBSD 7 restrictions:
+----------------------
+
+- MPLS is not supported on ``NetBSD``. MPLS requires a Linux Kernel
+ (4.5 or higher). LDP can be built, but may have limited use without
+ MPLS
+
+Install required packages
+-------------------------
+
+::
+
+ sudo pkgin install git autoconf automake libtool gmake gawk openssl \
+ pkg-config json-c python27 py27-test python35
+
+Install SSL Root Certificates (for git https access):
+
+::
+
+ sudo pkgin install mozilla-rootcerts
+ sudo touch /etc/openssl/openssl.cnf
+ sudo mozilla-rootcerts install
+
+Select default Python and py.test
+
+::
+
+ sudo ln -s /usr/pkg/bin/python2.7 /usr/bin/python
+ sudo ln -s /usr/pkg/bin/py.test-2.7 /usr/bin/py.test
+
+Get FRR, compile it and install it (from Git)
+---------------------------------------------
+
+Add frr groups and user
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo groupadd -g 92 frr
+ sudo groupadd -g 93 frrvty
+ sudo useradd -g 92 -u 92 -G frrvty -c "FRR suite" \
+ -d /nonexistent -s /sbin/nologin frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ MAKE=gmake
+ export LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib"
+ export CPPFLAGS="-I/usr/pkg/include"
+ ./configure \
+ --sysconfdir=/usr/pkg/etc/frr \
+ --enable-exampledir=/usr/pkg/share/examples/frr \
+ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \
+ --localstatedir=/var/run/frr \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ gmake
+ gmake check
+ sudo gmake install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo mkdir /usr/pkg/etc/frr
+ sudo touch /usr/pkg/etc/frr/zebra.conf
+ sudo touch /usr/pkg/etc/frr/bgpd.conf
+ sudo touch /usr/pkg/etc/frr/ospfd.conf
+ sudo touch /usr/pkg/etc/frr/ospf6d.conf
+ sudo touch /usr/pkg/etc/frr/isisd.conf
+ sudo touch /usr/pkg/etc/frr/ripd.conf
+ sudo touch /usr/pkg/etc/frr/ripngd.conf
+ sudo touch /usr/pkg/etc/frr/pimd.conf
+ sudo chown -R frr:frr /usr/pkg/etc/frr
+ sudo touch /usr/local/etc/frr/vtysh.conf
+ sudo chown frr:frrvty /usr/pkg/etc/frr/*.conf
+ sudo chmod 640 /usr/pkg/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
+
+Install rc.d init files
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ cp pkgsrc/*.sh /etc/rc.d/
+ chmod 555 /etc/rc.d/*.sh
+
+Enable FRR processes
+~~~~~~~~~~~~~~~~~~~~
+
+(Enable the required processes only)
+
+::
+
+ echo "zebra=YES" >> /etc/rc.conf
+ echo "bgpd=YES" >> /etc/rc.conf
+ echo "ospfd=YES" >> /etc/rc.conf
+ echo "ospf6d=YES" >> /etc/rc.conf
+ echo "isisd=YES" >> /etc/rc.conf
+ echo "ripngd=YES" >> /etc/rc.conf
+ echo "ripd=YES" >> /etc/rc.conf
+ echo "pimd=YES" >> /etc/rc.conf
--- /dev/null
+OmniOS (OpenSolaris)
+====================================================
+
+OmniOS restrictions:
+--------------------
+
+- MPLS is not supported on ``OmniOS`` or ``Solaris``. MPLS requires a
+ Linux Kernel (4.5 or higher). LDP can be built, but may have limited
+ use without MPLS
+
+Enable IP & IPv6 forwarding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ routeadm -e ipv4-forwarding
+ routeadm -e ipv6-forwarding
+
+Install required packages
+-------------------------
+
+Add packages:
+
+::
+
+ pkg install \
+ developer/build/autoconf \
+ developer/build/automake \
+ developer/lexer/flex \
+ developer/parser/bison \
+ developer/object-file \
+ developer/linker \
+ developer/library/lint \
+ developer/build/gnu-make \
+ developer/gcc51 \
+ library/idnkit \
+ library/idnkit/header-idnkit \
+ system/header \
+ system/library/math/header-math \
+ git libtool gawk pkg-config
+
+Add additional Solaris packages:
+
+::
+
+ pkgadd -d http://get.opencsw.org/now
+ /opt/csw/bin/pkgutil -U
+ /opt/csw/bin/pkgutil -y -i texinfo
+ /opt/csw/bin/pkgutil -y -i perl
+ /opt/csw/bin/pkgutil -y -i libjson_c_dev
+ /opt/csw/bin/pkgutil -y -i python27 py_pip python27_dev
+
+Add libjson to Solaris equivalent of ld.so.conf
+
+::
+
+ crle -l /opt/csw/lib -u
+
+Add pytest:
+
+::
+
+ pip install pytest
+
+Select Python 2.7 as default (required for pytest)
+
+::
+
+ rm -f /usr/bin/python
+ ln -s /opt/csw/bin/python2.7 /usr/bin/python
+
+Fix PATH for all users and non-interactive sessions. Edit
+``/etc/default/login`` and add the following default PATH:
+
+::
+
+ PATH=/usr/gnu/bin:/usr/bin:/usr/sbin:/sbin:/opt/csw/bin
+
+Edit ``~/.profile`` and add the following default PATH:
+
+::
+
+ PATH=/usr/gnu/bin:/usr/bin:/usr/sbin:/sbin:/opt/csw/bin
+
+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
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo groupadd -g 93 frr
+ sudo groupadd -g 94 frrvty
+ sudo useradd -g 93 -u 93 -G frrvty -c "FRR suite" \
+ -d /nonexistent -s /bin/false frr
+
+(You may prefer different options on configure statement. These are just
+an example)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ export MAKE=gmake
+ export LDFLAGS="-L/opt/csw/lib"
+ export CPPFLAGS="-I/opt/csw/include"
+ export PKG_CONFIG_PATH=/opt/csw/lib/pkgconfig
+ ./configure \
+ --sysconfdir=/etc/frr \
+ --enable-exampledir=/usr/share/doc/frr/examples/ \
+ --localstatedir=/var/run/frr \
+ --sbindir=/usr/lib/frr \
+ --enable-vtysh \
+ --enable-watchfrr \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ gmake
+ gmake check
+ sudo gmake install
+
+Enable IP & IPv6 forwarding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ routeadm -e ipv4-forwarding
+ routeadm -e ipv6-forwarding
--- /dev/null
+OpenBSD 6
+=========================================
+
+Install required packages
+-------------------------
+
+Configure PKG\_PATH
+
+::
+
+ export PKG_PATH=http://ftp5.usa.openbsd.org/pub/OpenBSD/$(uname -r)/packages/$(machine -a)/
+
+Add packages:
+
+::
+
+ pkg_add git autoconf-2.69p2 automake-1.15p0 libtool bison
+ pkg_add gmake gawk dejagnu openssl json-c py-test
+
+Select Python2.7 as default (required for pytest)
+
+::
+
+ ln -s /usr/local/bin/python2.7 /usr/local/bin/python
+
+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
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ groupadd -g 525 _frr
+ groupadd -g 526 _frrvty
+ useradd -g 525 -u 525 -c "FRR suite" -G _frrvty \
+ -d /nonexistent -s /sbin/nologin _frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ export AUTOCONF_VERSION="2.69"
+ export AUTOMAKE_VERSION="1.15"
+ ./bootstrap.sh
+ export LDFLAGS="-L/usr/local/lib"
+ export CPPFLAGS="-I/usr/local/include"
+ ./configure \
+ --sysconfdir=/etc/frr \
+ --localstatedir=/var/frr \
+ --enable-pimd \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=_frr \
+ --enable-group=_frr \
+ --enable-vty-group=_frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ gmake
+ gmake check
+ doas gmake install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ doas mkdir /var/frr
+ doas chown _frr:_frr /var/frr
+ doas chmod 755 /var/frr
+ doas mkdir /etc/frr
+ doas touch /etc/frr/zebra.conf
+ doas touch /etc/frr/bgpd.conf
+ doas touch /etc/frr/ospfd.conf
+ doas touch /etc/frr/ospf6d.conf
+ doas touch /etc/frr/isisd.conf
+ doas touch /etc/frr/ripd.conf
+ doas touch /etc/frr/ripngd.conf
+ doas touch /etc/frr/pimd.conf
+ doas touch /etc/frr/ldpd.conf
+ doas touch /etc/frr/nhrpd.conf
+ doas chown -R _frr:_frr /etc/frr
+ doas touch /etc/frr/vtysh.conf
+ doas chown -R _frr:_frrvty /etc/frr/vtysh.conf
+ doas chmod 750 /etc/frr
+ doas chmod 640 /etc/frr/*.conf
+
+Enable IP & IPv6 forwarding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add the following lines to the end of ``/etc/rc.conf``:
+
+::
+
+ net.inet6.ip6.forwarding=1 # 1=Permit forwarding of IPv6 packets
+ net.inet6.ip6.mforwarding=1 # 1=Permit forwarding of IPv6 multicast packets
+ net.inet6.ip6.multipath=1 # 1=Enable IPv6 multipath routing
+
+**Reboot** to apply the config to the system
+
+Enable MPLS Forwarding
+~~~~~~~~~~~~~~~~~~~~~~
+
+To enable MPLS forwarding on a given interface, use the following
+command:
+
+::
+
+ doas ifconfig em0 mpls
+
+Alternatively, to make MPLS forwarding persistent across reboots, add
+the "mpls" keyword in the hostname.\* files of the desired interfaces.
+Example:
+
+::
+
+ cat /etc/hostname.em0
+ inet 10.0.1.1 255.255.255.0 mpls
+
+Install rc.d init files
+~~~~~~~~~~~~~~~~~~~~~~~
+
+(create them in /etc/rc.d - no example are included at this time with
+FRR source)
+
+Example (for zebra - store as ``/etc/rc.d/frr_zebra.sh``)
+
+::
+
+ #!/bin/sh
+ #
+ # $OpenBSD: frr_zebra.rc,v 1.1 2013/04/18 20:29:08 sthen Exp $
+
+ daemon="/usr/local/sbin/zebra -d"
+
+ . /etc/rc.d/rc.subr
+
+ rc_cmd $1
+
+Enable FRR processes
+~~~~~~~~~~~~~~~~~~~~
+
+(Enable the required processes only)
+
+::
+
+ echo "frr_zebra=YES" >> /etc/rc.conf
+ echo "frr_bgpd=YES" >> /etc/rc.conf
+ echo "frr_ospfd=YES" >> /etc/rc.conf
+ echo "frr_ospf6d=YES" >> /etc/rc.conf
+ echo "frr_isisd=YES" >> /etc/rc.conf
+ echo "frr_ripngd=YES" >> /etc/rc.conf
+ echo "frr_ripd=YES" >> /etc/rc.conf
+ echo "frr_pimd=YES" >> /etc/rc.conf
+ echo "frr_ldpd=YES" >> /etc/rc.conf
--- /dev/null
+Ubuntu 12.04LTS
+===============================================
+
+- MPLS is not supported on ``Ubuntu 12.04`` with default kernel. MPLS
+ requires Linux Kernel 4.5 or higher (LDP can be built, but may have
+ limited use without MPLS) For an updated Ubuntu Kernel, see
+ http://kernel.ubuntu.com/~kernel-ppa/mainline/
+
+Install required packages
+-------------------------
+
+Add packages:
+
+::
+
+ apt-get install git autoconf automake libtool make gawk libreadline-dev \
+ texinfo libpam0g-dev dejagnu libjson0-dev pkg-config libpam0g-dev \
+ libjson0-dev flex python-pip libc-ares-dev python3-dev
+
+Install newer bison from 14.04 package source (Ubuntu 12.04 package
+source is too old)
+
+::
+
+ mkdir builddir
+ cd builddir
+ wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg-2.dsc
+ wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg.orig.tar.bz2
+ wget http://archive.ubuntu.com/ubuntu/pool/main/b/bison/bison_3.0.2.dfsg-2.debian.tar.gz
+ tar -jxvf bison_3.0.2.dfsg.orig.tar.bz2
+ cd bison-3.0.2.dfsg/
+ tar xzf ../bison_3.0.2.dfsg-2.debian.tar.gz
+ sudo apt-get build-dep bison
+ debuild -b -uc -us
+ cd ..
+ sudo dpkg -i ./libbison-dev_3.0.2.dfsg-2_amd64.deb ./bison_3.0.2.dfsg-2_amd64.deb
+ cd ..
+ rm -rf builddir
+
+Install newer version of autoconf and automake:
+
+::
+
+ wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
+ tar xvf autoconf-2.69.tar.gz
+ cd autoconf-2.69
+ ./configure --prefix=/usr
+ make
+ sudo make install
+ cd ..
+
+ wget http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz
+ tar xvf automake-1.15.tar.gz
+ cd automake-1.15
+ ./configure --prefix=/usr
+ make
+ sudo make install
+ cd ..
+
+Install pytest:
+
+::
+
+ pip install pytest
+
+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 groups and user
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo groupadd -g 92 frr
+ sudo groupadd -r -g 85 frrvty
+ sudo adduser --system --ingroup frr --home /var/run/frr/ \
+ --gecos "FRR suite" --shell /sbin/nologin frr
+ sudo usermod -a -G frrvty frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example.)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ ./configure \
+ --prefix=/usr \
+ --enable-exampledir=/usr/share/doc/frr/examples/ \
+ --localstatedir=/var/run/frr \
+ --sbindir=/usr/lib/frr \
+ --sysconfdir=/etc/frr \
+ --enable-pimd \
+ --enable-watchfrr \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ make
+ make check
+ sudo make install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -m 755 -o frr -g frr -d /var/log/frr
+ sudo install -m 775 -o frr -g frrvty -d /etc/frr
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
+ sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
+
+Enable IP & IPv6 forwarding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
+other settings)
+
+::
+
+ # Uncomment the next line to enable packet forwarding for IPv4
+ net.ipv4.ip_forward=1
+
+ # Uncomment the next line to enable packet forwarding for IPv6
+ # Enabling this option disables Stateless Address Autoconfiguration
+ # based on Router Advertisements for this host
+ net.ipv6.conf.all.forwarding=1
+
+**Reboot** or use ``sysctl -p`` to apply the same config to the running
+system
+
+Install the init.d service
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -m 755 tools/frr /etc/init.d/frr
+ sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
+ sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf
+ sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+
+Enable daemons
+~~~~~~~~~~~~~~
+
+| Edit ``/etc/frr/daemons`` and change the value from "no" to "yes" for
+ those daemons you want to start by systemd.
+| For example.
+
+::
+
+ zebra=yes
+ bgpd=yes
+ ospfd=yes
+ ospf6d=yes
+ ripd=yes
+ ripngd=yes
+ isisd=yes
+
+Start the init.d service
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+- /etc/init.d/frr start
+- use ``/etc/init.d/frr status`` to check its status.
--- /dev/null
+Ubuntu 14.04LTS
+===============================================
+
+- MPLS is not supported on ``Ubuntu 14.04`` with default kernel. MPLS
+ requires Linux Kernel 4.5 or higher (LDP can be built, but may have
+ limited use without MPLS) For an updated Ubuntu Kernel, see
+ http://kernel.ubuntu.com/~kernel-ppa/mainline/
+
+Install required packages
+-------------------------
+
+Add packages:
+
+::
+
+ apt-get install git autoconf automake libtool make gawk libreadline-dev \
+ texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \
+ python-pytest libc-ares-dev python3-dev
+
+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 groups and user
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo groupadd -g 92 frr
+ sudo groupadd -r -g 85 frrvty
+ sudo adduser --system --ingroup frr --home /var/run/frr/ \
+ --gecos "FRR suite" --shell /sbin/nologin frr
+ sudo usermod -a -G frrvty frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example.)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ ./configure \
+ --prefix=/usr \
+ --enable-exampledir=/usr/share/doc/frr/examples/ \
+ --localstatedir=/var/run/frr \
+ --sbindir=/usr/lib/frr \
+ --sysconfdir=/etc/frr \
+ --enable-pimd \
+ --enable-watchfrr \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --enable-ldpd \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ make
+ make check
+ sudo make install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -m 755 -o frr -g frr -d /var/log/frr
+ sudo install -m 775 -o frr -g frrvty -d /etc/frr
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
+ sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
+
+Enable IP & IPv6 forwarding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
+other settings)
+
+::
+
+ # Uncomment the next line to enable packet forwarding for IPv4
+ net.ipv4.ip_forward=1
+
+ # Uncomment the next line to enable packet forwarding for IPv6
+ # Enabling this option disables Stateless Address Autoconfiguration
+ # based on Router Advertisements for this host
+ net.ipv6.conf.all.forwarding=1
+
+**Reboot** or use ``sysctl -p`` to apply the same config to the running
+system ### Install the init.d service
+
+::
+
+ sudo install -m 755 tools/frr /etc/init.d/frr
+ sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
+ sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf
+ sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+
+Enable daemons
+~~~~~~~~~~~~~~
+
+| Edit ``/etc/frr/daemons`` and change the value from "no" to "yes" for
+ those daemons you want to start by systemd.
+| For example.
+
+::
+
+ zebra=yes
+ bgpd=yes
+ ospfd=yes
+ ospf6d=yes
+ ripd=yes
+ ripngd=yes
+ isisd=yes
+
+Start the init.d service
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+- /etc/init.d/frr start
+- use ``/etc/init.d/frr status`` to check its status.
--- /dev/null
+Ubuntu 16.04LTS
+===============================================
+
+- MPLS is not supported on ``Ubuntu 16.04`` with default kernel. MPLS
+ requires Linux Kernel 4.5 or higher (LDP can be built, but may have
+ limited use without MPLS) For an updated Ubuntu Kernel, see
+ http://kernel.ubuntu.com/~kernel-ppa/mainline/
+
+Install required packages
+-------------------------
+
+Add packages:
+
+::
+
+ apt-get install git autoconf automake libtool make gawk libreadline-dev \
+ texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \
+ python-pytest libc-ares-dev python3-dev libsystemd-dev python-ipaddr
+
+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 groups and user
+~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo groupadd -g 92 frr
+ sudo groupadd -r -g 85 frrvty
+ sudo adduser --system --ingroup frr --home /var/run/frr/ \
+ --gecos "FRR suite" --shell /sbin/nologin frr
+ sudo usermod -a -G frrvty frr
+
+Download Source, configure and compile it
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(You may prefer different options on configure statement. These are just
+an example.)
+
+::
+
+ git clone https://github.com/frrouting/frr.git frr
+ cd frr
+ ./bootstrap.sh
+ ./configure \
+ --prefix=/usr \
+ --enable-exampledir=/usr/share/doc/frr/examples/ \
+ --localstatedir=/var/run/frr \
+ --sbindir=/usr/lib/frr \
+ --sysconfdir=/etc/frr \
+ --enable-pimd \
+ --enable-watchfrr \
+ --enable-ospfclient=yes \
+ --enable-ospfapi=yes \
+ --enable-multipath=64 \
+ --enable-user=frr \
+ --enable-group=frr \
+ --enable-vty-group=frrvty \
+ --enable-configfile-mask=0640 \
+ --enable-logfile-mask=0640 \
+ --enable-rtadv \
+ --enable-fpm \
+ --enable-systemd=yes \
+ --with-pkg-git-version \
+ --with-pkg-extra-version=-MyOwnFRRVersion
+ make
+ make check
+ sudo make install
+
+Create empty FRR configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -m 755 -o frr -g frr -d /var/log/frr
+ sudo install -m 775 -o frr -g frrvty -d /etc/frr
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
+ sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
+ sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
+
+Enable IPv4 & IPv6 forwarding
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
+other settings)
+
+::
+
+ # Uncomment the next line to enable packet forwarding for IPv4
+ net.ipv4.ip_forward=1
+
+ # Uncomment the next line to enable packet forwarding for IPv6
+ # Enabling this option disables Stateless Address Autoconfiguration
+ # based on Router Advertisements for this host
+ net.ipv6.conf.all.forwarding=1
+
+Enable MPLS Forwarding (with Linux Kernel >= 4.5)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Edit ``/etc/sysctl.conf`` and the following lines. Make sure to add a
+line equal to ``net.mpls.conf.eth0.input`` or each interface used with
+MPLS
+
+::
+
+ # Enable MPLS Label processing on all interfaces
+ net.mpls.conf.eth0.input=1
+ net.mpls.conf.eth1.input=1
+ net.mpls.conf.eth2.input=1
+ net.mpls.platform_labels=100000
+
+Add MPLS kernel modules
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Add the following lines to ``/etc/modules-load.d/modules.conf``:
+
+::
+
+ # Load MPLS Kernel Modules
+ mpls-router
+ mpls-iptunnel
+
+**Reboot** or use ``sysctl -p`` to apply the same config to the running
+system
+
+Install the systemd service (if rebooted from last step, change directory back to frr directory)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service
+ sudo install -m 644 tools/etc/default/frr /etc/default/frr
+ sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
+ sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf
+ sudo install -m 644 tools/etc/frr/frr.conf /etc/frr/frr.conf
+ sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+
+Enable daemons
+~~~~~~~~~~~~~~
+
+| Edit ``/etc/frr/daemons`` and change the value from "no" to "yes" for
+ those daemons you want to start by systemd.
+| For example.
+
+::
+
+ zebra=yes
+ bgpd=yes
+ ospfd=yes
+ ospf6d=yes
+ ripd=yes
+ ripngd=yes
+ isisd=yes
+
+Enable the systemd service
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- systemctl enable frr
+
+Start the systemd service
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- systemctl start frr
+- use ``systemctl status frr`` to check its status.
--- /dev/null
+Building FRR
+=========================
+
+.. toctree::
+ :maxdepth: 2
+
+ Building_FRR_on_LEDE-OpenWRT
+ Building_FRR_on_CentOS6
+ Building_FRR_on_CentOS7
+ Building_FRR_on_Debian8
+ Building_FRR_on_Debian9
+ Building_FRR_on_Fedora24
+ Building_FRR_on_FreeBSD10
+ Building_FRR_on_FreeBSD11
+ Building_FRR_on_FreeBSD9
+ Building_FRR_on_NetBSD6
+ Building_FRR_on_NetBSD7
+ Building_FRR_on_OmniOS
+ Building_FRR_on_OpenBSD6
+ Building_FRR_on_Ubuntu1204
+ Building_FRR_on_Ubuntu1404
+ Building_FRR_on_Ubuntu1604
--- /dev/null
+FRR Command Line Interface
+==========================
+
+Definition Grammar
+------------------
+
+This is a reference for the syntax used when defining new CLI commands.
+An example definition is:
+
+::
+
+ DEFUN (command_name,
+ command_name_cmd,
+ --> "example <command|line [interface]> DEFINITION...",
+ <..doc strings..>)
+
+The arrowed part is the definition string.
+
+Explicit syntax rules in Flex and Bison may be found in
+lib/command\_lex.l and lib/command\_parse.y, respectively. If you can
+read BNF and regex those will be more useful than this document.
+
+If the parser is throwing syntax or other errors and you can't figure
+out why, it's unlikely to be a bug in the parser. If the error message
+is not useful, please file a bug for a better error message. If all else
+fails, read the token definitions in the lexer source and the Bison BNF
+in the parser source.
+
+Characters allowed in each token type:
+
+Tokens
+------
+
+- ``WORD`` -- A token that begins with +, -, or a lowercase letter. It
+ is an unchanging part of the command and will only match itself.
+ Example: "show ip bgp", every token is a WORD.
+- ``IPV4`` -- 'A.B.C.D', matches an IPv4 address.
+- ``IPV6`` -- 'X:X::X:X', matches an IPv6 address.
+- ``IPV4_PREFIX`` -- 'A.B.C.D/M', matches an IPv4 prefix in CIDR
+ notation.
+- ``IPV6_PREFIX`` -- 'X:X::X:X/M', matches an IPv6 prefix in CIDR
+ notation.
+- ``MAC`` -- 'M:A:C', matches a 48-bit mac address
+- ``MAC_PREFIX`` -- 'M:A:C/M', matches a 48-bit mac address with a mask
+- ``VARIABLE`` -- Begins with a capital letter. Matches any input.
+- ``RANGE`` -- Numeric range delimited by parentheses, e.g. (-100 -
+ 100) or (10-20). Will only match numbers in the range.
+
+Rules
+-----
+
+- ``<angle|brackets>`` -- Contain sequences of tokens separated by
+ pipes and provide mutual exclusion. Sequences may contain
+ ``<mutual|exclusion>`` but not as the first token. Disallowed:
+ ``"example <<a|b> c|d>"`` Allowed: ``"example <a c|b c|d>"``
+- ``[square brackets]`` -- Contains sequences of tokens that are
+ optional (can be omitted). ``[<a|b>]`` can be shortened to ``[a|b]``.
+- ``{curly|braces}`` -- similar to angle brackets, but instead of
+ mutual exclusion, curly braces indicate that one or more of the
+ pipe-separated sequences may be provided in any order.
+- ``VARIADICS...`` -- Any token which accepts input (so anything except
+ WORD) and that occurs as the last token of a line may be followed by
+ an ellipsis, which indicates that input matching the token may be
+ repeated an unlimited number of times.
+- ``$name`` -- Specify a variable name for the preceding token. See
+ "Variable Names" below.
+
+Some general notes:
+
+- Options are allowed at the beginning of the command. The developer is
+ entreated to use these extremely sparingly. They are most useful for
+ implementing the 'no' form of configuration commands. Please think
+ carefully before using them for anything else. There is usually a
+ better solution, even if it is just separating out the command
+ definition into separate ones.
+
+- The developer should judiciously apply separation of concerns when
+ defining
+
+CLI. CLI definitions for two unrelated or vaguely related commands or
+ configuration items should be defined in separate commands. Clarity
+ is preferred over LOC (within reason).
+
+- The maximum number of space-separated tokens that can be entered is
+ presently limited to 256. Please keep this limit in mind when
+ implementing new CLI.
+
+Variable Names
+--------------
+
+The parser tries to fill the "varname" field on each token. This can
+happen either manually or automatically. Manual specifications work by
+appending ``"$name"`` after the input specifier:
+
+::
+
+ foo bar$cmd WORD$name A.B.C.D$ip
+
+Note that you can also assign variable names to fixed input tokens, this
+can be useful if multiple commands share code. You can also use "$name"
+after a multiple-choice option:
+
+::
+
+ foo bar <A.B.C.D|X:X::X:X>$addr [optionA|optionB]$mode
+
+The variable name is in this case assigned to the last token in each of
+the branches.
+
+Automatic assignment of variable names works by applying the following
+rules:
+
+- manual names always have priority
+- a "[no]" at the beginning receives "no" as varname on the "no" token
+- VARIABLE tokens whose text is not "WORD" or "NAME" receive a cleaned
+ lowercase version of the token text as varname, e.g. "ROUTE-MAP"
+ becomes "route\_map".
+- other variable tokens (i.e. everything except "fixed") receive the
+ text of the preceding fixed token as varname, if one can be found.
+ E.g.: "ip route A.B.C.D/M INTERFACE" assigns "route" to the
+ "A.B.C.D/M" token.
+
+These rules should make it possible to avoid manual varname assignment
+in 90% of the cases.
+
+DEFPY
+-----
+
+``DEFPY(...)`` is an enhanced version of ``DEFUN()`` which is
+preprocessed by ``python/clidef.py``. The python script parses the
+command definition string, extracts variable names and types, and
+generates a C wrapper function that parses the variables and passes them
+on. This means that in the CLI function body, you will receive
+additional parameters with appropriate types.
+
+This is best explained by an example:
+
+::
+
+ DEFPY(func, func_cmd, "[no] foo bar A.B.C.D (0-99)$num", "...help...")
+
+ =>
+
+ func(self, vty, argc, argv, /* standard CLI arguments */
+
+ const char *no, /* unparsed "no" */
+ struct in_addr bar, /* parsed IP address */
+ const char *bar_str, /* unparsed IP address */
+ long num, /* parsed num */
+ const char *num_str) /* unparsed num */
+
+Note that as documented in the previous section, "bar" is automatically
+applied as variable name for "A.B.C.D". The python code then detects
+this is an IP address argument and generates code to parse it into a
+``struct in_addr``, passing it in ``bar``. The raw value is passed in
+``bar_str``. The range/number argument works in the same way with the
+explicitly given variable name.
+
+Type rules
+~~~~~~~~~~
+
++------------------------------+----------------------------------+----------------------------+
+| Token(s) | Type | Value if omitted by user |
++==============================+==================================+============================+
+| ``A.B.C.D`` | ``struct in_addr`` | 0.0.0.0 |
++------------------------------+----------------------------------+----------------------------+
+| ``X:X::X:X`` | ``struct in6_addr`` | :: |
++------------------------------+----------------------------------+----------------------------+
+| ``A.B.C.D + X:X::X:X`` | ``const union sockunion *`` | NULL |
++------------------------------+----------------------------------+----------------------------+
+| ``A.B.C.D/M`` | ``const struct prefix_ipv4 *`` | NULL |
++------------------------------+----------------------------------+----------------------------+
+| ``X:X::X:X/M`` | ``const struct prefix_ipv6 *`` | NULL |
++------------------------------+----------------------------------+----------------------------+
+| ``A.B.C.D/M + X:X::X:X/M`` | ``const struct prefix *`` | NULL |
++------------------------------+----------------------------------+----------------------------+
+| ``(0-9)`` | ``long`` | 0 |
++------------------------------+----------------------------------+----------------------------+
+| ``VARIABLE`` | ``const char *`` | NULL |
++------------------------------+----------------------------------+----------------------------+
+| ``word`` | ``const char *`` | NULL |
++------------------------------+----------------------------------+----------------------------+
+| *all other* | ``const char *`` | NULL |
++------------------------------+----------------------------------+----------------------------+
+
+Note the following details:
+
+- not all parameters are pointers, some are passed as values.
+- when the type is not ``const char *``, there will be an extra
+ ``_str`` argument with type ``const char *``.
+- you can give a variable name not only to ``VARIABLE`` tokens but also
+ to ``word`` tokens (e.g. constant words). This is useful if some
+ parts of a command are optional. The type will be ``const char *``.
+- ``[no]`` will be passed as ``const char *no``.
+- pointers will be NULL when the argument is optional and the user did
+ not use it.
+- if a parameter is not a pointer, but is optional and the user didn't
+ use it, the default value will be passed. Check the ``_str`` argument
+ if you need to determine whether the parameter was omitted.
+- if the definition contains multiple parameters with the same variable
+ name, they will be collapsed into a single function parameter. The
+ python code will detect if the types are compatible (i.e. IPv4 + IPv6
+ variantes) and choose a corresponding C type.
+- the standard DEFUN parameters (self, vty, argc, argv) are still
+ present and can be used. A DEFUN can simply be **edited into a DEFPY
+ without further changes and it will still work**; this allows easy
+ forward migration.
+- a file may contain both DEFUN and DEFPY statements.
+
+Getting a parameter dump
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The clidef.py script can be called to get a list of DEFUNs/DEFPYs with
+the parameter name/type list:
+
+::
+
+ lib/clippy python/clidef.py --all-defun --show lib/plist.c > /dev/null
+
+The generated code is printed to stdout, the info dump to stderr. The
+``--all-defun`` argument will make it process DEFUN blocks as well as
+DEFPYs, which is useful prior to converting some DEFUNs. **The dump does
+not list the ``_str`` arguments** to keep the output shorter.
+
+Note that the clidef.py script cannot be run with python directly, it
+needs to be run with *clippy* since the latter makes the CLI parser
+available.
+
+Include & Makefile requirements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A source file that uses DEFPY needs to include the ``_clippy.c`` file
+**before all DEFPY statements**:
+
+::
+
+ /* GPL header */
+ #include ...
+
+ ...
+
+ #include "daemon/filename_clippy.c"
+
+ DEFPY(...)
+ DEFPY(...)
+
+ install_element(...)
+
+This dependency needs to be marked in Makefile.am: (there is no ordering
+requirement)
+
+::
+
+ include ../common.am
+
+ # ...
+
+ # if linked into a LTLIBRARY (.la/.so):
+ filename.lo: filename_clippy.c
+
+ # if linked into an executable or static library (.a):
+ filename.o: filename_clippy.c
+
+Doc Strings
+-----------
+
+Each token in a command definition should be documented with a brief doc
+string that informs a user of the meaning and/or purpose of the
+subsequent command tree. These strings are provided as the last
+parameter to DEFUN macros, concatenated together and separated by an
+escaped newline (':raw-latex:`\n`'). These are best explained by
+example.
+
+::
+
+ DEFUN (config_terminal,
+ config_terminal_cmd,
+ "configure terminal",
+ "Configuration from vty interface\n"
+ "Configuration terminal\n")
+
+The last parameter is split into two lines for readability. Two newline
+delimited doc strings are present, one for each token in the command.
+The second string documents the functionality of the 'terminal' command
+in the 'configure' tree.
+
+Note that the first string, for 'configure' does not contain
+documentation for 'terminal'. This is because the CLI is best envisioned
+as a tree, with tokens defining branches. An imaginary 'start' token is
+the root of every command in a CLI node. Each subsequent written token
+descends into a subtree, so the documentation for that token ideally
+summarizes all the functionality contained in the subtree.
+
+A consequence of this structure is that the developer must be careful to
+use the same doc strings when defining multiple commands that are part
+of the same tree. Commands which share prefixes must share the same doc
+strings for those prefixes. On startup the parser will generate warnings
+if it notices inconsistent doc strings. Behavior is undefined; the same
+token may show up twice in completions, with different doc strings, or
+it may show up once with a random doc string. Parser warnings should be
+heeded and fixed to avoid confusing users.
+
+The number of doc strings provided must be equal to the amount of tokens
+present in the command definition, read left to right, ignoring any
+special constructs.
+
+In the examples below, each arrowed token needs a doc string.
+
+::
+
+ "show ip bgp"
+ ^ ^ ^
+
+ "command <foo|bar> [example]"
+ ^ ^ ^ ^
+
+Data Structures
+---------------
+
+On startup, the CLI parser sequentially parses each command string
+definition and constructs a directed graph with each token forming a
+node. This graph is the basis of the entire CLI system. It is used to
+match user input in order to generate command completions and match
+commands to functions.
+
+There is one graph per CLI node (not the same as a graph node in the CLI
+graph). The CLI node struct keeps a reference to its graph (see
+lib/command.h).
+
+While most of the graph maintains the form of a tree, special constructs
+outlined in the Rules section introduce some quirks. <>, [] and {} form
+self-contained 'subgraphs'. Each subgraph is a tree except that all of
+the 'leaves' actually share a child node. This helps with minimizing
+graph size and debugging.
+
+As an example, the subgraph generated by looks like this:
+
+::
+
+ .
+ .
+ |
+ +----+---+
+ +--- -+ FORK +----+
+ | +--------+ |
+ +--v---+ +--v---+
+ | foo | | bar |
+ +--+---+ +--+---+
+ | +------+ |
+ +------> JOIN <-----+
+ +---+--+
+ |
+ .
+ .
+
+FORK and JOIN nodes are plumbing nodes that don't correspond to user
+input. They're necessary in order to deduplicate these constructs where
+applicable.
+
+Options follow the same form, except that there is an edge from the FORK
+node to the JOIN node.
+
+Keywords follow the same form, except that there is an edge from JOIN to
+FORK. Because of this the CLI graph cannot be called acyclic. There is
+special logic in the input matching code that keeps a stack of paths
+already taken through the node in order to disallow following the same
+path more than once.
+
+Variadics are a bit special; they have an edge back to themselves, which
+allows repeating the same input indefinitely.
+
+The leaves of the graph are nodes that have no out edges. These nodes
+are special; their data section does not contain a token, as most nodes
+do, or NULL, as in FORK/JOIN nodes, but instead has a pointer to a
+cmd\_element. All paths through the graph that terminate on a leaf are
+guaranteed to be defined by that command. When a user enters a complete
+command, the command matcher tokenizes the input and executes a DFS on
+the CLI graph. If it is simultaneously able to exhaust all input (one
+input token per graph node), and then find exactly one leaf connected to
+the last node it reaches, then the input has matched the corresponding
+command and the command is executed. If it finds more than one node,
+then the command is ambiguous (more on this in deduplication). If it
+cannot exhaust all input, the command is unknown. If it exhausts all
+input but does not find an edge node, the command is incomplete.
+
+The parser uses an incremental strategy to build the CLI graph for a
+node. Each command is parsed into its own graph, and then this graph is
+merged into the overall graph. During this merge step, the parser makes
+a best-effort attempt to remove duplicate nodes. If it finds a node in
+the overall graph that is equal to a node in the corresponding position
+in the command graph, it will intelligently merge the properties from
+the node in the command graph into the already-existing node. Subgraphs
+are also checked for isomorphism and merged where possible. The
+definition of whether two nodes are 'equal' is based on the equality of
+some set of token properties; read the parser source for the most
+up-to-date definition of equality.
+
+When the parser is unable to deduplicate some complicated constructs,
+this can result in two identical paths through separate parts of the
+graph. If this occurs and the user enters input that matches these
+paths, they will receive an 'ambiguous command' error and will be unable
+to execute the command. Most of the time the parser can detect and warn
+about duplicate commands, but it will not always be able to do this.
+Hence care should be taken before defining a new command to ensure it is
+not defined elsewhere.
+
+Command handlers
+----------------
+
+The block that follows a CLI definition is executed when a user enters
+input that matches the definition. Its function signature looks like
+this:
+
+int (*func) (const struct cmd\_element *, struct vty *, int, struct
+cmd\_token *\ []);
+
+The first argument is the command definition struct. The last argument
+is an ordered array of tokens that correspond to the path taken through
+the graph, and the argument just prior to that is the length of the
+array.
+
+The arrangement of the token array has changed from the prior
+incarnation of the CLI system. In the old system, missing arguments were
+padded with NULLs so that the same parts of a command would show up at
+the same indices regardless of what was entered. The new system does not
+perform such padding and therefore it is generally *incorrect* to assume
+consistent indices in this array. As a simple example:
+
+Command definition:
+
+::
+
+ command [foo] <bar|baz>
+
+User enters:
+
+::
+
+ command foo bar
+
+Array:
+
+::
+
+ [0] -> command
+ [1] -> foo
+ [2] -> bar
+
+User enters:
+
+::
+
+ command baz
+
+Array:
+
+::
+
+ [0] -> command
+ [1] -> baz
+
+Command abbreviation & matching priority
+----------------------------------------
+
+As in the prior implementation, it is possible for users to elide parts
+of tokens when the CLI matcher does not need them to make an unambiguous
+match. This is best explained by example.
+
+Command definitions:
+
+::
+
+ command dog cow
+ command dog crow
+
+User input:
+
+::
+
+ c d c -> ambiguous command
+ c d co -> match "command dog cow"
+
+In the new implementation, this functionality has improved. Where
+previously the parser would stop at the first ambiguous token, it will
+now look ahead and attempt to disambiguate based on tokens later on in
+the input string.
+
+Command definitions:
+
+::
+
+ show ip bgp A.B.C.D
+ show ipv6 bgp X:X::X:X
+
+User enters:
+
+::
+
+ s i b 4.3.2.1 -> match "show ip bgp A.B.C.D"
+ s i b ::e0 -> match "show ipv6 bgp X:X::X:X"
+
+Previously both of these commands would be ambiguous since 'i' does not
+explicitly select either 'ip' or 'ipv6'. However, since the user later
+provides a token that matches only one of the commands (an IPv4 or IPv6
+address) the parser is able to look ahead and select the appropriate
+command. This has some implications for parsing the argv\*[] that is
+passed to the command handler.
+
+Now consider a command definition such as:
+
+::
+
+ command <foo|VAR>
+
+'foo' only matches the string 'foo', but 'VAR' matches any input,
+including 'foo'. Who wins? In situations like this the matcher will
+always choose the 'better' match, so 'foo' will win.
+
+Consider also:
+
+::
+
+ show <ip|ipv6> foo
+
+User input:
+
+::
+
+ show ip foo
+
+'ip' partially matches 'ipv6' but exactly matches 'ip', so 'ip' will
+win.
+
+struct cmd\_token
+-----------------
+
+::
+
+ /* Command token struct. */
+ struct cmd_token
+ {
+ enum cmd_token_type type; // token type
+ u_char attr; // token attributes
+ bool allowrepeat; // matcher allowed to match token repetitively?
+
+ char *text; // token text
+ char *desc; // token description
+ long long min, max; // for ranges
+ char *arg; // user input that matches this token
+ char *varname; // variable name
+ };
+
+This struct is used in the CLI graph to match input against. It is also
+used to pass user input to command handler functions, as it is
+frequently useful for handlers to have access to that information. When
+a command is matched, the sequence of cmd\_tokens that form the matching
+path are duplicated and placed in order into argv\*[]. Before this
+happens the ->arg field is set to point at the snippet of user input
+that matched it.
+
+For most nontrivial commands the handler function will need to determine
+which of the possible matching inputs was entered. Previously this was
+done by looking at the first few characters of input. This is now
+considered an anti-pattern and should be avoided. Instead, the ->type or
+->text fields for this logic. The ->type field can be used when the
+possible inputs differ in type. When the possible types are the same,
+use the ->text field. This field has the full text of the corresponding
+token in the definition string and using it makes for much more readable
+code. An example is helpful.
+
+Command definition:
+
+::
+
+ command <(1-10)|foo|BAR>
+
+In this example, the user may enter any one of: \* an integer between 1
+and 10 \* "foo" \* anything at all
+
+If the user enters "command f", then:
+
+::
+
+ argv[1]->type == WORD_TKN
+ argv[1]->arg == "f"
+ argv[1]->text == "foo"
+
+Range tokens have some special treatment; a token with ->type ==
+RANGE\_TKN will have the ->min and ->max fields set to the bounding
+values of the range.
+
+Permutations
+------------
+
+Finally, it is sometimes useful to check all the possible combinations
+of input that would match an arbitrary definition string. There is a
+tool in tools/ called 'permutations' that reads CLI definition strings
+on stdin and prints out all matching input permutations. It also dumps a
+text representation of the graph, which is more useful for debugging
+than anything else. It looks like this:
+
+::
+
+ $ ./permutations "show [ip] bgp [<view|vrf> WORD]"
+
+ show ip bgp view WORD
+ show ip bgp vrf WORD
+ show ip bgp
+ show bgp view WORD
+ show bgp vrf WORD
+ show bgp
+
+This functionality is also built into VTY/VTYSH; the 'list permutations'
+command will list all possible matching input permutations in the
+current CLI node.
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# FRR documentation build configuration file, created by
+# sphinx-quickstart on Tue Jan 31 16:00:52 2017.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+import re
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = ['sphinx.ext.todo']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'FRR'
+copyright = u'2017, FRR'
+author = u'FRR'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+
+# The short X.Y version.
+version = u'?.?'
+# The full version, including alpha/beta/rc tags.
+release = u'?.?-?'
+
+val = re.compile('^S\["([^"]+)"\]="(.*)"$')
+with open('../../config.status', 'r') as cfgstatus:
+ for ln in cfgstatus.readlines():
+ m = val.match(ln)
+ if m is None: continue
+ if m.group(1) == 'PACKAGE_VERSION':
+ release = m.group(2)
+ version = release.split('-')[0]
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = True
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'sphinx_rtd_theme'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
+# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
+#html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# Now only 'ja' uses this config value
+#html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#html_search_scorer = 'scorer.js'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'FRRdoc'
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+
+# Latex figure (float) alignment
+#'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ (master_doc, 'FRR.tex', u'FRR Developer\'s Documentation',
+ u'FRR', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (master_doc, 'frr', u'FRR Developer\'s Documentation',
+ [author], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (master_doc, 'FRR', u'FRR Developer\'s Documentation',
+ author, 'FRR', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
--- /dev/null
+Module and Hook support (developer docs)
+========================================
+
+What it does
+------------
+
+It uses ``dlopen()`` to load DSOs at startup.
+
+Limitations
+-----------
+
+- can't load, unload, or reload during runtime. This just needs some
+ work and can probably be done in the future.
+- doesn't fix any of the "things need to be changed in the code in the
+ library" issues. Most prominently, you can't add a CLI node because
+ CLI nodes are listed in the library...
+- if your module crashes, the daemon crashes. Should be obvious.
+- **does not provide a stable API or ABI**. Your module must match a
+ version of FRR and you may have to update it frequently to match
+ changes.
+- **does not create a license boundary**. Your module will need to link
+ libzebra and include header files from the daemons, meaning it will
+ be GPL-encumbered.
+
+Installation
+------------
+
+Look for ``moduledir`` in ``configure.ac``, default is normally
+``/usr/lib64/frr/modules`` but depends on ``--libdir`` / ``--prefix``.
+
+The daemon's name is prepended when looking for a module, e.g. "snmp"
+tries to find "zebra\_snmp" first when used in zebra. This is just to
+make it nicer for the user, with the snmp module having the same name
+everywhere.
+
+Modules can be packaged separately from FRR. The SNMP and FPM modules
+are good candidates for this because they have dependencies (net-snmp /
+protobuf) that are not FRR dependencies. However, any distro packages
+should have an "exact-match" dependency onto the FRR package. Using a
+module from a different FRR version will probably blow up nicely.
+
+For snapcraft (and during development), modules can be loaded with full
+path (e.g. -M ``$SNAP/lib/frr/modules/zebra_snmp.so``). Note that
+libtool puts output files in the .libs directory, so during development
+you have to use ``./zebra -M .libs/zebra_snmp.so``.
+
+Creating a module
+-----------------
+
+... best to look at the existing SNMP or FPM modules.
+
+Basic boilerplate:
+
+::
+
+ #include "hook.h"
+ #include "module.h"
+
+ static int
+ module_init (void)
+ {
+ hook_register(frr_late_init, module_late_init);
+ return 0;
+ }
+
+ FRR_MODULE_SETUP(
+ .name = "my module",
+ .version = "0.0",
+ .description = "my module",
+ .init = module_init,
+ )
+
+The ``frr_late_init`` hook will be called after the daemon has finished
+its other startup and is about to enter the main event loop; this is the
+best place for most initialisation.
+
+Compiler & Linker magic
+-----------------------
+
+There's a ``THIS_MODULE`` (like in the Linux kernel), which uses
+``visibility`` attributes to restrict it to the current module. If you
+get a linker error with ``_frrmod_this_module``, there is some linker
+SNAFU. This shouldn't be possible, though one way to get it would be to
+not include libzebra (which provides a fallback definition for the
+symbol).
+
+libzebra and the daemons each have their own ``THIS_MODULE``, as do all
+loadable modules. In any other libraries (e.g. ``libfrrsnmp``),
+``THIS_MODULE`` will use the definition in libzebra; same applies if the
+main executable doesn't use ``FRR_DAEMON_INFO`` (e.g. all testcases).
+
+The deciding factor here is "what dynamic linker unit are you using the
+symbol from." If you're in a library function and want to know who
+called you, you can't use ``THIS_MODULE`` (because that'll just tell you
+you're in the library). Put a macro around your function that adds
+``THIS_MODULE`` in the *caller's code calling your function*.
+
+The idea is to use this in the future for module unloading. Hooks
+already remember which module they were installed by, as groundwork for
+a function that removes all of a module's installed hooks.
+
+There's also the ``frr_module`` symbol in modules, pretty much a
+standard entry point for loadable modules.
+
+Hooks
+-----
+
+Hooks are just points in the code where you can register your callback
+to be called. The parameter list is specific to the hook point. Since
+there is no stable API, the hook code has some extra type safety checks
+making sure you get a compiler warning when the hook parameter list
+doesn't match your callback. Don't ignore these warnings.
+
+Relation to MTYPE macros
+------------------------
+
+The MTYPE macros, while primarily designed to decouple MTYPEs from the
+library and beautify the code, also work very nicely with loadable
+modules -- both constructors and destructors are executed when
+loading/unloading modules.
+
+This means there is absolutely no change required to MTYPEs, you can
+just use them in a module and they will even clean up themselves when we
+implement module unloading and an unload happens. In fact, it's
+impossible to create a bug where unloading fails to de-register a MTYPE.
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ viewBox="52 37 349.25195 651.46875"
+ width="349.25195"
+ height="651.46875"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="git_branches.svg">
+ <metadata
+ id="metadata376">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs374" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1596"
+ inkscape:window-height="848"
+ id="namedview372"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="0.89517435"
+ inkscape:cx="53.149337"
+ inkscape:cy="353.95197"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <g
+ id="g12"
+ transform="translate(-3.09375,-3.7812531)">
+ <path
+ d="M 216,98.125 216,684"
+ id="path14"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000100;stroke-width:8" />
+ <path
+ d="M 205,99.5 216,72 227,99.5"
+ id="path16"
+ inkscape:connector-curvature="0"
+ style="fill:#000100" />
+ <path
+ d="M 225.625,692.25 216,684 l -9.625,8.25 0,-30.25 9.625,-8.25 9.625,8.25"
+ id="path18"
+ inkscape:connector-curvature="0"
+ style="fill:#000100" />
+ </g>
+ <path
+ d="m 212.90625,644.21875 -72,-36"
+ id="path20"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 212.90625,428.21875 -72,-36"
+ id="path22"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <text
+ font-weight="bold"
+ font-size="12"
+ xml:space="preserve"
+ id="text30"
+ style="font-weight:bold;font-size:12px;font-family:Helvetica;text-anchor:middle;fill:#ff0000"
+ x="143.89426"
+ y="427.82574"><tspan
+ id="tspan32">1.0</tspan><tspan
+ x="143.89426"
+ y="443.82574"
+ id="tspan34">Release</tspan><tspan
+ x="143.89426"
+ y="459.82574"
+ id="tspan36">Branch</tspan></text>
+ <path
+ d="m 213.73825,392.21875 -72.832,-36"
+ id="path42"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 212.73825,356.21875 -71.832,-36"
+ id="path44"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 220.90625,644.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path46"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,464.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path48"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,428.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path50"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,608.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path52"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,140.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path54"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,356.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path58"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,392.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path60"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <text
+ font-weight="bold"
+ font-size="12"
+ xml:space="preserve"
+ id="text62"
+ style="font-weight:bold;font-size:12px;font-family:Helvetica;text-anchor:middle;fill:#000100"
+ x="213.21825"
+ y="45.748047"><tspan
+ id="tspan64">Master</tspan><tspan
+ x="213.21825"
+ y="61.748047"
+ id="tspan66">(Stable)</tspan></text>
+ <g
+ id="g82"
+ transform="translate(-3.09375,-3.7812531)">
+ <path
+ d="m 144.832,612 0,-117.875"
+ id="path84"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 133.832,495.5 11,-27.5 11,27.5"
+ id="path86"
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000" />
+ </g>
+ <g
+ id="g88"
+ transform="translate(-3.09375,-3.7812531)">
+ <path
+ d="m 144.832,396 0,-189.875"
+ id="path90"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 133.832,207.5 11,-27.5 11,27.5"
+ id="path92"
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000" />
+ </g>
+ <text
+ font-weight="bold"
+ font-size="12"
+ xml:space="preserve"
+ id="text94"
+ style="font-weight:bold;font-size:12px;font-family:Helvetica;text-anchor:middle;fill:#ff0000"
+ x="143.89426"
+ y="138.82574"><tspan
+ id="tspan96">1.1</tspan><tspan
+ x="143.89426"
+ y="154.82574"
+ id="tspan98">Release</tspan><tspan
+ x="143.89426"
+ y="170.82574"
+ id="tspan100">Branch</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text102"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"
+ x="51.90625"
+ y="611.97876"><tspan
+ id="tspan104">Version 1.</tspan><tspan
+ id="tspan106">0.a1</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text108"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"
+ x="52.679649"
+ y="395.97876"><tspan
+ id="tspan110">Version 1.1.a1</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text112"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"
+ x="51.90625"
+ y="359.97876"><tspan
+ id="tspan114">Version 1.1.a2</tspan></text>
+ <path
+ d="m 148.90625,608.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path116"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 148.90625,392.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path118"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 148.90625,356.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path120"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 148.90625,320.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path122"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text124"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"
+ x="52.679649"
+ y="323.97876"><tspan
+ id="tspan126">Version 1.</tspan><tspan
+ id="tspan128">1.b1</tspan></text>
+ <g
+ id="g156"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,540 -127.375,0"
+ id="path158"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,547 -17.5,-7 17.5,-7"
+ id="path160"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g162"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,504 -127.375,0"
+ id="path164"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,511 -17.5,-7 17.5,-7"
+ id="path166"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g168"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,468 -127.375,0"
+ id="path170"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,475 -17.5,-7 17.5,-7"
+ id="path172"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g174"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,432 -127.375,0"
+ id="path176"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,439 -17.5,-7 17.5,-7"
+ id="path178"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g180"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,396 -127.375,0"
+ id="path182"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,403 -17.5,-7 17.5,-7"
+ id="path184"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g186"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,360 -127.375,0"
+ id="path188"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,367 -17.5,-7 17.5,-7"
+ id="path190"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g192"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,324 -127.375,0"
+ id="path194"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,331 -17.5,-7 17.5,-7"
+ id="path196"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g198"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,288 -127.375,0"
+ id="path200"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,295 -17.5,-7 17.5,-7"
+ id="path202"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g204"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,252 -127.375,0"
+ id="path206"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,259 -17.5,-7 17.5,-7"
+ id="path208"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g210"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,216 -127.375,0"
+ id="path212"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,223 -17.5,-7 17.5,-7"
+ id="path214"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g216"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 404,180 -99.375,0"
+ id="path218"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,187 -17.5,-7 17.5,-7"
+ id="path220"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g222"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,180 -127.375,0"
+ id="path224"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,187 -17.5,-7 17.5,-7"
+ id="path226"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g228"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,144 -127.375,0"
+ id="path230"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,151 -17.5,-7 17.5,-7"
+ id="path232"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text234"
+ x="256.90625"
+ y="531.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan236">Patch Email (Patchwork)</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text238"
+ x="256.90625"
+ y="495.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan240">Github Pull Request</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text242"
+ x="256.90625"
+ y="459.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan244">Github Pull Request</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text246"
+ x="256.90625"
+ y="423.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan248">Patch Email (Patchwork)</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text250"
+ x="256.90625"
+ y="387.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan252">Patch Email (Patchwork)</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text254"
+ x="256.90625"
+ y="351.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan256">Github Pull Request</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text258"
+ x="256.90625"
+ y="315.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan260">Github Pull Request</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text262"
+ x="256.90625"
+ y="279.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan264">Github Pull Request</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text266"
+ x="256.90625"
+ y="243.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan268">Patch Email (Patchwork)</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text270"
+ x="256.90625"
+ y="207.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan272">Github Pull Request</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text274"
+ x="256.90625"
+ y="171.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan276">Github Pull Request</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text278"
+ x="256.90625"
+ y="135.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan280">Github Pull Request</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text282"
+ x="256.90625"
+ y="603.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan284">Github Pull Request</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text286"
+ x="256.90625"
+ y="567.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan288">Github Pull Request</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text290"
+ x="256.90625"
+ y="567.21875"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"><tspan
+ id="tspan292">Github Pull Request</tspan></text>
+ <g
+ id="g294"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,612 -127.72,0"
+ id="path296"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.155,619 -17.5,-7 17.5,-7"
+ id="path298"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <g
+ id="g300"
+ transform="translate(-67.09375,-3.7812531)">
+ <path
+ d="m 432,576 -127.375,0"
+ id="path302"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#666666;stroke-width:4" />
+ <path
+ d="m 305.5,583 -17.5,-7 17.5,-7"
+ id="path304"
+ inkscape:connector-curvature="0"
+ style="fill:#666666" />
+ </g>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text306"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"
+ x="52.90625"
+ y="577.21875"><tspan
+ id="tspan308">Version 1.</tspan><tspan
+ id="tspan310">0.a2</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text312"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"
+ x="52.90625"
+ y="541.21875"><tspan
+ id="tspan314">Version 1.</tspan><tspan
+ id="tspan316">0.b1</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text318"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"
+ x="52.90625"
+ y="505.21875"><tspan
+ id="tspan320">Version 1.</tspan><tspan
+ id="tspan322">0.0</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text324"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"
+ x="52.679649"
+ y="288.97876"><tspan
+ id="tspan326">Version 1.1.0</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text328"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"
+ x="51.90625"
+ y="252.97874"><tspan
+ id="tspan330">Version 1.1.1</tspan></text>
+ <text
+ font-size="12"
+ xml:space="preserve"
+ id="text332"
+ style="font-size:12px;font-family:Helvetica;fill:#000100"
+ x="52.679649"
+ y="216.97874"><tspan
+ id="tspan334">Version 1.</tspan><tspan
+ id="tspan336">1.2</tspan></text>
+ <path
+ d="m 212.90625,608.21875 -72,-36"
+ id="path338"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 212.90625,572.21875 -72,-36"
+ id="path340"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 212.90625,536.21875 -72,-36"
+ id="path342"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 212.90625,320.21875 -72,-36"
+ id="path344"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 212.90625,284.21875 -72,-36"
+ id="path346"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 212.90625,248.21875 -72,-36"
+ id="path348"
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ff0000;stroke-width:8" />
+ <path
+ d="m 148.90625,571.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path350"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 148.90625,535.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path352"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 148.90625,499.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path354"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 148.90625,284.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path356"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 148.90625,248.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path358"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 148.90625,212.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path360"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,572.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path362"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,536.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path364"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,320.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path366"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,248.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path368"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+ <path
+ d="m 220.90625,284.21875 c 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8 4.418,0 8,3.582 8,8 z"
+ id="path370"
+ inkscape:connector-curvature="0"
+ style="fill:#fffffe;stroke:#000100" />
+</svg>
--- /dev/null
+.. highlight:: c
+
+Hooks
+=====
+
+Libfrr provides type-safe subscribable hook points where other pieces of
+code can add one or more callback functions. "type-safe" in this case
+applies to the function pointers used for subscriptions. The
+implementations checks (at compile-time) wheter a callback to be added has
+the appropriate function signature (parameters) for the hook.
+
+Example:
+
+.. code-block:: c
+ :caption: mydaemon.h
+
+ #include "hook.h"
+ DECLARE_HOOK(some_update_event, (struct eventinfo *info), (info))
+
+.. code-block:: c
+ :caption: mydaemon.c
+
+ #include "mydaemon.h"
+ DEFINE_HOOK(some_update_event, (struct eventinfo *info), (info))
+ ...
+ hook_call(some_update_event, info);
+
+.. code-block:: c
+ :caption: mymodule.c
+
+ #include "mydaemon.h"
+ static int event_handler(struct eventinfo *info);
+ ...
+ hook_register(some_update_event, event_handler);
+
+Do not use parameter names starting with "hook", these can collide with
+names used by the hook code itself.
+
+
+Return values
+-------------
+
+Callbacks to be placed on hooks always return "int" for now; hook_call will
+sum up the return values from each called function. (The default is 0 if no
+callbacks are registered.)
+
+There are no pre-defined semantics for the value, in most cases it is
+ignored. For success/failure indication, 0 should be success, and
+handlers should make sure to only return 0 or 1 (not -1 or other values).
+
+There is no built-in way to abort executing a chain after a failure of one
+of the callbacks. If this is needed, the hook can use an extra
+``bool *aborted`` argument.
+
+
+Priorities
+----------
+
+Hooks support a "priority" value for ordering registered calls
+relative to each other. The priority is a signed integer where lower
+values are called earlier. There are also "Koohs", which is hooks with
+reverse priority ordering (for cleanup/deinit hooks, so you can use the
+same priority value).
+
+Recommended priority value ranges are:
+
+======================== ===================================================
+Range Usage
+------------------------ ---------------------------------------------------
+ -999 ... 0 ... 999 main executable / daemon, or library
+
+-1999 ... -1000 modules registering calls that should run before
+ the daemon's bits
+
+1000 ... 1999 modules' calls that should run after daemon's
+ (includes default value: 1000)
+======================== ===================================================
+
+Note: the default value is 1000, based on the following 2 expectations:
+
+- most hook_register() usage will be in loadable modules
+- usage of hook_register() in the daemon itself may need relative ordering
+ to itself, making an explicit value the expected case
+
+The priority value is passed as extra argument on hook_register_prio() /
+hook_register_arg_prio(). Whether a hook runs in reverse is determined
+solely by the code defining / calling the hook. (DECLARE_KOOH is actually
+the same thing as DECLARE_HOOK, it's just there to make it obvious.)
+
+
+Definition
+----------
+
+.. c:macro:: DECLARE_HOOK(name, arglist, passlist)
+.. c:macro:: DECLARE_KOOH(name, arglist, passlist)
+
+ :param name: Name of the hook to be defined
+ :param arglist: Function definition style parameter list in braces.
+ :param passlist: List of the same parameters without their types.
+
+ Note: the second and third macro args must be the hook function's
+ parameter list, with the same names for each parameter. The second
+ macro arg is with types (used for defining things), the third arg is
+ just the names (used for passing along parameters).
+
+ This macro must be placed in a header file; this header file must be
+ included to register a callback on the hook.
+
+ Examples:
+
+ .. code-block:: c
+
+ DECLARE_HOOK(foo, (), ())
+ DECLARE_HOOK(bar, (int arg), (arg))
+ DECLARE_HOOK(baz, (const void *x, in_addr_t y), (x, y))
+
+.. c:macro:: DEFINE_HOOK(name, arglist, passlist)
+
+ Implements an hook. Each ``DECLARE_HOOK`` must have be accompanied by
+ exactly one ``DEFINE_HOOK``, which needs to be placed in a source file.
+ **The hook can only be called from this source file.** This is intentional
+ to avoid overloading and/or misusing hooks for distinct purposes.
+
+ The compiled source file will include a global symbol with the name of the
+ hook prefixed by `_hook_`. Trying to register a callback for a hook that
+ doesn't exist will therefore result in a linker error, or a module
+ load-time error for dynamic modules.
+
+.. c:macro:: DEFINE_KOOH(name, arglist, passlist)
+
+ Same as ``DEFINE_HOOK``, but the sense of priorities / order of callbacks
+ is reversed. This should be used for cleanup hooks.
+
+.. c:function:: int hook_call(name, ...)
+
+ Calls the specified named hook. Parameters to the hook are passed right
+ after the hook name, e.g.:
+
+ .. code-block:: c
+
+ hook_call(foo);
+ hook_call(bar, 0);
+ hook_call(baz, NULL, INADDR_ANY);
+
+ Returns the sum of return values from all callbacks. The ``DEFINE_HOOK``
+ statement for the hook must be placed in the file before any ``hook_call``
+ use of the hook.
+
+
+Callback registration
+---------------------
+
+.. c:function:: void hook_register(name, int (*callback)(...))
+.. c:function:: void hook_register_prio(name, int priority, int (*callback)(...))
+.. c:function:: void hook_register_arg(name, int (*callback)(void *arg, ...), void *arg)
+.. c:function:: void hook_register_arg_prio(name, int priority, int (*callback)(void *arg, ...), void *arg)
+
+ Register a callback with an hook. If the caller needs to pass an extra
+ argument to the callback, the _arg variant can be used and the extra
+ parameter will be passed as first argument to the callback. There is no
+ typechecking for this argument.
+
+ The priority value is used as described above. The variants without a
+ priority parameter use 1000 as priority value.
+
+.. c:function:: void hook_unregister(name, int (*callback)(...))
+.. c:function:: void hook_unregister_arg(name, int (*callback)(void *arg, ...), void *arg)
+
+ Removes a previously registered callback from a hook. Note that there
+ is no _prio variant of these calls. The priority value is only used during
+ registration.
--- /dev/null
+Welcome to FRR's documentation!
+===============================
+
+.. toctree::
+ :maxdepth: 2
+
+ workflow
+ library
+ building
+
--- /dev/null
+## Topology
+
+The goal of this test is to verify that the all the basic functionality
+of ldpd is working as expected, be it running on Linux or OpenBSD. In
+addition to that, more advanced features are also tested, like LDP
+sessions over IPv6, MD5 authentication and pseudowire signaling.
+
+In the topology below there are 3 PE routers, 3 CE routers and one P
+router (not attached to any consumer site).
+
+All routers have IPv4 addresses and OSPF is used as the IGP. The
+three routers from the bottom of the picture, P, PE2 and PE3, are also
+configured for IPv6 (dual-stack) and static IPv6 routes are used to
+provide connectivity among them.
+
+The three CEs share the same VPLS membership. LDP is used to set up the
+LSPs among the PEs and to signal the pseudowires. MD5 authentication is
+used to protect all LDP sessions.
+
+```
+ CE1 172.16.1.1/24
+ +
+ |
+ +---+---+
+ | PE1 |
+ | IOS XE|
+ | |
+ +---+---+
+ |
+ | 10.0.1.0/24
+ |
+ +---+---+
+ | P |
+ +------+ IOS XR+------+
+ | | | |
+ | +-------+ |
+ 10.0.2.0/24 | | 10.0.3.0/24
+2001:db8:2::/64 | | 2001:db8:3::/64
+ | |
+ +---+---+ +---+---+
+ | PE2 | | PE3 |
+ |OpenBSD+-------------+ Linux |
+ | | | |
+ +---+---+ 10.0.4.0/24 +---+---+
+ | 2001:db8:4::/64 |
+ + +
+ 172.16.1.2/24 CE2 CE3 172.16.1.3/24
+```
+
+## Configuration
+
+#### Linux
+1 - Enable IPv4/v6 forwarding:
+```
+# sysctl -w net.ipv4.ip_forward=1
+# sysctl -w net.ipv6.conf.all.forwarding=1
+```
+
+2 - Enable MPLS forwarding:
+```
+# modprobe mpls-router
+# modprobe mpls-iptunnel
+# echo 100000 > /proc/sys/net/mpls/platform_labels
+# echo 1 > /proc/sys/net/mpls/conf/eth1/input
+# echo 1 > /proc/sys/net/mpls/conf/eth2/input
+```
+
+3 - Set up the interfaces:
+```
+# ip link add name lo1 type dummy
+# ip link set dev lo1 up
+# ip addr add 4.4.4.4/32 dev lo1
+# ip -6 addr add 4:4:4::4/128 dev lo1
+# ip link set dev eth1 up
+# ip addr add 10.0.4.4/24 dev eth1
+# ip -6 addr add 2001:db8:4::4/64 dev eth1
+# ip link set dev eth2 up
+# ip addr add 10.0.3.4/24 dev eth2
+# ip -6 addr add 2001:db8:3::4/64 dev eth2
+```
+
+4 - Set up the bridge and pseudowire interfaces:
+```
+# ip link add type bridge
+# ip link set dev bridge0 up
+# ip link set dev eth0 up
+# ip link set dev eth0 master bridge0
+# ip link add name mpw0 type dummy
+# ip link set dev mpw0 up
+# ip link set dev mpw0 master bridge0
+# ip link add name mpw1 type dummy
+# ip link set dev mpw1 up
+# ip link set dev mpw1 master bridge0
+```
+
+> NOTE: MPLS support in the Linux kernel is very recent and it still
+doesn't support pseudowire interfaces. We are using here dummy interfaces
+just to show how the VPLS configuration should look like in the future.
+
+5 - Add static IPv6 routes for the remote loopbacks:
+```
+# ip -6 route add 2:2:2::2/128 via 2001:db8:3::2
+# ip -6 route add 3:3:3::3/128 via 2001:db8:4::3
+```
+
+6 - Edit /etc/frr/ospfd.conf:
+```
+router ospf
+ network 4.4.4.4/32 area 0.0.0.0
+ network 10.0.3.4/24 area 0.0.0.0
+ network 10.0.4.4/24 area 0.0.0.0
+!
+```
+
+7 - Edit /etc/frr/ldpd.conf:
+```
+debug mpls ldp messages recv
+debug mpls ldp messages sent
+debug mpls ldp zebra
+!
+mpls ldp
+ router-id 4.4.4.4
+ dual-stack cisco-interop
+ neighbor 1.1.1.1 password opensourcerouting
+ neighbor 2.2.2.2 password opensourcerouting
+ neighbor 3.3.3.3 password opensourcerouting
+ !
+ address-family ipv4
+ discovery transport-address 4.4.4.4
+ label local advertise explicit-null
+ !
+ interface eth2
+ !
+ interface eth1
+ !
+ !
+ address-family ipv6
+ discovery transport-address 4:4:4::4
+ ttl-security disable
+ !
+ interface eth2
+ !
+ interface eth1
+ !
+ !
+!
+l2vpn ENG type vpls
+ bridge br0
+ member interface eth0
+ !
+ member pseudowire mpw0
+ neighbor lsr-id 1.1.1.1
+ pw-id 100
+ !
+ member pseudowire mpw1
+ neighbor lsr-id 3.3.3.3
+ neighbor address 3:3:3::3
+ pw-id 100
+ !
+!
+```
+
+> NOTE: We have to disable ttl-security under the ipv6 address-family
+in order to interoperate with the IOS-XR router. GTSM is mandatory for
+LDPv6 but the IOS-XR implementation is not RFC compliant in this regard.
+
+8 - Run zebra, ospfd and ldpd.
+
+#### OpenBSD
+1 - Enable IPv4/v6 forwarding:
+```
+# sysctl net.inet.ip.forwarding=1
+# sysctl net.inet6.ip6.forwarding=1
+```
+
+2 - Enable MPLS forwarding:
+```
+# ifconfig em2 10.0.2.3/24 mpls
+# ifconfig em3 10.0.4.3/24 mpls
+```
+
+3 - Set up the interfaces:
+```
+# ifconfig lo1 alias 3.3.3.3 netmask 255.255.255.255
+# ifconfig lo1 inet6 3:3:3::3/128
+# ifconfig em2 inet6 2001:db8:2::3/64
+# ifconfig em3 inet6 2001:db8:4::3/64
+```
+
+4 - Set up the bridge and pseudowire interfaces:
+```
+# ifconfig bridge0 create
+# ifconfig bridge0 up
+# ifconfig em1 up
+# ifconfig bridge0 add em1
+# ifconfig mpw0 create
+# ifconfig mpw0 up
+# ifconfig bridge0 add mpw0
+# ifconfig mpw1 create
+# ifconfig mpw1 up
+# ifconfig bridge0 add mpw1
+```
+
+5 - Add static IPv6 routes for the remote loopbacks:
+```
+# route -n add 4:4:4::4/128 2001:db8:4::4
+# route -n add 2:2:2::2/128 2001:db8:2::2
+```
+
+6 - Edit /etc/frr/ospfd.conf:
+```
+router ospf
+ network 10.0.2.3/24 area 0
+ network 10.0.4.3/24 area 0
+ network 3.3.3.3/32 area 0
+!
+```
+
+7 - Edit /etc/frr/ldpd.conf:
+```
+debug mpls ldp messages recv
+debug mpls ldp messages sent
+debug mpls ldp zebra
+!
+mpls ldp
+ router-id 3.3.3.3
+ dual-stack cisco-interop
+ neighbor 1.1.1.1 password opensourcerouting
+ neighbor 2.2.2.2 password opensourcerouting
+ neighbor 4.4.4.4 password opensourcerouting
+ !
+ address-family ipv4
+ discovery transport-address 3.3.3.3
+ label local advertise explicit-null
+ !
+ interface em3
+ !
+ interface em2
+ !
+ !
+ address-family ipv6
+ discovery transport-address 3:3:3::3
+ ttl-security disable
+ !
+ interface em3
+ !
+ interface em2
+ !
+ !
+!
+l2vpn ENG type vpls
+ bridge br0
+ member interface em1
+ !
+ member pseudowire mpw0
+ neighbor lsr-id 1.1.1.1
+ pw-id 100
+ !
+ member pseudowire mpw1
+ neighbor lsr-id 4.4.4.4
+ neighbor address 4:4:4::4
+ pw-id 100
+ !
+!
+```
+
+8 - Run zebra, ospfd and ldpd.
+
+#### Cisco routers
+CE1 (IOS):
+```
+interface FastEthernet0/0
+ ip address 172.16.1.1 255.255.255.0
+ !
+!
+```
+
+CE2 (IOS):
+```
+interface FastEthernet0/0
+ ip address 172.16.1.2 255.255.255.0
+ !
+!
+```
+
+CE3 (IOS):
+```
+interface FastEthernet0/0
+ ip address 172.16.1.3 255.255.255.0
+ !
+!
+```
+
+PE1 - IOS-XE (1):
+```
+mpls ldp neighbor 2.2.2.2 password opensourcerouting
+mpls ldp neighbor 3.3.3.3 password opensourcerouting
+mpls ldp neighbor 4.4.4.4 password opensourcerouting
+!
+l2vpn vfi context VFI
+ vpn id 1
+ member pseudowire2
+ member pseudowire1
+!
+bridge-domain 1
+ member GigabitEthernet1 service-instance 1
+ member vfi VFI
+!
+interface Loopback1
+ ip address 1.1.1.1 255.255.255.255
+!
+interface pseudowire1
+ encapsulation mpls
+ neighbor 3.3.3.3 100
+!
+interface pseudowire2
+ encapsulation mpls
+ neighbor 4.4.4.4 100
+!
+interface GigabitEthernet3
+ ip address 10.0.1.1 255.255.255.0
+ mpls ip
+!
+router ospf 1
+ network 0.0.0.0 255.255.255.255 area 0
+!
+```
+
+P - IOS-XR (2):
+```
+interface Loopback1
+ ipv4 address 2.2.2.2 255.255.255.255
+ ipv6 address 2:2:2::2/128
+!
+interface GigabitEthernet0/0/0/0
+ ipv4 address 10.0.1.2 255.255.255.0
+!
+interface GigabitEthernet0/0/0/1
+ ipv4 address 10.0.2.2 255.255.255.0
+ ipv6 address 2001:db8:2::2/64
+ ipv6 enable
+!
+interface GigabitEthernet0/0/0/2
+ ipv4 address 10.0.3.2 255.255.255.0
+ ipv6 address 2001:db8:3::2/64
+ ipv6 enable
+!
+router static
+ address-family ipv6 unicast
+ 3:3:3::3/128 2001:db8:2::3
+ 4:4:4::4/128 2001:db8:3::4
+ !
+!
+router ospf 1
+ router-id 2.2.2.2
+ address-family ipv4 unicast
+ area 0
+ interface Loopback1
+ !
+ interface GigabitEthernet0/0/0/0
+ !
+ interface GigabitEthernet0/0/0/1
+ !
+ interface GigabitEthernet0/0/0/2
+ !
+ !
+!
+mpls ldp
+ router-id 2.2.2.2
+ neighbor
+ 1.1.1.1:0 password clear opensourcerouting
+ 3.3.3.3:0 password clear opensourcerouting
+ 4.4.4.4:0 password clear opensourcerouting
+ !
+ address-family ipv4
+ !
+ address-family ipv6
+ discovery transport-address 2:2:2::2
+ !
+ interface GigabitEthernet0/0/0/0
+ address-family ipv4
+ !
+ !
+ interface GigabitEthernet0/0/0/1
+ address-family ipv4
+ !
+ address-family ipv6
+ !
+ !
+ interface GigabitEthernet0/0/0/2
+ address-family ipv4
+ !
+ address-family ipv6
+ !
+ !
+!
+```
+
+## Verification - Control Plane
+
+Using the CLI on the Linux box, the goal is to ensure that everything
+is working as expected.
+
+First, verify that all the required adjacencies and neighborships sessions
+were established:
+
+```
+linux# show mpls ldp discovery
+Local LDP Identifier: 4.4.4.4:0
+Discovery Sources:
+ Interfaces:
+ eth1: xmit/recv
+ LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
+ Hold time: 15 sec
+ LDP Id: 3.3.3.3:0, Transport address: 3:3:3::3
+ Hold time: 15 sec
+ eth2: xmit/recv
+ LDP Id: 2.2.2.2:0, Transport address: 2.2.2.2
+ Hold time: 15 sec
+ LDP Id: 2.2.2.2:0, Transport address: 2:2:2::2
+ Hold time: 15 sec
+ Targeted Hellos:
+ 4.4.4.4 -> 1.1.1.1: xmit/recv
+ LDP Id: 1.1.1.1:0, Transport address: 1.1.1.1
+ Hold time: 45 sec
+ 4:4:4::4 -> 3:3:3::3: xmit/recv
+ LDP Id: 3.3.3.3:0, Transport address: 3:3:3::3
+ Hold time: 45 sec
+
+linux# show mpls ldp neighbor
+Peer LDP Identifier: 1.1.1.1:0
+ TCP connection: 4.4.4.4:40921 - 1.1.1.1:646
+ Session Holdtime: 180 sec
+ State: OPERATIONAL; Downstream-Unsolicited
+ Up time: 00:06:02
+ LDP Discovery Sources:
+ IPv4:
+ Targeted Hello: 1.1.1.1
+
+Peer LDP Identifier: 2.2.2.2:0
+ TCP connection: 4:4:4::4:52286 - 2:2:2::2:646
+ Session Holdtime: 180 sec
+ State: OPERATIONAL; Downstream-Unsolicited
+ Up time: 00:06:02
+ LDP Discovery Sources:
+ IPv4:
+ Interface: eth2
+ IPv6:
+ Interface: eth2
+
+Peer LDP Identifier: 3.3.3.3:0
+ TCP connection: 4:4:4::4:60575 - 3:3:3::3:646
+ Session Holdtime: 180 sec
+ State: OPERATIONAL; Downstream-Unsolicited
+ Up time: 00:05:57
+ LDP Discovery Sources:
+ IPv4:
+ Interface: eth1
+ IPv6:
+ Targeted Hello: 3:3:3::3
+ Interface: eth1
+```
+
+Note that the neighborships with the P and PE2 routers were established
+over IPv6, since this is the default behavior for dual-stack LSRs, as
+specified in RFC 7552. If desired, the **dual-stack transport-connection
+prefer ipv4** command can be used to establish these sessions over IPv4
+(the command should be applied an all routers).
+
+Now, verify that there's a remote label for each PE address:
+```
+linux# show mpls ldp binding
+1.1.1.1/32
+ Local binding: label: 20
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 1.1.1.1 imp-null
+ 2.2.2.2 24000
+ 3.3.3.3 20
+2.2.2.2/32
+ Local binding: label: 21
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 1.1.1.1 18
+ 2.2.2.2 imp-null
+ 3.3.3.3 21
+3.3.3.3/32
+ Local binding: label: 22
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 1.1.1.1 21
+ 2.2.2.2 24003
+ 3.3.3.3 imp-null
+4.4.4.4/32
+ Local binding: label: imp-null
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 1.1.1.1 22
+ 2.2.2.2 24001
+ 3.3.3.3 22
+10.0.1.0/24
+ Local binding: label: 23
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 1.1.1.1 imp-null
+ 2.2.2.2 imp-null
+ 3.3.3.3 23
+10.0.2.0/24
+ Local binding: label: 24
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 1.1.1.1 20
+ 2.2.2.2 imp-null
+ 3.3.3.3 imp-null
+10.0.3.0/24
+ Local binding: label: imp-null
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 1.1.1.1 19
+ 2.2.2.2 imp-null
+ 3.3.3.3 24
+10.0.4.0/24
+ Local binding: label: imp-null
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 1.1.1.1 23
+ 2.2.2.2 24002
+ 3.3.3.3 imp-null
+2:2:2::2/128
+ Local binding: label: 18
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 2.2.2.2 imp-null
+ 3.3.3.3 18
+3:3:3::3/128
+ Local binding: label: 19
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 2.2.2.2 24007
+4:4:4::4/128
+ Local binding: label: imp-null
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 2.2.2.2 24006
+ 3.3.3.3 19
+2001:db8:2::/64
+ Local binding: label: -
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 2.2.2.2 imp-null
+ 3.3.3.3 imp-null
+2001:db8:3::/64
+ Local binding: label: imp-null
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 2.2.2.2 imp-null
+2001:db8:4::/64
+ Local binding: label: imp-null
+ Remote bindings:
+ Peer Label
+ ----------------- ---------
+ 3.3.3.3 imp-null
+```
+
+Check if the pseudowires are up:
+```
+linux# show l2vpn atom vc
+Interface Peer ID VC ID Name Status
+--------- --------------- ---------- ---------------- ----------
+mpw1 3.3.3.3 100 ENG UP
+mpw0 1.1.1.1 100 ENG UP
+```
+
+Check the label bindings of the pseudowires:
+```
+linux# show l2vpn atom binding
+ Destination Address: 1.1.1.1, VC ID: 100
+ Local Label: 25
+ Cbit: 1, VC Type: Ethernet, GroupID: 0
+ MTU: 1500
+ Remote Label: 16
+ Cbit: 1, VC Type: Ethernet, GroupID: 0
+ MTU: 1500
+ Destination Address: 3.3.3.3, VC ID: 100
+ Local Label: 26
+ Cbit: 1, VC Type: Ethernet, GroupID: 0
+ MTU: 1500
+ Remote Label: 26
+ Cbit: 1, VC Type: Ethernet, GroupID: 0
+ MTU: 1500
+```
+
+## Verification - Data Plane
+
+Verify that all the exchanged label mappings were installed in zebra:
+```
+linux# show mpls table
+ Inbound Outbound
+ Label Type Nexthop Label
+-------- ------- --------------- --------
+ 17 LDP 2001:db8:3::2 3
+ 19 LDP 2001:db8:3::2 24005
+ 20 LDP 10.0.3.2 24000
+ 21 LDP 10.0.3.2 3
+ 22 LDP 10.0.3.2 24001
+ 23 LDP 10.0.3.2 3
+ 24 LDP 10.0.3.2 3
+ 25 LDP 10.0.3.2 3
+
+linux# show ip route ldp
+Codes: K - kernel route, C - connected, S - static, R - RIP,
+ O - OSPF, I - IS-IS, B - BGP, P - PIM, A - Babel, L - LDP,
+ > - selected route, * - FIB route
+
+L>* 1.1.1.1/32 [0/0] via 10.0.3.2, eth2 label 24000
+L>* 3.3.3.3/32 [0/0] via 10.0.3.2, eth2 label 24001
+```
+
+Verify that all the exchanged label mappings were installed in the kernel:
+```
+$ ip -M ro
+17 via inet6 2001:db8:3::2 dev eth2 proto zebra
+19 as to 24005 via inet6 2001:db8:3::2 dev eth2 proto zebra
+20 as to 24000 via inet 10.0.3.2 dev eth2 proto zebra
+21 via inet 10.0.3.2 dev eth2 proto zebra
+22 as to 24001 via inet 10.0.3.2 dev eth2 proto zebra
+23 via inet 10.0.3.2 dev eth2 proto zebra
+24 via inet 10.0.3.2 dev eth2 proto zebra
+25 via inet 10.0.3.2 dev eth2 proto zebra
+$
+$ ip route | grep mpls
+1.1.1.1 encap mpls 24000 via 10.0.3.2 dev eth2 proto zebra metric 20
+3.3.3.3 encap mpls 24001 via 10.0.3.2 dev eth2 proto zebra metric 20
+```
+
+Now ping PE1's loopback using lo1's address as a source address:
+```
+$ ping -c 5 -I 4.4.4.4 1.1.1.1
+PING 1.1.1.1 (1.1.1.1) from 4.4.4.4 : 56(84) bytes of data.
+64 bytes from 1.1.1.1: icmp_seq=1 ttl=253 time=3.02 ms
+64 bytes from 1.1.1.1: icmp_seq=2 ttl=253 time=3.13 ms
+64 bytes from 1.1.1.1: icmp_seq=3 ttl=253 time=3.19 ms
+64 bytes from 1.1.1.1: icmp_seq=4 ttl=253 time=3.07 ms
+64 bytes from 1.1.1.1: icmp_seq=5 ttl=253 time=3.27 ms
+
+--- 1.1.1.1 ping statistics ---
+5 packets transmitted, 5 received, 0% packet loss, time 4005ms
+rtt min/avg/max/mdev = 3.022/3.140/3.278/0.096 ms
+```
+
+Verify that the ICMP echo request packets are leaving with the MPLS
+label advertised by the P router. Also, verify that the ICMP echo reply
+packets are arriving with an explicit-null MPLS label:
+```
+# tcpdump -n -i eth2 mpls and icmp
+tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
+listening on eth2, link-type EN10MB (Ethernet), capture size 262144 bytes
+10:01:40.758771 MPLS (label 24000, exp 0, [S], ttl 64) IP 4.4.4.4 > 1.1.1.1: ICMP echo request, id 13370, seq 1, length 64
+10:01:40.761777 MPLS (label 0, exp 0, [S], ttl 254) IP 1.1.1.1 > 4.4.4.4: ICMP echo reply, id 13370, seq 1, length 64
+10:01:41.760343 MPLS (label 24000, exp 0, [S], ttl 64) IP 4.4.4.4 > 1.1.1.1: ICMP echo request, id 13370, seq 2, length 64
+10:01:41.763448 MPLS (label 0, exp 0, [S], ttl 254) IP 1.1.1.1 > 4.4.4.4: ICMP echo reply, id 13370, seq 2, length 64
+10:01:42.761758 MPLS (label 24000, exp 0, [S], ttl 64) IP 4.4.4.4 > 1.1.1.1: ICMP echo request, id 13370, seq 3, length 64
+10:01:42.764924 MPLS (label 0, exp 0, [S], ttl 254) IP 1.1.1.1 > 4.4.4.4: ICMP echo reply, id 13370, seq 3, length 64
+10:01:43.763193 MPLS (label 24000, exp 0, [S], ttl 64) IP 4.4.4.4 > 1.1.1.1: ICMP echo request, id 13370, seq 4, length 64
+10:01:43.766237 MPLS (label 0, exp 0, [S], ttl 254) IP 1.1.1.1 > 4.4.4.4: ICMP echo reply, id 13370, seq 4, length 64
+10:01:44.764552 MPLS (label 24000, exp 0, [S], ttl 64) IP 4.4.4.4 > 1.1.1.1: ICMP echo request, id 13370, seq 5, length 64
+10:01:44.767803 MPLS (label 0, exp 0, [S], ttl 254) IP 1.1.1.1 > 4.4.4.4: ICMP echo reply, id 13370, seq 5, length 64
+```
--- /dev/null
+libfrr library facilities
+=========================
+
+.. toctree::
+ :maxdepth: 2
+
+ memtypes
+ hooks
+ cli
+ dev-modules
+
+
--- /dev/null
+.. highlight:: c
+
+Memtypes
+========
+
+FRR includes wrappers arround ``malloc()`` and ``free()`` that count the number
+of objects currently allocated, for each of a defined ``MTYPE``.
+
+To this extent, there are `memory groups` and `memory types`. Each memory
+type must belong to a memory group, this is used just to provide some basic
+structure.
+
+Example:
+
+.. code-block:: c
+ :caption: mydaemon.h
+
+ DECLARE_MGROUP(MYDAEMON)
+ DECLARE_MTYPE(MYNEIGHBOR)
+
+.. code-block:: c
+ :caption: mydaemon.c
+
+ DEFINE_MGROUP( MYDAEMON, "My daemon's memory")
+ DEFINE_MTYPE( MYDAEMON, MYNEIGHBOR, "Neighbor entry")
+ DEFINE_MTYPE_STATIC(MYDAEMON, MYNEIGHBORNAME, "Neighbor name")
+
+ struct neigh *neighbor_new(const char *name)
+ {
+ struct neigh *n = XMALLOC(MYNEIGHBOR, sizeof(*n));
+ n->name = XSTRDUP(MYNEIGHBORNAME, name);
+ return n;
+ }
+
+ void neighbor_free(struct neigh *n)
+ {
+ XFREE(MYNEIGHBORNAME, n->name);
+ XFREE(MYNEIGHBOR, n);
+ }
+
+
+Definition
+----------
+
+.. c:macro:: DECLARE_MGROUP(name)
+
+ This macro forward-declares a memory group and should be placed in a
+ ``.h`` file. It expands to an ``extern struct memgroup`` statement.
+
+.. c:macro:: DEFINE_MGROUP(mname, description)
+
+ Defines/implements a memory group. Must be placed into exactly one ``.c``
+ file (multiple inclusion will result in a link-time symbol conflict).
+
+ Contains additional logic (constructor and destructor) to register the
+ memory group in a global list.
+
+.. c:macro:: DECLARE_MTYPE(name)
+
+ Forward-declares a memory type and makes ``MTYPE_name`` available for use.
+ Note that the ``MTYPE_`` prefix must not be included in the name, it is
+ automatically prefixed.
+
+ ``MTYPE_name`` is created as a `static const` symbol, i.e. a compile-time
+ constant. It refers to an ``extern struct memtype _mt_name``, where `name`
+ is replaced with the actual name.
+
+.. c:macro:: DEFINE_MTYPE(group, name, description)
+
+ Define/implement a memory type, must be placed into exactly one ``.c``
+ file (multiple inclusion will result in a link-time symbol conflict).
+
+ Like ``DEFINE_MGROUP``, this contains actual code to register the MTYPE
+ under its group.
+
+.. c:macro:: DEFINE_MTYPE_STATIC(group, name, description)
+
+ Same as ``DEFINE_MTYPE``, but the ``DEFINE_MTYPE_STATIC`` variant places
+ the C ``static`` keyword on the definition, restricting the MTYPE's
+ availability to the current source file. This should be appropriate in
+ >80% of cases.
+
+ .. todo::
+
+ Daemons currently have ``daemon_memory.[ch]`` files listing all of
+ their MTYPEs. This is not how it should be, most of these types
+ should be moved into the appropriate files where they are used.
+ Only a few MTYPEs should remain non-static after that.
+
+
+Usage
+-----
+
+.. c:function:: void *XMALLOC(struct memtype *mtype, size_t size)
+
+.. c:function:: void *XCALLOC(struct memtype *mtype, size_t size)
+
+.. c:function:: void *XSTRDUP(struct memtype *mtype, size_t size)
+
+ Allocation wrappers for malloc/calloc/realloc/strdup, taking an extra
+ mtype parameter.
+
+.. c:function:: void *XREALLOC(struct memtype *mtype, void *ptr, size_t size)
+
+ Wrapper around realloc() with MTYPE tracking. Note that ``ptr`` may
+ be NULL, in which case the function does the same as XMALLOC (regardless
+ of whether the system realloc() supports this.)
+
+.. c:function:: void XFREE(struct memtype *mtype, void *ptr)
+
+ Wrapper around free(), again taking an extra mtype parameter. This is
+ actually a macro, with the following additional properties:
+
+ - the macro contains ``ptr = NULL``
+ - if ptr is NULL, no operation is performed (as is guaranteed by system
+ implementations.) Do not surround XFREE with ``if (ptr != NULL)``
+ checks.
--- /dev/null
+0. Introduction
+
+This is the design specification for next hop tracking feature in
+Frr.
+
+1. Background
+
+Recursive routes are of the form:
+
+ p/m --> n
+ [Ex: 1.1.0.0/16 --> 2.2.2.2]
+
+where 'n' itself is resolved through another route as follows:
+
+ p2/m --> h, interface
+ [Ex: 2.2.2.0/24 --> 3.3.3.3, eth0]
+
+Usually, BGP routes are recursive in nature and BGP nexthops get
+resolved through an IGP route. IGP usually adds its routes pointing to
+an interface (these are called non-recursive routes).
+
+When BGP receives a recursive route from a peer, it needs to validate
+the nexthop. The path is marked valid or invalid based on the
+reachability status of the nexthop. Nexthop validation is also
+important for BGP decision process as the metric to reach the nexthop
+is a parameter to best path selection process.
+
+As it goes with routing, this is a dynamic process. Route to the
+nexthop can change. The nexthop can become unreachable or
+reachable. In the current BGP implementation, the nexthop validation
+is done periodically in the scanner run. The default scanner run
+interval is one minute. Every minute, the scanner task walks the
+entire BGP table. It checks the validity of each nexthop with Zebra
+(the routing table manager) through a request and response message
+exchange between BGP and Zebra process. BGP process is blocked for
+that duration. The mechanism has two major drawbacks:
+
+(1) The scanner task runs to completion. That can potentially starve
+ the other tasks for long periods of time, based on the BGP table
+ size and number of nexthops.
+
+(2) Convergence around routing changes that affect the nexthops can be
+ long (around a minute with the default intervals). The interval
+ can be shortened to achieve faster reaction time, but it makes the
+ first problem worse, with the scanner task consuming most of the
+ CPU resources.
+
+"Next hop tracking" feature makes this process event-driven. It
+eliminates periodic nexthop validation and introduces an asynchronous
+communication path between BGP and Zebra for route change notifications
+that can then be acted upon.
+
+2. Goal
+
+Stating the obvious, the main goal is to remove the two limitations we
+discussed in the previous section. The goals, in a constructive tone,
+are the following:
+
+- fairness: the scanner run should not consume an unjustly high amount
+ of CPU time. This should give an overall good performance and
+ response time to other events (route changes, session events,
+ IO/user interface).
+
+- convergence: BGP must react to nexthop changes instantly and provide
+ sub-second convergence. This may involve diverting the routes from
+ one nexthop to another.
+
+3. Overview of the changes
+
+The changes are in both BGP and Zebra modules. The short summary is
+the following:
+
+- Zebra implements a registration mechanism by which clients can
+ register for next hop notification. Consequently, it maintains a
+ separate table, per (VRF, AF) pair, of next hops and interested
+ client-list per next hop.
+
+- When the main routing table changes in Zebra, it evaluates the next
+ hop table: for each next hop, it checks if the route table
+ modifications have changed its state. If so, it notifies the
+ interested clients.
+
+- BGP is one such client. It registers the next hops corresponding to
+ all of its received routes/paths. It also threads the paths against
+ each nexthop structure.
+
+- When BGP receives a next hop notification from Zebra, it walks the
+ corresponding path list. It makes them valid or invalid depending
+ on the next hop notification. It then re-computes best path for the
+ corresponding destination. This may result in re-announcing those
+ destinations to peers.
+
+4. Design
+
+4.1. Modules
+
+The core design introduces an "nht" (next hop tracking) module in BGP
+and "rnh" (recursive nexthop) module in Zebra. The "nht" module
+provides the following APIs:
+
+bgp_find_or_add_nexthop() : find or add a nexthop in BGP nexthop table
+bgp_find_nexthop() : find a nexthop in BGP nexthop table
+bgp_parse_nexthop_update() : parse a nexthop update message coming
+ from zebra
+
+The "rnh" module provides the following APIs:
+
+zebra_add_rnh() : add a recursive nexthop
+zebra_delete_rnh() : delete a recursive nexthop
+zebra_lookup_rnh() : lookup a recursive nexthop
+
+zebra_add_rnh_client() : register a client for nexthop notifications
+ against a recursive nexthop
+
+zebra_remove_rnh_client(): remove the client registration for a
+ recursive nexthop
+
+zebra_evaluate_rnh_table(): (re)evaluate the recursive nexthop table
+ (most probably because the main routing
+ table has changed).
+
+zebra_cleanup_rnh_client(): Cleanup a client from the "rnh" module
+ data structures (most probably because the
+ client is going away).
+
+4.2. Control flow
+
+The next hop registration control flow is the following:
+
+<==== BGP Process ====>|<==== Zebra Process ====>
+ |
+receive module nht module | zserv module rnh module
+----------------------------------------------------------------------
+ | | |
+bgp_update_ | | |
+ main() | bgp_find_or_add_ | |
+ | nexthop() | |
+ | | |
+ | | zserv_nexthop_ |
+ | | register() |
+ | | | zebra_add_rnh()
+ | | |
+
+
+The next hop notification control flow is the following:
+
+<==== Zebra Process ====>|<==== BGP Process ====>
+ |
+rib module rnh module | zebra module nht module
+----------------------------------------------------------------------
+ | | |
+meta_queue_ | | |
+ process() | zebra_evaluate_ | |
+ | rnh_table() | |
+ | | |
+ | | bgp_read_nexthop_ |
+ | | update() |
+ | | | bgp_parse_
+ | | | nexthop_update()
+ | | |
+
+
+4.3. zclient message format
+
+ZEBRA_NEXTHOP_REGISTER and ZEBRA_NEXTHOP_UNREGISTER messages are
+encoded in the following way:
+
+/*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | AF | prefix len |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * . Nexthop prefix .
+ * . .
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * . .
+ * . .
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | AF | prefix len |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * . Nexthop prefix .
+ * . .
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+ZEBRA_NEXTHOP_UPDATE message is encoded as follows:
+
+/*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | AF | prefix len |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * . Nexthop prefix getting resolved .
+ * . .
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | metric |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | #nexthops |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | nexthop type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * . resolving Nexthop details .
+ * . .
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * . .
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | nexthop type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * . resolving Nexthop details .
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+4.4. BGP data structure
+
+Legend:
+
+/\ struct bgp_node: a BGP destination/route/prefix
+\/
+
+[ ] struct bgp_info: a BGP path (e.g. route received from a peer)
+
+ _
+(_) struct bgp_nexthop_cache: a BGP nexthop
+
+
+
+ /\ NULL
+ \/--+ ^
+ | :
+ +--[ ]--[ ]--[ ]--> NULL
+ /\ :
+ \/--+ :
+ | :
+ +--[ ]--[ ]--> NULL
+ :
+ _ :
+ (_).............
+
+
+4.5. Zebra data structure
+
+rnh table:
+
+ O
+ / \
+ O O
+ / \
+ O O
+
+ struct rnh
+ {
+ u_char flags;
+ struct route_entry *state;
+ struct list *client_list;
+ struct route_node *node;
+ };
+
+5. User interface changes
+
+frr# show ip nht
+3.3.3.3
+ resolved via kernel
+ via 11.0.0.6, swp1
+ Client list: bgp(fd 12)
+11.0.0.10
+ resolved via connected
+ is directly connected, swp2
+ Client list: bgp(fd 12)
+11.0.0.18
+ resolved via connected
+ is directly connected, swp4
+ Client list: bgp(fd 12)
+11.11.11.11
+ resolved via kernel
+ via 10.0.1.2, eth0
+ Client list: bgp(fd 12)
+
+frr# show ip bgp nexthop
+Current BGP nexthop cache:
+ 3.3.3.3 valid [IGP metric 0], #paths 3
+ Last update: Wed Oct 16 04:43:49 2013
+
+ 11.0.0.10 valid [IGP metric 1], #paths 1
+ Last update: Wed Oct 16 04:43:51 2013
+
+ 11.0.0.18 valid [IGP metric 1], #paths 2
+ Last update: Wed Oct 16 04:43:47 2013
+
+ 11.11.11.11 valid [IGP metric 0], #paths 1
+ Last update: Wed Oct 16 04:43:47 2013
+
+frr# show ipv6 nht
+frr# show ip bgp nexthop detail
+
+frr# debug bgp nht
+frr# debug zebra nht
+
+6. Sample test cases
+
+ r2----r3
+ / \ /
+ r1----r4
+
+- Verify that a change in IGP cost triggers NHT
+ + shutdown the r1-r4 and r2-r4 links
+ + no shut the r1-r4 and r2-r4 links and wait for OSPF to come back
+ up
+ + We should be back to the original nexthop via r4 now
+- Verify that a NH becoming unreachable triggers NHT
+ + Shutdown all links to r4
+- Verify that a NH becoming reachable triggers NHT
+ + no shut all links to r4
+
+7. Future work
+
+- route-policy for next hop validation (e.g. ignore default route)
+- damping for rapid next hop changes
+- prioritized handling of nexthop changes ((un)reachability vs. metric
+ changes)
+- handling recursion loop, e.g.
+ 11.11.11.11/32 -> 12.12.12.12
+ 12.12.12.12/32 -> 11.11.11.11
+ 11.0.0.0/8 -> <interface>
+- better statistics
--- /dev/null
+Developing for FRRouting
+========================
+
+General note on this document
+-----------------------------
+
+This document is "descriptive/post-factual" in that it documents
+pratices that are in use; it is not "definitive/pre-factual" in
+prescribing practices.
+
+This means that when a procedure changes, it is agreed upon, then put
+into practice, and then documented here. If this document doesn't match
+reality, it's the document that needs to be updated, not reality.
+
+Git Structure
+-------------
+
+The master Git for FRRouting resides on Github at
+`https://github.com/frrouting/frr <https://github.com/FRRouting/frr>`__
+
+.. figure:: git_branches.svg
+ :alt: git branches continually merging to the left from 3 lanes;
+ float-right
+
+ git branches continually merging to the left from 3 lanes;
+ float-right
+
+There is one main branch for development and a release branch for each
+major release.
+
+New contributions are done against the head of the master branch. The CI
+systems will pick up the Github Pull Requests or the new patch from
+Patchwork, run some basic build and functional tests.
+
+For each major release (1.0, 1.1 etc) a new release branch is created
+based on the master.
+
+There was an attempt to use a "develop" branch automatically maintained
+by the CI system. This is not currently in active use, though the system
+is operational. If the "develop" branch is in active use and this
+paragraph is still here, this document obviously wasn't updated.
+
+Programming language, Tools and Libraries
+-----------------------------------------
+
+The core of FRRouting is written in C (gcc or clang supported) and makes
+use of GNU compiler extensions. A few non-essential scripts are
+implemented in Perl and Python. FRRouting requires the following tools
+to build distribution packages: automake, autoconf, texinfo, libtool and
+gawk and various libraries (i.e. libpam and libjson-c).
+
+If your contribution requires a new library or other tool, then please
+highlight this in your description of the change. Also make sure it’s
+supported by all FRRouting platform OSes or provide a way to build
+without the library (potentially without the new feature) on the other
+platforms.
+
+Documentation should be written in Tex (.texi) or Markdown (.md) format
+with a preference for Markdown.
+
+Mailing lists
+-------------
+
+Italicized lists are private.
+
++----------------------------------+--------------------------------+
+| Topic | List |
++==================================+================================+
+| Development | dev@lists.frrouting.org |
++----------------------------------+--------------------------------+
+| Users & Operators | frog@lists.frrouting.org |
++----------------------------------+--------------------------------+
+| Announcements | announce@lists.frrouting.org |
++----------------------------------+--------------------------------+
+| *Security* | security@lists.frrouting.org |
++----------------------------------+--------------------------------+
+| *Technical Steering Committee* | tsc@lists.frrouting.org |
++----------------------------------+--------------------------------+
+
+Changelog
+~~~~~~~~~
+
+The changelog will be the base for the release notes. A changelog entry
+for your changes is usually not required and will be added based on your
+commit messages by the maintainers. However, you are free to include an
+update to the changelog with some better description. The changelog will
+be the base for the release notes.
+
+Submitting Patches and Enhancements
+-----------------------------------
+
+Pre-submission Checklist
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Format code (see `Developer's Guidelines <#developers-guidelines>`__)
+- Verify and acknowledge license (see `License for
+ contributions <#license-for-contributions>`__)
+- Ensure you have properly signed off (see `Signing
+ Off <#signing-off>`__)
+- Test building with various configurations:
+
+ - ``buildtest.sh``
+
+- Verify building source distribution:
+
+ - ``make dist`` (and try rebuilding from the resulting tar file)
+
+- Run unit tests:
+
+ - ``make test``
+
+- Document Regression Runs and plans for continued maintenance of the
+ feature
+
+License for contributions
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+FRRouting is under a “GPLv2 or later” license. Any code submitted must
+be released under the same license (preferred) or any license which
+allows redistribution under this GPLv2 license (eg MIT License).
+
+Signing Off
+~~~~~~~~~~~
+
+Code submitted to FRRouting must be signed off. We have the same
+requirements for using the signed-off-by process as the Linux kernel. In
+short, you must include a signed-off-by tag in every patch.
+
+``Signed-off-by:`` this is a developer's certification that he or she
+has the right to submit the patch for inclusion into the project. It is
+an agreement to the Developer's Certificate of Origin (below). Code
+without a proper signoff can not and will not be merged.
+
+If you are unfamiliar with this process, you should read the `official
+policy at
+kernel.org <https://www.kernel.org/doc/html/latest/process/submitting-patches.html>`__
+and you might find this article about `participating in the Linux
+community on the Linux Foundation
+website <http://www.linuxfoundation.org/content/how-participate-linux-community-0>`__
+to be a helpful resource.
+
+In short, when you sign off on a commit, you assert your agreement to
+all of the following:
+
+ Developer's Certificate of Origin 1.1
+
+ By making a contribution to this project, I certify that:
+
+ (a) The contribution was created in whole or in part by me and I
+ have the right to submit it under the open source license
+ indicated in the file; or
+
+ (b) The contribution is based upon previous work that, to the best
+ of my knowledge, is covered under an appropriate open source
+ license and I have the right under that license to submit that
+ work with modifications, whether created in whole or in part by
+ me, under the same open source license (unless I am permitted to
+ submit under a different license), as indicated in the file; or
+
+ (c) The contribution was provided directly to me by some other
+ person who certified (a), (b) or (c) and I have not modified it.
+
+ (d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
+
+What do I submit my changes against?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We've documented where we would like to have the different fixes applied
+at
+https://github.com/FRRouting/frr/wiki/Where-Do-I-create-a-Pull-Request-against%3F
+If you are unsure where your submission goes, look at that document or
+ask a project maintainer.
+
+Github pull requests
+~~~~~~~~~~~~~~~~~~~~
+
+The preferred method of submitting changes is a Github pull request.
+Code submitted by pull request will be automatically tested by one or
+more CI systems. Once the automated tests succeed, other developers will
+review your code for quality and correctness. After any concerns are
+resolved, your code will be merged into the branch it was submitted
+against.
+
+Patch submission via mailing list
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As an alternative submission method, a patch can be mailed to the
+development mailing list. Patches received on the mailing list will be
+picked up by Patchwork and tested against the latest development branch.
+
+The recommended way to send the patch (or series of NN patches) to the
+list is by using ``git send-email`` as follows (assuming they are the N
+most recent commit(s) in your git history:
+
+::
+
+ git send-email -NN --annotate --to=dev@lists.frrouting.org
+
+If your commits do not already contain a ``Signed-off-by`` line, then
+use the following command to add it (after making sure you agree to the
+Developer Certificate of Origin as outlined above):
+
+::
+
+ git send-email -NN --annotate --signoff --to=dev@lists.frrouting.org
+
+Submitting multi-commit patches as a Github pull request is **strongly
+encouraged** and increases the probability of your patch getting
+reviewed and merged in a timely manner.
+
+After submitting your changes
+-----------------------------
+
+- Watch for Continuous Integration (CI) Test results
+
+ - You should automatically receive an email with the test results
+ within less than 2 hrs of the submission. If you don’t get the
+ email, then check status on the github pull request (if submitted
+ by pull request) or on Patchwork at
+ https://patchwork.frrouting.org (if submitted as patch to mailing
+ list).
+ - Please notify the development mailing list if you think something
+ doesn’t work.
+
+- If the tests failed:
+
+ - In general, expect the community to ignore the submission until
+ the tests pass.
+ - It is up to you to fix and resubmit.
+
+ - This includes fixing existing unit (“make test”) tests if your
+ changes broke or changed them.
+ - It also includes fixing distribution packages for the failing
+ platforms (ie if new libraries are required).
+ - Feel free to ask for help on the development list.
+
+ - Go back to the submission process and repeat until the tests pass.
+
+- If the tests pass:
+
+ - Wait for reviewers. Someone will review your code or be assigned
+ to review your code.
+ - Respond to any comments or concerns the reviewer has.
+ - After all comments and concerns are addressed, expect your patch
+ to be merged.
+
+- Watch out for questions on the mailing list. At this time there will
+ be a manual code review and further (longer) tests by various
+ community members.
+- Your submission is done once it is merged to the master branch.
+
+Developer's Guidelines
+----------------------
+
+Commit messages
+~~~~~~~~~~~~~~~
+
+Commit messages should be formatted in the same way as Linux kernel
+commit messages. The format is roughly
+
+::
+
+ dir: short summary
+
+ extended summary
+
+``dir`` should be the top level source directory under which the change
+was made. For example, a change in bgpd/rfapi would be formatted as:
+
+``bgpd: short summary``
+
+The first line should be no longer than 50 characters. Subsequent lines
+should be wrapped to 72 characters.
+
+Source file header
+~~~~~~~~~~~~~~~~~~
+
+New files need to have a Copyright header (see `License for
+contributions <#license-for-contributions>`__ above) added to the file.
+Preferred form of the header is as follows:
+
+::
+
+ /*
+ * Title/Function of file
+ * Copyright (C) YEAR Author’s Name
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+ #include <zebra.h>
+
+Adding copyright claims to existing files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When adding copyright claims for modifications to an existing file,
+please preface the claim with "Portions: " on a line before it and
+indent the "Copyright ..." string. If such a case already exists, add
+your indented claim immediately after. E.g.:
+
+::
+
+ Portions:
+ Copyright (C) 2010 Entity A ....
+ Copyright (C) 2016 Your name [optional brief change description]
+
+Code formatting
+~~~~~~~~~~~~~~~
+
+FRR uses Linux kernel style except where noted below. Code which does
+not comply with these style guidelines will not be accepted.
+
+To assist with compliance, in the project root there is a .clang-format
+configuration file which can be used with the ``clang-format`` tool from
+the LLVM project. In the ``tools/`` directory there is a Python script
+named ``indent.py`` that wraps clang-format and handles some edge cases
+specific to FRR. If you are submitting a new file, it is recommended to
+run that script over the new file after ensuring that the latest stable
+release of ``clang-format`` is in your PATH.
+
+**Whitespace changes in untouched parts of the code are not acceptable
+in patches that change actual code.** To change/fix formatting issues,
+please create a separate patch that only does formatting changes and
+nothing else.
+
+Style documentation
+^^^^^^^^^^^^^^^^^^^
+
+Kernel and BSD styles are documented externally:
+
+- https://www.kernel.org/doc/html/latest/process/coding-style.html
+- http://man.openbsd.org/style
+
+For GNU coding style, use ``indent`` with the following invocation:
+
+::
+
+ indent -nut -nfc1 file_for_submission.c
+
+Exceptions
+^^^^^^^^^^
+
+FRR project code comes from a variety of sources, so there are some
+stylistic exceptions in place. They are organized here by branch.
+
+**For ``master``:**
+
+BSD coding style applies to:
+
+- ``ldpd/``
+
+``babeld`` uses, approximately, the following style:
+
+- K&R style braces
+- Indents are 4 spaces
+- Function return types are on their own line
+
+**For ``stable/3.0`` and ``stable/2.0``:**
+
+GNU coding style apply to the following parts:
+
+- ``lib/``
+- ``zebra/``
+- ``bgpd/``
+- ``ospfd/``
+- ``ospf6d/``
+- ``isisd/``
+- ``ripd/``
+- ``ripngd/``
+- ``vtysh/``
+
+BSD coding style applies to:
+
+- ``ldpd/``
+
+Documentation
+~~~~~~~~~~~~~
+
+FRRouting is a large and complex software project developed by many
+different people over a long period of time. Without adequate
+documentation, it can be exceedingly difficult to understand code
+segments, APIs and other interfaces. In the interest of keeping the
+project healthy and maintainable, you should make every effort to
+document your code so that other people can understand what it does
+without needing to closely read the code itself.
+
+Some specific guidelines that contributors should follow are:
+
+- Functions exposed in header files should have descriptive comments
+ above their signatures in the header file. At a minimum, a function
+ comment should contain information about the return value,
+ parameters, and a general summary of the function's purpose.
+ Documentation on parameter values can be omitted if it is (very)
+ obvious what they are used for.
+
+Function comments must follow the style for multiline comments laid out
+in the kernel style guide.
+
+Example:
+
+::
+
+ /*
+ * Determines whether or not a string is cool.
+ *
+ * @param text - the string to check for coolness
+ * @param is_clccfc - whether capslock is cruise control for cool
+ * @return 7 if the text is cool, 0 otherwise
+ */
+ int check_coolness(const char *text, bool is_clccfc);
+
+The Javadoc-style annotations are not required, but you should still
+strive to make it equally clear what parameters and return values are
+used for.
+
+- Static functions should have descriptive comments in the same form as
+ above if what they do is not immediately obvious. Use good
+ engineering judgement when deciding whether a comment is necessary.
+ If you are unsure, document your code.
+
+- Global variables, static or not, should have a comment describing
+ their use.
+
+- **For new code in ``lib/``, these guidelines are hard requirements.**
+
+If you are contributing code that adds significant user-visible
+functionality or introduces a new API, please document it in ``doc/``.
+Markdown and LaTeX are acceptable formats, although Markdown is
+currently preferred for new documentation. This may change in the near
+future.
+
+Finally, if you come across some code that is undocumented and feel like
+going above and beyond, document it! We absolutely appreciate and accept
+patches that document previously undocumented code.
+
+Compile-time conditional code
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Many users access FRR via binary packages from 3rd party sources;
+compile-time code puts inclusion/exclusion in the hands of the package
+maintainer. Please think very carefully before making code conditional
+at compile time, as it increases regression testing, maintenance
+burdens, and user confusion. In particular, please avoid gratuitous
+``--enable-…`` switches to the configure script - in general, code
+should be of high quality and in working condition, or it shouldn’t be
+in FRR at all.
+
+When code must be compile-time conditional, try have the compiler make
+it conditional rather than the C pre-processor so that it will still be
+checked by the compiler, even if disabled. For example,
+
+::
+
+ if (SOME_SYMBOL)
+ frobnicate();
+
+is preferred to
+
+::
+
+ #ifdef SOME_SYMBOL
+ frobnicate ();
+ #endif /* SOME_SYMBOL */
+
+Note that the former approach requires ensuring that ``SOME_SYMBOL``
+will be defined (watch your ``AC_DEFINE``\ s).
+
+Debug-guards in code
+~~~~~~~~~~~~~~~~~~~~
+
+Debugging statements are an important methodology to allow developers to
+fix issues found in the code after it has been released. The caveat here
+is that the developer must remember that people will be using the code
+at scale and in ways that can be unexpected for the original
+implementor. As such debugs **MUST** be guarded in such a way that they
+can be turned off. FRR has the ability to turn on/off debugs from the
+CLI and it is expected that the developer will use this convention to
+allow control of their debugs.
+
+CLI changes
+~~~~~~~~~~~
+
+CLI's are a complicated ugly beast. Additions or changes to the CLI
+should use a DEFUN to encapsulate one setting as much as is possible.
+Additionally as new DEFUN's are added to the system, documentation
+should be provided for the new commands.
+
+Backwards Compatibility
+~~~~~~~~~~~~~~~~~~~~~~~
+
+As a general principle, changes to CLI and code in the lib/ directory
+should be made in a backwards compatible fashion. This means that
+changes that are purely stylistic in nature should be avoided, e.g.,
+renaming an existing macro or library function name without any
+functional change. When adding new parameters to common functions, it is
+also good to consider if this too should be done in a backward
+compatible fashion, e.g., by preserving the old form in addition to
+adding the new form.
+
+This is not to say that minor or even major functional changes to CLI
+and common code should be avoided, but rather that the benefit gained
+from a change should be weighed against the added cost/complexity to
+existing code. Also, that when making such changes, it is good to
+preserve compatibility when possible to do so without introducing
+maintenance overhead/cost. It is also important to keep in mind,
+existing code includes code that may reside in private repositories (and
+is yet to be submitted) or code that has yet to be migrated from Quagga
+to FRR.
+
+That said, compatibility measures can (and should) be removed when
+either:
+
+- they become a significant burden, e.g. when data structures change
+ and the compatibility measure would need a complex adaptation layer
+ or becomes flat-out impossible
+- some measure of time (dependent on the specific case) has passed, so
+ that the compatibility grace period is considered expired.
+
+In all cases, compatibility pieces should be marked with
+compiler/preprocessor annotations to print warnings at compile time,
+pointing to the appropriate update path. A ``-Werror`` build should fail
+if compatibility bits are used.
+
+Miscellaneous
+~~~~~~~~~~~~~
+
+When in doubt, follow the guidelines in the Linux kernel style guide, or
+ask on the development mailing list / public Slack instance.
+++ /dev/null
-## Topology
-
-The goal of this test is to verify that the all the basic functionality
-of ldpd is working as expected, be it running on Linux or OpenBSD. In
-addition to that, more advanced features are also tested, like LDP
-sessions over IPv6, MD5 authentication and pseudowire signaling.
-
-In the topology below there are 3 PE routers, 3 CE routers and one P
-router (not attached to any consumer site).
-
-All routers have IPv4 addresses and OSPF is used as the IGP. The
-three routers from the bottom of the picture, P, PE2 and PE3, are also
-configured for IPv6 (dual-stack) and static IPv6 routes are used to
-provide connectivity among them.
-
-The three CEs share the same VPLS membership. LDP is used to set up the
-LSPs among the PEs and to signal the pseudowires. MD5 authentication is
-used to protect all LDP sessions.
-
-```
- CE1 172.16.1.1/24
- +
- |
- +---+---+
- | PE1 |
- | IOS XE|
- | |
- +---+---+
- |
- | 10.0.1.0/24
- |
- +---+---+
- | P |
- +------+ IOS XR+------+
- | | | |
- | +-------+ |
- 10.0.2.0/24 | | 10.0.3.0/24
-2001:db8:2::/64 | | 2001:db8:3::/64
- | |
- +---+---+ +---+---+
- | PE2 | | PE3 |
- |OpenBSD+-------------+ Linux |
- | | | |
- +---+---+ 10.0.4.0/24 +---+---+
- | 2001:db8:4::/64 |
- + +
- 172.16.1.2/24 CE2 CE3 172.16.1.3/24
-```
-
-## Configuration
-
-#### Linux
-1 - Enable IPv4/v6 forwarding:
-```
-# sysctl -w net.ipv4.ip_forward=1
-# sysctl -w net.ipv6.conf.all.forwarding=1
-```
-
-2 - Enable MPLS forwarding:
-```
-# modprobe mpls-router
-# modprobe mpls-iptunnel
-# echo 100000 > /proc/sys/net/mpls/platform_labels
-# echo 1 > /proc/sys/net/mpls/conf/eth1/input
-# echo 1 > /proc/sys/net/mpls/conf/eth2/input
-```
-
-3 - Set up the interfaces:
-```
-# ip link add name lo1 type dummy
-# ip link set dev lo1 up
-# ip addr add 4.4.4.4/32 dev lo1
-# ip -6 addr add 4:4:4::4/128 dev lo1
-# ip link set dev eth1 up
-# ip addr add 10.0.4.4/24 dev eth1
-# ip -6 addr add 2001:db8:4::4/64 dev eth1
-# ip link set dev eth2 up
-# ip addr add 10.0.3.4/24 dev eth2
-# ip -6 addr add 2001:db8:3::4/64 dev eth2
-```
-
-4 - Set up the bridge and pseudowire interfaces:
-```
-# ip link add type bridge
-# ip link set dev bridge0 up
-# ip link set dev eth0 up
-# ip link set dev eth0 master bridge0
-# ip link add name mpw0 type dummy
-# ip link set dev mpw0 up
-# ip link set dev mpw0 master bridge0
-# ip link add name mpw1 type dummy
-# ip link set dev mpw1 up
-# ip link set dev mpw1 master bridge0
-```
-
-> NOTE: MPLS support in the Linux kernel is very recent and it still
-doesn't support pseudowire interfaces. We are using here dummy interfaces
-just to show how the VPLS configuration should look like in the future.
-
-5 - Add static IPv6 routes for the remote loopbacks:
-```
-# ip -6 route add 2:2:2::2/128 via 2001:db8:3::2
-# ip -6 route add 3:3:3::3/128 via 2001:db8:4::3
-```
-
-6 - Edit /etc/frr/ospfd.conf:
-```
-router ospf
- network 4.4.4.4/32 area 0.0.0.0
- network 10.0.3.4/24 area 0.0.0.0
- network 10.0.4.4/24 area 0.0.0.0
-!
-```
-
-7 - Edit /etc/frr/ldpd.conf:
-```
-debug mpls ldp messages recv
-debug mpls ldp messages sent
-debug mpls ldp zebra
-!
-mpls ldp
- router-id 4.4.4.4
- dual-stack cisco-interop
- neighbor 1.1.1.1 password opensourcerouting
- neighbor 2.2.2.2 password opensourcerouting
- neighbor 3.3.3.3 password opensourcerouting
- !
- address-family ipv4
- discovery transport-address 4.4.4.4
- label local advertise explicit-null
- !
- interface eth2
- !
- interface eth1
- !
- !
- address-family ipv6
- discovery transport-address 4:4:4::4
- ttl-security disable
- !
- interface eth2
- !
- interface eth1
- !
- !
-!
-l2vpn ENG type vpls
- bridge br0
- member interface eth0
- !
- member pseudowire mpw0
- neighbor lsr-id 1.1.1.1
- pw-id 100
- !
- member pseudowire mpw1
- neighbor lsr-id 3.3.3.3
- neighbor address 3:3:3::3
- pw-id 100
- !
-!
-```
-
-> NOTE: We have to disable ttl-security under the ipv6 address-family
-in order to interoperate with the IOS-XR router. GTSM is mandatory for
-LDPv6 but the IOS-XR implementation is not RFC compliant in this regard.
-
-8 - Run zebra, ospfd and ldpd.
-
-#### OpenBSD
-1 - Enable IPv4/v6 forwarding:
-```
-# sysctl net.inet.ip.forwarding=1
-# sysctl net.inet6.ip6.forwarding=1
-```
-
-2 - Enable MPLS forwarding:
-```
-# ifconfig em2 10.0.2.3/24 mpls
-# ifconfig em3 10.0.4.3/24 mpls
-```
-
-3 - Set up the interfaces:
-```
-# ifconfig lo1 alias 3.3.3.3 netmask 255.255.255.255
-# ifconfig lo1 inet6 3:3:3::3/128
-# ifconfig em2 inet6 2001:db8:2::3/64
-# ifconfig em3 inet6 2001:db8:4::3/64
-```
-
-4 - Set up the bridge and pseudowire interfaces:
-```
-# ifconfig bridge0 create
-# ifconfig bridge0 up
-# ifconfig em1 up
-# ifconfig bridge0 add em1
-# ifconfig mpw0 create
-# ifconfig mpw0 up
-# ifconfig bridge0 add mpw0
-# ifconfig mpw1 create
-# ifconfig mpw1 up
-# ifconfig bridge0 add mpw1
-```
-
-5 - Add static IPv6 routes for the remote loopbacks:
-```
-# route -n add 4:4:4::4/128 2001:db8:4::4
-# route -n add 2:2:2::2/128 2001:db8:2::2
-```
-
-6 - Edit /etc/frr/ospfd.conf:
-```
-router ospf
- network 10.0.2.3/24 area 0
- network 10.0.4.3/24 area 0
- network 3.3.3.3/32 area 0
-!
-```
-
-7 - Edit /etc/frr/ldpd.conf:
-```
-debug mpls ldp messages recv
-debug mpls ldp messages sent
-debug mpls ldp zebra
-!
-mpls ldp
- router-id 3.3.3.3
- dual-stack cisco-interop
- neighbor 1.1.1.1 password opensourcerouting
- neighbor 2.2.2.2 password opensourcerouting
- neighbor 4.4.4.4 password opensourcerouting
- !
- address-family ipv4
- discovery transport-address 3.3.3.3
- label local advertise explicit-null
- !
- interface em3
- !
- interface em2
- !
- !
- address-family ipv6
- discovery transport-address 3:3:3::3
- ttl-security disable
- !
- interface em3
- !
- interface em2
- !
- !
-!
-l2vpn ENG type vpls
- bridge br0
- member interface em1
- !
- member pseudowire mpw0
- neighbor lsr-id 1.1.1.1
- pw-id 100
- !
- member pseudowire mpw1
- neighbor lsr-id 4.4.4.4
- neighbor address 4:4:4::4
- pw-id 100
- !
-!
-```
-
-8 - Run zebra, ospfd and ldpd.
-
-#### Cisco routers
-CE1 (IOS):
-```
-interface FastEthernet0/0
- ip address 172.16.1.1 255.255.255.0
- !
-!
-```
-
-CE2 (IOS):
-```
-interface FastEthernet0/0
- ip address 172.16.1.2 255.255.255.0
- !
-!
-```
-
-CE3 (IOS):
-```
-interface FastEthernet0/0
- ip address 172.16.1.3 255.255.255.0
- !
-!
-```
-
-PE1 - IOS-XE (1):
-```
-mpls ldp neighbor 2.2.2.2 password opensourcerouting
-mpls ldp neighbor 3.3.3.3 password opensourcerouting
-mpls ldp neighbor 4.4.4.4 password opensourcerouting
-!
-l2vpn vfi context VFI
- vpn id 1
- member pseudowire2
- member pseudowire1
-!
-bridge-domain 1
- member GigabitEthernet1 service-instance 1
- member vfi VFI
-!
-interface Loopback1
- ip address 1.1.1.1 255.255.255.255
-!
-interface pseudowire1
- encapsulation mpls
- neighbor 3.3.3.3 100
-!
-interface pseudowire2
- encapsulation mpls
- neighbor 4.4.4.4 100
-!
-interface GigabitEthernet3
- ip address 10.0.1.1 255.255.255.0
- mpls ip
-!
-router ospf 1
- network 0.0.0.0 255.255.255.255 area 0
-!
-```
-
-P - IOS-XR (2):
-```
-interface Loopback1
- ipv4 address 2.2.2.2 255.255.255.255
- ipv6 address 2:2:2::2/128
-!
-interface GigabitEthernet0/0/0/0
- ipv4 address 10.0.1.2 255.255.255.0
-!
-interface GigabitEthernet0/0/0/1
- ipv4 address 10.0.2.2 255.255.255.0
- ipv6 address 2001:db8:2::2/64
- ipv6 enable
-!
-interface GigabitEthernet0/0/0/2
- ipv4 address 10.0.3.2 255.255.255.0
- ipv6 address 2001:db8:3::2/64
- ipv6 enable
-!
-router static
- address-family ipv6 unicast
- 3:3:3::3/128 2001:db8:2::3
- 4:4:4::4/128 2001:db8:3::4
- !
-!
-router ospf 1
- router-id 2.2.2.2
- address-family ipv4 unicast
- area 0
- interface Loopback1
- !
- interface GigabitEthernet0/0/0/0
- !
- interface GigabitEthernet0/0/0/1
- !
- interface GigabitEthernet0/0/0/2
- !
- !
-!
-mpls ldp
- router-id 2.2.2.2
- neighbor
- 1.1.1.1:0 password clear opensourcerouting
- 3.3.3.3:0 password clear opensourcerouting
- 4.4.4.4:0 password clear opensourcerouting
- !
- address-family ipv4
- !
- address-family ipv6
- discovery transport-address 2:2:2::2
- !
- interface GigabitEthernet0/0/0/0
- address-family ipv4
- !
- !
- interface GigabitEthernet0/0/0/1
- address-family ipv4
- !
- address-family ipv6
- !
- !
- interface GigabitEthernet0/0/0/2
- address-family ipv4
- !
- address-family ipv6
- !
- !
-!
-```
-
-## Verification - Control Plane
-
-Using the CLI on the Linux box, the goal is to ensure that everything
-is working as expected.
-
-First, verify that all the required adjacencies and neighborships sessions
-were established:
-
-```
-linux# show mpls ldp discovery
-Local LDP Identifier: 4.4.4.4:0
-Discovery Sources:
- Interfaces:
- eth1: xmit/recv
- LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
- Hold time: 15 sec
- LDP Id: 3.3.3.3:0, Transport address: 3:3:3::3
- Hold time: 15 sec
- eth2: xmit/recv
- LDP Id: 2.2.2.2:0, Transport address: 2.2.2.2
- Hold time: 15 sec
- LDP Id: 2.2.2.2:0, Transport address: 2:2:2::2
- Hold time: 15 sec
- Targeted Hellos:
- 4.4.4.4 -> 1.1.1.1: xmit/recv
- LDP Id: 1.1.1.1:0, Transport address: 1.1.1.1
- Hold time: 45 sec
- 4:4:4::4 -> 3:3:3::3: xmit/recv
- LDP Id: 3.3.3.3:0, Transport address: 3:3:3::3
- Hold time: 45 sec
-
-linux# show mpls ldp neighbor
-Peer LDP Identifier: 1.1.1.1:0
- TCP connection: 4.4.4.4:40921 - 1.1.1.1:646
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: 00:06:02
- LDP Discovery Sources:
- IPv4:
- Targeted Hello: 1.1.1.1
-
-Peer LDP Identifier: 2.2.2.2:0
- TCP connection: 4:4:4::4:52286 - 2:2:2::2:646
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: 00:06:02
- LDP Discovery Sources:
- IPv4:
- Interface: eth2
- IPv6:
- Interface: eth2
-
-Peer LDP Identifier: 3.3.3.3:0
- TCP connection: 4:4:4::4:60575 - 3:3:3::3:646
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: 00:05:57
- LDP Discovery Sources:
- IPv4:
- Interface: eth1
- IPv6:
- Targeted Hello: 3:3:3::3
- Interface: eth1
-```
-
-Note that the neighborships with the P and PE2 routers were established
-over IPv6, since this is the default behavior for dual-stack LSRs, as
-specified in RFC 7552. If desired, the **dual-stack transport-connection
-prefer ipv4** command can be used to establish these sessions over IPv4
-(the command should be applied an all routers).
-
-Now, verify that there's a remote label for each PE address:
-```
-linux# show mpls ldp binding
-1.1.1.1/32
- Local binding: label: 20
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 imp-null
- 2.2.2.2 24000
- 3.3.3.3 20
-2.2.2.2/32
- Local binding: label: 21
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 18
- 2.2.2.2 imp-null
- 3.3.3.3 21
-3.3.3.3/32
- Local binding: label: 22
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 21
- 2.2.2.2 24003
- 3.3.3.3 imp-null
-4.4.4.4/32
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 22
- 2.2.2.2 24001
- 3.3.3.3 22
-10.0.1.0/24
- Local binding: label: 23
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 imp-null
- 2.2.2.2 imp-null
- 3.3.3.3 23
-10.0.2.0/24
- Local binding: label: 24
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 20
- 2.2.2.2 imp-null
- 3.3.3.3 imp-null
-10.0.3.0/24
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 19
- 2.2.2.2 imp-null
- 3.3.3.3 24
-10.0.4.0/24
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 23
- 2.2.2.2 24002
- 3.3.3.3 imp-null
-2:2:2::2/128
- Local binding: label: 18
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
- 3.3.3.3 18
-3:3:3::3/128
- Local binding: label: 19
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 24007
-4:4:4::4/128
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 24006
- 3.3.3.3 19
-2001:db8:2::/64
- Local binding: label: -
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
- 3.3.3.3 imp-null
-2001:db8:3::/64
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
-2001:db8:4::/64
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 3.3.3.3 imp-null
-```
-
-Check if the pseudowires are up:
-```
-linux# show l2vpn atom vc
-Interface Peer ID VC ID Name Status
---------- --------------- ---------- ---------------- ----------
-mpw1 3.3.3.3 100 ENG UP
-mpw0 1.1.1.1 100 ENG UP
-```
-
-Check the label bindings of the pseudowires:
-```
-linux# show l2vpn atom binding
- Destination Address: 1.1.1.1, VC ID: 100
- Local Label: 25
- Cbit: 1, VC Type: Ethernet, GroupID: 0
- MTU: 1500
- Remote Label: 16
- Cbit: 1, VC Type: Ethernet, GroupID: 0
- MTU: 1500
- Destination Address: 3.3.3.3, VC ID: 100
- Local Label: 26
- Cbit: 1, VC Type: Ethernet, GroupID: 0
- MTU: 1500
- Remote Label: 26
- Cbit: 1, VC Type: Ethernet, GroupID: 0
- MTU: 1500
-```
-
-## Verification - Data Plane
-
-Verify that all the exchanged label mappings were installed in zebra:
-```
-linux# show mpls table
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- 17 LDP 2001:db8:3::2 3
- 19 LDP 2001:db8:3::2 24005
- 20 LDP 10.0.3.2 24000
- 21 LDP 10.0.3.2 3
- 22 LDP 10.0.3.2 24001
- 23 LDP 10.0.3.2 3
- 24 LDP 10.0.3.2 3
- 25 LDP 10.0.3.2 3
-
-linux# show ip route ldp
-Codes: K - kernel route, C - connected, S - static, R - RIP,
- O - OSPF, I - IS-IS, B - BGP, P - PIM, A - Babel, L - LDP,
- > - selected route, * - FIB route
-
-L>* 1.1.1.1/32 [0/0] via 10.0.3.2, eth2 label 24000
-L>* 3.3.3.3/32 [0/0] via 10.0.3.2, eth2 label 24001
-```
-
-Verify that all the exchanged label mappings were installed in the kernel:
-```
-$ ip -M ro
-17 via inet6 2001:db8:3::2 dev eth2 proto zebra
-19 as to 24005 via inet6 2001:db8:3::2 dev eth2 proto zebra
-20 as to 24000 via inet 10.0.3.2 dev eth2 proto zebra
-21 via inet 10.0.3.2 dev eth2 proto zebra
-22 as to 24001 via inet 10.0.3.2 dev eth2 proto zebra
-23 via inet 10.0.3.2 dev eth2 proto zebra
-24 via inet 10.0.3.2 dev eth2 proto zebra
-25 via inet 10.0.3.2 dev eth2 proto zebra
-$
-$ ip route | grep mpls
-1.1.1.1 encap mpls 24000 via 10.0.3.2 dev eth2 proto zebra metric 20
-3.3.3.3 encap mpls 24001 via 10.0.3.2 dev eth2 proto zebra metric 20
-```
-
-Now ping PE1's loopback using lo1's address as a source address:
-```
-$ ping -c 5 -I 4.4.4.4 1.1.1.1
-PING 1.1.1.1 (1.1.1.1) from 4.4.4.4 : 56(84) bytes of data.
-64 bytes from 1.1.1.1: icmp_seq=1 ttl=253 time=3.02 ms
-64 bytes from 1.1.1.1: icmp_seq=2 ttl=253 time=3.13 ms
-64 bytes from 1.1.1.1: icmp_seq=3 ttl=253 time=3.19 ms
-64 bytes from 1.1.1.1: icmp_seq=4 ttl=253 time=3.07 ms
-64 bytes from 1.1.1.1: icmp_seq=5 ttl=253 time=3.27 ms
-
---- 1.1.1.1 ping statistics ---
-5 packets transmitted, 5 received, 0% packet loss, time 4005ms
-rtt min/avg/max/mdev = 3.022/3.140/3.278/0.096 ms
-```
-
-Verify that the ICMP echo request packets are leaving with the MPLS
-label advertised by the P router. Also, verify that the ICMP echo reply
-packets are arriving with an explicit-null MPLS label:
-```
-# tcpdump -n -i eth2 mpls and icmp
-tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
-listening on eth2, link-type EN10MB (Ethernet), capture size 262144 bytes
-10:01:40.758771 MPLS (label 24000, exp 0, [S], ttl 64) IP 4.4.4.4 > 1.1.1.1: ICMP echo request, id 13370, seq 1, length 64
-10:01:40.761777 MPLS (label 0, exp 0, [S], ttl 254) IP 1.1.1.1 > 4.4.4.4: ICMP echo reply, id 13370, seq 1, length 64
-10:01:41.760343 MPLS (label 24000, exp 0, [S], ttl 64) IP 4.4.4.4 > 1.1.1.1: ICMP echo request, id 13370, seq 2, length 64
-10:01:41.763448 MPLS (label 0, exp 0, [S], ttl 254) IP 1.1.1.1 > 4.4.4.4: ICMP echo reply, id 13370, seq 2, length 64
-10:01:42.761758 MPLS (label 24000, exp 0, [S], ttl 64) IP 4.4.4.4 > 1.1.1.1: ICMP echo request, id 13370, seq 3, length 64
-10:01:42.764924 MPLS (label 0, exp 0, [S], ttl 254) IP 1.1.1.1 > 4.4.4.4: ICMP echo reply, id 13370, seq 3, length 64
-10:01:43.763193 MPLS (label 24000, exp 0, [S], ttl 64) IP 4.4.4.4 > 1.1.1.1: ICMP echo request, id 13370, seq 4, length 64
-10:01:43.766237 MPLS (label 0, exp 0, [S], ttl 254) IP 1.1.1.1 > 4.4.4.4: ICMP echo reply, id 13370, seq 4, length 64
-10:01:44.764552 MPLS (label 24000, exp 0, [S], ttl 64) IP 4.4.4.4 > 1.1.1.1: ICMP echo request, id 13370, seq 5, length 64
-10:01:44.767803 MPLS (label 0, exp 0, [S], ttl 254) IP 1.1.1.1 > 4.4.4.4: ICMP echo reply, id 13370, seq 5, length 64
-```
+++ /dev/null
-0. Introduction
-
-This is the design specification for next hop tracking feature in
-Frr.
-
-1. Background
-
-Recursive routes are of the form:
-
- p/m --> n
- [Ex: 1.1.0.0/16 --> 2.2.2.2]
-
-where 'n' itself is resolved through another route as follows:
-
- p2/m --> h, interface
- [Ex: 2.2.2.0/24 --> 3.3.3.3, eth0]
-
-Usually, BGP routes are recursive in nature and BGP nexthops get
-resolved through an IGP route. IGP usually adds its routes pointing to
-an interface (these are called non-recursive routes).
-
-When BGP receives a recursive route from a peer, it needs to validate
-the nexthop. The path is marked valid or invalid based on the
-reachability status of the nexthop. Nexthop validation is also
-important for BGP decision process as the metric to reach the nexthop
-is a parameter to best path selection process.
-
-As it goes with routing, this is a dynamic process. Route to the
-nexthop can change. The nexthop can become unreachable or
-reachable. In the current BGP implementation, the nexthop validation
-is done periodically in the scanner run. The default scanner run
-interval is one minute. Every minute, the scanner task walks the
-entire BGP table. It checks the validity of each nexthop with Zebra
-(the routing table manager) through a request and response message
-exchange between BGP and Zebra process. BGP process is blocked for
-that duration. The mechanism has two major drawbacks:
-
-(1) The scanner task runs to completion. That can potentially starve
- the other tasks for long periods of time, based on the BGP table
- size and number of nexthops.
-
-(2) Convergence around routing changes that affect the nexthops can be
- long (around a minute with the default intervals). The interval
- can be shortened to achieve faster reaction time, but it makes the
- first problem worse, with the scanner task consuming most of the
- CPU resources.
-
-"Next hop tracking" feature makes this process event-driven. It
-eliminates periodic nexthop validation and introduces an asynchronous
-communication path between BGP and Zebra for route change notifications
-that can then be acted upon.
-
-2. Goal
-
-Stating the obvious, the main goal is to remove the two limitations we
-discussed in the previous section. The goals, in a constructive tone,
-are the following:
-
-- fairness: the scanner run should not consume an unjustly high amount
- of CPU time. This should give an overall good performance and
- response time to other events (route changes, session events,
- IO/user interface).
-
-- convergence: BGP must react to nexthop changes instantly and provide
- sub-second convergence. This may involve diverting the routes from
- one nexthop to another.
-
-3. Overview of the changes
-
-The changes are in both BGP and Zebra modules. The short summary is
-the following:
-
-- Zebra implements a registration mechanism by which clients can
- register for next hop notification. Consequently, it maintains a
- separate table, per (VRF, AF) pair, of next hops and interested
- client-list per next hop.
-
-- When the main routing table changes in Zebra, it evaluates the next
- hop table: for each next hop, it checks if the route table
- modifications have changed its state. If so, it notifies the
- interested clients.
-
-- BGP is one such client. It registers the next hops corresponding to
- all of its received routes/paths. It also threads the paths against
- each nexthop structure.
-
-- When BGP receives a next hop notification from Zebra, it walks the
- corresponding path list. It makes them valid or invalid depending
- on the next hop notification. It then re-computes best path for the
- corresponding destination. This may result in re-announcing those
- destinations to peers.
-
-4. Design
-
-4.1. Modules
-
-The core design introduces an "nht" (next hop tracking) module in BGP
-and "rnh" (recursive nexthop) module in Zebra. The "nht" module
-provides the following APIs:
-
-bgp_find_or_add_nexthop() : find or add a nexthop in BGP nexthop table
-bgp_find_nexthop() : find a nexthop in BGP nexthop table
-bgp_parse_nexthop_update() : parse a nexthop update message coming
- from zebra
-
-The "rnh" module provides the following APIs:
-
-zebra_add_rnh() : add a recursive nexthop
-zebra_delete_rnh() : delete a recursive nexthop
-zebra_lookup_rnh() : lookup a recursive nexthop
-
-zebra_add_rnh_client() : register a client for nexthop notifications
- against a recursive nexthop
-
-zebra_remove_rnh_client(): remove the client registration for a
- recursive nexthop
-
-zebra_evaluate_rnh_table(): (re)evaluate the recursive nexthop table
- (most probably because the main routing
- table has changed).
-
-zebra_cleanup_rnh_client(): Cleanup a client from the "rnh" module
- data structures (most probably because the
- client is going away).
-
-4.2. Control flow
-
-The next hop registration control flow is the following:
-
-<==== BGP Process ====>|<==== Zebra Process ====>
- |
-receive module nht module | zserv module rnh module
-----------------------------------------------------------------------
- | | |
-bgp_update_ | | |
- main() | bgp_find_or_add_ | |
- | nexthop() | |
- | | |
- | | zserv_nexthop_ |
- | | register() |
- | | | zebra_add_rnh()
- | | |
-
-
-The next hop notification control flow is the following:
-
-<==== Zebra Process ====>|<==== BGP Process ====>
- |
-rib module rnh module | zebra module nht module
-----------------------------------------------------------------------
- | | |
-meta_queue_ | | |
- process() | zebra_evaluate_ | |
- | rnh_table() | |
- | | |
- | | bgp_read_nexthop_ |
- | | update() |
- | | | bgp_parse_
- | | | nexthop_update()
- | | |
-
-
-4.3. zclient message format
-
-ZEBRA_NEXTHOP_REGISTER and ZEBRA_NEXTHOP_UNREGISTER messages are
-encoded in the following way:
-
-/*
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | AF | prefix len |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * . Nexthop prefix .
- * . .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * . .
- * . .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | AF | prefix len |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * . Nexthop prefix .
- * . .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
-ZEBRA_NEXTHOP_UPDATE message is encoded as follows:
-
-/*
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | AF | prefix len |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * . Nexthop prefix getting resolved .
- * . .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | metric |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | #nexthops |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | nexthop type |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * . resolving Nexthop details .
- * . .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * . .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | nexthop type |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * . resolving Nexthop details .
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
-4.4. BGP data structure
-
-Legend:
-
-/\ struct bgp_node: a BGP destination/route/prefix
-\/
-
-[ ] struct bgp_info: a BGP path (e.g. route received from a peer)
-
- _
-(_) struct bgp_nexthop_cache: a BGP nexthop
-
-
-
- /\ NULL
- \/--+ ^
- | :
- +--[ ]--[ ]--[ ]--> NULL
- /\ :
- \/--+ :
- | :
- +--[ ]--[ ]--> NULL
- :
- _ :
- (_).............
-
-
-4.5. Zebra data structure
-
-rnh table:
-
- O
- / \
- O O
- / \
- O O
-
- struct rnh
- {
- u_char flags;
- struct route_entry *state;
- struct list *client_list;
- struct route_node *node;
- };
-
-5. User interface changes
-
-frr# show ip nht
-3.3.3.3
- resolved via kernel
- via 11.0.0.6, swp1
- Client list: bgp(fd 12)
-11.0.0.10
- resolved via connected
- is directly connected, swp2
- Client list: bgp(fd 12)
-11.0.0.18
- resolved via connected
- is directly connected, swp4
- Client list: bgp(fd 12)
-11.11.11.11
- resolved via kernel
- via 10.0.1.2, eth0
- Client list: bgp(fd 12)
-
-frr# show ip bgp nexthop
-Current BGP nexthop cache:
- 3.3.3.3 valid [IGP metric 0], #paths 3
- Last update: Wed Oct 16 04:43:49 2013
-
- 11.0.0.10 valid [IGP metric 1], #paths 1
- Last update: Wed Oct 16 04:43:51 2013
-
- 11.0.0.18 valid [IGP metric 1], #paths 2
- Last update: Wed Oct 16 04:43:47 2013
-
- 11.11.11.11 valid [IGP metric 0], #paths 1
- Last update: Wed Oct 16 04:43:47 2013
-
-frr# show ipv6 nht
-frr# show ip bgp nexthop detail
-
-frr# debug bgp nht
-frr# debug zebra nht
-
-6. Sample test cases
-
- r2----r3
- / \ /
- r1----r4
-
-- Verify that a change in IGP cost triggers NHT
- + shutdown the r1-r4 and r2-r4 links
- + no shut the r1-r4 and r2-r4 links and wait for OSPF to come back
- up
- + We should be back to the original nexthop via r4 now
-- Verify that a NH becoming unreachable triggers NHT
- + Shutdown all links to r4
-- Verify that a NH becoming reachable triggers NHT
- + no shut all links to r4
-
-7. Future work
-
-- route-policy for next hop validation (e.g. ignore default route)
-- damping for rapid next hop changes
-- prioritized handling of nexthop changes ((un)reachability vs. metric
- changes)
-- handling recursion loop, e.g.
- 11.11.11.11/32 -> 12.12.12.12
- 12.12.12.12/32 -> 11.11.11.11
- 11.0.0.0/8 -> <interface>
-- better statistics