mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 05:18:47 +00:00
Merge remote-tracking branch 'frr/master' into warnings
Conflicts: zebra/if_ioctl_solaris.c zebra/rtread_getmsg.c Signed-off-by: David Lamparter <equinox@diac24.net>
This commit is contained in:
commit
e991eff5b5
136
.gitignore
vendored
136
.gitignore
vendored
@ -1,87 +1,87 @@
|
||||
compile
|
||||
config.log
|
||||
config.h
|
||||
config.cache
|
||||
config.status
|
||||
config.guess
|
||||
config.sub
|
||||
ltmain.sh
|
||||
stamp-h
|
||||
stamp-h[0-9]*
|
||||
### autoconf/automake root stuff
|
||||
|
||||
/compile
|
||||
/config.log
|
||||
/config.h
|
||||
/config.cache
|
||||
/config.status
|
||||
/config.guess
|
||||
/config.sub
|
||||
/ltmain.sh
|
||||
/stamp-h
|
||||
/stamp-h[0-9]*
|
||||
*-stamp
|
||||
Makefile
|
||||
INSTALL
|
||||
/INSTALL
|
||||
/depcomp
|
||||
/missing
|
||||
/install-sh
|
||||
/mkinstalldirs
|
||||
/ylwrap
|
||||
/autom4te*.cache
|
||||
/configure.lineno
|
||||
/configure
|
||||
/config.h.in
|
||||
/confdefs.h
|
||||
/conftest
|
||||
/conftest.err
|
||||
/aclocal.m4
|
||||
/libtool
|
||||
|
||||
/Makefile
|
||||
/Makefile.in
|
||||
|
||||
### autoconf/automake subdir stuff
|
||||
|
||||
.deps
|
||||
depcomp
|
||||
missing
|
||||
install-sh
|
||||
mkinstalldirs
|
||||
ylwrap
|
||||
autom4te*.cache
|
||||
configure.lineno
|
||||
configure
|
||||
config.h.in
|
||||
confdefs.h
|
||||
conftest
|
||||
conftest.err
|
||||
aclocal.m4
|
||||
Makefile.in
|
||||
*.tar.gz
|
||||
*.tar.gz.asc
|
||||
*.tar.?z
|
||||
.nfs*
|
||||
libtool
|
||||
.libs
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
{arch}
|
||||
build
|
||||
.msg
|
||||
.rebase-*
|
||||
*~
|
||||
|
||||
### build outputs
|
||||
|
||||
*.o
|
||||
*.lo
|
||||
*.a
|
||||
*.la
|
||||
*.so
|
||||
*.loT
|
||||
m4/*.m4
|
||||
!m4/ax_sys_weak_alias.m4
|
||||
!m4/ax_compare_version.m4
|
||||
!m4/ax_prog_perl_modules.m4
|
||||
!m4/pkg.m4
|
||||
debian/autoreconf.after
|
||||
debian/autoreconf.before
|
||||
debian/files
|
||||
debian/frr-dbg.debhelper.log
|
||||
debian/frr-dbg.substvars
|
||||
debian/frr-dbg/
|
||||
debian/frr-doc.debhelper.log
|
||||
debian/frr-doc.substvars
|
||||
debian/frr-doc/
|
||||
debian/frr.debhelper.log
|
||||
debian/frr.postinst.debhelper
|
||||
debian/frr.postrm.debhelper
|
||||
debian/frr.prerm.debhelper
|
||||
debian/frr.substvars
|
||||
debian/frr/
|
||||
debian/tmp/
|
||||
*.pb.h
|
||||
*.pb-c.h
|
||||
*.pb-c.c
|
||||
*_clippy.c
|
||||
|
||||
### dist
|
||||
|
||||
*.tar.?z
|
||||
*.tar.?z.asc
|
||||
*.tar.asc
|
||||
*.deb
|
||||
*.ddeb
|
||||
*.dsc
|
||||
*.changes
|
||||
*.pyc
|
||||
|
||||
### other garbage
|
||||
|
||||
.nfs*
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
{arch}
|
||||
build
|
||||
.cache
|
||||
.msg
|
||||
.rebase-*
|
||||
*~
|
||||
*.bak
|
||||
*.swp
|
||||
*.pyc
|
||||
__pycache__
|
||||
*.patch
|
||||
*.diff
|
||||
cscope.*
|
||||
*.pb.h
|
||||
*.pb-c.h
|
||||
*.pb-c.c
|
||||
TAGS
|
||||
tags
|
||||
GTAGS
|
||||
GSYMS
|
||||
GRTAGS
|
||||
GPATH
|
||||
*.la
|
||||
*.lo
|
||||
compile_commands.json
|
||||
.dirstamp
|
||||
|
||||
# clippy generated source
|
||||
*_clippy.c
|
||||
refix
|
||||
|
6
AUTHORS
6
AUTHORS
@ -1,6 +0,0 @@
|
||||
Kunihiro Ishiguro <kunihiro@zebra.org>
|
||||
Toshiaki Takada <takada@zebra.org>
|
||||
Yasuhiro Ohara <yasu@sfc.wide.ad.jp>
|
||||
Alex D. Zinin <azinin@hotmail.com>
|
||||
Gleb Natapov <gleb@nbase.co.il>
|
||||
Akihiro Mizutani <mizutani@dml.com>
|
@ -1,4 +0,0 @@
|
||||
ChangeLog information for FRRouting is for now recorded in source-code
|
||||
management system. Please see:
|
||||
|
||||
http://www.frrouting.org/
|
60
Makefile.am
60
Makefile.am
@ -1,10 +1,19 @@
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
AUTOMAKE_OPTIONS = subdir-objects 1.12
|
||||
include common.am
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/lib \
|
||||
AM_CFLAGS = \
|
||||
$(SAN_FLAGS) \
|
||||
$(WERROR) \
|
||||
# end
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/lib \
|
||||
-I$(top_builddir) -I$(top_builddir)/include -I$(top_builddir)/lib
|
||||
AM_LDFLAGS = \
|
||||
-export-dynamic \
|
||||
$(SAN_FLAGS) \
|
||||
# end
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE)
|
||||
LIBCAP = @LIBCAP@
|
||||
|
||||
@ -83,6 +92,7 @@ pkginclude_HEADERS =
|
||||
nodist_pkginclude_HEADERS =
|
||||
dist_examples_DATA =
|
||||
man_MANS =
|
||||
vtysh_scan =
|
||||
|
||||
## libtool, the self-made GNU scourge
|
||||
## ... this should fix relinking
|
||||
@ -106,6 +116,9 @@ include tools/subdir.am
|
||||
include debianpkg/subdir.am
|
||||
include solaris/subdir.am
|
||||
|
||||
include bgpd/subdir.am
|
||||
include bgpd/rfp-example/librfp/subdir.am
|
||||
include bgpd/rfp-example/rfptest/subdir.am
|
||||
include ripd/subdir.am
|
||||
include ripngd/subdir.am
|
||||
include ospfd/subdir.am
|
||||
@ -122,16 +135,8 @@ include pbrd/subdir.am
|
||||
include staticd/subdir.am
|
||||
include bfdd/subdir.am
|
||||
|
||||
SUBDIRS = . @LIBRFP@ @RFPTEST@ \
|
||||
@BGPD@ \
|
||||
@VTYSH@ \
|
||||
tests
|
||||
|
||||
DIST_SUBDIRS = . bgpd \
|
||||
vtysh tests \
|
||||
bgpd/rfp-example/librfp \
|
||||
bgpd/rfp-example/rfptest \
|
||||
# end
|
||||
include vtysh/subdir.am
|
||||
include tests/subdir.am
|
||||
|
||||
if PKGSRC
|
||||
rcdir=@pkgsrcrcdir@
|
||||
@ -147,6 +152,7 @@ endif
|
||||
|
||||
EXTRA_DIST += \
|
||||
aclocal.m4 \
|
||||
README.md \
|
||||
m4/README.txt \
|
||||
\
|
||||
python/clidef.py \
|
||||
@ -169,17 +175,37 @@ EXTRA_DIST += \
|
||||
snapcraft/helpers \
|
||||
snapcraft/snap \
|
||||
\
|
||||
vtysh/Makefile.am \
|
||||
vtysh/Makefile.in \
|
||||
\
|
||||
babeld/Makefile \
|
||||
bgpd/Makefile \
|
||||
bgpd/rfp-example/librfp/Makefile \
|
||||
bgpd/rfp-example/rfptest/Makefile \
|
||||
doc/Makefile \
|
||||
doc/developer/Makefile \
|
||||
doc/manpages/Makefile \
|
||||
doc/user/Makefile \
|
||||
eigrpd/Makefile \
|
||||
fpm/Makefile \
|
||||
isisd/Makefile \
|
||||
ldpd/Makefile \
|
||||
lib/Makefile \
|
||||
nhrpd/Makefile \
|
||||
ospf6d/Makefile \
|
||||
ospfclient/Makefile \
|
||||
ospfd/Makefile \
|
||||
pbrd/Makefile \
|
||||
pimd/Makefile \
|
||||
ports/Makefile \
|
||||
qpb/Makefile \
|
||||
ripd/Makefile \
|
||||
ripngd/Makefile \
|
||||
staticd/Makefile \
|
||||
tests/Makefile \
|
||||
tools/Makefile \
|
||||
vtysh/Makefile \
|
||||
watchfrr/Makefile \
|
||||
zebra/Makefile \
|
||||
# end
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
noinst_HEADERS += defaults.h
|
||||
|
||||
indent:
|
||||
|
16
README
16
README
@ -1,16 +0,0 @@
|
||||
FRRouting is free software that implements and manages various IPv4 and IPv6
|
||||
routing protocols.
|
||||
|
||||
Currently FRRouting supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, RIPv2, RIPng,
|
||||
IS-IS, PIM-SM/MSDP, LDP and Babel as well as very early support for EIGRP and
|
||||
NHRP.
|
||||
|
||||
See doc/user/bugs.rst for information on how to report bugs.
|
||||
|
||||
See doc/developer/workflow.rst for information on contributing.
|
||||
|
||||
See the file COPYING for copying conditions.
|
||||
|
||||
Public email discussion can be found at https://lists.frrouting.org/listinfo
|
||||
|
||||
Our public slack channel is at https://frrouting.slack.com
|
74
README.md
Normal file
74
README.md
Normal file
@ -0,0 +1,74 @@
|
||||
FRRouting
|
||||
=========
|
||||
|
||||
FRR is free software that implements and manages various IPv4 and IPv6 routing
|
||||
protocols. It runs on nearly all distributions of Linux and BSD as well as
|
||||
Solaris and supports all modern CPU architectures.
|
||||
|
||||
FRR currently supports the following protocols:
|
||||
|
||||
* BGP
|
||||
* OSPFv2
|
||||
* OSPFv3
|
||||
* RIPv1
|
||||
* RIPv2
|
||||
* RIPng
|
||||
* IS-IS
|
||||
* PIM-SM/MSDP
|
||||
* LDP
|
||||
* BFD
|
||||
* Babel
|
||||
* EIGRP (alpha)
|
||||
* NHRP (alpha)
|
||||
|
||||
Installation & Use
|
||||
------------------
|
||||
|
||||
Packages are available for various distributions on our
|
||||
[releases page](https://github.com/FRRouting/frr/releases).
|
||||
|
||||
Snaps are also available [here](https://snapcraft.io/frr).
|
||||
|
||||
Instructions on building and installing from source for supported platforms may
|
||||
be found
|
||||
[here](http://docs.frrouting.org/projects/dev-guide/en/latest/building.html).
|
||||
|
||||
Once installed, please refer to the [user guide](http://docs.frrouting.org/)
|
||||
for instructions on use.
|
||||
|
||||
Community
|
||||
---------
|
||||
|
||||
The FRRouting email list server is located
|
||||
[here](https://lists.frrouting.org/listinfo) and offers the following public
|
||||
lists:
|
||||
|
||||
| Topic | List |
|
||||
|-------------------|------------------------------|
|
||||
| Development | dev@lists.frrouting.org |
|
||||
| Users & Operators | frog@lists.frrouting.org |
|
||||
| Announcements | announce@lists.frrouting.org |
|
||||
|
||||
For chat, we currently use [Slack](https://frrouting.slack.com). Please email
|
||||
the mailing list to request an invite as we do not issue automatic invites.
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
FRR maintains [developer's documentation](http://docs.frrouting.org/projects/dev-guide/en/latest/index.html)
|
||||
which contains the [project workflow](http://docs.frrouting.org/projects/dev-guide/en/latest/workflow.html)
|
||||
and expectations for contributors. Some technical documentation on project
|
||||
internals is also available.
|
||||
|
||||
We welcome and appreciate all contributions, no matter how small!
|
||||
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
To report security issues, please use our security mailing list:
|
||||
|
||||
```
|
||||
security [at] lists.frrouting.org
|
||||
```
|
@ -20,6 +20,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "babel_filter.h"
|
||||
#include "vty.h"
|
||||
#include "filter.h"
|
||||
|
@ -21,6 +21,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/param.h>
|
||||
#include <time.h>
|
||||
|
@ -20,6 +20,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
@ -20,6 +20,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
@ -20,6 +20,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
@ -20,6 +20,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -6,6 +6,11 @@ if BABELD
|
||||
noinst_LIBRARIES += babeld/libbabel.a
|
||||
sbin_PROGRAMS += babeld/babeld
|
||||
dist_examples_DATA += babeld/babeld.conf.sample
|
||||
vtysh_scan += \
|
||||
$(top_srcdir)/babeld/babel_interface.c \
|
||||
$(top_srcdir)/babeld/babel_zebra.c \
|
||||
$(top_srcdir)/babeld/babeld.c \
|
||||
# end
|
||||
endif
|
||||
|
||||
babeld_libbabel_a_SOURCES = \
|
||||
|
@ -21,6 +21,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
1
bfdd/.gitignore
vendored
1
bfdd/.gitignore
vendored
@ -1,3 +1,2 @@
|
||||
# ignore binary files
|
||||
*.a
|
||||
bfdd
|
||||
|
@ -248,6 +248,8 @@ ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
|
||||
struct iovec iov[1];
|
||||
uint8_t cmsgbuf[255];
|
||||
|
||||
port[0] = '\0';
|
||||
|
||||
/* Prepare the recvmsg params. */
|
||||
iov[0].iov_base = msgbuf;
|
||||
iov[0].iov_len = msgbuflen;
|
||||
|
@ -289,7 +289,7 @@ static int _ptm_msg_read(struct stream *msg, int command,
|
||||
{
|
||||
uint32_t pid;
|
||||
uint8_t ttl __attribute__((unused));
|
||||
uint8_t ifnamelen;
|
||||
size_t ifnamelen;
|
||||
|
||||
/*
|
||||
* Register/Deregister/Update Message format:
|
||||
|
@ -6,6 +6,8 @@ if BFDD
|
||||
noinst_LIBRARIES += bfdd/libbfd.a
|
||||
sbin_PROGRAMS += bfdd/bfdd
|
||||
dist_examples_DATA += bfdd/bfdd.conf.sample
|
||||
vtysh_scan += $(top_srcdir)/bfdd/bfdd_vty.c
|
||||
man8 += $(MANBUILD)/bfdd.8
|
||||
endif
|
||||
|
||||
bfdd_libbfd_a_SOURCES = \
|
||||
|
15
bgpd/.gitignore
vendored
15
bgpd/.gitignore
vendored
@ -1,18 +1,3 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
bgpd
|
||||
bgp_btoa
|
||||
bgpd.conf
|
||||
tags
|
||||
TAGS
|
||||
.deps
|
||||
.nfs*
|
||||
*.lo
|
||||
*.la
|
||||
*.a
|
||||
*.libs
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
|
10
bgpd/Makefile
Normal file
10
bgpd/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
all: ALWAYS
|
||||
@$(MAKE) -s -C .. bgpd/bgpd
|
||||
%: ALWAYS
|
||||
@$(MAKE) -s -C .. bgpd/$@
|
||||
|
||||
Makefile:
|
||||
#nothing
|
||||
ALWAYS:
|
||||
.PHONY: ALWAYS makefiles
|
||||
.SUFFIXES:
|
140
bgpd/Makefile.am
140
bgpd/Makefile.am
@ -1,140 +0,0 @@
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
|
||||
include ../common.am
|
||||
|
||||
if ENABLE_BGP_VNC
|
||||
#o file to keep linker happy
|
||||
BGP_VNC_RFP_LIB=rfapi/rfapi_descriptor_rfp_utils.o @top_builddir@/$(LIBRFP)/librfp.a
|
||||
BGP_VNC_RFP_INC=-I@top_srcdir@/$(RFPINC)
|
||||
BGP_VNC_RFP_HD=\
|
||||
@top_srcdir@/$(RFPINC)/rfp.h
|
||||
BGP_VNC_RFP_LD_FLAGS_FILE=@top_srcdir@/$(LIBRFP)/rfp_ld_flags
|
||||
BGP_VNC_RFP_LD_FLAGS=`if [ -e "$(BGP_VNC_RFP_LD_FLAGS_FILE)" ] ; then cat "$(BGP_VNC_RFP_LD_FLAGS_FILE)" ; fi `
|
||||
|
||||
#BGP_VNC_RFAPI_SRCDIR=rfapi
|
||||
BGP_VNC_RFAPI_SRCDIR=
|
||||
BGP_VNC_RFAPI_INC=-Irfapi
|
||||
BGP_VNC_RFAPI_SRC=rfapi/bgp_rfapi_cfg.c \
|
||||
rfapi/rfapi_import.c \
|
||||
rfapi/rfapi.c \
|
||||
rfapi/rfapi_ap.c \
|
||||
rfapi/rfapi_descriptor_rfp_utils.c \
|
||||
rfapi/rfapi_encap_tlv.c \
|
||||
rfapi/rfapi_nve_addr.c \
|
||||
rfapi/rfapi_monitor.c \
|
||||
rfapi/rfapi_rib.c \
|
||||
rfapi/rfapi_vty.c \
|
||||
rfapi/vnc_debug.c \
|
||||
rfapi/vnc_export_bgp.c \
|
||||
rfapi/vnc_export_table.c \
|
||||
rfapi/vnc_import_bgp.c \
|
||||
rfapi/vnc_zebra.c
|
||||
BGP_VNC_RFAPI_HD=rfapi/bgp_rfapi_cfg.h \
|
||||
rfapi/rfapi_import.h \
|
||||
rfapi/rfapi.h \
|
||||
rfapi/rfapi_ap.h \
|
||||
rfapi/rfapi_backend.h \
|
||||
rfapi/rfapi_descriptor_rfp_utils.h \
|
||||
rfapi/rfapi_encap_tlv.h \
|
||||
rfapi/rfapi_nve_addr.h \
|
||||
rfapi/rfapi_monitor.h \
|
||||
rfapi/rfapi_private.h \
|
||||
rfapi/rfapi_rib.h \
|
||||
rfapi/rfapi_vty.h \
|
||||
rfapi/vnc_debug.h \
|
||||
rfapi/vnc_export_bgp.h \
|
||||
rfapi/vnc_export_table.h \
|
||||
rfapi/vnc_import_bgp.h \
|
||||
rfapi/vnc_zebra.h \
|
||||
rfapi/vnc_export_bgp_p.h \
|
||||
rfapi/vnc_import_bgp_p.h \
|
||||
bgp_vnc_types.h $(BGP_VNC_RFP_HD)
|
||||
|
||||
else
|
||||
BGP_VNC_RFAPI_INC=
|
||||
BGP_VNC_RFAPI_SRC=
|
||||
BGP_VNC_RFAPI_HD=
|
||||
BGP_VNC_RFP_LIB=
|
||||
BGP_VNC_RFP_INC=
|
||||
BGP_VNC_RFP_HD=
|
||||
BGP_VNC_RFP_LD_FLAGS=
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS += -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib \
|
||||
$(BGP_VNC_RFAPI_INC) $(BGP_VNC_RFP_INC)
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
INSTALL_SDATA=@INSTALL@ -m 600
|
||||
|
||||
noinst_LIBRARIES = libbgp.a
|
||||
module_LTLIBRARIES =
|
||||
sbin_PROGRAMS = bgpd
|
||||
bin_PROGRAMS = bgp_btoa
|
||||
|
||||
BUILT_SOURCES =
|
||||
|
||||
libbgp_a_SOURCES = \
|
||||
bgp_memory.c \
|
||||
bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \
|
||||
bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \
|
||||
bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
|
||||
bgp_dump.c bgp_ecommunity.c bgp_lcommunity.c \
|
||||
bgp_mplsvpn.c bgp_nexthop.c \
|
||||
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
|
||||
bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
|
||||
bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c \
|
||||
bgp_evpn.c bgp_evpn_vty.c bgp_vpn.c bgp_label.c bgp_rd.c \
|
||||
bgp_keepalives.c bgp_io.c bgp_flowspec.c bgp_flowspec_util.c \
|
||||
bgp_flowspec_vty.c bgp_labelpool.c bgp_pbr.c bgp_errors.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
bgp_memory.h \
|
||||
bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \
|
||||
bgp_network.h bgp_open.h bgp_packet.h bgp_regex.h bgp_route.h \
|
||||
bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
|
||||
bgp_ecommunity.h bgp_lcommunity.h \
|
||||
bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
|
||||
bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \
|
||||
bgp_updgrp.h bgp_bfd.h bgp_encap_tlv.h bgp_encap_types.h \
|
||||
$(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h \
|
||||
bgp_vpn.h bgp_label.h bgp_rd.h bgp_evpn_private.h bgp_keepalives.h \
|
||||
bgp_io.h bgp_flowspec.h bgp_flowspec_private.h bgp_flowspec_util.h \
|
||||
bgp_labelpool.h bgp_pbr.h bgp_errors.h
|
||||
|
||||
bgpd_SOURCES = bgp_main.c
|
||||
bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@
|
||||
bgpd_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS)
|
||||
|
||||
bgp_btoa_SOURCES = bgp_btoa.c
|
||||
bgp_btoa_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@
|
||||
bgp_btoa_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS)
|
||||
|
||||
if SNMP
|
||||
module_LTLIBRARIES += bgpd_snmp.la
|
||||
endif
|
||||
|
||||
bgpd_snmp_la_SOURCES = bgp_snmp.c
|
||||
bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99
|
||||
bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la
|
||||
|
||||
if RPKI
|
||||
module_LTLIBRARIES += bgpd_rpki.la
|
||||
BUILT_SOURCES += bgp_rpki_clippy.c
|
||||
endif
|
||||
|
||||
bgpd_rpki_la_SOURCES = bgp_rpki.c
|
||||
bgpd_rpki_la_CFLAGS = $(WERROR) $(RTRLIB_CFLAGS)
|
||||
bgpd_rpki_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
bgpd_rpki_la_LIBADD = $(RTRLIB_LIBS)
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \
|
||||
bgpd.conf.vnc.sample
|
||||
|
||||
bgp_vty.o: bgp_vty_clippy.c
|
||||
bgp_route.o: bgp_route_clippy.c
|
||||
bgp_debug.o: bgp_debug_clippy.c
|
||||
|
||||
EXTRA_DIST = BGP4-MIB.txt
|
||||
|
@ -18,9 +18,9 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
|
||||
#include <zebra.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "prefix.h"
|
||||
#include "lib_errors.h"
|
||||
|
||||
|
@ -5456,7 +5456,8 @@ static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
|
||||
XFREE(MTYPE_BGP_AGGREGATE, aggregate);
|
||||
}
|
||||
|
||||
static int bgp_aggregate_info_same(struct bgp_info *ri, struct aspath *aspath,
|
||||
static int bgp_aggregate_info_same(struct bgp_info *ri, uint8_t origin,
|
||||
struct aspath *aspath,
|
||||
struct community *comm)
|
||||
{
|
||||
static struct aspath *ae = NULL;
|
||||
@ -5467,6 +5468,9 @@ static int bgp_aggregate_info_same(struct bgp_info *ri, struct aspath *aspath,
|
||||
if (!ri)
|
||||
return 0;
|
||||
|
||||
if (origin != ri->attr->origin)
|
||||
return 0;
|
||||
|
||||
if (!aspath_cmp(ri->attr->aspath, (aspath) ? aspath : ae))
|
||||
return 0;
|
||||
|
||||
@ -5501,7 +5505,8 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
* If the aggregate information has not changed
|
||||
* no need to re-install it again.
|
||||
*/
|
||||
if (bgp_aggregate_info_same(rn->info, aspath, community)) {
|
||||
if (bgp_aggregate_info_same(rn->info, origin, aspath,
|
||||
community)) {
|
||||
bgp_unlock_node(rn);
|
||||
|
||||
if (aspath)
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "bgpd/bgp_route.h"
|
||||
#include "lib/network.h"
|
||||
#include "lib/thread.h"
|
||||
#ifndef VTYSH_EXTRACT_PL
|
||||
#include "rtrlib/rtrlib.h"
|
||||
#include "rtrlib/rtr_mgr.h"
|
||||
#include "rtrlib/lib/ip.h"
|
||||
@ -56,6 +57,7 @@
|
||||
#if defined(FOUND_SSH)
|
||||
#include "rtrlib/transport/ssh/ssh_transport.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "hook.h"
|
||||
#include "libfrr.h"
|
||||
#include "version.h"
|
||||
|
@ -18,9 +18,6 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "lib/zebra.h"
|
||||
#include "lib/prefix.h"
|
||||
#include "lib/agg_table.h"
|
||||
|
@ -18,8 +18,6 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "lib/zebra.h"
|
||||
#include "lib/prefix.h"
|
||||
#include "lib/agg_table.h"
|
||||
|
@ -18,9 +18,6 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "lib/zebra.h"
|
||||
#include "lib/prefix.h"
|
||||
#include "lib/table.h"
|
||||
|
@ -23,8 +23,6 @@
|
||||
* Purpose: Handle import of routes from BGP to RFAPI
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "lib/zebra.h"
|
||||
#include "lib/prefix.h"
|
||||
#include "lib/agg_table.h"
|
||||
|
@ -24,8 +24,6 @@
|
||||
|
||||
/* TBD remove unneeded includes */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "lib/zebra.h"
|
||||
#include "lib/prefix.h"
|
||||
#include "lib/agg_table.h"
|
||||
|
@ -23,8 +23,6 @@
|
||||
* Purpose: maintain per-nve ribs and generate change lists
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "lib/zebra.h"
|
||||
#include "lib/prefix.h"
|
||||
#include "lib/agg_table.h"
|
||||
|
@ -18,9 +18,6 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "lib/zebra.h"
|
||||
#include "lib/prefix.h"
|
||||
#include "lib/agg_table.h"
|
||||
|
10
bgpd/rfp-example/librfp/Makefile
Normal file
10
bgpd/rfp-example/librfp/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
all: ALWAYS
|
||||
@$(MAKE) -s -C ../../.. bgpd/rfp-example/librfp/librfp.a
|
||||
%: ALWAYS
|
||||
@$(MAKE) -s -C ../../.. bgpd/rfp-example/librfp/$@
|
||||
|
||||
Makefile:
|
||||
#nothing
|
||||
ALWAYS:
|
||||
.PHONY: ALWAYS makefiles
|
||||
.SUFFIXES:
|
@ -1,40 +0,0 @@
|
||||
#
|
||||
# This file has been modified by LabN Consulting, L.L.C.
|
||||
#
|
||||
#
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
if ENABLE_BGP_VNC
|
||||
BGP_VNC_RFAPI_INC=-I$(top_srcdir)/bgpd/rfapi
|
||||
BGP_VNC_RFP_LIBDIR=.
|
||||
BGP_VNC_RFP_INCDIR=$(BGP_VNC_RFP_LIBDIR)
|
||||
BGP_VNC_RFP_LIB=librfp.a
|
||||
BGP_VNC_RFP_INC=-I$(BGP_VNC_RFP_INCDIR)
|
||||
|
||||
librfp_a_SOURCES = \
|
||||
rfp_example.c
|
||||
|
||||
librfp_a_INCLUDES = \
|
||||
rfp.h \
|
||||
rfp_internal.h
|
||||
|
||||
else
|
||||
BGP_VNC_RFAPI_INC=
|
||||
BGP_VNC_RFAPI_SRC=
|
||||
BGP_VNC_RFP_LIB=
|
||||
BGP_VNC_RFP_INC=
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib \
|
||||
-I$(top_builddir) -I$(top_builddir)/lib \
|
||||
$(BGP_VNC_RFAPI_INC) $(BGP_VNC_RFP_INC)
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
INSTALL_SDATA=@INSTALL@ -m 600
|
||||
|
||||
AM_CFLAGS = $(PICFLAGS)
|
||||
AM_LDFLAGS = $(PILDFLAGS)
|
||||
|
||||
noinst_LIBRARIES = $(BGP_VNC_RFP_LIB)
|
||||
|
||||
noinst_HEADERS = \
|
||||
$(librfp_a_INCLUDES)
|
@ -18,6 +18,10 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* stub rfp */
|
||||
#include "rfp_internal.h"
|
||||
#include "bgpd/rfapi/rfapi.h"
|
||||
|
17
bgpd/rfp-example/librfp/subdir.am
Normal file
17
bgpd/rfp-example/librfp/subdir.am
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# librfp
|
||||
#
|
||||
|
||||
if ENABLE_BGP_VNC
|
||||
noinst_LIBRARIES += bgpd/rfp-example/librfp/librfp.a
|
||||
RFPLDADD = bgpd/rfp-example/librfp/librfp.a
|
||||
endif
|
||||
|
||||
bgpd_rfp_example_librfp_librfp_a_SOURCES = \
|
||||
bgpd/rfp-example/librfp/rfp_example.c \
|
||||
# end
|
||||
|
||||
noinst_HEADERS += \
|
||||
bgpd/rfp-example/librfp/rfp.h \
|
||||
bgpd/rfp-example/librfp/rfp_internal.h \
|
||||
# end
|
10
bgpd/rfp-example/rfptest/Makefile
Normal file
10
bgpd/rfp-example/rfptest/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
all: ALWAYS
|
||||
@$(MAKE) -s -C ../../.. bgpd/rfp-example/rfptest/rfptest
|
||||
%: ALWAYS
|
||||
@$(MAKE) -s -C ../../.. bgpd/rfp-example/rfptest/$@
|
||||
|
||||
Makefile:
|
||||
#nothing
|
||||
ALWAYS:
|
||||
.PHONY: ALWAYS makefiles
|
||||
.SUFFIXES:
|
@ -1,52 +0,0 @@
|
||||
#
|
||||
# This file has been modified by LabN Consulting, L.L.C.
|
||||
#
|
||||
#
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
if ENABLE_BGP_VNC
|
||||
BGP_VNC_RFAPI_INC=-I$(top_srcdir)/bgpd/rfapi
|
||||
BGP_VNC_RFP_LIBDIR=../librfp
|
||||
BGP_VNC_RFP_INCDIR=$(BGP_VNC_RFP_LIBDIR)
|
||||
BGP_VNC_RFP_LIB=$(BGP_VNC_RFP_LIBDIR)/librfp.a
|
||||
BGP_VNC_RFP_INC=-I$(BGP_VNC_RFP_INCDIR)
|
||||
|
||||
rfptest_SOURCES = \
|
||||
rfptest.c
|
||||
|
||||
rfptest_INCLUDES = \
|
||||
rfptest.h
|
||||
|
||||
|
||||
RFPTEST_BIN = rfptest
|
||||
|
||||
else
|
||||
BGP_VNC_RFAPI_INC=
|
||||
BGP_VNC_RFAPI_SRC=
|
||||
BGP_VNC_RFP_LIB=
|
||||
BGP_VNC_RFP_INC=
|
||||
RFPTEST_BIN=
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib \
|
||||
-I$(top_builddir) -I$(top_builddir)/lib \
|
||||
$(BGP_VNC_RFAPI_INC) $(BGP_VNC_RFP_INC)
|
||||
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
INSTALL_SDATA=@INSTALL@ -m 600
|
||||
|
||||
|
||||
AM_CFLAGS = $(PICFLAGS)
|
||||
AM_LDFLAGS = $(PILDFLAGS)
|
||||
|
||||
|
||||
noinst_HEADERS = \
|
||||
$(rfptest_INCLUDES)
|
||||
|
||||
noinst_LIBRARIES =
|
||||
sbin_PROGRAMS = $(RFPTEST_BIN)
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
|
||||
rfptest_LDADD = $(top_builddir)/lib/libfrr.la $(BGP_VNC_RFP_LIB)
|
||||
dist_examples_DATA =
|
@ -18,6 +18,9 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* dummy test program */
|
||||
#include <stdio.h>
|
||||
|
20
bgpd/rfp-example/rfptest/subdir.am
Normal file
20
bgpd/rfp-example/rfptest/subdir.am
Normal file
@ -0,0 +1,20 @@
|
||||
#
|
||||
# libtest
|
||||
#
|
||||
|
||||
if ENABLE_BGP_VNC
|
||||
sbin_PROGRAMS += bgpd/rfp-example/rfptest/rfptest
|
||||
endif
|
||||
|
||||
bgpd_rfp_example_rfptest_rfptest_CFLAGS = -I$(top_srcdir)/bgpd/rfapi
|
||||
bgpd_rfp_example_rfptest_rfptest_SOURCES = \
|
||||
bgpd/rfp-example/rfptest/rfptest.c \
|
||||
# end
|
||||
noinst_HEADERS += \
|
||||
bgpd/rfp-example/rfptest/rfptest.h \
|
||||
# end
|
||||
|
||||
bgpd_rfp_example_rfptest_rfptest_LDADD = \
|
||||
lib/libfrr.la \
|
||||
$(RFPLDADD) \
|
||||
# end
|
221
bgpd/subdir.am
Normal file
221
bgpd/subdir.am
Normal file
@ -0,0 +1,221 @@
|
||||
#
|
||||
# bgpd
|
||||
#
|
||||
|
||||
if BGPD
|
||||
noinst_LIBRARIES += bgpd/libbgp.a
|
||||
sbin_PROGRAMS += bgpd/bgpd
|
||||
noinst_PROGRAMS += bgpd/bgp_btoa
|
||||
dist_examples_DATA += \
|
||||
bgpd/bgpd.conf.sample \
|
||||
bgpd/bgpd.conf.sample2 \
|
||||
bgpd/bgpd.conf.vnc.sample \
|
||||
# end
|
||||
vtysh_scan += \
|
||||
$(top_srcdir)/bgpd/bgp_bfd.c \
|
||||
$(top_srcdir)/bgpd/bgp_debug.c \
|
||||
$(top_srcdir)/bgpd/bgp_dump.c \
|
||||
$(top_srcdir)/bgpd/bgp_evpn_vty.c \
|
||||
$(top_srcdir)/bgpd/bgp_filter.c \
|
||||
$(top_srcdir)/bgpd/bgp_mplsvpn.c \
|
||||
$(top_srcdir)/bgpd/bgp_nexthop.c \
|
||||
$(top_srcdir)/bgpd/bgp_route.c \
|
||||
$(top_srcdir)/bgpd/bgp_routemap.c \
|
||||
$(top_srcdir)/bgpd/bgp_vty.c \
|
||||
$(top_srcdir)/bgpd/bgp_flowspec_vty.c \
|
||||
# end
|
||||
|
||||
# can be loaded as DSO - always include for vtysh
|
||||
vtysh_scan += $(top_srcdir)/bgpd/bgp_rpki.c
|
||||
|
||||
if ENABLE_BGP_VNC
|
||||
vtysh_scan += \
|
||||
$(top_srcdir)/bgpd/rfapi/bgp_rfapi_cfg.c \
|
||||
$(top_srcdir)/bgpd/rfapi/rfapi.c \
|
||||
$(top_srcdir)/bgpd/rfapi/rfapi_vty.c \
|
||||
$(top_srcdir)/bgpd/rfapi/vnc_debug.c \
|
||||
# end
|
||||
endif
|
||||
if SNMP
|
||||
module_LTLIBRARIES += bgpd/bgpd_snmp.la
|
||||
endif
|
||||
if RPKI
|
||||
module_LTLIBRARIES += bgpd/bgpd_rpki.la
|
||||
endif
|
||||
man8 += $(MANBUILD)/bgpd.8
|
||||
endif
|
||||
|
||||
bgpd_libbgp_a_SOURCES = \
|
||||
bgpd/bgp_advertise.c \
|
||||
bgpd/bgp_aspath.c \
|
||||
bgpd/bgp_attr.c \
|
||||
bgpd/bgp_attr_evpn.c \
|
||||
bgpd/bgp_bfd.c \
|
||||
bgpd/bgp_clist.c \
|
||||
bgpd/bgp_community.c \
|
||||
bgpd/bgp_damp.c \
|
||||
bgpd/bgp_debug.c \
|
||||
bgpd/bgp_dump.c \
|
||||
bgpd/bgp_ecommunity.c \
|
||||
bgpd/bgp_encap_tlv.c \
|
||||
bgpd/bgp_errors.c \
|
||||
bgpd/bgp_evpn.c \
|
||||
bgpd/bgp_evpn_vty.c \
|
||||
bgpd/bgp_filter.c \
|
||||
bgpd/bgp_flowspec.c \
|
||||
bgpd/bgp_flowspec_util.c \
|
||||
bgpd/bgp_flowspec_vty.c \
|
||||
bgpd/bgp_fsm.c \
|
||||
bgpd/bgp_io.c \
|
||||
bgpd/bgp_keepalives.c \
|
||||
bgpd/bgp_label.c \
|
||||
bgpd/bgp_labelpool.c \
|
||||
bgpd/bgp_lcommunity.c \
|
||||
bgpd/bgp_memory.c \
|
||||
bgpd/bgp_mpath.c \
|
||||
bgpd/bgp_mplsvpn.c \
|
||||
bgpd/bgp_network.c \
|
||||
bgpd/bgp_nexthop.c \
|
||||
bgpd/bgp_nht.c \
|
||||
bgpd/bgp_open.c \
|
||||
bgpd/bgp_packet.c \
|
||||
bgpd/bgp_pbr.c \
|
||||
bgpd/bgp_rd.c \
|
||||
bgpd/bgp_regex.c \
|
||||
bgpd/bgp_route.c \
|
||||
bgpd/bgp_routemap.c \
|
||||
bgpd/bgp_table.c \
|
||||
bgpd/bgp_updgrp.c \
|
||||
bgpd/bgp_updgrp_adv.c \
|
||||
bgpd/bgp_updgrp_packet.c \
|
||||
bgpd/bgp_vpn.c \
|
||||
bgpd/bgp_vty.c \
|
||||
bgpd/bgp_zebra.c \
|
||||
bgpd/bgpd.c \
|
||||
# end
|
||||
|
||||
if ENABLE_BGP_VNC
|
||||
bgpd_libbgp_a_SOURCES += \
|
||||
bgpd/rfapi/bgp_rfapi_cfg.c \
|
||||
bgpd/rfapi/rfapi_import.c \
|
||||
bgpd/rfapi/rfapi.c \
|
||||
bgpd/rfapi/rfapi_ap.c \
|
||||
bgpd/rfapi/rfapi_descriptor_rfp_utils.c \
|
||||
bgpd/rfapi/rfapi_encap_tlv.c \
|
||||
bgpd/rfapi/rfapi_nve_addr.c \
|
||||
bgpd/rfapi/rfapi_monitor.c \
|
||||
bgpd/rfapi/rfapi_rib.c \
|
||||
bgpd/rfapi/rfapi_vty.c \
|
||||
bgpd/rfapi/vnc_debug.c \
|
||||
bgpd/rfapi/vnc_export_bgp.c \
|
||||
bgpd/rfapi/vnc_export_table.c \
|
||||
bgpd/rfapi/vnc_import_bgp.c \
|
||||
bgpd/rfapi/vnc_zebra.c \
|
||||
# end
|
||||
endif
|
||||
|
||||
noinst_HEADERS += \
|
||||
bgpd/bgp_advertise.h \
|
||||
bgpd/bgp_aspath.h \
|
||||
bgpd/bgp_attr.h \
|
||||
bgpd/bgp_attr_evpn.h \
|
||||
bgpd/bgp_bfd.h \
|
||||
bgpd/bgp_clist.h \
|
||||
bgpd/bgp_community.h \
|
||||
bgpd/bgp_damp.h \
|
||||
bgpd/bgp_debug.h \
|
||||
bgpd/bgp_dump.h \
|
||||
bgpd/bgp_ecommunity.h \
|
||||
bgpd/bgp_encap_tlv.h \
|
||||
bgpd/bgp_encap_types.h \
|
||||
bgpd/bgp_errors.h \
|
||||
bgpd/bgp_evpn.h \
|
||||
bgpd/bgp_evpn_private.h \
|
||||
bgpd/bgp_evpn_vty.h \
|
||||
bgpd/bgp_filter.h \
|
||||
bgpd/bgp_flowspec.h \
|
||||
bgpd/bgp_flowspec_private.h \
|
||||
bgpd/bgp_flowspec_util.h \
|
||||
bgpd/bgp_fsm.h \
|
||||
bgpd/bgp_io.h \
|
||||
bgpd/bgp_keepalives.h \
|
||||
bgpd/bgp_label.h \
|
||||
bgpd/bgp_labelpool.h \
|
||||
bgpd/bgp_lcommunity.h \
|
||||
bgpd/bgp_memory.h \
|
||||
bgpd/bgp_mpath.h \
|
||||
bgpd/bgp_mplsvpn.h \
|
||||
bgpd/bgp_network.h \
|
||||
bgpd/bgp_nexthop.h \
|
||||
bgpd/bgp_nht.h \
|
||||
bgpd/bgp_open.h \
|
||||
bgpd/bgp_packet.h \
|
||||
bgpd/bgp_pbr.h \
|
||||
bgpd/bgp_rd.h \
|
||||
bgpd/bgp_regex.h \
|
||||
bgpd/bgp_route.h \
|
||||
bgpd/bgp_table.h \
|
||||
bgpd/bgp_updgrp.h \
|
||||
bgpd/bgp_vpn.h \
|
||||
bgpd/bgp_vty.h \
|
||||
bgpd/bgp_zebra.h \
|
||||
bgpd/bgpd.h \
|
||||
\
|
||||
bgpd/rfapi/bgp_rfapi_cfg.h \
|
||||
bgpd/rfapi/rfapi_import.h \
|
||||
bgpd/rfapi/rfapi.h \
|
||||
bgpd/rfapi/rfapi_ap.h \
|
||||
bgpd/rfapi/rfapi_backend.h \
|
||||
bgpd/rfapi/rfapi_descriptor_rfp_utils.h \
|
||||
bgpd/rfapi/rfapi_encap_tlv.h \
|
||||
bgpd/rfapi/rfapi_nve_addr.h \
|
||||
bgpd/rfapi/rfapi_monitor.h \
|
||||
bgpd/rfapi/rfapi_private.h \
|
||||
bgpd/rfapi/rfapi_rib.h \
|
||||
bgpd/rfapi/rfapi_vty.h \
|
||||
bgpd/rfapi/vnc_debug.h \
|
||||
bgpd/rfapi/vnc_export_bgp.h \
|
||||
bgpd/rfapi/vnc_export_table.h \
|
||||
bgpd/rfapi/vnc_import_bgp.h \
|
||||
bgpd/rfapi/vnc_zebra.h \
|
||||
bgpd/rfapi/vnc_export_bgp_p.h \
|
||||
bgpd/rfapi/vnc_import_bgp_p.h \
|
||||
bgpd/bgp_vnc_types.h \
|
||||
# end
|
||||
|
||||
bgpd_bgpd_SOURCES = bgpd/bgp_main.c
|
||||
bgpd_bgp_btoa_SOURCES = bgpd/bgp_btoa.c
|
||||
|
||||
if ENABLE_BGP_VNC
|
||||
bgpd_bgpd_SOURCES += bgpd/rfapi/rfapi_descriptor_rfp_utils.c
|
||||
bgpd_bgpd_CFLAGS = -Irfapi -I@top_srcdir@/$(RFPINC)
|
||||
|
||||
bgpd_bgp_btoa_SOURCES += bgpd/rfapi/rfapi_descriptor_rfp_utils.c
|
||||
bgpd_bgp_btoa_CFLAGS = -Irfapi -I@top_srcdir@/$(RFPINC)
|
||||
endif
|
||||
|
||||
# RFPLDADD is set in bgpd/rfp-example/librfp/subdir.am
|
||||
bgpd_bgpd_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la @LIBCAP@ @LIBM@
|
||||
bgpd_bgp_btoa_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la @LIBCAP@ @LIBM@
|
||||
|
||||
bgpd_bgpd_snmp_la_SOURCES = bgpd/bgp_snmp.c
|
||||
bgpd_bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99
|
||||
bgpd_bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
bgpd_bgpd_snmp_la_LIBADD = lib/libfrrsnmp.la
|
||||
|
||||
bgpd_bgpd_rpki_la_SOURCES = bgpd/bgp_rpki.c
|
||||
bgpd_bgpd_rpki_la_CFLAGS = $(WERROR) $(RTRLIB_CFLAGS)
|
||||
bgpd_bgpd_rpki_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
bgpd_bgpd_rpki_la_LIBADD = $(RTRLIB_LIBS)
|
||||
|
||||
bgpd/bgp_vty_clippy.c: $(CLIPPY_DEPS)
|
||||
bgpd/bgp_vty.$(OBJEXT): bgpd/bgp_vty_clippy.c
|
||||
bgpd/bgp_route_clippy.c: $(CLIPPY_DEPS)
|
||||
bgpd/bgp_route.$(OBJEXT): bgpd/bgp_route_clippy.c
|
||||
bgpd/bgp_debug_clippy.c: $(CLIPPY_DEPS)
|
||||
bgpd/bgp_debug.$(OBJEXT): bgpd/bgp_debug_clippy.c
|
||||
bgpd/bgp_rpki_clippy.c: $(CLIPPY_DEPS)
|
||||
$(AUTOMAKE_DUMMY)bgpd/bgpd_bgpd_rpki_la-bgp_rpki.lo: bgpd/bgp_rpki_clippy.c
|
||||
$(AUTOMAKE_DUMMY)bgpd/bgpd_rpki_la-bgp_rpki.lo: bgpd/bgp_rpki_clippy.c
|
||||
|
||||
EXTRA_DIST += bgpd/BGP4-MIB.txt
|
61
common.am
61
common.am
@ -1,61 +0,0 @@
|
||||
#
|
||||
# Automake fragment intended to be shared by Makefile.am files in the
|
||||
# tree. When used, should be included at the very top of the file.
|
||||
#
|
||||
AM_CPPFLAGS = @ASAN_FLAGS@ @TSAN_FLAGS@ @MSAN_FLAGS@
|
||||
AM_CFLAGS = @ASAN_FLAGS@ @TSAN_FLAGS@ @MSAN_FLAGS@ $(WERROR)
|
||||
|
||||
AM_V_CLIPPY = $(am__v_CLIPPY_$(V))
|
||||
am__v_CLIPPY_ = $(am__v_CLIPPY_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CLIPPY_0 = @echo " CLIPPY " $@;
|
||||
am__v_CLIPPY_1 =
|
||||
|
||||
CLIPPY_DEPS = $(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py
|
||||
|
||||
SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h
|
||||
.c_clippy.c:
|
||||
@{ test -x $(top_builddir)/$(HOSTTOOLS)lib/clippy || $(MAKE) -C $(top_builddir)/$(HOSTTOOLS) lib/clippy; }
|
||||
$(AM_V_CLIPPY) $(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py -o $@ $<
|
||||
|
||||
## automake's "ylwrap" is a great piece of GNU software... not.
|
||||
.l.c:
|
||||
$(AM_V_LEX)$(am__skiplex) $(LEXCOMPILE) $<
|
||||
.y.c:
|
||||
$(AM_V_YACC)$(am__skipyacc) $(YACCCOMPILE) $<
|
||||
|
||||
|
||||
if HAVE_PROTOBUF
|
||||
|
||||
# Uncomment to use an non-system version of libprotobuf-c.
|
||||
#
|
||||
# Q_PROTOBUF_C_CLIENT_INCLUDES = -I$(top_srcdir)/third-party/protobuf-c/src
|
||||
# Q_PROTOBUF_C_CLIENT_LDOPTS = $(top_builddir)/third-party/protobuf-c/src/libprotobuf-c.la
|
||||
|
||||
Q_PROTOBUF_C_CLIENT_INCLUDES=
|
||||
Q_PROTOBUF_C_CLIENT_LDOPTS=-lprotobuf-c
|
||||
|
||||
Q_PROTOC=protoc
|
||||
Q_PROTOC_C=protoc-c
|
||||
|
||||
# Rules
|
||||
.proto.pb.h:
|
||||
$(Q_PROTOC) -I$(top_srcdir) --cpp_out=$(top_srcdir) $(top_srcdir)/$^
|
||||
|
||||
AM_V_PROTOC_C = $(am__v_PROTOC_C_$(V))
|
||||
am__v_PROTOC_C_ = $(am__v_PROTOC_C_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_PROTOC_C_0 = @echo " PROTOC_C" $@;
|
||||
am__v_PROTOC_C_1 =
|
||||
|
||||
.proto.pb-c.c:
|
||||
$(AM_V_PROTOC_C)$(Q_PROTOC_C) -I$(top_srcdir) --c_out=$(top_srcdir) $(top_srcdir)/$^
|
||||
.pb-c.c.pb-c.h:
|
||||
@/bin/true
|
||||
|
||||
#
|
||||
# Information about how to link to various libraries.
|
||||
#
|
||||
Q_FRR_PB_CLIENT_LDOPTS = $(top_srcdir)/qpb/libfrr_pb.la $(Q_PROTOBUF_C_CLIENT_LDOPTS)
|
||||
|
||||
Q_FPM_PB_CLIENT_LDOPTS = $(top_srcdir)/fpm/libfrrfpm_pb.la $(Q_FRR_PB_CLIENT_LDOPTS)
|
||||
|
||||
endif # HAVE_PROTOBUF
|
216
configure.ac
216
configure.ac
@ -57,7 +57,7 @@ AM_CONDITIONAL([BUILD_CLIPPY], [$build_clippy])
|
||||
|
||||
# Disable portability warnings -- our automake code (in particular
|
||||
# common.am) uses some constructs specific to gmake.
|
||||
AM_INIT_AUTOMAKE([1.12 -Wno-portability])
|
||||
AM_INIT_AUTOMAKE([1.12 -Wno-portability foreign])
|
||||
m4_ifndef([AM_SILENT_RULES], [m4_define([AM_SILENT_RULES],[])])
|
||||
AM_SILENT_RULES([yes])
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
@ -189,46 +189,6 @@ CC="${CC% -std=c99}"
|
||||
|
||||
AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"])
|
||||
|
||||
dnl AddressSanitizer support
|
||||
AC_ARG_ENABLE([address-sanitizer], AS_HELP_STRING([--enable-address-sanitizer], \
|
||||
[enabled AddressSanitizer support for detecting a wide variety of \
|
||||
memory allocation and deallocation errors]), \
|
||||
[AC_DEFINE(HAVE_ADDRESS_SANITIZER, 1, [enable AddressSanitizer])
|
||||
ASAN_FLAGS="-fsanitize=address"
|
||||
SAN_CLIPPY_FLAGS="-fno-sanitize=all"
|
||||
AC_SUBST([ASAN_FLAGS])
|
||||
AC_SUBST([SAN_CLIPPY_FLAGS])
|
||||
LIBS="-ldl $LIBS"
|
||||
AC_TRY_COMPILE([],[const int i=0;],[AC_MSG_NOTICE([Address Sanitizer Enabled])],
|
||||
[AC_MSG_ERROR([Address Sanitizer not available])])
|
||||
])
|
||||
|
||||
dnl ThreadSanitizer support
|
||||
AC_ARG_ENABLE([thread-sanitizer], AS_HELP_STRING([--enable-thread-sanitizer], \
|
||||
[enabled ThreadSanitizer support for detecting data races]), \
|
||||
[AC_DEFINE(HAVE_THREAD_SANITIZER, 1, [enable ThreadSanitizer])
|
||||
TSAN_FLAGS="-fsanitize=thread"
|
||||
SAN_CLIPPY_FLAGS="-fno-sanitize=all"
|
||||
AC_SUBST([TSAN_FLAGS])
|
||||
AC_SUBST([SAN_CLIPPY_FLAGS])
|
||||
LIBS="-ldl $LIBS"
|
||||
AC_TRY_COMPILE([],[const int i=0;],[AC_MSG_NOTICE([Thread Sanitizer Enabled])],
|
||||
[AC_MSG_ERROR([Thread Sanitizer not available])])
|
||||
])
|
||||
|
||||
dnl MemorySanitizer support
|
||||
AC_ARG_ENABLE([memory-sanitizer], AS_HELP_STRING([--enable-memory-sanitizer], \
|
||||
[enabled MemorySanitizer support for detecting uninitialized memory reads]), \
|
||||
[AC_DEFINE(HAVE_THREAD_SANITIZER, 1, [enable MemorySanitizer])
|
||||
MSAN_FLAGS="-fsanitize=memory -fPIE -pie"
|
||||
SAN_CLIPPY_FLAGS="-fno-sanitize=all"
|
||||
AC_SUBST([MSAN_FLAGS])
|
||||
AC_SUBST([SAN_CLIPPY_FLAGS])
|
||||
LIBS="-ldl $LIBS"
|
||||
AC_TRY_COMPILE([],[const int i=0;],[AC_MSG_NOTICE([Memory Sanitizer Enabled])],
|
||||
[AC_MSG_ERROR([Memory Sanitizer not available])])
|
||||
])
|
||||
|
||||
dnl if the user has specified any CFLAGS, override our settings
|
||||
if test "x${enable_gcov}" = "xyes"; then
|
||||
if test "z$orig_cflags" = "z"; then
|
||||
@ -287,19 +247,29 @@ if test x"${enable_werror}" = x"yes" ; then
|
||||
fi
|
||||
AC_SUBST(WERROR)
|
||||
|
||||
dnl need link on this one, not compile
|
||||
AC_LANG_PUSH(C)
|
||||
ac_ld_flag_save="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS -rdynamic"
|
||||
AC_MSG_CHECKING([[whether linker supports -rdynamic]])
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([[]])],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[
|
||||
LDFLAGS="$ac_ld_flag_save"
|
||||
AC_MSG_RESULT([no])
|
||||
SAN_FLAGS=""
|
||||
if test "$enable_address_sanitizer" = "yes"; then
|
||||
AC_C_FLAG([-fsanitize=address], [
|
||||
AC_MSG_ERROR([$CC does not support Address Sanitizer.])
|
||||
], [
|
||||
SAN_FLAGS="$SAN_FLAGS -fsanitize=address"
|
||||
])
|
||||
AC_LANG_POP(C)
|
||||
fi
|
||||
if test "$enable_thread_sanitizer" = "yes"; then
|
||||
AC_C_FLAG([-fsanitize=thread], [
|
||||
AC_MSG_ERROR([$CC does not support Thread Sanitizer.])
|
||||
], [
|
||||
SAN_FLAGS="$SAN_FLAGS -fsanitize=thread"
|
||||
])
|
||||
fi
|
||||
if test "$enable_memory_sanitizer" = "yes"; then
|
||||
AC_C_FLAG([-fsanitize=thread -fPIE -pie], [
|
||||
AC_MSG_ERROR([$CC does not support Thread Sanitizer.])
|
||||
], [
|
||||
SAN_FLAGS="-fsanitize=memory -fPIE -pie"
|
||||
])
|
||||
fi
|
||||
AC_SUBST([SAN_FLAGS])
|
||||
|
||||
dnl ----------
|
||||
dnl Essentials
|
||||
@ -313,6 +283,13 @@ AX_PTHREAD([
|
||||
AC_MSG_FAILURE([This FRR version needs pthreads])
|
||||
])
|
||||
|
||||
AC_SEARCH_LIBS([pthread_condattr_setclock], [],
|
||||
[frr_cv_pthread_condattr_setclock=yes],
|
||||
[frr_cv_pthread_condattr_setclock=no])
|
||||
if test "$frr_cv_pthread_condattr_setclock" = yes; then
|
||||
AC_DEFINE(HAVE_PTHREAD_CONDATTR_SETCLOCK, 1, [Have pthread.h pthread_condattr_setclock])
|
||||
fi
|
||||
|
||||
dnl --------------
|
||||
dnl Check programs
|
||||
dnl --------------
|
||||
@ -321,11 +298,6 @@ AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AC_CHECK_TOOL(AR, ar)
|
||||
|
||||
dnl -----------------
|
||||
dnl System extensions
|
||||
dnl -----------------
|
||||
AC_GNU_SOURCE
|
||||
|
||||
dnl -------
|
||||
dnl libtool
|
||||
dnl -------
|
||||
@ -381,12 +353,12 @@ AC_ARG_ENABLE(sharpd,
|
||||
AS_HELP_STRING([--enable-sharpd], [build sharpd]))
|
||||
AC_ARG_ENABLE(staticd,
|
||||
AS_HELP_STRING([--disable-staticd], [do not build staticd]))
|
||||
AC_ARG_ENABLE(fabricd,
|
||||
AS_HELP_STRING([--disable-fabricd], [do not build fabricd]))
|
||||
AC_ARG_ENABLE(bgp-announce,
|
||||
AS_HELP_STRING([--disable-bgp-announce,], [turn off BGP route announcement]))
|
||||
AC_ARG_ENABLE(bgp-vnc,
|
||||
AS_HELP_STRING([--disable-bgp-vnc],[turn off BGP VNC support]))
|
||||
AC_ARG_WITH(rfp-path,
|
||||
AS_HELP_STRING([--with-rfp-path[=DIR]],[path to replaced stub RFP used with BGP VNC]))
|
||||
AC_ARG_ENABLE(snmp,
|
||||
AS_HELP_STRING([--enable-snmp], [enable SNMP support for agentx]))
|
||||
AC_ARG_ENABLE(zeromq,
|
||||
@ -460,6 +432,12 @@ AC_ARG_ENABLE([gcov],
|
||||
AS_HELP_STRING([--enable-gcov], [Add code coverage information]))
|
||||
AC_ARG_ENABLE(bfdd,
|
||||
AS_HELP_STRING([--disable-bfdd], [do not build bfdd]))
|
||||
AC_ARG_ENABLE([address-sanitizer],
|
||||
AS_HELP_STRING([--enable-address-sanitizer], [enable AddressSanitizer support for detecting a wide variety of memory allocation and deallocation errors]))
|
||||
AC_ARG_ENABLE([thread-sanitizer],
|
||||
AS_HELP_STRING([--enable-thread-sanitizer], [enable ThreadSanitizer support for detecting data races]))
|
||||
AC_ARG_ENABLE([memory-sanitizer],
|
||||
AS_HELP_STRING([--enable-memory-sanitizer], [enable MemorySanitizer support for detecting uninitialized memory reads]))
|
||||
|
||||
AS_IF([test "${enable_clippy_only}" != "yes"], [
|
||||
AC_CHECK_HEADERS(json-c/json.h)
|
||||
@ -623,27 +601,26 @@ AC_SUBST(PYTHON_LIBS)
|
||||
# Logic for protobuf support.
|
||||
#
|
||||
if test "$enable_protobuf" = "yes"; then
|
||||
have_protobuf=yes
|
||||
# Check for protoc & protoc-c
|
||||
|
||||
# Check for protoc-c
|
||||
AC_CHECK_PROG([PROTOC_C], [protoc-c], [protoc-c], [/bin/false])
|
||||
if test "x$PROTOC_C" = "x/bin/false"; then
|
||||
have_protobuf=no
|
||||
else
|
||||
found_protobuf_c=no
|
||||
PKG_CHECK_MODULES([PROTOBUF_C], libprotobuf-c >= 0.14,
|
||||
[found_protobuf_c=yes],
|
||||
[AC_MSG_RESULT([pkg-config did not find libprotobuf-c])])
|
||||
# protoc is not required, it's only for a "be nice" helper target
|
||||
AC_CHECK_PROGS([PROTOC], [protoc], [/bin/false])
|
||||
|
||||
if test "x$found_protobuf_c" = "xyes"; then
|
||||
LDFLAGS="$LDFLAGS $PROTOBUF_C_LIBS"
|
||||
CFLAGS="$CFLAGS $PROTOBUF_C_CFLAGS"
|
||||
else
|
||||
AC_CHECK_HEADER([google/protobuf-c/protobuf-c.h], [],
|
||||
[have_protobuf=no; AC_MSG_RESULT([Couldn't find google/protobuf-c.h])])
|
||||
fi
|
||||
AC_CHECK_PROGS([PROTOC_C], [protoc-c], [/bin/false])
|
||||
if test "$PROTOC_C" = "/bin/false"; then
|
||||
AC_MSG_FAILURE([protobuf requested but protoc-c not found. Install protobuf-c.])
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES([PROTOBUF_C], [libprotobuf-c >= 0.14],, [
|
||||
AC_MSG_FAILURE([protobuf requested but libprotobuf-c not found. Install protobuf-c.])
|
||||
])
|
||||
AC_CHECK_HEADER([google/protobuf-c/protobuf-c.h], [], [
|
||||
AC_MSG_FAILURE([protobuf requested but protobuf-c.h not found. Install protobuf-c.])
|
||||
])
|
||||
|
||||
AC_DEFINE(HAVE_PROTOBUF,, protobuf)
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$enable_protobuf" = "xyes"])
|
||||
|
||||
#
|
||||
# Logic for old vpn commans support.
|
||||
@ -652,18 +629,6 @@ if test "$enable_oldvpn_commands" = "yes"; then
|
||||
AC_DEFINE(KEEP_OLD_VPN_COMMANDS,, [Define for compiling with old vpn commands])
|
||||
fi
|
||||
|
||||
# Fail if the user explicity enabled protobuf support and we couldn't
|
||||
# find the compiler or libraries.
|
||||
if test "x$have_protobuf" = "xno" && test "x$enable_protobuf" = "xyes"; then
|
||||
AC_MSG_ERROR([Protobuf enabled explicitly but can't find libraries/tools])
|
||||
fi
|
||||
|
||||
if test "x$have_protobuf" = "xyes"; then
|
||||
AC_DEFINE(HAVE_PROTOBUF,, protobuf)
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$have_protobuf" = "xyes"])
|
||||
|
||||
#
|
||||
# End of logic for protobuf support.
|
||||
#
|
||||
@ -850,10 +815,15 @@ int main(int argc, char **argv) {
|
||||
])
|
||||
])
|
||||
|
||||
AC_CHECK_HEADERS([pthread_np.h],,, [
|
||||
#include <pthread.h>
|
||||
])
|
||||
AC_CHECK_FUNCS([pthread_setname_np pthread_set_name_np])
|
||||
|
||||
dnl Utility macro to avoid retyping includes all the time
|
||||
m4_define([FRR_INCLUDES],
|
||||
[#ifdef SUNOS_5
|
||||
#define _XPG4_2
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define __EXTENSIONS__
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
@ -946,6 +916,7 @@ case "$host_os" in
|
||||
|
||||
AC_DEFINE(SUNOS_5, 1, [SunOS 5])
|
||||
AC_DEFINE(SOLARIS_IPV6, 1, Solaris IPv6)
|
||||
AC_DEFINE(_POSIX_C_SOURCE, 200809L, [enable POSIX.1-2008 and XPG7/SUSv4])
|
||||
|
||||
AC_CHECK_LIB(socket, main)
|
||||
AC_CHECK_LIB(nsl, main)
|
||||
@ -1049,6 +1020,10 @@ dnl [TODO] on Linux, and in [TODO] on Solaris.
|
||||
if test $ac_cv_lib_readline_rl_completion_matches = no; then
|
||||
AC_DEFINE(rl_completion_matches,completion_matches,Old readline)
|
||||
fi
|
||||
AC_SEARCH_LIBS([append_history], [readline], [frr_cv_append_history=yes], [frr_cv_append_history=no])
|
||||
if test "$frr_cv_append_history" = yes; then
|
||||
AC_DEFINE(HAVE_APPEND_HISTORY, 1, [Have history.h append_history])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(LIBREADLINE)
|
||||
@ -1197,11 +1172,12 @@ case "$host_os" in
|
||||
if test $ac_cv_header_net_bpf_h = no; then
|
||||
if test $ac_cv_header_sys_dlpi_h = no; then
|
||||
AC_MSG_RESULT(none)
|
||||
if test "${enable_isisd}" = yes; then
|
||||
if test "${enable_isisd}" = yes -o "${enable_fabricd}" = yes; then
|
||||
AC_MSG_FAILURE([IS-IS support requested but no packet backend found])
|
||||
fi
|
||||
AC_MSG_WARN([*** IS-IS support will not be built ***])
|
||||
enable_isisd="no"
|
||||
enable_fabricd="no"
|
||||
else
|
||||
AC_MSG_RESULT(DLPI)
|
||||
fi
|
||||
@ -1339,8 +1315,13 @@ FRR_INCLUDES
|
||||
])dnl
|
||||
|
||||
dnl disable doc check
|
||||
AC_CHECK_PROGS([SPHINXBUILD], [sphinx-build sphinx-build3 sphinx-build2], [no])
|
||||
AM_CONDITIONAL(DOC, test "${enable_doc}" != "no")
|
||||
AC_CHECK_PROGS([SPHINXBUILD], [sphinx-build sphinx-build3 sphinx-build2], [/bin/false])
|
||||
if test "$SPHINXBUILD" = "/bin/false"; then
|
||||
if test "${enable_doc}" = "yes"; then
|
||||
AC_MSG_ERROR([Documentation was explicitly requested with --enable-doc but sphinx-build is not available. Please disable docs or install sphinx.])
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL(DOC, test "${enable_doc}" != "no" -a "$SPHINXBUILD" != "/bin/false")
|
||||
AM_CONDITIONAL(DOC_HTML, test "${enable_doc_html}" = "yes")
|
||||
|
||||
dnl --------------------
|
||||
@ -1429,6 +1410,7 @@ AM_CONDITIONAL(PIMD, test "${enable_pimd}" != "no")
|
||||
AM_CONDITIONAL(PBRD, test "${enable_pbrd}" != "no")
|
||||
AM_CONDITIONAL(SHARPD, test "${enable_sharpd}" = "yes")
|
||||
AM_CONDITIONAL(STATICD, test "${enable_staticd}" != "no")
|
||||
AM_CONDITIONAL(FABRICD, test "${enable_fabricd}" != "no")
|
||||
|
||||
if test "${enable_bgp_announce}" = "no";then
|
||||
AC_DEFINE(DISABLE_BGP_ANNOUNCE,1,Disable BGP installation to zebra)
|
||||
@ -1436,33 +1418,12 @@ else
|
||||
AC_DEFINE(DISABLE_BGP_ANNOUNCE,0,Disable BGP installation to zebra)
|
||||
fi
|
||||
|
||||
if test "${with_rfp_path}" = "yes" || test x"${with_rfp_path}" = x""; then
|
||||
with_rfp_path="bgpd/rfp-example"
|
||||
fi
|
||||
if test "${with_rfp_path}" != "no"; then
|
||||
VNC_RFP_PATH="${with_rfp_path}"
|
||||
AC_SUBST(VNC_RFP_PATH)
|
||||
fi
|
||||
|
||||
if test "${enable_bgp_vnc}" != "no";then
|
||||
AC_DEFINE(ENABLE_BGP_VNC,1,Enable BGP VNC support)
|
||||
RFPTEST="${with_rfp_path}/rfptest"
|
||||
LIBRFP="${with_rfp_path}/librfp"
|
||||
RFPINC="${with_rfp_path}/librfp"
|
||||
else
|
||||
RFPTEST=
|
||||
LIBRFP=
|
||||
RFPINC="bgpd/rfp-example/librfp"
|
||||
fi
|
||||
# set
|
||||
AM_CONDITIONAL([ENABLE_BGP_VNC], [test x${enable_bgp_vnc} != xno])
|
||||
|
||||
AC_SUBST(RFPTEST)
|
||||
AC_SUBST(LIBRFP)
|
||||
AC_SUBST(RFPINC)
|
||||
AC_SUBST(BGPD)
|
||||
AC_SUBST(SOLARIS)
|
||||
AC_SUBST(VTYSH)
|
||||
AC_SUBST(CURSES)
|
||||
AC_CHECK_LIB(crypt, crypt, [],
|
||||
[AC_CHECK_LIB(crypto, DES_crypt)])
|
||||
@ -1833,13 +1794,16 @@ dnl order to check no alternative allocator
|
||||
dnl has been specified, which might not provide
|
||||
dnl mallinfo, e.g. such as Umem on Solaris.
|
||||
dnl -----------------------------------------
|
||||
AC_CHECK_HEADERS([malloc.h malloc/malloc.h],,, [FRR_INCLUDES])
|
||||
AC_CHECK_HEADERS([malloc.h malloc_np.h malloc/malloc.h],,, [FRR_INCLUDES])
|
||||
|
||||
AC_CACHE_CHECK([whether mallinfo is available], [frr_cv_mallinfo], [
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([FRR_INCLUDES [
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#ifdef HAVE_MALLOC_NP_H
|
||||
#include <malloc_np.h>
|
||||
#endif
|
||||
#ifdef HAVE_MALLOC_MALLOC_H
|
||||
#include <malloc/malloc.h>
|
||||
#endif
|
||||
@ -1983,8 +1947,7 @@ dnl Enable RPKI and add librtr to libs
|
||||
dnl ------------------------------------
|
||||
if test "${enable_rpki}" = "yes"; then
|
||||
PKG_CHECK_MODULES(RTRLIB,[rtrlib >= 0.5.0],
|
||||
[AC_DEFINE(HAVE_RPKI,1,Enable RPKI prefix validation for BGP)
|
||||
RPKI=true],
|
||||
[RPKI=true],
|
||||
[RPKI=false
|
||||
AC_MSG_ERROR([rtrlib was not found on your system or is too old.])]
|
||||
)
|
||||
@ -2016,11 +1979,6 @@ AC_MSG_RESULT($ac_cv_htonl_works)
|
||||
AC_CONFIG_FILES([Makefile],[sed -e 's/^#AUTODERP# //' -i Makefile])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
bgpd/Makefile
|
||||
vtysh/Makefile
|
||||
tests/Makefile
|
||||
bgpd/rfp-example/rfptest/Makefile
|
||||
bgpd/rfp-example/librfp/Makefile
|
||||
redhat/frr.spec
|
||||
solaris/Makefile
|
||||
debianpkg/changelog
|
||||
@ -2032,12 +1990,6 @@ AC_CONFIG_FILES([
|
||||
pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh
|
||||
pkgsrc/eigrpd.sh])
|
||||
|
||||
if test "${enable_bgp_vnc}" != "no"; then
|
||||
if test "${with_rfp_path}" != "bgpd/rfp-example" ; then
|
||||
AC_CONFIG_FILES([${with_rfp_path}/rfptest/Makefile ${with_rfp_path}/librfp/Makefile])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES([vtysh/extract.pl],[chmod +x vtysh/extract.pl])
|
||||
|
||||
AC_CONFIG_COMMANDS([lib/route_types.h], [
|
||||
@ -2079,9 +2031,9 @@ FRR version : ${PACKAGE_VERSION}
|
||||
host operating system : ${host_os}
|
||||
source code location : ${srcdir}
|
||||
compiler : ${CC}
|
||||
compiler flags : ${CFLAGS}
|
||||
compiler flags : ${CFLAGS} ${SAN_FLAGS}
|
||||
make : ${MAKE-make}
|
||||
linker flags : ${LDFLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM}
|
||||
linker flags : ${LDFLAGS} ${SAN_FLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM}
|
||||
state file directory : ${frr_statedir}
|
||||
config file directory : `eval echo \`echo ${sysconfdir}\``
|
||||
example directory : `eval echo \`echo ${exampledir}\``
|
||||
@ -2091,12 +2043,12 @@ group to run as : ${enable_group}
|
||||
group for vty sockets : ${enable_vty_group}
|
||||
config file mask : ${enable_configfile_mask}
|
||||
log file mask : ${enable_logfile_mask}
|
||||
zebra protobuf enabled : ${have_protobuf:-no}
|
||||
zebra protobuf enabled : ${enable_protobuf:-no}
|
||||
|
||||
The above user and group must have read/write access to the state file
|
||||
directory and to the config files in the config file directory."
|
||||
|
||||
if test "${enable_doc}" != "no";then
|
||||
AS_IF([test "x$SPHINXBUILD" = xno],
|
||||
AS_IF([test "$SPHINXBUILD" = /bin/false],
|
||||
AC_MSG_WARN(sphinx-build is missing but required to build documentation))
|
||||
fi
|
||||
|
@ -1,5 +1,3 @@
|
||||
AUTHORS
|
||||
NEWS
|
||||
README
|
||||
README.md
|
||||
doc/user/*.rst
|
||||
doc/figures/*.png
|
||||
|
6
doc/.gitignore
vendored
6
doc/.gitignore
vendored
@ -1,4 +1,3 @@
|
||||
!Makefile
|
||||
mdate-sh
|
||||
draft-zebra-00.txt
|
||||
*.pdf
|
||||
@ -6,7 +5,6 @@ draft-zebra-00.txt
|
||||
frr.ps
|
||||
frr.dvi
|
||||
stamp-vti
|
||||
.nfs*
|
||||
*.aux
|
||||
*.cp
|
||||
*.cps
|
||||
@ -20,8 +18,4 @@ stamp-vti
|
||||
*.toc
|
||||
*.tp
|
||||
*.vr
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
refix
|
||||
|
@ -128,8 +128,8 @@ Add frr groups and user
|
||||
.. code-block:: shell
|
||||
|
||||
sudo groupadd -g 92 frr
|
||||
sudo groupadd -r -g 85 frrvt
|
||||
sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
|
||||
sudo groupadd -r -g 85 frrvty
|
||||
sudo useradd -u 92 -g 92 -M -r -G frrvty -s /sbin/nologin \
|
||||
-c "FRR FRRouting suite" -d /var/run/frr frr
|
||||
|
||||
Download Source, configure and compile it
|
||||
@ -158,7 +158,7 @@ an example.)
|
||||
--enable-ospfapi=yes \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvt \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-rtadv \
|
||||
--disable-exampledir \
|
||||
--enable-watchfrr \
|
||||
@ -168,10 +168,11 @@ an example.)
|
||||
--enable-eigrpd \
|
||||
--enable-babeld \
|
||||
--with-pkg-git-version \
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion
|
||||
make SPHINXBUILD=sphinx-build2.7
|
||||
make check PYTHON=/usr/bin/python2.7 SPHINXBUILD=sphinx-build2.7
|
||||
sudo make SPHINXBUILD=sphinx-build2.7 install
|
||||
--with-pkg-extra-version=-MyOwnFRRVersion \
|
||||
SPHINXBUILD=sphinx-build2.7
|
||||
make
|
||||
make check PYTHON=/usr/bin/python2.7
|
||||
sudo make install
|
||||
|
||||
Create empty FRR configuration files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -36,8 +36,8 @@ 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 \
|
||||
sudo groupadd -r -g 85 frrvty
|
||||
sudo useradd -u 92 -g 92 -M -r -G frrvty -s /sbin/nologin \
|
||||
-c "FRR FRRouting suite" -d /var/run/frr frr
|
||||
|
||||
Download Source, configure and compile it
|
||||
@ -66,7 +66,7 @@ an example.)
|
||||
--enable-ospfapi=yes \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvt \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-rtadv \
|
||||
--enable-systemd=yes \
|
||||
--disable-exampledir \
|
||||
@ -102,7 +102,7 @@ Create empty FRR configuration files
|
||||
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 chown frr:frrvty /etc/frr/vtysh.conf
|
||||
sudo chmod 640 /etc/frr/*.conf
|
||||
|
||||
Install daemon config file
|
||||
|
@ -29,8 +29,8 @@ 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 \
|
||||
sudo groupadd -r -g 85 frrvty
|
||||
sudo useradd -u 92 -g 92 -M -r -G frrvty -s /sbin/nologin \
|
||||
-c "FRR FRRouting suite" -d /var/run/frr frr
|
||||
|
||||
Download Source, configure and compile it
|
||||
@ -59,7 +59,7 @@ an example.)
|
||||
--enable-ospfapi=yes \
|
||||
--enable-user=frr \
|
||||
--enable-group=frr \
|
||||
--enable-vty-group=frrvt \
|
||||
--enable-vty-group=frrvty \
|
||||
--enable-rtadv \
|
||||
--disable-exampledir \
|
||||
--enable-watchfrr \
|
||||
@ -95,7 +95,7 @@ Create empty FRR configuration files
|
||||
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 chown frr:frrvty /etc/frr/vtysh.conf
|
||||
sudo chmod 640 /etc/frr/*.conf
|
||||
|
||||
Install daemon config file
|
||||
|
@ -450,8 +450,6 @@ is no ordering requirement)
|
||||
|
||||
.. code-block:: make
|
||||
|
||||
include ../common.am
|
||||
|
||||
# ...
|
||||
|
||||
# if linked into a LTLIBRARY (.la/.so):
|
||||
|
@ -125,6 +125,7 @@ These following options control the daemon's VTY (interactive command line) inte
|
||||
pbrd 2615
|
||||
staticd 2616
|
||||
bfdd 2617
|
||||
fabricd 2618
|
||||
|
||||
Port 2607 is used for ospfd's Opaque LSA API.
|
||||
|
||||
|
@ -333,6 +333,7 @@ man_pages = [
|
||||
('vtysh', 'vtysh', 'an integrated shell for FRRouting.', [], 1),
|
||||
('frr', 'frr', 'a systemd interaction script', [], 1),
|
||||
('bfdd', 'bfdd', fwfrr.format("a bfd"), [], 8),
|
||||
('fabricd', 'fabricd', fwfrr.format("an OpenFabric "), [], 8),
|
||||
]
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
38
doc/manpages/fabricd.rst
Normal file
38
doc/manpages/fabricd.rst
Normal file
@ -0,0 +1,38 @@
|
||||
*******
|
||||
FABRICD
|
||||
*******
|
||||
|
||||
.. include:: defines.rst
|
||||
.. |DAEMON| replace:: fabricd
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|DAEMON| |synopsis-options-hv|
|
||||
|
||||
|DAEMON| |synopsis-options|
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|DAEMON| is a routing component that works with the FRRouting routing engine.
|
||||
|
||||
OPTIONS
|
||||
=======
|
||||
OPTIONS available for the |DAEMON| command:
|
||||
|
||||
.. include:: common-options.rst
|
||||
|
||||
FILES
|
||||
=====
|
||||
|
||||
|INSTALL_PREFIX_SBIN|/|DAEMON|
|
||||
The default location of the |DAEMON| binary.
|
||||
|
||||
|INSTALL_PREFIX_ETC|/|DAEMON|.conf
|
||||
The default location of the |DAEMON| config file.
|
||||
|
||||
$(PWD)/|DAEMON|.log
|
||||
If the |DAEMON| process is configured to output logs to a file, then you
|
||||
will find this file in the directory where you started |DAEMON|.
|
||||
|
||||
.. include:: epilogue.rst
|
||||
|
@ -10,6 +10,7 @@
|
||||
bgpd
|
||||
eigrpd
|
||||
isisd
|
||||
fabricd
|
||||
ldpd
|
||||
nhrpd
|
||||
ospf6d
|
||||
|
@ -9,6 +9,7 @@ man_RSTFILES = \
|
||||
doc/manpages/defines.rst \
|
||||
doc/manpages/eigrpd.rst \
|
||||
doc/manpages/epilogue.rst \
|
||||
doc/manpages/fabricd.rst \
|
||||
doc/manpages/frr.rst \
|
||||
doc/manpages/index.rst \
|
||||
doc/manpages/isisd.rst \
|
||||
@ -46,83 +47,16 @@ rstman8dir = $(mandir)/man8
|
||||
rstman1_DATA =
|
||||
rstman8_DATA =
|
||||
|
||||
rstman1_DATA += $(MANBUILD)/frr.1
|
||||
if DOC
|
||||
rstman1_DATA += $(man1)
|
||||
rstman8_DATA += $(man8)
|
||||
endif # DOC
|
||||
|
||||
if PIMD
|
||||
rstman8_DATA += $(MANBUILD)/pimd.8
|
||||
rstman8_DATA += $(MANBUILD)/mtracebis.8
|
||||
endif
|
||||
|
||||
if PBRD
|
||||
rstman8_DATA += $(MANBUILD)/pbrd.8
|
||||
endif
|
||||
|
||||
if BGPD
|
||||
rstman8_DATA += $(MANBUILD)/bgpd.8
|
||||
endif
|
||||
|
||||
if ISISD
|
||||
rstman8_DATA += $(MANBUILD)/isisd.8
|
||||
endif
|
||||
|
||||
if OSPF6D
|
||||
rstman8_DATA += $(MANBUILD)/ospf6d.8
|
||||
endif
|
||||
|
||||
if OSPFCLIENT
|
||||
rstman8_DATA += $(MANBUILD)/ospfclient.8
|
||||
endif
|
||||
|
||||
if OSPFD
|
||||
rstman8_DATA += $(MANBUILD)/ospfd.8
|
||||
endif
|
||||
|
||||
if LDPD
|
||||
rstman8_DATA += $(MANBUILD)/ldpd.8
|
||||
endif
|
||||
|
||||
if RIPD
|
||||
rstman8_DATA += $(MANBUILD)/ripd.8
|
||||
endif
|
||||
|
||||
if RIPNGD
|
||||
rstman8_DATA += $(MANBUILD)/ripngd.8
|
||||
endif
|
||||
|
||||
if NHRPD
|
||||
rstman8_DATA += $(MANBUILD)/nhrpd.8
|
||||
endif
|
||||
|
||||
if VTYSH
|
||||
rstman1_DATA += $(MANBUILD)/vtysh.1
|
||||
endif
|
||||
|
||||
if WATCHFRR
|
||||
rstman8_DATA += $(MANBUILD)/watchfrr.8
|
||||
endif
|
||||
|
||||
if ZEBRA
|
||||
rstman8_DATA += $(MANBUILD)/zebra.8
|
||||
endif
|
||||
|
||||
if EIGRPD
|
||||
rstman8_DATA += $(MANBUILD)/eigrpd.8
|
||||
endif
|
||||
|
||||
if SHARPD
|
||||
rstman8_DATA += $(MANBUILD)/sharpd.8
|
||||
endif
|
||||
|
||||
if STATICD
|
||||
rstman8_DATA += $(MANBUILD)/staticd.8
|
||||
endif
|
||||
|
||||
if BFDD
|
||||
rstman8_DATA += $(MANBUILD)/bfdd.8
|
||||
endif
|
||||
man1 = $(MANBUILD)/frr.1
|
||||
man8 =
|
||||
|
||||
# dependency
|
||||
$(rstman8_DATA) $(rstman1_DATA): $(MANBUILD)/man.stamp
|
||||
$(man8) $(man1): $(MANBUILD)/man.stamp
|
||||
|
||||
#
|
||||
# hook-ins for clean / doc
|
||||
|
5
doc/mpls/.gitignore
vendored
5
doc/mpls/.gitignore
vendored
@ -1,5 +0,0 @@
|
||||
.arch-ids
|
||||
.arch-inventory
|
||||
*~
|
||||
*.loT
|
||||
|
404
doc/user/fabricd.rst
Normal file
404
doc/user/fabricd.rst
Normal file
@ -0,0 +1,404 @@
|
||||
.. _fabricd:
|
||||
|
||||
**********
|
||||
OpenFabric
|
||||
**********
|
||||
|
||||
OpenFabric, specified in :t:`draft-white-openfabric-06.txt`, is a routing
|
||||
protocol derived from IS-IS, providing link-state routing with efficient
|
||||
flooding for topologies like spine-leaf networks.
|
||||
|
||||
FRR implements OpenFabric in a daemon called *fabricd*
|
||||
|
||||
.. _configuring-fabricd:
|
||||
|
||||
Configuring fabricd
|
||||
===================
|
||||
|
||||
There are no *fabricd* specific options. Common options can be specified
|
||||
(:ref:`common-invocation-options`) to *fabricd*. *fabricd* needs to acquire
|
||||
interface information from *zebra* in order to function. Therefore *zebra* must
|
||||
be running before invoking *fabricd*. Also, if *zebra* is restarted then *fabricd*
|
||||
must be too.
|
||||
|
||||
Like other daemons, *fabricd* configuration is done in an OpenFabric specific
|
||||
configuration file :file:`fabricd.conf`.
|
||||
|
||||
.. _openfabric-router:
|
||||
|
||||
OpenFabric router
|
||||
=================
|
||||
|
||||
To enable the OpenFabric routing protocol, an OpenFabric router needs to be created
|
||||
in the configuration:
|
||||
|
||||
.. index:: router openfabric WORD
|
||||
.. clicmd:: router openfabric WORD
|
||||
|
||||
.. index:: no router openfabric WORD
|
||||
.. clicmd:: no router openfabric WORD
|
||||
|
||||
Enable or disable the OpenFabric process by specifying the OpenFabric domain with
|
||||
'WORD'.
|
||||
|
||||
.. index:: net XX.XXXX. ... .XXX.XX
|
||||
.. clicmd:: net XX.XXXX. ... .XXX.XX
|
||||
|
||||
.. index:: no net XX.XXXX. ... .XXX.XX
|
||||
.. clicmd:: no net XX.XXXX. ... .XXX.XX
|
||||
|
||||
Set/Unset network entity title (NET) provided in ISO format.
|
||||
|
||||
.. index:: domain-password [clear | md5] <password>
|
||||
.. clicmd:: domain-password [clear | md5] <password>
|
||||
|
||||
.. index:: no domain-password
|
||||
.. clicmd:: no domain-password
|
||||
|
||||
Configure the authentication password for a domain, as clear text or md5 one.
|
||||
|
||||
.. index:: log-adjacency-changes
|
||||
.. clicmd:: log-adjacency-changes
|
||||
|
||||
.. index:: no log-adjacency-changes
|
||||
.. clicmd:: no log-adjacency-changes
|
||||
|
||||
Log changes in adjacency state.
|
||||
|
||||
.. index:: set-overload-bit
|
||||
.. clicmd:: set-overload-bit
|
||||
|
||||
.. index:: no set-overload-bit
|
||||
.. clicmd:: no set-overload-bit
|
||||
|
||||
Set overload bit to avoid any transit traffic.
|
||||
|
||||
.. index:: purge-originator
|
||||
.. clicmd:: purge-originator
|
||||
|
||||
.. index:: no purge-originator
|
||||
.. clicmd:: no purge-originator
|
||||
|
||||
Enable or disable :rfc:`6232` purge originator identification.
|
||||
|
||||
.. index:: fabric-tier (0-14)
|
||||
.. clicmd:: fabric-tier (0-14)
|
||||
|
||||
.. index:: no fabric-tier
|
||||
.. clicmd:: no fabric-tier
|
||||
|
||||
Configure a static tier number to advertise as location in the fabric
|
||||
|
||||
.. _openfabric-timer:
|
||||
|
||||
OpenFabric Timer
|
||||
================
|
||||
|
||||
.. index:: lsp-gen-interval (1-120)
|
||||
.. clicmd:: lsp-gen-interval (1-120)
|
||||
|
||||
.. index:: no lsp-gen-interval
|
||||
.. clicmd:: no lsp-gen-interval
|
||||
|
||||
Set minimum interval in seconds between regenerating same LSP.
|
||||
|
||||
.. index:: lsp-refresh-interval (1-65235)
|
||||
.. clicmd:: lsp-refresh-interval (1-65235)
|
||||
|
||||
.. index:: no lsp-refresh-interval
|
||||
.. clicmd:: no lsp-refresh-interval
|
||||
|
||||
Set LSP refresh interval in seconds.
|
||||
|
||||
.. index:: max-lsp-lifetime (360-65535)
|
||||
.. clicmd:: max-lsp-lifetime (360-65535)
|
||||
|
||||
.. index:: no max-lsp-lifetime
|
||||
.. clicmd:: no max-lsp-lifetime
|
||||
|
||||
Set LSP maximum LSP lifetime in seconds.
|
||||
|
||||
.. index:: spf-interval (1-120)
|
||||
.. clicmd:: spf-interval (1-120)
|
||||
|
||||
.. index:: no spf-interval
|
||||
.. clicmd:: no spf-interval
|
||||
|
||||
Set minimum interval between consecutive SPF calculations in seconds.
|
||||
|
||||
.. _openfabric-interface:
|
||||
|
||||
OpenFabric interface
|
||||
====================
|
||||
|
||||
.. index:: ip router openfabric WORD
|
||||
.. clicmd:: ip router openfabric WORD
|
||||
|
||||
.. index:: no ip router openfabric WORD
|
||||
.. clicmd:: no ip router openfabric WORD
|
||||
|
||||
.. _ip-router-openfabric-word:
|
||||
|
||||
Activate OpenFabric on this interface. Note that the name
|
||||
of OpenFabric instance must be the same as the one used to configure the
|
||||
routing process (see command :clicmd:`router openfabric WORD`).
|
||||
|
||||
.. index:: openfabric csnp-interval (1-600)
|
||||
.. clicmd:: openfabric csnp-interval (1-600)
|
||||
|
||||
.. index:: no openfabric csnp-interval
|
||||
.. clicmd:: no openfabric csnp-interval
|
||||
|
||||
Set CSNP interval in seconds.
|
||||
|
||||
.. index:: openfabric hello-interval (1-600)
|
||||
.. clicmd:: openfabric hello-interval (1-600)
|
||||
|
||||
.. index:: no openfabric hello-interval
|
||||
.. clicmd:: no openfabric hello-interval
|
||||
|
||||
Set Hello interval in seconds.
|
||||
|
||||
.. index:: openfabric hello-multiplier (2-100)
|
||||
.. clicmd:: openfabric hello-multiplier (2-100)
|
||||
|
||||
.. index:: no openfabric hello-multiplier
|
||||
.. clicmd:: no openfabric hello-multiplier
|
||||
|
||||
Set multiplier for Hello holding time.
|
||||
|
||||
.. index:: openfabric metric (0-16777215)
|
||||
.. clicmd:: openfabric metric (0-16777215)
|
||||
|
||||
.. index:: no openfabric metric
|
||||
.. clicmd:: no openfabric metric
|
||||
|
||||
Set interface metric value.
|
||||
|
||||
.. index:: openfabric passive
|
||||
.. clicmd:: openfabric passive
|
||||
|
||||
.. index:: no openfabric passive
|
||||
.. clicmd:: no openfabric passive
|
||||
|
||||
Configure the passive mode for this interface.
|
||||
|
||||
.. index:: openfabric password [clear | md5] <password>
|
||||
.. clicmd:: openfabric password [clear | md5] <password>
|
||||
|
||||
.. index:: no openfabric password
|
||||
.. clicmd:: no openfabric password
|
||||
|
||||
Configure the authentication password (clear or encoded text) for the
|
||||
interface.
|
||||
|
||||
.. index:: openfabric psnp-interval (1-120)
|
||||
.. clicmd:: openfabric psnp-interval (1-120)
|
||||
|
||||
.. index:: no openfabric psnp-interval
|
||||
.. clicmd:: no openfabric psnp-interval
|
||||
|
||||
Set PSNP interval in seconds.
|
||||
|
||||
.. _showing-openfabric-information:
|
||||
|
||||
Showing OpenFabric information
|
||||
==============================
|
||||
|
||||
.. index:: show openfabric summary
|
||||
.. clicmd:: show openfabric summary
|
||||
|
||||
Show summary information about OpenFabric.
|
||||
|
||||
.. index:: show openfabric hostname
|
||||
.. clicmd:: show openfabric hostname
|
||||
|
||||
Show which hostnames are associated with which OpenFabric system ids.
|
||||
|
||||
.. index:: show openfabric interface
|
||||
.. clicmd:: show openfabric interface
|
||||
|
||||
.. index:: show openfabric interface detail
|
||||
.. clicmd:: show openfabric interface detail
|
||||
|
||||
.. index:: show openfabric interface <interface name>
|
||||
.. clicmd:: show openfabric interface <interface name>
|
||||
|
||||
Show state and configuration of specified OpenFabric interface, or all interfaces
|
||||
if no interface is given with or without details.
|
||||
|
||||
.. index:: show openfabric neighbor
|
||||
.. clicmd:: show openfabric neighbor
|
||||
|
||||
.. index:: show openfabric neighbor <System Id>
|
||||
.. clicmd:: show openfabric neighbor <System Id>
|
||||
|
||||
.. index:: show openfabric neighbor detail
|
||||
.. clicmd:: show openfabric neighbor detail
|
||||
|
||||
Show state and information of specified OpenFabric neighbor, or all neighbors if
|
||||
no system id is given with or without details.
|
||||
|
||||
.. index:: show openfabric database
|
||||
.. clicmd:: show openfabric database
|
||||
|
||||
.. index:: show openfabric database [detail]
|
||||
.. clicmd:: show openfabric database [detail]
|
||||
|
||||
.. index:: show openfabric database <LSP id> [detail]
|
||||
.. clicmd:: show openfabric database <LSP id> [detail]
|
||||
|
||||
.. index:: show openfabric database detail <LSP id>
|
||||
.. clicmd:: show openfabric database detail <LSP id>
|
||||
|
||||
Show the OpenFabric database globally, for a specific LSP id without or with
|
||||
details.
|
||||
|
||||
.. index:: show openfabric topology
|
||||
.. clicmd:: show openfabric topology
|
||||
|
||||
Show calculated OpenFabric paths and associated topology information.
|
||||
|
||||
.. _debugging-openfabric:
|
||||
|
||||
Debugging OpenFabric
|
||||
====================
|
||||
|
||||
.. index:: debug openfabric adj-packets
|
||||
.. clicmd:: debug openfabric adj-packets
|
||||
|
||||
.. index:: no debug openfabric adj-packets
|
||||
.. clicmd:: no debug openfabric adj-packets
|
||||
|
||||
OpenFabric Adjacency related packets.
|
||||
|
||||
.. index:: debug openfabric checksum-errors
|
||||
.. clicmd:: debug openfabric checksum-errors
|
||||
|
||||
.. index:: no debug openfabric checksum-errors
|
||||
.. clicmd:: no debug openfabric checksum-errors
|
||||
|
||||
OpenFabric LSP checksum errors.
|
||||
|
||||
.. index:: debug openfabric events
|
||||
.. clicmd:: debug openfabric events
|
||||
|
||||
.. index:: no debug openfabric events
|
||||
.. clicmd:: no debug openfabric events
|
||||
|
||||
OpenFabric Events.
|
||||
|
||||
.. index:: debug openfabric local-updates
|
||||
.. clicmd:: debug openfabric local-updates
|
||||
|
||||
.. index:: no debug openfabric local-updates
|
||||
.. clicmd:: no debug openfabric local-updates
|
||||
|
||||
OpenFabric local update packets.
|
||||
|
||||
.. index:: debug openfabric lsp-gen
|
||||
.. clicmd:: debug openfabric lsp-gen
|
||||
|
||||
.. index:: no debug openfabric lsp-gen
|
||||
.. clicmd:: no debug openfabric lsp-gen
|
||||
|
||||
Generation of own LSPs.
|
||||
|
||||
.. index:: debug openfabric lsp-sched
|
||||
.. clicmd:: debug openfabric lsp-sched
|
||||
|
||||
.. index:: no debug openfabric lsp-sched
|
||||
.. clicmd:: no debug openfabric lsp-sched
|
||||
|
||||
Debug scheduling of generation of own LSPs.
|
||||
|
||||
.. index:: debug openfabric packet-dump
|
||||
.. clicmd:: debug openfabric packet-dump
|
||||
|
||||
.. index:: no debug openfabric packet-dump
|
||||
.. clicmd:: no debug openfabric packet-dump
|
||||
|
||||
OpenFabric packet dump.
|
||||
|
||||
.. index:: debug openfabric protocol-errors
|
||||
.. clicmd:: debug openfabric protocol-errors
|
||||
|
||||
.. index:: no debug openfabric protocol-errors
|
||||
.. clicmd:: no debug openfabric protocol-errors
|
||||
|
||||
OpenFabric LSP protocol errors.
|
||||
|
||||
.. index:: debug openfabric route-events
|
||||
.. clicmd:: debug openfabric route-events
|
||||
|
||||
.. index:: no debug openfabric route-events
|
||||
.. clicmd:: no debug openfabric route-events
|
||||
|
||||
OpenFabric Route related events.
|
||||
|
||||
.. index:: debug openfabric snp-packets
|
||||
.. clicmd:: debug openfabric snp-packets
|
||||
|
||||
.. index:: no debug openfabric snp-packets
|
||||
.. clicmd:: no debug openfabric snp-packets
|
||||
|
||||
OpenFabric CSNP/PSNP packets.
|
||||
|
||||
.. index:: debug openfabric spf-events
|
||||
.. clicmd:: debug openfabric spf-events
|
||||
|
||||
.. index:: debug openfabric spf-statistics
|
||||
.. clicmd:: debug openfabric spf-statistics
|
||||
|
||||
.. index:: debug openfabric spf-triggers
|
||||
.. clicmd:: debug openfabric spf-triggers
|
||||
|
||||
.. index:: no debug openfabric spf-events
|
||||
.. clicmd:: no debug openfabric spf-events
|
||||
|
||||
.. index:: no debug openfabric spf-statistics
|
||||
.. clicmd:: no debug openfabric spf-statistics
|
||||
|
||||
.. index:: no debug openfabric spf-triggers
|
||||
.. clicmd:: no debug openfabric spf-triggers
|
||||
|
||||
OpenFabric Shortest Path First Events, Timing and Statistic Data and triggering
|
||||
events.
|
||||
|
||||
.. index:: debug openfabric update-packets
|
||||
.. clicmd:: debug openfabric update-packets
|
||||
|
||||
.. index:: no debug openfabric update-packets
|
||||
.. clicmd:: no debug openfabric update-packets
|
||||
|
||||
Update related packets.
|
||||
|
||||
.. index:: show debugging openfabric
|
||||
.. clicmd:: show debugging openfabric
|
||||
|
||||
Print which OpenFabric debug levels are active.
|
||||
|
||||
OpenFabric configuration example
|
||||
================================
|
||||
|
||||
A simple example:
|
||||
|
||||
.. code-block:: frr
|
||||
|
||||
!
|
||||
interface lo
|
||||
ip address 192.0.2.1/32
|
||||
ip router openfabric 1
|
||||
ipv6 address 2001:db8::1/128
|
||||
ipv6 router openfabric 1
|
||||
!
|
||||
interface eth0
|
||||
ip router openfabric 1
|
||||
ipv6 router openfabric 1
|
||||
!
|
||||
interface eth1
|
||||
ip router openfabric 1
|
||||
ipv6 router openfabric 1
|
||||
!
|
||||
router openfabric 1
|
||||
net 49.0000.0000.0001.00
|
@ -42,6 +42,7 @@ Protocols
|
||||
bfd
|
||||
bgp
|
||||
babeld
|
||||
fabricd
|
||||
ldpd
|
||||
eigrpd
|
||||
isisd
|
||||
|
@ -139,6 +139,10 @@ options from the list below.
|
||||
|
||||
Do not build isisd.
|
||||
|
||||
.. option:: --disable-fabricd
|
||||
|
||||
Do not build fabricd.
|
||||
|
||||
.. option:: --enable-isis-topology
|
||||
|
||||
Enable IS-IS topology generator.
|
||||
|
@ -106,6 +106,14 @@ writing, *isisd* does not support multiple ISIS processes.
|
||||
|
||||
Set overload bit to avoid any transit traffic.
|
||||
|
||||
.. index:: purge-originator
|
||||
.. clicmd:: purge-originator
|
||||
|
||||
.. index:: no purge-originator
|
||||
.. clicmd:: no purge-originator
|
||||
|
||||
Enable or disable :rfc:`6232` purge originator identification.
|
||||
|
||||
.. _isis-timer:
|
||||
|
||||
ISIS Timer
|
||||
|
@ -32,6 +32,7 @@ systemd. The file initially looks like this:
|
||||
staticd=no
|
||||
pbrd=no
|
||||
bfdd=no
|
||||
fabricd=no
|
||||
|
||||
To enable a particular daemon, simply change the corresponding 'no' to 'yes'.
|
||||
Subsequent service restarts should start the daemon.
|
||||
@ -68,6 +69,7 @@ This file has several parts. Here is an example:
|
||||
staticd_options=" --daemon -A 127.0.0.1"
|
||||
pbrd_options=" --daemon -A 127.0.0.1"
|
||||
bfdd_options=" --daemon -A 127.0.0.1"
|
||||
fabricd_options=" --daemon -A 127.0.0.1"
|
||||
|
||||
# The list of daemons to watch is automatically generated by the init script.
|
||||
watchfrr_enable=yes
|
||||
@ -139,6 +141,7 @@ add the following entries to :file:`/etc/services`.
|
||||
ldpd 2612/tcp # LDPd vty
|
||||
eigprd 2613/tcp # EIGRPd vty
|
||||
bfdd 2617/tcp # bfdd vty
|
||||
fabricd 2618/tcp # fabricd vty
|
||||
|
||||
|
||||
If you use a FreeBSD newer than 2.2.8, the above entries are already added to
|
||||
|
@ -10,6 +10,7 @@ user_RSTFILES = \
|
||||
doc/user/bugs.rst \
|
||||
doc/user/conf.py \
|
||||
doc/user/eigrpd.rst \
|
||||
doc/user/fabricd.rst \
|
||||
doc/user/filter.rst \
|
||||
doc/user/glossary.rst \
|
||||
doc/user/index.rst \
|
||||
|
16
eigrpd/.gitignore
vendored
16
eigrpd/.gitignore
vendored
@ -1,18 +1,2 @@
|
||||
!Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.a
|
||||
eigrpd
|
||||
eigrpd.conf
|
||||
tags
|
||||
TAGS
|
||||
.deps
|
||||
.nfs*
|
||||
*.lo
|
||||
*.la
|
||||
*.libs
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
|
||||
|
@ -67,8 +67,8 @@
|
||||
* 7- state not changed, usually by receiving not last reply
|
||||
*/
|
||||
|
||||
#include <thread.h>
|
||||
#include <zebra.h>
|
||||
#include <thread.h>
|
||||
|
||||
#include "prefix.h"
|
||||
#include "table.h"
|
||||
|
@ -6,6 +6,12 @@ if EIGRPD
|
||||
noinst_LIBRARIES += eigrpd/libeigrp.a
|
||||
sbin_PROGRAMS += eigrpd/eigrpd
|
||||
dist_examples_DATA += eigrpd/eigrpd.conf.sample
|
||||
vtysh_scan += \
|
||||
$(top_srcdir)/eigrpd/eigrp_dump.c \
|
||||
$(top_srcdir)/eigrpd/eigrp_vty.c \
|
||||
# end
|
||||
# $(top_srcdir)/eigrpd/eigrp_routemap.c
|
||||
man8 += $(MANBUILD)/eigrpd.8
|
||||
endif
|
||||
|
||||
eigrpd_libeigrp_a_SOURCES = \
|
||||
|
15
fpm/.gitignore
vendored
15
fpm/.gitignore
vendored
@ -1,15 +0,0 @@
|
||||
!Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
tags
|
||||
TAGS
|
||||
.deps
|
||||
.nfs*
|
||||
*.lo
|
||||
*.la
|
||||
*.a
|
||||
*.libs
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
@ -3,8 +3,7 @@ lib_LTLIBRARIES += fpm/libfrrfpm_pb.la
|
||||
endif
|
||||
|
||||
fpm_libfrrfpm_pb_la_LDFLAGS = -version-info 0:0:0
|
||||
fpm_libfrrfpm_pb_la_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib \
|
||||
$(Q_PROTOBUF_C_CLIENT_INCLUDES)
|
||||
fpm_libfrrfpm_pb_la_CPPFLAGS = $(AM_CPPFLAGS) $(PROTOBUF_C_CFLAGS)
|
||||
fpm_libfrrfpm_pb_la_SOURCES = \
|
||||
fpm/fpm.h \
|
||||
fpm/fpm_pb.h \
|
||||
@ -12,11 +11,14 @@ fpm_libfrrfpm_pb_la_SOURCES = \
|
||||
# end
|
||||
|
||||
if HAVE_PROTOBUF
|
||||
nodist_fpm_libfrrfpm_pb_la_SOURCES = fpm/fpm.pb-c.c
|
||||
nodist_fpm_libfrrfpm_pb_la_SOURCES = \
|
||||
fpm/fpm.pb-c.c \
|
||||
# end
|
||||
endif
|
||||
|
||||
CLEANFILES += \
|
||||
fpm/fpm.pb-c.c \
|
||||
fpm/fpm.pb-c.h \
|
||||
# end
|
||||
endif
|
||||
|
||||
EXTRA_DIST += fpm/fpm.proto
|
||||
|
6
init/.gitignore
vendored
6
init/.gitignore
vendored
@ -1,6 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
.nfs*
|
||||
*~
|
||||
*.loT
|
||||
|
14
isisd/.gitignore
vendored
14
isisd/.gitignore
vendored
@ -1,15 +1,3 @@
|
||||
!Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
isisd
|
||||
.deps
|
||||
fabricd
|
||||
isisd.conf
|
||||
.nfs*
|
||||
*.lo
|
||||
*.la
|
||||
*.libs
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
*.a
|
||||
|
717
isisd/fabricd.c
Normal file
717
isisd/fabricd.c
Normal file
@ -0,0 +1,717 @@
|
||||
/*
|
||||
* IS-IS Rout(e)ing protocol - OpenFabric extensions
|
||||
*
|
||||
* Copyright (C) 2018 Christian Franke
|
||||
*
|
||||
* This file is part of FreeRangeRouting (FRR)
|
||||
*
|
||||
* FRR 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, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* FRR 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>
|
||||
#include "isisd/fabricd.h"
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_memory.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_misc.h"
|
||||
#include "isisd/isis_adjacency.h"
|
||||
#include "isisd/isis_spf.h"
|
||||
#include "isisd/isis_tlvs.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
#include "isisd/isis_spf_private.h"
|
||||
#include "isisd/isis_tx_queue.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(ISISD, FABRICD_STATE, "ISIS OpenFabric")
|
||||
DEFINE_MTYPE_STATIC(ISISD, FABRICD_NEIGHBOR, "ISIS OpenFabric Neighbor Entry")
|
||||
|
||||
/* Tracks initial synchronization as per section 2.4
|
||||
*
|
||||
* We declare the sync complete once we have seen at least one
|
||||
* CSNP and there are no more LSPs with SSN or SRM set.
|
||||
*/
|
||||
enum fabricd_sync_state {
|
||||
FABRICD_SYNC_PENDING,
|
||||
FABRICD_SYNC_STARTED,
|
||||
FABRICD_SYNC_COMPLETE
|
||||
};
|
||||
|
||||
struct fabricd {
|
||||
struct isis_area *area;
|
||||
|
||||
enum fabricd_sync_state initial_sync_state;
|
||||
time_t initial_sync_start;
|
||||
struct isis_circuit *initial_sync_circuit;
|
||||
struct thread *initial_sync_timeout;
|
||||
|
||||
struct isis_spftree *spftree;
|
||||
struct skiplist *neighbors;
|
||||
struct hash *neighbors_neighbors;
|
||||
|
||||
uint8_t tier;
|
||||
uint8_t tier_config;
|
||||
uint8_t tier_pending;
|
||||
struct thread *tier_calculation_timer;
|
||||
struct thread *tier_set_timer;
|
||||
};
|
||||
|
||||
/* Code related to maintaining the neighbor lists */
|
||||
|
||||
struct neighbor_entry {
|
||||
struct isis_vertex *vertex;
|
||||
bool present;
|
||||
};
|
||||
|
||||
static struct neighbor_entry *neighbor_entry_new(struct isis_vertex *vertex)
|
||||
{
|
||||
struct neighbor_entry *rv = XMALLOC(MTYPE_FABRICD_NEIGHBOR, sizeof(*rv));
|
||||
|
||||
rv->vertex = vertex;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void neighbor_entry_del(struct neighbor_entry *neighbor)
|
||||
{
|
||||
XFREE(MTYPE_FABRICD_NEIGHBOR, neighbor);
|
||||
}
|
||||
|
||||
static void neighbor_entry_del_void(void *arg)
|
||||
{
|
||||
neighbor_entry_del((struct neighbor_entry *)arg);
|
||||
}
|
||||
|
||||
static void neighbor_lists_clear(struct fabricd *f)
|
||||
{
|
||||
while (!skiplist_empty(f->neighbors))
|
||||
skiplist_delete_first(f->neighbors);
|
||||
|
||||
hash_clean(f->neighbors_neighbors, neighbor_entry_del_void);
|
||||
}
|
||||
|
||||
static unsigned neighbor_entry_hash_key(void *np)
|
||||
{
|
||||
struct neighbor_entry *n = np;
|
||||
|
||||
return jhash(n->vertex->N.id, ISIS_SYS_ID_LEN, 0x55aa5a5a);
|
||||
}
|
||||
|
||||
static int neighbor_entry_hash_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct neighbor_entry *na = a, *nb = b;
|
||||
|
||||
return memcmp(na->vertex->N.id, nb->vertex->N.id, ISIS_SYS_ID_LEN) == 0;
|
||||
}
|
||||
|
||||
static int neighbor_entry_list_cmp(void *a, void *b)
|
||||
{
|
||||
struct neighbor_entry *na = a, *nb = b;
|
||||
|
||||
return -memcmp(na->vertex->N.id, nb->vertex->N.id, ISIS_SYS_ID_LEN);
|
||||
}
|
||||
|
||||
static struct neighbor_entry *neighbor_entry_lookup_list(struct skiplist *list,
|
||||
const uint8_t *id)
|
||||
{
|
||||
struct isis_vertex querier;
|
||||
isis_vertex_id_init(&querier, id, VTYPE_NONPSEUDO_TE_IS);
|
||||
|
||||
struct neighbor_entry n = {
|
||||
.vertex = &querier
|
||||
};
|
||||
|
||||
struct neighbor_entry *rv;
|
||||
|
||||
if (skiplist_search(list, &n, (void**)&rv))
|
||||
return NULL;
|
||||
|
||||
if (!rv->present)
|
||||
return NULL;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static struct neighbor_entry *neighbor_entry_lookup_hash(struct hash *hash,
|
||||
const uint8_t *id)
|
||||
{
|
||||
struct isis_vertex querier;
|
||||
isis_vertex_id_init(&querier, id, VTYPE_NONPSEUDO_TE_IS);
|
||||
|
||||
struct neighbor_entry n = {
|
||||
.vertex = &querier
|
||||
};
|
||||
|
||||
struct neighbor_entry *rv = hash_lookup(hash, &n);
|
||||
|
||||
if (!rv || !rv->present)
|
||||
return NULL;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void neighbor_lists_update(struct fabricd *f)
|
||||
{
|
||||
neighbor_lists_clear(f);
|
||||
|
||||
struct listnode *node;
|
||||
struct isis_vertex *v;
|
||||
|
||||
for (ALL_QUEUE_ELEMENTS_RO(&f->spftree->paths, node, v)) {
|
||||
if (!v->d_N || !VTYPE_IS(v->type))
|
||||
continue;
|
||||
|
||||
if (v->d_N > 2)
|
||||
break;
|
||||
|
||||
struct neighbor_entry *n = neighbor_entry_new(v);
|
||||
if (v->d_N == 1) {
|
||||
skiplist_insert(f->neighbors, n, n);
|
||||
} else {
|
||||
struct neighbor_entry *inserted;
|
||||
inserted = hash_get(f->neighbors_neighbors, n, hash_alloc_intern);
|
||||
assert(inserted == n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct fabricd *fabricd_new(struct isis_area *area)
|
||||
{
|
||||
struct fabricd *rv = XCALLOC(MTYPE_FABRICD_STATE, sizeof(*rv));
|
||||
|
||||
rv->area = area;
|
||||
rv->initial_sync_state = FABRICD_SYNC_PENDING;
|
||||
|
||||
rv->spftree = isis_spftree_new(area);
|
||||
rv->neighbors = skiplist_new(0, neighbor_entry_list_cmp,
|
||||
neighbor_entry_del_void);
|
||||
rv->neighbors_neighbors = hash_create(neighbor_entry_hash_key,
|
||||
neighbor_entry_hash_cmp,
|
||||
"Fabricd Neighbors");
|
||||
|
||||
rv->tier = rv->tier_config = ISIS_TIER_UNDEFINED;
|
||||
return rv;
|
||||
};
|
||||
|
||||
void fabricd_finish(struct fabricd *f)
|
||||
{
|
||||
if (f->initial_sync_timeout)
|
||||
thread_cancel(f->initial_sync_timeout);
|
||||
|
||||
if (f->tier_calculation_timer)
|
||||
thread_cancel(f->tier_calculation_timer);
|
||||
|
||||
if (f->tier_set_timer)
|
||||
thread_cancel(f->tier_set_timer);
|
||||
|
||||
isis_spftree_del(f->spftree);
|
||||
neighbor_lists_clear(f);
|
||||
skiplist_free(f->neighbors);
|
||||
hash_free(f->neighbors_neighbors);
|
||||
}
|
||||
|
||||
static int fabricd_initial_sync_timeout(struct thread *thread)
|
||||
{
|
||||
struct fabricd *f = THREAD_ARG(thread);
|
||||
|
||||
zlog_info("OpenFabric: Initial synchronization on %s timed out!",
|
||||
f->initial_sync_circuit->interface->name);
|
||||
f->initial_sync_state = FABRICD_SYNC_PENDING;
|
||||
f->initial_sync_circuit = NULL;
|
||||
f->initial_sync_timeout = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fabricd_initial_sync_hello(struct isis_circuit *circuit)
|
||||
{
|
||||
struct fabricd *f = circuit->area->fabricd;
|
||||
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
if (f->initial_sync_state > FABRICD_SYNC_PENDING)
|
||||
return;
|
||||
|
||||
f->initial_sync_state = FABRICD_SYNC_STARTED;
|
||||
|
||||
long timeout = 2 * circuit->hello_interval[1] * circuit->hello_multiplier[1];
|
||||
|
||||
f->initial_sync_circuit = circuit;
|
||||
if (f->initial_sync_timeout)
|
||||
return;
|
||||
|
||||
thread_add_timer(master, fabricd_initial_sync_timeout, f,
|
||||
timeout, &f->initial_sync_timeout);
|
||||
f->initial_sync_start = monotime(NULL);
|
||||
|
||||
zlog_info("OpenFabric: Started initial synchronization with %s on %s",
|
||||
sysid_print(circuit->u.p2p.neighbor->sysid),
|
||||
circuit->interface->name);
|
||||
}
|
||||
|
||||
bool fabricd_initial_sync_is_in_progress(struct isis_area *area)
|
||||
{
|
||||
struct fabricd *f = area->fabricd;
|
||||
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
if (f->initial_sync_state > FABRICD_SYNC_PENDING
|
||||
&& f->initial_sync_state < FABRICD_SYNC_COMPLETE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fabricd_initial_sync_is_complete(struct isis_area *area)
|
||||
{
|
||||
struct fabricd *f = area->fabricd;
|
||||
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
return f->initial_sync_state == FABRICD_SYNC_COMPLETE;
|
||||
}
|
||||
|
||||
struct isis_circuit *fabricd_initial_sync_circuit(struct isis_area *area)
|
||||
{
|
||||
struct fabricd *f = area->fabricd;
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
return f->initial_sync_circuit;
|
||||
}
|
||||
|
||||
void fabricd_initial_sync_finish(struct isis_area *area)
|
||||
{
|
||||
struct fabricd *f = area->fabricd;
|
||||
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
if (monotime(NULL) - f->initial_sync_start < 5)
|
||||
return;
|
||||
|
||||
zlog_info("OpenFabric: Initial synchronization on %s complete.",
|
||||
f->initial_sync_circuit->interface->name);
|
||||
f->initial_sync_state = FABRICD_SYNC_COMPLETE;
|
||||
f->initial_sync_circuit = NULL;
|
||||
thread_cancel(f->initial_sync_timeout);
|
||||
f->initial_sync_timeout = NULL;
|
||||
}
|
||||
|
||||
static void fabricd_bump_tier_calculation_timer(struct fabricd *f);
|
||||
static void fabricd_set_tier(struct fabricd *f, uint8_t tier);
|
||||
|
||||
static uint8_t fabricd_calculate_fabric_tier(struct isis_area *area)
|
||||
{
|
||||
struct isis_spftree *local_tree = fabricd_spftree(area);
|
||||
struct listnode *node;
|
||||
|
||||
struct isis_vertex *furthest_t0 = NULL,
|
||||
*second_furthest_t0 = NULL;
|
||||
|
||||
struct isis_vertex *v;
|
||||
|
||||
for (ALL_QUEUE_ELEMENTS_RO(&local_tree->paths, node, v)) {
|
||||
struct isis_lsp *lsp = lsp_for_vertex(local_tree, v);
|
||||
|
||||
if (!lsp || !lsp->tlvs
|
||||
|| !lsp->tlvs->spine_leaf
|
||||
|| !lsp->tlvs->spine_leaf->has_tier
|
||||
|| lsp->tlvs->spine_leaf->tier != 0)
|
||||
continue;
|
||||
|
||||
second_furthest_t0 = furthest_t0;
|
||||
furthest_t0 = v;
|
||||
}
|
||||
|
||||
if (!second_furthest_t0) {
|
||||
zlog_info("OpenFabric: Could not find two T0 routers");
|
||||
return ISIS_TIER_UNDEFINED;
|
||||
}
|
||||
|
||||
zlog_info("OpenFabric: Found %s as furthest t0 from local system, dist == %"
|
||||
PRIu32, rawlspid_print(furthest_t0->N.id), furthest_t0->d_N);
|
||||
|
||||
struct isis_spftree *remote_tree =
|
||||
isis_run_hopcount_spf(area, furthest_t0->N.id, NULL);
|
||||
|
||||
struct isis_vertex *furthest_from_remote =
|
||||
isis_vertex_queue_last(&remote_tree->paths);
|
||||
|
||||
if (!furthest_from_remote) {
|
||||
zlog_info("OpenFabric: Found no furthest node in remote spf");
|
||||
isis_spftree_del(remote_tree);
|
||||
return ISIS_TIER_UNDEFINED;
|
||||
} else {
|
||||
zlog_info("OpenFabric: Found %s as furthest from remote dist == %"
|
||||
PRIu32, rawlspid_print(furthest_from_remote->N.id),
|
||||
furthest_from_remote->d_N);
|
||||
}
|
||||
|
||||
int64_t tier = furthest_from_remote->d_N - furthest_t0->d_N;
|
||||
isis_spftree_del(remote_tree);
|
||||
|
||||
if (tier < 0 || tier >= ISIS_TIER_UNDEFINED) {
|
||||
zlog_info("OpenFabric: Calculated tier %" PRId64 " seems implausible",
|
||||
tier);
|
||||
return ISIS_TIER_UNDEFINED;
|
||||
}
|
||||
|
||||
zlog_info("OpenFabric: Calculated %" PRId64 " as tier", tier);
|
||||
return tier;
|
||||
}
|
||||
|
||||
static int fabricd_tier_set_timer(struct thread *thread)
|
||||
{
|
||||
struct fabricd *f = THREAD_ARG(thread);
|
||||
f->tier_set_timer = NULL;
|
||||
|
||||
fabricd_set_tier(f, f->tier_pending);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fabricd_tier_calculation_cb(struct thread *thread)
|
||||
{
|
||||
struct fabricd *f = THREAD_ARG(thread);
|
||||
uint8_t tier = ISIS_TIER_UNDEFINED;
|
||||
f->tier_calculation_timer = NULL;
|
||||
|
||||
tier = fabricd_calculate_fabric_tier(f->area);
|
||||
if (tier == ISIS_TIER_UNDEFINED)
|
||||
return 0;
|
||||
|
||||
zlog_info("OpenFabric: Got tier %" PRIu8 " from algorithm. Arming timer.",
|
||||
tier);
|
||||
f->tier_pending = tier;
|
||||
thread_add_timer(master, fabricd_tier_set_timer, f,
|
||||
f->area->lsp_gen_interval[ISIS_LEVEL2 - 1],
|
||||
&f->tier_set_timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fabricd_bump_tier_calculation_timer(struct fabricd *f)
|
||||
{
|
||||
/* Cancel timer if we already know our tier */
|
||||
if (f->tier != ISIS_TIER_UNDEFINED
|
||||
|| f->tier_set_timer) {
|
||||
if (f->tier_calculation_timer) {
|
||||
thread_cancel(f->tier_calculation_timer);
|
||||
f->tier_calculation_timer = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we need to calculate the tier, wait some
|
||||
* time for the topology to settle before running
|
||||
* the calculation */
|
||||
if (f->tier_calculation_timer) {
|
||||
thread_cancel(f->tier_calculation_timer);
|
||||
f->tier_calculation_timer = NULL;
|
||||
}
|
||||
|
||||
thread_add_timer(master, fabricd_tier_calculation_cb, f,
|
||||
2 * f->area->lsp_gen_interval[ISIS_LEVEL2 - 1],
|
||||
&f->tier_calculation_timer);
|
||||
}
|
||||
|
||||
static void fabricd_set_tier(struct fabricd *f, uint8_t tier)
|
||||
{
|
||||
if (f->tier == tier)
|
||||
return;
|
||||
|
||||
zlog_info("OpenFabric: Set own tier to %" PRIu8, tier);
|
||||
f->tier = tier;
|
||||
|
||||
fabricd_bump_tier_calculation_timer(f);
|
||||
lsp_regenerate_schedule(f->area, ISIS_LEVEL2, 0);
|
||||
}
|
||||
|
||||
void fabricd_run_spf(struct isis_area *area)
|
||||
{
|
||||
struct fabricd *f = area->fabricd;
|
||||
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
isis_run_hopcount_spf(area, isis->sysid, f->spftree);
|
||||
neighbor_lists_update(f);
|
||||
fabricd_bump_tier_calculation_timer(f);
|
||||
}
|
||||
|
||||
struct isis_spftree *fabricd_spftree(struct isis_area *area)
|
||||
{
|
||||
struct fabricd *f = area->fabricd;
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
return f->spftree;
|
||||
}
|
||||
|
||||
void fabricd_configure_tier(struct isis_area *area, uint8_t tier)
|
||||
{
|
||||
struct fabricd *f = area->fabricd;
|
||||
|
||||
if (!f || f->tier_config == tier)
|
||||
return;
|
||||
|
||||
f->tier_config = tier;
|
||||
fabricd_set_tier(f, tier);
|
||||
}
|
||||
|
||||
uint8_t fabricd_tier(struct isis_area *area)
|
||||
{
|
||||
struct fabricd *f = area->fabricd;
|
||||
|
||||
if (!f)
|
||||
return ISIS_TIER_UNDEFINED;
|
||||
|
||||
return f->tier;
|
||||
}
|
||||
|
||||
int fabricd_write_settings(struct isis_area *area, struct vty *vty)
|
||||
{
|
||||
struct fabricd *f = area->fabricd;
|
||||
int written = 0;
|
||||
|
||||
if (!f)
|
||||
return written;
|
||||
|
||||
if (f->tier_config != ISIS_TIER_UNDEFINED) {
|
||||
vty_out(vty, " fabric-tier %" PRIu8 "\n", f->tier_config);
|
||||
written++;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static void move_to_dnr(struct isis_lsp *lsp, struct neighbor_entry *n)
|
||||
{
|
||||
struct isis_adjacency *adj = listnode_head(n->vertex->Adj_N);
|
||||
|
||||
n->present = false;
|
||||
|
||||
if (isis->debugs & DEBUG_FABRICD_FLOODING) {
|
||||
char buff[PREFIX2STR_BUFFER];
|
||||
zlog_debug("OpenFabric: Adding %s to DNR",
|
||||
vid2string(n->vertex, buff, sizeof(buff)));
|
||||
}
|
||||
|
||||
if (adj) {
|
||||
isis_tx_queue_add(adj->circuit->tx_queue, lsp,
|
||||
TX_LSP_CIRCUIT_SCOPED);
|
||||
}
|
||||
}
|
||||
|
||||
static void move_to_rf(struct isis_lsp *lsp, struct neighbor_entry *n)
|
||||
{
|
||||
struct isis_adjacency *adj = listnode_head(n->vertex->Adj_N);
|
||||
|
||||
n->present = false;
|
||||
|
||||
if (isis->debugs & DEBUG_FABRICD_FLOODING) {
|
||||
char buff[PREFIX2STR_BUFFER];
|
||||
zlog_debug("OpenFabric: Adding %s to RF",
|
||||
vid2string(n->vertex, buff, sizeof(buff)));
|
||||
}
|
||||
|
||||
if (adj) {
|
||||
isis_tx_queue_add(adj->circuit->tx_queue, lsp,
|
||||
TX_LSP_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_neighbor_as_present(struct hash_backet *backet, void *arg)
|
||||
{
|
||||
struct neighbor_entry *n = backet->data;
|
||||
|
||||
n->present = true;
|
||||
}
|
||||
|
||||
static void handle_firsthops(struct hash_backet *backet, void *arg)
|
||||
{
|
||||
struct isis_lsp *lsp = arg;
|
||||
struct fabricd *f = lsp->area->fabricd;
|
||||
struct isis_vertex *vertex = backet->data;
|
||||
|
||||
struct neighbor_entry *n;
|
||||
|
||||
n = neighbor_entry_lookup_list(f->neighbors, vertex->N.id);
|
||||
if (n) {
|
||||
if (isis->debugs & DEBUG_FABRICD_FLOODING) {
|
||||
char buff[PREFIX2STR_BUFFER];
|
||||
zlog_debug("Removing %s from NL as its in the reverse path",
|
||||
vid2string(vertex, buff, sizeof(buff)));
|
||||
}
|
||||
n->present = false;
|
||||
}
|
||||
|
||||
n = neighbor_entry_lookup_hash(f->neighbors_neighbors, vertex->N.id);
|
||||
if (n) {
|
||||
if (isis->debugs & DEBUG_FABRICD_FLOODING) {
|
||||
char buff[PREFIX2STR_BUFFER];
|
||||
zlog_debug("Removing %s from NN as its in the reverse path",
|
||||
vid2string(vertex, buff, sizeof(buff)));
|
||||
}
|
||||
n->present = false;
|
||||
}
|
||||
}
|
||||
|
||||
void fabricd_lsp_flood(struct isis_lsp *lsp)
|
||||
{
|
||||
struct fabricd *f = lsp->area->fabricd;
|
||||
assert(f);
|
||||
|
||||
void *cursor = NULL;
|
||||
struct neighbor_entry *n;
|
||||
|
||||
if (isis->debugs & DEBUG_FABRICD_FLOODING) {
|
||||
zlog_debug("OpenFabric: Flooding LSP %s",
|
||||
rawlspid_print(lsp->hdr.lsp_id));
|
||||
}
|
||||
|
||||
/* Mark all elements in NL as present and move T0s into DNR */
|
||||
while (!skiplist_next(f->neighbors, NULL, (void **)&n, &cursor)) {
|
||||
n->present = true;
|
||||
|
||||
struct isis_lsp *lsp = lsp_for_vertex(f->spftree, n->vertex);
|
||||
if (!lsp || !lsp->tlvs || !lsp->tlvs->spine_leaf)
|
||||
continue;
|
||||
|
||||
if (!lsp->tlvs->spine_leaf->has_tier
|
||||
|| lsp->tlvs->spine_leaf->tier != 0)
|
||||
continue;
|
||||
|
||||
if (isis->debugs & DEBUG_FABRICD_FLOODING) {
|
||||
zlog_debug("Moving %s to DNR because it's T0",
|
||||
rawlspid_print(lsp->hdr.lsp_id));
|
||||
}
|
||||
|
||||
move_to_dnr(lsp, n);
|
||||
}
|
||||
|
||||
/* Mark all elements in NN as present */
|
||||
hash_iterate(f->neighbors_neighbors, mark_neighbor_as_present, NULL);
|
||||
|
||||
struct isis_vertex *originator = isis_find_vertex(&f->spftree->paths,
|
||||
lsp->hdr.lsp_id,
|
||||
VTYPE_NONPSEUDO_TE_IS);
|
||||
|
||||
/* Remove all IS from NL and NN in the shortest path
|
||||
* to the IS that originated the LSP */
|
||||
if (originator)
|
||||
hash_iterate(originator->firsthops, handle_firsthops, lsp);
|
||||
|
||||
/* Iterate over all remaining IS in NL */
|
||||
cursor = NULL;
|
||||
while (!skiplist_next(f->neighbors, NULL, (void **)&n, &cursor)) {
|
||||
if (!n->present)
|
||||
continue;
|
||||
|
||||
struct isis_lsp *nlsp = lsp_for_vertex(f->spftree, n->vertex);
|
||||
if (!nlsp || !nlsp->tlvs) {
|
||||
if (isis->debugs & DEBUG_FABRICD_FLOODING) {
|
||||
char buff[PREFIX2STR_BUFFER];
|
||||
zlog_debug("Moving %s to DNR as it has no LSP",
|
||||
vid2string(n->vertex, buff, sizeof(buff)));
|
||||
}
|
||||
|
||||
move_to_dnr(lsp, n);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isis->debugs & DEBUG_FABRICD_FLOODING) {
|
||||
char buff[PREFIX2STR_BUFFER];
|
||||
zlog_debug("Considering %s from NL...",
|
||||
vid2string(n->vertex, buff, sizeof(buff)));
|
||||
}
|
||||
|
||||
/* For all neighbors of the NL IS check whether they are present
|
||||
* in NN. If yes, remove from NN and set need_reflood. */
|
||||
bool need_reflood = false;
|
||||
struct isis_extended_reach *er;
|
||||
for (er = (struct isis_extended_reach *)nlsp->tlvs->extended_reach.head;
|
||||
er; er = er->next) {
|
||||
struct neighbor_entry *nn;
|
||||
|
||||
nn = neighbor_entry_lookup_hash(f->neighbors_neighbors,
|
||||
er->id);
|
||||
|
||||
if (nn) {
|
||||
if (isis->debugs & DEBUG_FABRICD_FLOODING) {
|
||||
char buff[PREFIX2STR_BUFFER];
|
||||
zlog_debug("Found neighbor %s in NN, removing it from NN and setting reflood.",
|
||||
vid2string(nn->vertex, buff, sizeof(buff)));
|
||||
}
|
||||
|
||||
nn->present = false;
|
||||
need_reflood = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_reflood)
|
||||
move_to_rf(lsp, n);
|
||||
else
|
||||
move_to_dnr(lsp, n);
|
||||
}
|
||||
|
||||
if (isis->debugs & DEBUG_FABRICD_FLOODING) {
|
||||
zlog_debug("OpenFabric: Flooding algorithm complete.");
|
||||
}
|
||||
}
|
||||
|
||||
void fabricd_trigger_csnp(struct isis_area *area)
|
||||
{
|
||||
struct fabricd *f = area->fabricd;
|
||||
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
struct listnode *node;
|
||||
struct isis_circuit *circuit;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
|
||||
if (!circuit->t_send_csnp[1])
|
||||
continue;
|
||||
|
||||
thread_cancel(circuit->t_send_csnp[ISIS_LEVEL2 - 1]);
|
||||
thread_add_timer_msec(master, send_l2_csnp, circuit,
|
||||
isis_jitter(500, CSNP_JITTER),
|
||||
&circuit->t_send_csnp[ISIS_LEVEL2 - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
struct list *fabricd_ip_addrs(struct isis_circuit *circuit)
|
||||
{
|
||||
if (circuit->ip_addrs && listcount(circuit->ip_addrs))
|
||||
return circuit->ip_addrs;
|
||||
|
||||
if (!fabricd || !circuit->area || !circuit->area->circuit_list)
|
||||
return NULL;
|
||||
|
||||
struct listnode *node;
|
||||
struct isis_circuit *c;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(circuit->area->circuit_list, node, c)) {
|
||||
if (c->circ_type != CIRCUIT_T_LOOPBACK)
|
||||
continue;
|
||||
|
||||
if (!c->ip_addrs || !listcount(c->ip_addrs))
|
||||
return NULL;
|
||||
|
||||
return c->ip_addrs;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
27
isisd/fabricd.conf.sample
Normal file
27
isisd/fabricd.conf.sample
Normal file
@ -0,0 +1,27 @@
|
||||
! -*- openfabric -*-
|
||||
!
|
||||
! fabricd sample configuration file
|
||||
!
|
||||
hostname fabricd
|
||||
password foo
|
||||
enable password foo
|
||||
log stdout
|
||||
!log file /tmp/fabricd.log
|
||||
!
|
||||
!
|
||||
router openfabric DEAD
|
||||
net 47.0023.0000.0003.0300.0100.0102.0304.0506.00
|
||||
! lsp-lifetime 65535
|
||||
|
||||
! hostname isisd-router
|
||||
! domain-password foobar
|
||||
|
||||
interface eth0
|
||||
ip router openfabric DEAD
|
||||
! openfabric hello-interval 5
|
||||
! openfabric lsp-interval 1000
|
||||
|
||||
! -- optional
|
||||
! openfabric retransmit-interval 10
|
||||
! openfabric retransmit-throttle-interval
|
||||
!
|
49
isisd/fabricd.h
Normal file
49
isisd/fabricd.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* IS-IS Rout(e)ing protocol - OpenFabric extensions
|
||||
*
|
||||
* Copyright (C) 2018 Christian Franke
|
||||
*
|
||||
* This file is part of FreeRangeRouting (FRR)
|
||||
*
|
||||
* FRR 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, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* FRR 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
|
||||
*/
|
||||
#ifndef FABRICD_H
|
||||
#define FABRICD_H
|
||||
|
||||
struct fabricd;
|
||||
|
||||
struct isis_circuit;
|
||||
struct isis_area;
|
||||
struct isis_spftree;
|
||||
struct isis_lsp;
|
||||
struct vty;
|
||||
|
||||
struct fabricd *fabricd_new(struct isis_area *area);
|
||||
void fabricd_finish(struct fabricd *f);
|
||||
void fabricd_initial_sync_hello(struct isis_circuit *circuit);
|
||||
bool fabricd_initial_sync_is_complete(struct isis_area *area);
|
||||
bool fabricd_initial_sync_is_in_progress(struct isis_area *area);
|
||||
struct isis_circuit *fabricd_initial_sync_circuit(struct isis_area *area);
|
||||
void fabricd_initial_sync_finish(struct isis_area *area);
|
||||
void fabricd_run_spf(struct isis_area *area);
|
||||
struct isis_spftree *fabricd_spftree(struct isis_area *area);
|
||||
void fabricd_configure_tier(struct isis_area *area, uint8_t tier);
|
||||
uint8_t fabricd_tier(struct isis_area *area);
|
||||
int fabricd_write_settings(struct isis_area *area, struct vty *vty);
|
||||
void fabricd_lsp_flood(struct isis_lsp *lsp);
|
||||
void fabricd_trigger_csnp(struct isis_area *area);
|
||||
struct list *fabricd_ip_addrs(struct isis_circuit *circuit);
|
||||
|
||||
#endif
|
@ -48,6 +48,7 @@
|
||||
#include "isisd/isis_events.h"
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/isis_tlvs.h"
|
||||
#include "isisd/fabricd.h"
|
||||
|
||||
extern struct isis *isis;
|
||||
|
||||
@ -193,6 +194,9 @@ void isis_adj_process_threeway(struct isis_adjacency *adj,
|
||||
}
|
||||
}
|
||||
|
||||
if (next_tw_state != ISIS_THREEWAY_DOWN)
|
||||
fabricd_initial_sync_hello(adj->circuit);
|
||||
|
||||
if (next_tw_state == ISIS_THREEWAY_DOWN) {
|
||||
isis_adj_state_change(adj, ISIS_ADJ_DOWN, "Neighbor restarted");
|
||||
return;
|
||||
@ -264,7 +268,7 @@ void isis_adj_state_change(struct isis_adjacency *adj,
|
||||
|
||||
circuit->upadjcount[level - 1]--;
|
||||
if (circuit->upadjcount[level - 1] == 0)
|
||||
isis_circuit_lsp_queue_clean(circuit);
|
||||
isis_tx_queue_clean(circuit->tx_queue);
|
||||
|
||||
isis_event_adjacency_state_change(adj,
|
||||
new_state);
|
||||
@ -306,16 +310,21 @@ void isis_adj_state_change(struct isis_adjacency *adj,
|
||||
adj->last_flap = time(NULL);
|
||||
adj->flaps++;
|
||||
|
||||
/* 7.3.17 - going up on P2P -> send CSNP */
|
||||
/* FIXME: yup, I know its wrong... but i will do
|
||||
* it! (for now) */
|
||||
send_csnp(circuit, level);
|
||||
if (level == IS_LEVEL_1) {
|
||||
thread_add_timer(master, send_l1_csnp,
|
||||
circuit, 0,
|
||||
&circuit->t_send_csnp[0]);
|
||||
} else {
|
||||
thread_add_timer(master, send_l2_csnp,
|
||||
circuit, 0,
|
||||
&circuit->t_send_csnp[1]);
|
||||
}
|
||||
} else if (new_state == ISIS_ADJ_DOWN) {
|
||||
if (adj->circuit->u.p2p.neighbor == adj)
|
||||
adj->circuit->u.p2p.neighbor = NULL;
|
||||
circuit->upadjcount[level - 1]--;
|
||||
if (circuit->upadjcount[level - 1] == 0)
|
||||
isis_circuit_lsp_queue_clean(circuit);
|
||||
isis_tx_queue_clean(circuit->tx_queue);
|
||||
|
||||
isis_event_adjacency_state_change(adj,
|
||||
new_state);
|
||||
|
@ -213,7 +213,7 @@ int isis_sock_init(struct isis_circuit *circuit)
|
||||
|
||||
int isis_recv_pdu_bcast(struct isis_circuit *circuit, uint8_t *ssnpa)
|
||||
{
|
||||
int bytesread = 0, bytestoread, offset, one = 1, err = ISIS_OK;
|
||||
int bytesread = 0, bytestoread, offset, one = 1;
|
||||
uint8_t *buff_ptr;
|
||||
struct bpf_hdr *bpf_hdr;
|
||||
|
||||
@ -249,7 +249,7 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, uint8_t *ssnpa)
|
||||
memcpy(ssnpa, buff_ptr + bpf_hdr->bh_hdrlen + ETHER_ADDR_LEN,
|
||||
ETHER_ADDR_LEN);
|
||||
|
||||
err = isis_handle_pdu(circuit, ssnpa);
|
||||
isis_handle_pdu(circuit, ssnpa);
|
||||
stream_reset(circuit->rcv_stream);
|
||||
buff_ptr += BPF_WORDALIGN(bpf_hdr->bh_hdrlen +
|
||||
bpf_hdr->bh_datalen);
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
#include "isisd/isis_lsp_hash.h"
|
||||
#include "isisd/isis_pdu.h"
|
||||
#include "isisd/isis_network.h"
|
||||
#include "isisd/isis_misc.h"
|
||||
@ -58,6 +57,7 @@
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/isis_errors.h"
|
||||
#include "isisd/isis_tx_queue.h"
|
||||
|
||||
DEFINE_QOBJ_TYPE(isis_circuit)
|
||||
|
||||
@ -412,7 +412,7 @@ void isis_circuit_if_add(struct isis_circuit *circuit, struct interface *ifp)
|
||||
isis_circuit_if_bind(circuit, ifp);
|
||||
|
||||
if (if_is_broadcast(ifp)) {
|
||||
if (circuit->circ_type_config == CIRCUIT_T_P2P)
|
||||
if (fabricd || circuit->circ_type_config == CIRCUIT_T_P2P)
|
||||
circuit->circ_type = CIRCUIT_T_P2P;
|
||||
else
|
||||
circuit->circ_type = CIRCUIT_T_BROADCAST;
|
||||
@ -495,29 +495,29 @@ static void isis_circuit_update_all_srmflags(struct isis_circuit *circuit,
|
||||
{
|
||||
struct isis_area *area;
|
||||
struct isis_lsp *lsp;
|
||||
dnode_t *dnode, *dnode_next;
|
||||
dnode_t *dnode;
|
||||
int level;
|
||||
|
||||
assert(circuit);
|
||||
area = circuit->area;
|
||||
assert(area);
|
||||
for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
|
||||
if (level & circuit->is_type) {
|
||||
if (area->lspdb[level - 1]
|
||||
&& dict_count(area->lspdb[level - 1]) > 0) {
|
||||
if (!(level & circuit->is_type))
|
||||
continue;
|
||||
|
||||
if (!area->lspdb[level - 1]
|
||||
|| !dict_count(area->lspdb[level - 1]))
|
||||
continue;
|
||||
|
||||
for (dnode = dict_first(area->lspdb[level - 1]);
|
||||
dnode != NULL; dnode = dnode_next) {
|
||||
dnode_next = dict_next(
|
||||
area->lspdb[level - 1], dnode);
|
||||
dnode != NULL;
|
||||
dnode = dict_next(area->lspdb[level - 1], dnode)) {
|
||||
lsp = dnode_get(dnode);
|
||||
if (is_set) {
|
||||
ISIS_SET_FLAG(lsp->SRMflags,
|
||||
circuit);
|
||||
isis_tx_queue_add(circuit->tx_queue, lsp,
|
||||
TX_LSP_NORMAL);
|
||||
} else {
|
||||
ISIS_CLEAR_FLAG(lsp->SRMflags,
|
||||
circuit);
|
||||
}
|
||||
}
|
||||
isis_tx_queue_del(circuit->tx_queue, lsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -672,10 +672,7 @@ int isis_circuit_up(struct isis_circuit *circuit)
|
||||
|
||||
isis_circuit_prepare(circuit);
|
||||
|
||||
circuit->lsp_queue = list_new();
|
||||
circuit->lsp_hash = isis_lsp_hash_new();
|
||||
circuit->lsp_queue_last_push[0] = circuit->lsp_queue_last_push[1] =
|
||||
monotime(NULL);
|
||||
circuit->tx_queue = isis_tx_queue_new(circuit, send_lsp);
|
||||
|
||||
return ISIS_OK;
|
||||
}
|
||||
@ -743,13 +740,9 @@ void isis_circuit_down(struct isis_circuit *circuit)
|
||||
THREAD_OFF(circuit->t_send_lsp);
|
||||
THREAD_OFF(circuit->t_read);
|
||||
|
||||
if (circuit->lsp_queue) {
|
||||
list_delete_and_null(&circuit->lsp_queue);
|
||||
}
|
||||
|
||||
if (circuit->lsp_hash) {
|
||||
isis_lsp_hash_free(circuit->lsp_hash);
|
||||
circuit->lsp_hash = NULL;
|
||||
if (circuit->tx_queue) {
|
||||
isis_tx_queue_free(circuit->tx_queue);
|
||||
circuit->tx_queue = NULL;
|
||||
}
|
||||
|
||||
/* send one gratuitous hello to spead up convergence */
|
||||
@ -957,42 +950,44 @@ int isis_interface_config_write(struct vty *vty)
|
||||
if (circuit == NULL)
|
||||
continue;
|
||||
if (circuit->ip_router) {
|
||||
vty_out(vty, " ip router isis %s\n",
|
||||
vty_out(vty, " ip router " PROTO_NAME " %s\n",
|
||||
area->area_tag);
|
||||
write++;
|
||||
}
|
||||
if (circuit->is_passive) {
|
||||
vty_out(vty, " isis passive\n");
|
||||
vty_out(vty, " " PROTO_NAME " passive\n");
|
||||
write++;
|
||||
}
|
||||
if (circuit->circ_type_config == CIRCUIT_T_P2P) {
|
||||
vty_out(vty, " isis network point-to-point\n");
|
||||
vty_out(vty, " " PROTO_NAME " network point-to-point\n");
|
||||
write++;
|
||||
}
|
||||
if (circuit->ipv6_router) {
|
||||
vty_out(vty, " ipv6 router isis %s\n",
|
||||
vty_out(vty, " ipv6 router " PROTO_NAME " %s\n",
|
||||
area->area_tag);
|
||||
write++;
|
||||
}
|
||||
|
||||
/* ISIS - circuit type */
|
||||
if (!fabricd) {
|
||||
if (circuit->is_type == IS_LEVEL_1) {
|
||||
vty_out(vty, " isis circuit-type level-1\n");
|
||||
vty_out(vty, " " PROTO_NAME " circuit-type level-1\n");
|
||||
write++;
|
||||
} else {
|
||||
if (circuit->is_type == IS_LEVEL_2) {
|
||||
vty_out(vty,
|
||||
" isis circuit-type level-2-only\n");
|
||||
" " PROTO_NAME " circuit-type level-2-only\n");
|
||||
write++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ISIS - CSNP interval */
|
||||
if (circuit->csnp_interval[0]
|
||||
== circuit->csnp_interval[1]) {
|
||||
if (circuit->csnp_interval[0]
|
||||
!= DEFAULT_CSNP_INTERVAL) {
|
||||
vty_out(vty, " isis csnp-interval %d\n",
|
||||
vty_out(vty, " " PROTO_NAME " csnp-interval %d\n",
|
||||
circuit->csnp_interval[0]);
|
||||
write++;
|
||||
}
|
||||
@ -1001,7 +996,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
if (circuit->csnp_interval[i]
|
||||
!= DEFAULT_CSNP_INTERVAL) {
|
||||
vty_out(vty,
|
||||
" isis csnp-interval %d level-%d\n",
|
||||
" " PROTO_NAME " csnp-interval %d level-%d\n",
|
||||
circuit->csnp_interval
|
||||
[i],
|
||||
i + 1);
|
||||
@ -1015,7 +1010,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
== circuit->psnp_interval[1]) {
|
||||
if (circuit->psnp_interval[0]
|
||||
!= DEFAULT_PSNP_INTERVAL) {
|
||||
vty_out(vty, " isis psnp-interval %d\n",
|
||||
vty_out(vty, " " PROTO_NAME " psnp-interval %d\n",
|
||||
circuit->psnp_interval[0]);
|
||||
write++;
|
||||
}
|
||||
@ -1024,7 +1019,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
if (circuit->psnp_interval[i]
|
||||
!= DEFAULT_PSNP_INTERVAL) {
|
||||
vty_out(vty,
|
||||
" isis psnp-interval %d level-%d\n",
|
||||
" " PROTO_NAME " psnp-interval %d level-%d\n",
|
||||
circuit->psnp_interval
|
||||
[i],
|
||||
i + 1);
|
||||
@ -1036,7 +1031,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
/* ISIS - Hello padding - Defaults to true so only
|
||||
* display if false */
|
||||
if (circuit->pad_hellos == 0) {
|
||||
vty_out(vty, " no isis hello padding\n");
|
||||
vty_out(vty, " no " PROTO_NAME " hello padding\n");
|
||||
write++;
|
||||
}
|
||||
|
||||
@ -1051,7 +1046,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
if (circuit->hello_interval[0]
|
||||
!= DEFAULT_HELLO_INTERVAL) {
|
||||
vty_out(vty,
|
||||
" isis hello-interval %d\n",
|
||||
" " PROTO_NAME " hello-interval %d\n",
|
||||
circuit->hello_interval[0]);
|
||||
write++;
|
||||
}
|
||||
@ -1060,7 +1055,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
if (circuit->hello_interval[i]
|
||||
!= DEFAULT_HELLO_INTERVAL) {
|
||||
vty_out(vty,
|
||||
" isis hello-interval %d level-%d\n",
|
||||
" " PROTO_NAME " hello-interval %d level-%d\n",
|
||||
circuit->hello_interval
|
||||
[i],
|
||||
i + 1);
|
||||
@ -1075,7 +1070,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
if (circuit->hello_multiplier[0]
|
||||
!= DEFAULT_HELLO_MULTIPLIER) {
|
||||
vty_out(vty,
|
||||
" isis hello-multiplier %d\n",
|
||||
" " PROTO_NAME " hello-multiplier %d\n",
|
||||
circuit->hello_multiplier[0]);
|
||||
write++;
|
||||
}
|
||||
@ -1084,7 +1079,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
if (circuit->hello_multiplier[i]
|
||||
!= DEFAULT_HELLO_MULTIPLIER) {
|
||||
vty_out(vty,
|
||||
" isis hello-multiplier %d level-%d\n",
|
||||
" " PROTO_NAME " hello-multiplier %d level-%d\n",
|
||||
circuit->hello_multiplier
|
||||
[i],
|
||||
i + 1);
|
||||
@ -1096,7 +1091,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
/* ISIS - Priority */
|
||||
if (circuit->priority[0] == circuit->priority[1]) {
|
||||
if (circuit->priority[0] != DEFAULT_PRIORITY) {
|
||||
vty_out(vty, " isis priority %d\n",
|
||||
vty_out(vty, " " PROTO_NAME " priority %d\n",
|
||||
circuit->priority[0]);
|
||||
write++;
|
||||
}
|
||||
@ -1105,7 +1100,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
if (circuit->priority[i]
|
||||
!= DEFAULT_PRIORITY) {
|
||||
vty_out(vty,
|
||||
" isis priority %d level-%d\n",
|
||||
" " PROTO_NAME " priority %d level-%d\n",
|
||||
circuit->priority[i],
|
||||
i + 1);
|
||||
write++;
|
||||
@ -1117,7 +1112,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
if (circuit->te_metric[0] == circuit->te_metric[1]) {
|
||||
if (circuit->te_metric[0]
|
||||
!= DEFAULT_CIRCUIT_METRIC) {
|
||||
vty_out(vty, " isis metric %d\n",
|
||||
vty_out(vty, " " PROTO_NAME " metric %d\n",
|
||||
circuit->te_metric[0]);
|
||||
write++;
|
||||
}
|
||||
@ -1126,7 +1121,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
if (circuit->te_metric[i]
|
||||
!= DEFAULT_CIRCUIT_METRIC) {
|
||||
vty_out(vty,
|
||||
" isis metric %d level-%d\n",
|
||||
" " PROTO_NAME " metric %d level-%d\n",
|
||||
circuit->te_metric[i],
|
||||
i + 1);
|
||||
write++;
|
||||
@ -1134,12 +1129,12 @@ int isis_interface_config_write(struct vty *vty)
|
||||
}
|
||||
}
|
||||
if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) {
|
||||
vty_out(vty, " isis password md5 %s\n",
|
||||
vty_out(vty, " " PROTO_NAME " password md5 %s\n",
|
||||
circuit->passwd.passwd);
|
||||
write++;
|
||||
} else if (circuit->passwd.type
|
||||
== ISIS_PASSWD_TYPE_CLEARTXT) {
|
||||
vty_out(vty, " isis password clear %s\n",
|
||||
vty_out(vty, " " PROTO_NAME " password clear %s\n",
|
||||
circuit->passwd.passwd);
|
||||
write++;
|
||||
}
|
||||
@ -1343,60 +1338,4 @@ void isis_circuit_init()
|
||||
/* Install interface node */
|
||||
install_node(&interface_node, isis_interface_config_write);
|
||||
if_cmd_init();
|
||||
|
||||
isis_vty_init();
|
||||
}
|
||||
|
||||
void isis_circuit_schedule_lsp_send(struct isis_circuit *circuit)
|
||||
{
|
||||
if (circuit->t_send_lsp)
|
||||
return;
|
||||
circuit->t_send_lsp =
|
||||
thread_add_event(master, send_lsp, circuit, 0, NULL);
|
||||
}
|
||||
|
||||
void isis_circuit_queue_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp)
|
||||
{
|
||||
if (isis_lsp_hash_lookup(circuit->lsp_hash, lsp))
|
||||
return;
|
||||
|
||||
listnode_add(circuit->lsp_queue, lsp);
|
||||
isis_lsp_hash_add(circuit->lsp_hash, lsp);
|
||||
isis_circuit_schedule_lsp_send(circuit);
|
||||
}
|
||||
|
||||
void isis_circuit_lsp_queue_clean(struct isis_circuit *circuit)
|
||||
{
|
||||
if (!circuit->lsp_queue)
|
||||
return;
|
||||
|
||||
list_delete_all_node(circuit->lsp_queue);
|
||||
isis_lsp_hash_clean(circuit->lsp_hash);
|
||||
}
|
||||
|
||||
void isis_circuit_cancel_queued_lsp(struct isis_circuit *circuit,
|
||||
struct isis_lsp *lsp)
|
||||
{
|
||||
if (!circuit->lsp_queue)
|
||||
return;
|
||||
|
||||
listnode_delete(circuit->lsp_queue, lsp);
|
||||
isis_lsp_hash_release(circuit->lsp_hash, lsp);
|
||||
}
|
||||
|
||||
struct isis_lsp *isis_circuit_lsp_queue_pop(struct isis_circuit *circuit)
|
||||
{
|
||||
if (!circuit->lsp_queue)
|
||||
return NULL;
|
||||
|
||||
struct listnode *node = listhead(circuit->lsp_queue);
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
struct isis_lsp *rv = listgetdata(node);
|
||||
|
||||
list_delete_node(circuit->lsp_queue, node);
|
||||
isis_lsp_hash_release(circuit->lsp_hash, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -80,14 +80,8 @@ struct isis_circuit {
|
||||
struct thread *t_send_csnp[2];
|
||||
struct thread *t_send_psnp[2];
|
||||
struct thread *t_send_lsp;
|
||||
struct list *lsp_queue; /* LSPs to be txed (both levels) */
|
||||
struct isis_lsp_hash *lsp_hash; /* Hashtable synchronized with lsp_queue */
|
||||
time_t lsp_queue_last_push[2]; /* timestamp used to enforce transmit
|
||||
* interval;
|
||||
* for scalability, use one timestamp per
|
||||
* circuit, instead of one per lsp per
|
||||
* circuit
|
||||
*/
|
||||
struct isis_tx_queue *tx_queue;
|
||||
|
||||
/* there is no real point in two streams, just for programming kicker */
|
||||
int (*rx)(struct isis_circuit *circuit, uint8_t *ssnpa);
|
||||
struct stream *rcv_stream; /* Stream for receiving */
|
||||
@ -114,10 +108,10 @@ struct isis_circuit {
|
||||
struct isis_passwd passwd; /* Circuit rx/tx password */
|
||||
int is_type; /* circuit is type == level of circuit
|
||||
* differentiated from circuit type (media) */
|
||||
uint32_t hello_interval[2]; /* l1HelloInterval in msecs */
|
||||
uint16_t hello_multiplier[2]; /* l1HelloMultiplier */
|
||||
uint16_t csnp_interval[2]; /* level-1 csnp-interval in seconds */
|
||||
uint16_t psnp_interval[2]; /* level-1 psnp-interval in seconds */
|
||||
uint32_t hello_interval[2]; /* hello-interval in seconds */
|
||||
uint16_t hello_multiplier[2]; /* hello-multiplier */
|
||||
uint16_t csnp_interval[2]; /* csnp-interval in seconds */
|
||||
uint16_t psnp_interval[2]; /* psnp-interval in seconds */
|
||||
uint8_t metric[2];
|
||||
uint32_t te_metric[2];
|
||||
struct mpls_te_circuit
|
||||
@ -196,10 +190,4 @@ ferr_r isis_circuit_passwd_hmac_md5_set(struct isis_circuit *circuit,
|
||||
int isis_circuit_mt_enabled_set(struct isis_circuit *circuit, uint16_t mtid,
|
||||
bool enabled);
|
||||
|
||||
void isis_circuit_schedule_lsp_send(struct isis_circuit *circuit);
|
||||
void isis_circuit_queue_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp);
|
||||
void isis_circuit_lsp_queue_clean(struct isis_circuit *circuit);
|
||||
void isis_circuit_cancel_queued_lsp(struct isis_circuit *circuit,
|
||||
struct isis_lsp *lsp);
|
||||
struct isis_lsp *isis_circuit_lsp_queue_pop(struct isis_circuit *circuit);
|
||||
#endif /* _ZEBRA_ISIS_CIRCUIT_H */
|
||||
|
164
isisd/isis_lsp.c
164
isisd/isis_lsp.c
@ -56,6 +56,8 @@
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/isis_tlvs.h"
|
||||
#include "isisd/fabricd.h"
|
||||
#include "isisd/isis_tx_queue.h"
|
||||
|
||||
static int lsp_l1_refresh(struct thread *thread);
|
||||
static int lsp_l2_refresh(struct thread *thread);
|
||||
@ -117,10 +119,9 @@ static void lsp_destroy(struct isis_lsp *lsp)
|
||||
return;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(lsp->area->circuit_list, cnode, circuit))
|
||||
isis_circuit_cancel_queued_lsp(circuit, lsp);
|
||||
isis_tx_queue_del(circuit->tx_queue, lsp);
|
||||
|
||||
ISIS_FLAGS_CLEAR_ALL(lsp->SSNflags);
|
||||
ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags);
|
||||
|
||||
lsp_clear_data(lsp);
|
||||
|
||||
@ -352,7 +353,21 @@ void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno)
|
||||
isis_spf_schedule(lsp->area, lsp->level);
|
||||
}
|
||||
|
||||
static void lsp_purge(struct isis_lsp *lsp, int level)
|
||||
static void lsp_purge_add_poi(struct isis_lsp *lsp,
|
||||
const uint8_t *sender)
|
||||
{
|
||||
if (!lsp->area->purge_originator)
|
||||
return;
|
||||
|
||||
/* add purge originator identification */
|
||||
if (!lsp->tlvs)
|
||||
lsp->tlvs = isis_alloc_tlvs();
|
||||
isis_tlvs_set_purge_originator(lsp->tlvs, isis->sysid, sender);
|
||||
isis_tlvs_set_dynamic_hostname(lsp->tlvs, cmd_hostname_get());
|
||||
}
|
||||
|
||||
static void lsp_purge(struct isis_lsp *lsp, int level,
|
||||
const uint8_t *sender)
|
||||
{
|
||||
/* reset stream */
|
||||
lsp_clear_data(lsp);
|
||||
@ -364,8 +379,10 @@ static void lsp_purge(struct isis_lsp *lsp, int level)
|
||||
lsp->level = level;
|
||||
lsp->age_out = lsp->area->max_lsp_lifetime[level - 1];
|
||||
|
||||
lsp_purge_add_poi(lsp, sender);
|
||||
|
||||
lsp_pack_pdu(lsp);
|
||||
lsp_set_all_srmflags(lsp);
|
||||
lsp_flood(lsp, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -385,7 +402,7 @@ static void lsp_seqno_update(struct isis_lsp *lsp0)
|
||||
if (lsp->tlvs)
|
||||
lsp_inc_seqno(lsp, 0);
|
||||
else
|
||||
lsp_purge(lsp, lsp0->level);
|
||||
lsp_purge(lsp, lsp0->level, NULL);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -425,7 +442,8 @@ static void lsp_update_data(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
|
||||
|
||||
lsp->tlvs = tlvs;
|
||||
|
||||
if (area->dynhostname && lsp->tlvs->hostname) {
|
||||
if (area->dynhostname && lsp->tlvs->hostname
|
||||
&& lsp->hdr.rem_lifetime) {
|
||||
isis_dynhn_insert(lsp->hdr.lsp_id, lsp->tlvs->hostname,
|
||||
(lsp->hdr.lsp_bits & LSPBIT_IST)
|
||||
== IS_LEVEL_1_AND_2
|
||||
@ -462,10 +480,10 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
|
||||
lsp->own_lsp = 0;
|
||||
}
|
||||
|
||||
lsp_update_data(lsp, hdr, tlvs, stream, area, level);
|
||||
if (confusion) {
|
||||
lsp->hdr.rem_lifetime = hdr->rem_lifetime = 0;
|
||||
put_lsp_hdr(lsp, NULL, true);
|
||||
lsp_purge(lsp, level, NULL);
|
||||
} else {
|
||||
lsp_update_data(lsp, hdr, tlvs, stream, area, level);
|
||||
}
|
||||
|
||||
if (LSP_FRAGMENT(lsp->hdr.lsp_id) && !lsp->lspu.zero_lsp) {
|
||||
@ -928,6 +946,14 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
|
||||
lsp_debug("ISIS (%s): Adding circuit specific information.",
|
||||
area->area_tag);
|
||||
|
||||
if (fabricd) {
|
||||
lsp_debug(
|
||||
"ISIS (%s): Adding tier %" PRIu8 " spine-leaf-extension tlv.",
|
||||
area->area_tag, fabricd_tier(area));
|
||||
isis_tlvs_add_spine_leaf(lsp->tlvs, fabricd_tier(area), true,
|
||||
false, false, false);
|
||||
}
|
||||
|
||||
struct isis_circuit *circuit;
|
||||
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
|
||||
if (!circuit->interface)
|
||||
@ -1091,9 +1117,16 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
|
||||
*/
|
||||
subtlv_len = 0;
|
||||
|
||||
uint32_t neighbor_metric;
|
||||
if (fabricd_tier(area) == 0) {
|
||||
neighbor_metric = 0xffe;
|
||||
} else {
|
||||
neighbor_metric = metric;
|
||||
}
|
||||
|
||||
tlvs_add_mt_p2p(lsp->tlvs, circuit,
|
||||
ne_id, metric, subtlvs,
|
||||
subtlv_len);
|
||||
ne_id, neighbor_metric,
|
||||
subtlvs, subtlv_len);
|
||||
}
|
||||
} else {
|
||||
lsp_debug(
|
||||
@ -1192,7 +1225,7 @@ int lsp_generate(struct isis_area *area, int level)
|
||||
/* time to calculate our checksum */
|
||||
lsp_seqno_update(newlsp);
|
||||
newlsp->last_generated = time(NULL);
|
||||
lsp_set_all_srmflags(newlsp);
|
||||
lsp_flood(newlsp, NULL);
|
||||
|
||||
refresh_time = lsp_refresh_time(newlsp, rem_lifetime);
|
||||
|
||||
@ -1223,7 +1256,7 @@ int lsp_generate(struct isis_area *area, int level)
|
||||
}
|
||||
|
||||
/*
|
||||
* Search own LSPs, update holding time and set SRM
|
||||
* Search own LSPs, update holding time and flood
|
||||
*/
|
||||
static int lsp_regenerate(struct isis_area *area, int level)
|
||||
{
|
||||
@ -1255,7 +1288,7 @@ static int lsp_regenerate(struct isis_area *area, int level)
|
||||
rem_lifetime = lsp_rem_lifetime(area, level);
|
||||
lsp->hdr.rem_lifetime = rem_lifetime;
|
||||
lsp->last_generated = time(NULL);
|
||||
lsp_set_all_srmflags(lsp);
|
||||
lsp_flood(lsp, NULL);
|
||||
for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
|
||||
frag->hdr.lsp_bits = lsp_bits_generate(
|
||||
level, area->overload_bit, area->attached_bit);
|
||||
@ -1265,7 +1298,7 @@ static int lsp_regenerate(struct isis_area *area, int level)
|
||||
*/
|
||||
frag->hdr.rem_lifetime = rem_lifetime;
|
||||
frag->age_out = ZERO_AGE_LIFETIME;
|
||||
lsp_set_all_srmflags(frag);
|
||||
lsp_flood(frag, NULL);
|
||||
}
|
||||
lsp_seqno_update(lsp);
|
||||
|
||||
@ -1565,7 +1598,7 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level)
|
||||
lsp_pack_pdu(lsp);
|
||||
lsp->own_lsp = 1;
|
||||
lsp_insert(lsp, lspdb);
|
||||
lsp_set_all_srmflags(lsp);
|
||||
lsp_flood(lsp, NULL);
|
||||
|
||||
refresh_time = lsp_refresh_time(lsp, rem_lifetime);
|
||||
THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[level - 1]);
|
||||
@ -1624,7 +1657,7 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level)
|
||||
lsp_build_pseudo(lsp, circuit, level);
|
||||
lsp_inc_seqno(lsp, 0);
|
||||
lsp->last_generated = time(NULL);
|
||||
lsp_set_all_srmflags(lsp);
|
||||
lsp_flood(lsp, NULL);
|
||||
|
||||
refresh_time = lsp_refresh_time(lsp, rem_lifetime);
|
||||
if (level == IS_LEVEL_1)
|
||||
@ -1800,30 +1833,25 @@ int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level)
|
||||
/*
|
||||
* Walk through LSPs for an area
|
||||
* - set remaining lifetime
|
||||
* - set LSPs with SRMflag set for sending
|
||||
*/
|
||||
int lsp_tick(struct thread *thread)
|
||||
{
|
||||
struct isis_area *area;
|
||||
struct isis_circuit *circuit;
|
||||
struct isis_lsp *lsp;
|
||||
struct list *lsp_list;
|
||||
struct listnode *lspnode, *cnode;
|
||||
dnode_t *dnode, *dnode_next;
|
||||
int level;
|
||||
uint16_t rem_lifetime;
|
||||
time_t now = monotime(NULL);
|
||||
|
||||
lsp_list = list_new();
|
||||
bool fabricd_sync_incomplete = false;
|
||||
|
||||
area = THREAD_ARG(thread);
|
||||
assert(area);
|
||||
area->t_tick = NULL;
|
||||
thread_add_timer(master, lsp_tick, area, 1, &area->t_tick);
|
||||
|
||||
struct isis_circuit *fabricd_init_c = fabricd_initial_sync_circuit(area);
|
||||
|
||||
/*
|
||||
* Build a list of LSPs with (any) SRMflag set
|
||||
* and removed the ones that have aged out
|
||||
* Remove LSPs which have aged out
|
||||
*/
|
||||
for (level = 0; level < ISIS_LEVELS; level++) {
|
||||
if (area->lspdb[level] && dict_count(area->lspdb[level]) > 0) {
|
||||
@ -1854,17 +1882,14 @@ int lsp_tick(struct thread *thread)
|
||||
*/
|
||||
if (rem_lifetime == 1 && lsp->hdr.seqno != 0) {
|
||||
/* 7.3.16.4 a) set SRM flags on all */
|
||||
lsp_set_all_srmflags(lsp);
|
||||
/* 7.3.16.4 b) retain only the header
|
||||
* FIXME */
|
||||
/* 7.3.16.4 b) retain only the header */
|
||||
if (lsp->area->purge_originator)
|
||||
lsp_purge(lsp, lsp->level, NULL);
|
||||
else
|
||||
lsp_flood(lsp, NULL);
|
||||
/* 7.3.16.4 c) record the time to purge
|
||||
* FIXME */
|
||||
/* run/schedule spf */
|
||||
/* isis_spf_schedule is called inside
|
||||
* lsp_destroy() below;
|
||||
* so it is not needed here. */
|
||||
/* isis_spf_schedule (lsp->area,
|
||||
* lsp->level); */
|
||||
isis_spf_schedule(lsp->area, lsp->level);
|
||||
}
|
||||
|
||||
if (lsp->age_out == 0) {
|
||||
@ -1878,44 +1903,22 @@ int lsp_tick(struct thread *thread)
|
||||
lsp = NULL;
|
||||
dict_delete_free(area->lspdb[level],
|
||||
dnode);
|
||||
} else if (flags_any_set(lsp->SRMflags))
|
||||
listnode_add(lsp_list, lsp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send LSPs on circuits indicated by the SRMflags
|
||||
*/
|
||||
if (listcount(lsp_list) > 0) {
|
||||
for (ALL_LIST_ELEMENTS_RO(area->circuit_list,
|
||||
cnode, circuit)) {
|
||||
if (!circuit->lsp_queue)
|
||||
continue;
|
||||
|
||||
if (now - circuit->lsp_queue_last_push[level]
|
||||
< MIN_LSP_RETRANS_INTERVAL) {
|
||||
continue;
|
||||
if (fabricd_init_c) {
|
||||
fabricd_sync_incomplete |=
|
||||
ISIS_CHECK_FLAG(lsp->SSNflags,
|
||||
fabricd_init_c);
|
||||
}
|
||||
|
||||
circuit->lsp_queue_last_push[level] = now;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(
|
||||
lsp_list, lspnode, lsp)) {
|
||||
if (circuit->upadjcount
|
||||
[lsp->level - 1]
|
||||
&& ISIS_CHECK_FLAG(
|
||||
lsp->SRMflags,
|
||||
circuit)) {
|
||||
isis_circuit_queue_lsp(
|
||||
circuit, lsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
list_delete_all_node(lsp_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list_delete_and_null(&lsp_list);
|
||||
if (fabricd_init_c
|
||||
&& !fabricd_sync_incomplete
|
||||
&& !isis_tx_queue_len(fabricd_init_c->tx_queue)) {
|
||||
fabricd_initial_sync_finish(area);
|
||||
}
|
||||
|
||||
return ISIS_OK;
|
||||
}
|
||||
@ -1928,7 +1931,7 @@ void lsp_purge_pseudo(uint8_t *id, struct isis_circuit *circuit, int level)
|
||||
if (!lsp)
|
||||
return;
|
||||
|
||||
lsp_purge(lsp, level);
|
||||
lsp_purge(lsp, level, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1952,27 +1955,44 @@ void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr,
|
||||
memcpy(&lsp->hdr, hdr, sizeof(lsp->hdr));
|
||||
lsp->hdr.rem_lifetime = 0;
|
||||
|
||||
lsp_purge_add_poi(lsp, NULL);
|
||||
|
||||
lsp_pack_pdu(lsp);
|
||||
|
||||
lsp_insert(lsp, area->lspdb[lsp->level - 1]);
|
||||
lsp_set_all_srmflags(lsp);
|
||||
lsp_flood(lsp, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void lsp_set_all_srmflags(struct isis_lsp *lsp)
|
||||
void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct isis_circuit *circuit;
|
||||
|
||||
assert(lsp);
|
||||
|
||||
ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags);
|
||||
if (!lsp->area)
|
||||
return;
|
||||
|
||||
if (lsp->area) {
|
||||
struct list *circuit_list = lsp->area->circuit_list;
|
||||
for (ALL_LIST_ELEMENTS_RO(circuit_list, node, circuit)) {
|
||||
ISIS_SET_FLAG(lsp->SRMflags, circuit);
|
||||
if (set) {
|
||||
isis_tx_queue_add(circuit->tx_queue, lsp,
|
||||
TX_LSP_NORMAL);
|
||||
} else {
|
||||
isis_tx_queue_del(circuit->tx_queue, lsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit)
|
||||
{
|
||||
if (!fabricd) {
|
||||
lsp_set_all_srmflags(lsp, true);
|
||||
if (circuit)
|
||||
isis_tx_queue_del(circuit->tx_queue, lsp);
|
||||
} else {
|
||||
fabricd_lsp_flood(lsp);
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ struct isis_lsp {
|
||||
struct list *frags;
|
||||
struct isis_lsp *zero_lsp;
|
||||
} lspu;
|
||||
uint32_t SRMflags[ISIS_MAX_CIRCUITS];
|
||||
uint32_t SSNflags[ISIS_MAX_CIRCUITS];
|
||||
int level; /* L1 or L2? */
|
||||
int scheduled; /* scheduled for sending */
|
||||
@ -100,6 +99,7 @@ void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost);
|
||||
void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost);
|
||||
int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost);
|
||||
/* sets SRMflags for all active circuits of an lsp */
|
||||
void lsp_set_all_srmflags(struct isis_lsp *lsp);
|
||||
void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set);
|
||||
void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit);
|
||||
|
||||
#endif /* ISIS_LSP */
|
||||
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* IS-IS Rout(e)ing protocol - LSP Hash
|
||||
*
|
||||
* Copyright (C) 2017 Christian Franke
|
||||
*
|
||||
* This file is part of FreeRangeRouting (FRR)
|
||||
*
|
||||
* FRR 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, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* FRR 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>
|
||||
|
||||
#include "hash.h"
|
||||
#include "jhash.h"
|
||||
|
||||
#include "isisd/isis_memory.h"
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "dict.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
#include "isisd/isis_lsp_hash.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(ISISD, LSP_HASH, "ISIS LSP Hash")
|
||||
|
||||
struct isis_lsp_hash {
|
||||
struct hash *h;
|
||||
};
|
||||
|
||||
static unsigned lsp_hash_key(void *lp)
|
||||
{
|
||||
struct isis_lsp *lsp = lp;
|
||||
|
||||
return jhash(lsp->hdr.lsp_id, ISIS_SYS_ID_LEN + 2, 0x55aa5a5a);
|
||||
}
|
||||
|
||||
static int lsp_hash_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct isis_lsp *la = a, *lb = b;
|
||||
|
||||
return 0 == memcmp(la->hdr.lsp_id, lb->hdr.lsp_id, ISIS_SYS_ID_LEN + 2);
|
||||
}
|
||||
|
||||
struct isis_lsp_hash *isis_lsp_hash_new(void)
|
||||
{
|
||||
struct isis_lsp_hash *rv = XCALLOC(MTYPE_LSP_HASH, sizeof(*rv));
|
||||
|
||||
rv->h = hash_create(lsp_hash_key, lsp_hash_cmp, NULL);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void isis_lsp_hash_clean(struct isis_lsp_hash *ih)
|
||||
{
|
||||
hash_clean(ih->h, NULL);
|
||||
}
|
||||
|
||||
void isis_lsp_hash_free(struct isis_lsp_hash *ih)
|
||||
{
|
||||
isis_lsp_hash_clean(ih);
|
||||
hash_free(ih->h);
|
||||
}
|
||||
|
||||
struct isis_lsp *isis_lsp_hash_lookup(struct isis_lsp_hash *ih,
|
||||
struct isis_lsp *lsp)
|
||||
{
|
||||
return hash_lookup(ih->h, lsp);
|
||||
}
|
||||
|
||||
void isis_lsp_hash_add(struct isis_lsp_hash *ih, struct isis_lsp *lsp)
|
||||
{
|
||||
struct isis_lsp *inserted;
|
||||
inserted = hash_get(ih->h, lsp, hash_alloc_intern);
|
||||
assert(inserted == lsp);
|
||||
}
|
||||
|
||||
void isis_lsp_hash_release(struct isis_lsp_hash *ih, struct isis_lsp *lsp)
|
||||
{
|
||||
hash_release(ih->h, lsp);
|
||||
}
|
@ -54,11 +54,13 @@
|
||||
#include "isisd/isis_zebra.h"
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_errors.h"
|
||||
#include "isisd/isis_vty_common.h"
|
||||
|
||||
/* Default configuration file name */
|
||||
#define ISISD_DEFAULT_CONFIG "isisd.conf"
|
||||
/* Default vty port */
|
||||
#define ISISD_VTY_PORT 2608
|
||||
#define FABRICD_VTY_PORT 2618
|
||||
|
||||
/* isisd privileges */
|
||||
zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND};
|
||||
@ -145,9 +147,15 @@ struct quagga_signal_t isisd_signals[] = {
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef FABRICD
|
||||
FRR_DAEMON_INFO(fabricd, OPEN_FABRIC, .vty_port = FABRICD_VTY_PORT,
|
||||
|
||||
.proghelp = "Implementation of the OpenFabric routing protocol.",
|
||||
#else
|
||||
FRR_DAEMON_INFO(isisd, ISIS, .vty_port = ISISD_VTY_PORT,
|
||||
|
||||
.proghelp = "Implementation of the IS-IS routing protocol.",
|
||||
#endif
|
||||
.copyright =
|
||||
"Copyright (c) 2001-2002 Sampo Saaristo,"
|
||||
" Ofer Wald and Hannes Gredler",
|
||||
@ -164,7 +172,11 @@ int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
int opt;
|
||||
|
||||
#ifdef FABRICD
|
||||
frr_preinit(&fabricd_di, argc, argv);
|
||||
#else
|
||||
frr_preinit(&isisd_di, argc, argv);
|
||||
#endif
|
||||
frr_opt_add("", longopts, "");
|
||||
|
||||
/* Command line argument treatment. */
|
||||
@ -196,6 +208,7 @@ int main(int argc, char **argv, char **envp)
|
||||
prefix_list_init();
|
||||
isis_init();
|
||||
isis_circuit_init();
|
||||
isis_vty_init();
|
||||
isis_spf_cmds_init();
|
||||
isis_redist_init();
|
||||
isis_route_map_init();
|
||||
|
@ -311,7 +311,7 @@ int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty)
|
||||
for (ALL_LIST_ELEMENTS_RO(circuit->mt_settings, node, setting)) {
|
||||
const char *name = isis_mtid2str(setting->mtid);
|
||||
if (name && !setting->enabled) {
|
||||
vty_out(vty, " no isis topology %s\n", name);
|
||||
vty_out(vty, " no " PROTO_NAME " topology %s\n", name);
|
||||
written++;
|
||||
}
|
||||
}
|
||||
|
181
isisd/isis_pdu.c
181
isisd/isis_pdu.c
@ -56,6 +56,8 @@
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/isis_tlvs.h"
|
||||
#include "isisd/isis_errors.h"
|
||||
#include "isisd/fabricd.h"
|
||||
#include "isisd/isis_tx_queue.h"
|
||||
|
||||
static int ack_lsp(struct isis_lsp_hdr *hdr, struct isis_circuit *circuit,
|
||||
int level)
|
||||
@ -207,6 +209,12 @@ static int process_p2p_hello(struct iih_info *iih)
|
||||
thread_add_timer(master, isis_adj_expire, adj, (long)adj->hold_time,
|
||||
&adj->t_expire);
|
||||
|
||||
/* While fabricds initial sync is in progress, ignore hellos from other
|
||||
* interfaces than the one we are performing the initial sync on. */
|
||||
if (fabricd_initial_sync_is_in_progress(iih->circuit->area)
|
||||
&& fabricd_initial_sync_circuit(iih->circuit->area) != iih->circuit)
|
||||
return ISIS_OK;
|
||||
|
||||
/* 8.2.5.2 a) a match was detected */
|
||||
if (isis_tlvs_area_addresses_match(iih->tlvs,
|
||||
iih->circuit->area->area_addrs)) {
|
||||
@ -671,7 +679,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
|
||||
goto out;
|
||||
}
|
||||
|
||||
iih.v4_usable = (circuit->ip_addrs && listcount(circuit->ip_addrs)
|
||||
iih.v4_usable = (fabricd_ip_addrs(circuit)
|
||||
&& iih.tlvs->ipv4_address.count);
|
||||
|
||||
iih.v6_usable = (circuit->ipv6_link && listcount(circuit->ipv6_link)
|
||||
@ -700,14 +708,37 @@ out:
|
||||
* Section 7.3.15.1 - Action on receipt of a link state PDU
|
||||
*/
|
||||
static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
|
||||
const uint8_t *ssnpa)
|
||||
const uint8_t *ssnpa, uint8_t max_area_addrs)
|
||||
{
|
||||
int level = (pdu_type == L1_LINK_STATE) ? ISIS_LEVEL1 : ISIS_LEVEL2;
|
||||
int level;
|
||||
bool circuit_scoped;
|
||||
|
||||
if (pdu_type == FS_LINK_STATE) {
|
||||
if (!fabricd)
|
||||
return ISIS_ERROR;
|
||||
if (max_area_addrs != L2_CIRCUIT_FLOODING_SCOPE)
|
||||
return ISIS_ERROR;
|
||||
level = ISIS_LEVEL2;
|
||||
circuit_scoped = true;
|
||||
|
||||
/* The stream is used verbatim for sending out new LSPDUs.
|
||||
* So make sure we store it as an L2 LSPDU internally.
|
||||
* (compare for the reverse in `send_lsp`) */
|
||||
stream_putc_at(circuit->rcv_stream, 4, L2_LINK_STATE);
|
||||
stream_putc_at(circuit->rcv_stream, 7, 0);
|
||||
} else {
|
||||
if (pdu_type == L1_LINK_STATE)
|
||||
level = ISIS_LEVEL1;
|
||||
else
|
||||
level = ISIS_LEVEL2;
|
||||
circuit_scoped = false;
|
||||
}
|
||||
|
||||
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
|
||||
zlog_debug(
|
||||
"ISIS-Upd (%s): Rcvd L%d LSP on %s, cirType %s, cirID %u",
|
||||
circuit->area->area_tag, level,
|
||||
"ISIS-Upd (%s): Rcvd %sL%d LSP on %s, cirType %s, cirID %u",
|
||||
circuit->area->area_tag,
|
||||
circuit_scoped ? "Circuit scoped " : "", level,
|
||||
circuit->interface->name,
|
||||
circuit_t2string(circuit->is_type),
|
||||
circuit->circuit_id);
|
||||
@ -869,7 +900,8 @@ dontcheckadj:
|
||||
* but
|
||||
* wrong checksum, initiate a purge. */
|
||||
if (lsp && (lsp->hdr.seqno == hdr.seqno)
|
||||
&& (lsp->hdr.checksum != hdr.checksum)) {
|
||||
&& (lsp->hdr.checksum != hdr.checksum)
|
||||
&& hdr.rem_lifetime) {
|
||||
zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08" PRIx32
|
||||
" with confused checksum received.",
|
||||
circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
|
||||
@ -899,7 +931,8 @@ dontcheckadj:
|
||||
lsp_confusion);
|
||||
tlvs = NULL;
|
||||
/* ii */
|
||||
lsp_set_all_srmflags(lsp);
|
||||
if (!circuit_scoped)
|
||||
lsp_flood(lsp, NULL);
|
||||
/* v */
|
||||
ISIS_FLAGS_CLEAR_ALL(
|
||||
lsp->SSNflags); /* FIXME:
|
||||
@ -913,9 +946,10 @@ dontcheckadj:
|
||||
* Otherwise, don't reflood
|
||||
* through incoming circuit as usual */
|
||||
if (!lsp_confusion) {
|
||||
/* iii */
|
||||
ISIS_CLEAR_FLAG(lsp->SRMflags,
|
||||
circuit);
|
||||
isis_tx_queue_del(
|
||||
circuit->tx_queue,
|
||||
lsp);
|
||||
|
||||
/* iv */
|
||||
if (circuit->circ_type
|
||||
!= CIRCUIT_T_BROADCAST)
|
||||
@ -926,7 +960,8 @@ dontcheckadj:
|
||||
} /* 7.3.16.4 b) 2) */
|
||||
else if (comp == LSP_EQUAL) {
|
||||
/* i */
|
||||
ISIS_CLEAR_FLAG(lsp->SRMflags, circuit);
|
||||
isis_tx_queue_del(circuit->tx_queue,
|
||||
lsp);
|
||||
/* ii */
|
||||
if (circuit->circ_type
|
||||
!= CIRCUIT_T_BROADCAST)
|
||||
@ -934,16 +969,19 @@ dontcheckadj:
|
||||
circuit);
|
||||
} /* 7.3.16.4 b) 3) */
|
||||
else {
|
||||
ISIS_SET_FLAG(lsp->SRMflags, circuit);
|
||||
isis_tx_queue_add(circuit->tx_queue,
|
||||
lsp, TX_LSP_NORMAL);
|
||||
ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
|
||||
}
|
||||
} else if (lsp->hdr.rem_lifetime != 0) {
|
||||
/* our own LSP -> 7.3.16.4 c) */
|
||||
if (comp == LSP_NEWER) {
|
||||
lsp_inc_seqno(lsp, hdr.seqno);
|
||||
lsp_set_all_srmflags(lsp);
|
||||
if (!circuit_scoped)
|
||||
lsp_flood(lsp, NULL);
|
||||
} else {
|
||||
ISIS_SET_FLAG(lsp->SRMflags, circuit);
|
||||
isis_tx_queue_add(circuit->tx_queue,
|
||||
lsp, TX_LSP_NORMAL);
|
||||
ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
|
||||
}
|
||||
if (isis->debugs & DEBUG_UPDATE_PACKETS)
|
||||
@ -985,7 +1023,7 @@ dontcheckadj:
|
||||
}
|
||||
/* If the received LSP is older or equal,
|
||||
* resend the LSP which will act as ACK */
|
||||
lsp_set_all_srmflags(lsp);
|
||||
lsp_flood(lsp, NULL);
|
||||
} else {
|
||||
/* 7.3.15.1 e) - This lsp originated on another system */
|
||||
|
||||
@ -1006,7 +1044,7 @@ dontcheckadj:
|
||||
if (!lsp0) {
|
||||
zlog_debug(
|
||||
"Got lsp frag, while zero lsp not in database");
|
||||
return ISIS_OK;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* i */
|
||||
@ -1023,10 +1061,8 @@ dontcheckadj:
|
||||
circuit->area, level, false);
|
||||
tlvs = NULL;
|
||||
}
|
||||
/* ii */
|
||||
lsp_set_all_srmflags(lsp);
|
||||
/* iii */
|
||||
ISIS_CLEAR_FLAG(lsp->SRMflags, circuit);
|
||||
if (!circuit_scoped)
|
||||
lsp_flood(lsp, circuit);
|
||||
|
||||
/* iv */
|
||||
if (circuit->circ_type != CIRCUIT_T_BROADCAST)
|
||||
@ -1035,7 +1071,7 @@ dontcheckadj:
|
||||
}
|
||||
/* 7.3.15.1 e) 2) LSP equal to the one in db */
|
||||
else if (comp == LSP_EQUAL) {
|
||||
ISIS_CLEAR_FLAG(lsp->SRMflags, circuit);
|
||||
isis_tx_queue_del(circuit->tx_queue, lsp);
|
||||
lsp_update(lsp, &hdr, tlvs, circuit->rcv_stream,
|
||||
circuit->area, level, false);
|
||||
tlvs = NULL;
|
||||
@ -1044,7 +1080,8 @@ dontcheckadj:
|
||||
}
|
||||
/* 7.3.15.1 e) 3) LSP older than the one in db */
|
||||
else {
|
||||
ISIS_SET_FLAG(lsp->SRMflags, circuit);
|
||||
isis_tx_queue_add(circuit->tx_queue, lsp,
|
||||
TX_LSP_NORMAL);
|
||||
ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
|
||||
}
|
||||
}
|
||||
@ -1052,6 +1089,10 @@ dontcheckadj:
|
||||
retval = ISIS_OK;
|
||||
|
||||
out:
|
||||
if (circuit_scoped) {
|
||||
fabricd_trigger_csnp(circuit->area);
|
||||
}
|
||||
|
||||
isis_free_tlvs(tlvs);
|
||||
return retval;
|
||||
}
|
||||
@ -1157,7 +1198,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
|
||||
circuit->u.bc.adjdb[level - 1]))
|
||||
return ISIS_OK; /* Silently discard */
|
||||
} else {
|
||||
if (!circuit->u.p2p.neighbor) {
|
||||
if (!fabricd && !circuit->u.p2p.neighbor) {
|
||||
zlog_warn("no p2p neighbor on circuit %s",
|
||||
circuit->interface->name);
|
||||
return ISIS_OK; /* Silently discard */
|
||||
@ -1206,6 +1247,8 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
|
||||
}
|
||||
}
|
||||
|
||||
bool resync_needed = false;
|
||||
|
||||
/* 7.3.15.2 b) Actions on LSP_ENTRIES reported */
|
||||
for (struct isis_lsp_entry *entry = entry_head; entry;
|
||||
entry = entry->next) {
|
||||
@ -1221,25 +1264,28 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
|
||||
if (cmp == LSP_EQUAL) {
|
||||
/* if (circuit->circ_type !=
|
||||
* CIRCUIT_T_BROADCAST) */
|
||||
ISIS_CLEAR_FLAG(lsp->SRMflags, circuit);
|
||||
isis_tx_queue_del(circuit->tx_queue, lsp);
|
||||
}
|
||||
/* 7.3.15.2 b) 3) if it is older, clear SSN and set SRM
|
||||
*/
|
||||
else if (cmp == LSP_OLDER) {
|
||||
ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);
|
||||
ISIS_SET_FLAG(lsp->SRMflags, circuit);
|
||||
isis_tx_queue_add(circuit->tx_queue, lsp,
|
||||
TX_LSP_NORMAL);
|
||||
}
|
||||
/* 7.3.15.2 b) 4) if it is newer, set SSN and clear SRM
|
||||
on p2p */
|
||||
else {
|
||||
if (own_lsp) {
|
||||
lsp_inc_seqno(lsp, entry->seqno);
|
||||
ISIS_SET_FLAG(lsp->SRMflags, circuit);
|
||||
isis_tx_queue_add(circuit->tx_queue, lsp,
|
||||
TX_LSP_NORMAL);
|
||||
} else {
|
||||
ISIS_SET_FLAG(lsp->SSNflags, circuit);
|
||||
/* if (circuit->circ_type !=
|
||||
* CIRCUIT_T_BROADCAST) */
|
||||
ISIS_CLEAR_FLAG(lsp->SRMflags, circuit);
|
||||
isis_tx_queue_del(circuit->tx_queue, lsp);
|
||||
resync_needed = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1271,8 +1317,10 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
|
||||
entry->checksum, lsp0, level);
|
||||
lsp_insert(lsp,
|
||||
circuit->area->lspdb[level - 1]);
|
||||
ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags);
|
||||
|
||||
lsp_set_all_srmflags(lsp, false);
|
||||
ISIS_SET_FLAG(lsp->SSNflags, circuit);
|
||||
resync_needed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1303,12 +1351,18 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
|
||||
}
|
||||
|
||||
/* on remaining LSPs we set SRM (neighbor knew not of) */
|
||||
for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp))
|
||||
ISIS_SET_FLAG(lsp->SRMflags, circuit);
|
||||
for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) {
|
||||
isis_tx_queue_add(circuit->tx_queue, lsp, TX_LSP_NORMAL);
|
||||
resync_needed = true;
|
||||
}
|
||||
|
||||
/* lets free it */
|
||||
list_delete_and_null(&lsp_list);
|
||||
}
|
||||
|
||||
if (fabricd_initial_sync_is_complete(circuit->area) && resync_needed)
|
||||
zlog_warn("OpenFabric: Needed to resync LSPDB using CSNP!\n");
|
||||
|
||||
retval = ISIS_OK;
|
||||
out:
|
||||
isis_free_tlvs(tlvs);
|
||||
@ -1327,6 +1381,7 @@ static int pdu_size(uint8_t pdu_type, uint8_t *size)
|
||||
break;
|
||||
case L1_LINK_STATE:
|
||||
case L2_LINK_STATE:
|
||||
case FS_LINK_STATE:
|
||||
*size = ISIS_LSP_HDR_LEN;
|
||||
break;
|
||||
case L1_COMPLETE_SEQ_NUM:
|
||||
@ -1427,7 +1482,9 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
|
||||
}
|
||||
|
||||
/* either 3 or 0 */
|
||||
if (max_area_addrs != 0 && max_area_addrs != isis->max_area_addrs) {
|
||||
if (pdu_type != FS_LINK_STATE /* FS PDU doesn't contain max area addr field */
|
||||
&& max_area_addrs != 0
|
||||
&& max_area_addrs != isis->max_area_addrs) {
|
||||
flog_err(
|
||||
ISIS_ERR_PACKET,
|
||||
"maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8
|
||||
@ -1440,11 +1497,18 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
|
||||
case L1_LAN_HELLO:
|
||||
case L2_LAN_HELLO:
|
||||
case P2P_HELLO:
|
||||
if (fabricd && pdu_type != P2P_HELLO)
|
||||
return ISIS_ERROR;
|
||||
retval = process_hello(pdu_type, circuit, ssnpa);
|
||||
break;
|
||||
case L1_LINK_STATE:
|
||||
case L2_LINK_STATE:
|
||||
retval = process_lsp(pdu_type, circuit, ssnpa);
|
||||
case FS_LINK_STATE:
|
||||
if (fabricd
|
||||
&& pdu_type != L2_LINK_STATE
|
||||
&& pdu_type != FS_LINK_STATE)
|
||||
return ISIS_ERROR;
|
||||
retval = process_lsp(pdu_type, circuit, ssnpa, max_area_addrs);
|
||||
break;
|
||||
case L1_COMPLETE_SEQ_NUM:
|
||||
case L2_COMPLETE_SEQ_NUM:
|
||||
@ -1582,8 +1646,15 @@ int send_hello(struct isis_circuit *circuit, int level)
|
||||
&& !circuit->disable_threeway_adj) {
|
||||
uint32_t ext_circuit_id = circuit->idx;
|
||||
if (circuit->u.p2p.neighbor) {
|
||||
uint8_t threeway_state;
|
||||
|
||||
if (fabricd_initial_sync_is_in_progress(circuit->area)
|
||||
&& fabricd_initial_sync_circuit(circuit->area) != circuit)
|
||||
threeway_state = ISIS_THREEWAY_DOWN;
|
||||
else
|
||||
threeway_state = circuit->u.p2p.neighbor->threeway_state;
|
||||
isis_tlvs_add_threeway_adj(tlvs,
|
||||
circuit->u.p2p.neighbor->threeway_state,
|
||||
threeway_state,
|
||||
ext_circuit_id,
|
||||
circuit->u.p2p.neighbor->sysid,
|
||||
circuit->u.p2p.neighbor->ext_circuit_id);
|
||||
@ -1618,8 +1689,12 @@ int send_hello(struct isis_circuit *circuit, int level)
|
||||
false, false);
|
||||
}
|
||||
|
||||
if (circuit->ip_router && circuit->ip_addrs)
|
||||
isis_tlvs_add_ipv4_addresses(tlvs, circuit->ip_addrs);
|
||||
if (circuit->ip_router) {
|
||||
struct list *circuit_ip_addrs = fabricd_ip_addrs(circuit);
|
||||
|
||||
if (circuit_ip_addrs)
|
||||
isis_tlvs_add_ipv4_addresses(tlvs, circuit_ip_addrs);
|
||||
}
|
||||
|
||||
if (circuit->ipv6_router && circuit->ipv6_link)
|
||||
isis_tlvs_add_ipv6_addresses(tlvs, circuit->ipv6_link);
|
||||
@ -1889,8 +1964,9 @@ int send_l1_csnp(struct thread *thread)
|
||||
|
||||
circuit->t_send_csnp[0] = NULL;
|
||||
|
||||
if (circuit->circ_type == CIRCUIT_T_BROADCAST
|
||||
&& circuit->u.bc.is_dr[0]) {
|
||||
if ((circuit->circ_type == CIRCUIT_T_BROADCAST
|
||||
&& circuit->u.bc.is_dr[0])
|
||||
|| circuit->circ_type == CIRCUIT_T_P2P) {
|
||||
send_csnp(circuit, 1);
|
||||
}
|
||||
/* set next timer thread */
|
||||
@ -1911,8 +1987,9 @@ int send_l2_csnp(struct thread *thread)
|
||||
|
||||
circuit->t_send_csnp[1] = NULL;
|
||||
|
||||
if (circuit->circ_type == CIRCUIT_T_BROADCAST
|
||||
&& circuit->u.bc.is_dr[1]) {
|
||||
if ((circuit->circ_type == CIRCUIT_T_BROADCAST
|
||||
&& circuit->u.bc.is_dr[1])
|
||||
|| circuit->circ_type == CIRCUIT_T_P2P) {
|
||||
send_csnp(circuit, 2);
|
||||
}
|
||||
/* set next timer thread */
|
||||
@ -2086,25 +2163,12 @@ int send_l2_psnp(struct thread *thread)
|
||||
/*
|
||||
* ISO 10589 - 7.3.14.3
|
||||
*/
|
||||
int send_lsp(struct thread *thread)
|
||||
void send_lsp(void *arg, struct isis_lsp *lsp, enum isis_tx_type tx_type)
|
||||
{
|
||||
struct isis_circuit *circuit;
|
||||
struct isis_lsp *lsp;
|
||||
struct isis_circuit *circuit = arg;
|
||||
int clear_srm = 1;
|
||||
int retval = ISIS_OK;
|
||||
|
||||
circuit = THREAD_ARG(thread);
|
||||
assert(circuit);
|
||||
circuit->t_send_lsp = NULL;
|
||||
|
||||
lsp = isis_circuit_lsp_queue_pop(circuit);
|
||||
if (!lsp)
|
||||
return ISIS_OK;
|
||||
|
||||
if (!list_isempty(circuit->lsp_queue)) {
|
||||
isis_circuit_schedule_lsp_send(circuit);
|
||||
}
|
||||
|
||||
if (circuit->state != C_STATE_UP || circuit->is_passive == 1)
|
||||
goto out;
|
||||
|
||||
@ -2144,6 +2208,11 @@ int send_lsp(struct thread *thread)
|
||||
/* copy our lsp to the send buffer */
|
||||
stream_copy(circuit->snd_stream, lsp->pdu);
|
||||
|
||||
if (tx_type == TX_LSP_CIRCUIT_SCOPED) {
|
||||
stream_putc_at(circuit->snd_stream, 4, FS_LINK_STATE);
|
||||
stream_putc_at(circuit->snd_stream, 7, L2_CIRCUIT_FLOODING_SCOPE);
|
||||
}
|
||||
|
||||
if (isis->debugs & DEBUG_UPDATE_PACKETS) {
|
||||
zlog_debug("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08" PRIx32
|
||||
", cksum 0x%04" PRIx16 ", lifetime %" PRIu16
|
||||
@ -2181,8 +2250,6 @@ out:
|
||||
* to clear
|
||||
* the fag.
|
||||
*/
|
||||
ISIS_CLEAR_FLAG(lsp->SRMflags, circuit);
|
||||
isis_tx_queue_del(circuit->tx_queue, lsp);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
#ifndef _ZEBRA_ISIS_PDU_H
|
||||
#define _ZEBRA_ISIS_PDU_H
|
||||
|
||||
#include "isisd/isis_tx_queue.h"
|
||||
|
||||
#ifdef __SUNPRO_C
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
@ -125,6 +127,8 @@ struct isis_p2p_hello_hdr {
|
||||
|
||||
#define L1_LINK_STATE 18
|
||||
#define L2_LINK_STATE 20
|
||||
#define FS_LINK_STATE 10
|
||||
#define L2_CIRCUIT_FLOODING_SCOPE 2
|
||||
struct isis_lsp_hdr {
|
||||
uint16_t pdu_len;
|
||||
uint16_t rem_lifetime;
|
||||
@ -212,7 +216,7 @@ int send_l1_csnp(struct thread *thread);
|
||||
int send_l2_csnp(struct thread *thread);
|
||||
int send_l1_psnp(struct thread *thread);
|
||||
int send_l2_psnp(struct thread *thread);
|
||||
int send_lsp(struct thread *thread);
|
||||
void send_lsp(void *arg, struct isis_lsp *lsp, enum isis_tx_type tx_type);
|
||||
void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream);
|
||||
int send_hello(struct isis_circuit *circuit, int level);
|
||||
int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa);
|
||||
|
@ -377,7 +377,7 @@ static void isis_redist_update_zebra_subscriptions(struct isis *isis)
|
||||
* routes to Zebra and has nothing to do with
|
||||
* redistribution,
|
||||
* so skip it. */
|
||||
if (type == ZEBRA_ROUTE_ISIS)
|
||||
if (type == PROTO_TYPE)
|
||||
continue;
|
||||
|
||||
afi_t afi = afi_for_redist_protocol(protocol);
|
||||
@ -515,13 +515,19 @@ void isis_redist_area_finish(struct isis_area *area)
|
||||
|
||||
DEFUN (isis_redistribute,
|
||||
isis_redistribute_cmd,
|
||||
"redistribute <ipv4|ipv6> " FRR_REDIST_STR_ISISD " <level-1|level-2> [<metric (0-16777215)|route-map WORD>]",
|
||||
"redistribute <ipv4|ipv6> " PROTO_REDIST_STR
|
||||
#ifndef FABRICD
|
||||
" <level-1|level-2>"
|
||||
#endif
|
||||
" [<metric (0-16777215)|route-map WORD>]",
|
||||
REDIST_STR
|
||||
"Redistribute IPv4 routes\n"
|
||||
"Redistribute IPv6 routes\n"
|
||||
FRR_REDIST_HELP_STR_ISISD
|
||||
PROTO_REDIST_HELP
|
||||
#ifndef FABRICD
|
||||
"Redistribute into level-1\n"
|
||||
"Redistribute into level-2\n"
|
||||
#endif
|
||||
"Metric for redistributed routes\n"
|
||||
"ISIS default metric\n"
|
||||
"Route map reference\n"
|
||||
@ -530,7 +536,7 @@ DEFUN (isis_redistribute,
|
||||
int idx_afi = 1;
|
||||
int idx_protocol = 2;
|
||||
int idx_level = 3;
|
||||
int idx_metric_rmap = 4;
|
||||
int idx_metric_rmap = fabricd ? 3 : 4;
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
int family;
|
||||
int afi;
|
||||
@ -551,7 +557,9 @@ DEFUN (isis_redistribute,
|
||||
if (type < 0)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
if (!strcmp("level-1", argv[idx_level]->arg))
|
||||
if (fabricd)
|
||||
level = 2;
|
||||
else if (!strcmp("level-1", argv[idx_level]->arg))
|
||||
level = 1;
|
||||
else if (!strcmp("level-2", argv[idx_level]->arg))
|
||||
level = 2;
|
||||
@ -585,14 +593,20 @@ DEFUN (isis_redistribute,
|
||||
|
||||
DEFUN (no_isis_redistribute,
|
||||
no_isis_redistribute_cmd,
|
||||
"no redistribute <ipv4|ipv6> " FRR_REDIST_STR_ISISD " <level-1|level-2>",
|
||||
NO_STR
|
||||
"no redistribute <ipv4|ipv6> " PROTO_REDIST_STR
|
||||
#ifndef FABRICD
|
||||
" <level-1|level-2>"
|
||||
#endif
|
||||
, NO_STR
|
||||
REDIST_STR
|
||||
"Redistribute IPv4 routes\n"
|
||||
"Redistribute IPv6 routes\n"
|
||||
FRR_REDIST_HELP_STR_ISISD
|
||||
PROTO_REDIST_HELP
|
||||
#ifndef FABRICD
|
||||
"Redistribute into level-1\n"
|
||||
"Redistribute into level-2\n")
|
||||
"Redistribute into level-2\n"
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int idx_afi = 2;
|
||||
int idx_protocol = 3;
|
||||
@ -615,6 +629,9 @@ DEFUN (no_isis_redistribute,
|
||||
if (type < 0)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
if (fabricd)
|
||||
level = 2;
|
||||
else
|
||||
level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
|
||||
|
||||
isis_redist_unset(area, level, family, type);
|
||||
@ -623,13 +640,19 @@ DEFUN (no_isis_redistribute,
|
||||
|
||||
DEFUN (isis_default_originate,
|
||||
isis_default_originate_cmd,
|
||||
"default-information originate <ipv4|ipv6> <level-1|level-2> [always] [<metric (0-16777215)|route-map WORD>]",
|
||||
"default-information originate <ipv4|ipv6>"
|
||||
#ifndef FABRICD
|
||||
" <level-1|level-2>"
|
||||
#endif
|
||||
" [always] [<metric (0-16777215)|route-map WORD>]",
|
||||
"Control distribution of default information\n"
|
||||
"Distribute a default route\n"
|
||||
"Distribute default route for IPv4\n"
|
||||
"Distribute default route for IPv6\n"
|
||||
#ifndef FABRICD
|
||||
"Distribute default route into level-1\n"
|
||||
"Distribute default route into level-2\n"
|
||||
#endif
|
||||
"Always advertise default route\n"
|
||||
"Metric for default route\n"
|
||||
"ISIS default metric\n"
|
||||
@ -638,8 +661,8 @@ DEFUN (isis_default_originate,
|
||||
{
|
||||
int idx_afi = 2;
|
||||
int idx_level = 3;
|
||||
int idx_always = 4;
|
||||
int idx_metric_rmap = 4;
|
||||
int idx_always = fabricd ? 3 : 4;
|
||||
int idx_metric_rmap = fabricd ? 3 : 4;
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
int family;
|
||||
int originate_type = DEFAULT_ORIGINATE;
|
||||
@ -651,6 +674,9 @@ DEFUN (isis_default_originate,
|
||||
if (family < 0)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
if (fabricd)
|
||||
level = 2;
|
||||
else
|
||||
level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
|
||||
|
||||
if ((area->is_type & level) != level) {
|
||||
@ -685,14 +711,20 @@ DEFUN (isis_default_originate,
|
||||
|
||||
DEFUN (no_isis_default_originate,
|
||||
no_isis_default_originate_cmd,
|
||||
"no default-information originate <ipv4|ipv6> <level-1|level-2>",
|
||||
NO_STR
|
||||
"no default-information originate <ipv4|ipv6>"
|
||||
#ifndef FABRICD
|
||||
" <level-1|level-2>"
|
||||
#endif
|
||||
, NO_STR
|
||||
"Control distribution of default information\n"
|
||||
"Distribute a default route\n"
|
||||
"Distribute default route for IPv4\n"
|
||||
"Distribute default route for IPv6\n"
|
||||
#ifndef FABRICD
|
||||
"Distribute default route into level-1\n"
|
||||
"Distribute default route into level-2\n")
|
||||
"Distribute default route into level-2\n"
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int idx_afi = 3;
|
||||
int idx_level = 4;
|
||||
@ -704,7 +736,9 @@ DEFUN (no_isis_default_originate,
|
||||
if (family < 0)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
if (strmatch("level-1", argv[idx_level]->text))
|
||||
if (fabricd)
|
||||
level = 2;
|
||||
else if (strmatch("level-1", argv[idx_level]->text))
|
||||
level = 1;
|
||||
else if (strmatch("level-2", argv[idx_level]->text))
|
||||
level = 2;
|
||||
@ -732,15 +766,17 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area,
|
||||
return 0;
|
||||
|
||||
for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
|
||||
if (type == ZEBRA_ROUTE_ISIS)
|
||||
if (type == PROTO_TYPE)
|
||||
continue;
|
||||
|
||||
for (level = 1; level <= ISIS_LEVELS; level++) {
|
||||
redist = get_redist_settings(area, family, type, level);
|
||||
if (!redist->redist)
|
||||
continue;
|
||||
vty_out(vty, " redistribute %s %s level-%d", family_str,
|
||||
zebra_route_string(type), level);
|
||||
vty_out(vty, " redistribute %s %s", family_str,
|
||||
zebra_route_string(type));
|
||||
if (!fabricd)
|
||||
vty_out(vty, " level-%d", level);
|
||||
if (redist->metric)
|
||||
vty_out(vty, " metric %u", redist->metric);
|
||||
if (redist->map_name)
|
||||
@ -755,8 +791,10 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area,
|
||||
get_redist_settings(area, family, DEFAULT_ROUTE, level);
|
||||
if (!redist->redist)
|
||||
continue;
|
||||
vty_out(vty, " default-information originate %s level-%d",
|
||||
family_str, level);
|
||||
vty_out(vty, " default-information originate %s",
|
||||
family_str);
|
||||
if (!fabricd)
|
||||
vty_out(vty, " level-%d", level);
|
||||
if (redist->redist == DEFAULT_ORIGINATE_ALWAYS)
|
||||
vty_out(vty, " always");
|
||||
if (redist->metric)
|
||||
@ -772,8 +810,8 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area,
|
||||
|
||||
void isis_redist_init(void)
|
||||
{
|
||||
install_element(ISIS_NODE, &isis_redistribute_cmd);
|
||||
install_element(ISIS_NODE, &no_isis_redistribute_cmd);
|
||||
install_element(ISIS_NODE, &isis_default_originate_cmd);
|
||||
install_element(ISIS_NODE, &no_isis_default_originate_cmd);
|
||||
install_element(ROUTER_NODE, &isis_redistribute_cmd);
|
||||
install_element(ROUTER_NODE, &no_isis_redistribute_cmd);
|
||||
install_element(ROUTER_NODE, &isis_default_originate_cmd);
|
||||
install_element(ROUTER_NODE, &no_isis_default_originate_cmd);
|
||||
}
|
||||
|
471
isisd/isis_spf.c
471
isisd/isis_spf.c
@ -31,14 +31,10 @@
|
||||
#include "command.h"
|
||||
#include "memory.h"
|
||||
#include "prefix.h"
|
||||
#include "hash.h"
|
||||
#include "if.h"
|
||||
#include "table.h"
|
||||
#include "spf_backoff.h"
|
||||
#include "jhash.h"
|
||||
#include "skiplist.h"
|
||||
#include "srcdest_table.h"
|
||||
#include "lib_errors.h"
|
||||
|
||||
#include "isis_constants.h"
|
||||
#include "isis_common.h"
|
||||
@ -56,256 +52,11 @@
|
||||
#include "isis_csm.h"
|
||||
#include "isis_mt.h"
|
||||
#include "isis_tlvs.h"
|
||||
#include "fabricd.h"
|
||||
#include "isis_spf_private.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info");
|
||||
|
||||
enum vertextype {
|
||||
VTYPE_PSEUDO_IS = 1,
|
||||
VTYPE_PSEUDO_TE_IS,
|
||||
VTYPE_NONPSEUDO_IS,
|
||||
VTYPE_NONPSEUDO_TE_IS,
|
||||
VTYPE_ES,
|
||||
VTYPE_IPREACH_INTERNAL,
|
||||
VTYPE_IPREACH_EXTERNAL,
|
||||
VTYPE_IPREACH_TE,
|
||||
VTYPE_IP6REACH_INTERNAL,
|
||||
VTYPE_IP6REACH_EXTERNAL
|
||||
};
|
||||
|
||||
#define VTYPE_IS(t) ((t) >= VTYPE_PSEUDO_IS && (t) <= VTYPE_NONPSEUDO_TE_IS)
|
||||
#define VTYPE_ES(t) ((t) == VTYPE_ES)
|
||||
#define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL)
|
||||
|
||||
struct prefix_pair {
|
||||
struct prefix dest;
|
||||
struct prefix_ipv6 src;
|
||||
};
|
||||
|
||||
/*
|
||||
* Triple <N, d(N), {Adj(N)}>
|
||||
*/
|
||||
union isis_N {
|
||||
uint8_t id[ISIS_SYS_ID_LEN + 1];
|
||||
struct prefix_pair ip;
|
||||
};
|
||||
struct isis_vertex {
|
||||
enum vertextype type;
|
||||
union isis_N N;
|
||||
uint32_t d_N; /* d(N) Distance from this IS */
|
||||
uint16_t depth; /* The depth in the imaginary tree */
|
||||
struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */
|
||||
struct list *parents; /* list of parents for ECMP */
|
||||
uint64_t insert_counter;
|
||||
};
|
||||
|
||||
/* Vertex Queue and associated functions */
|
||||
|
||||
struct isis_vertex_queue {
|
||||
union {
|
||||
struct skiplist *slist;
|
||||
struct list *list;
|
||||
} l;
|
||||
struct hash *hash;
|
||||
uint64_t insert_counter;
|
||||
};
|
||||
|
||||
static unsigned isis_vertex_queue_hash_key(void *vp)
|
||||
{
|
||||
struct isis_vertex *vertex = vp;
|
||||
|
||||
if (VTYPE_IP(vertex->type)) {
|
||||
uint32_t key;
|
||||
|
||||
key = prefix_hash_key(&vertex->N.ip.dest);
|
||||
key = jhash_1word(prefix_hash_key(&vertex->N.ip.src), key);
|
||||
return key;
|
||||
}
|
||||
|
||||
return jhash(vertex->N.id, ISIS_SYS_ID_LEN + 1, 0x55aa5a5a);
|
||||
}
|
||||
|
||||
static int isis_vertex_queue_hash_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct isis_vertex *va = a, *vb = b;
|
||||
|
||||
if (va->type != vb->type)
|
||||
return 0;
|
||||
|
||||
if (VTYPE_IP(va->type)) {
|
||||
if (prefix_cmp(&va->N.ip.dest, &vb->N.ip.dest))
|
||||
return 0;
|
||||
|
||||
return prefix_cmp((struct prefix *)&va->N.ip.src,
|
||||
(struct prefix *)&vb->N.ip.src) == 0;
|
||||
}
|
||||
|
||||
return memcmp(va->N.id, vb->N.id, ISIS_SYS_ID_LEN + 1) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compares vertizes for sorting in the TENT list. Returns true
|
||||
* if candidate should be considered before current, false otherwise.
|
||||
*/
|
||||
static int isis_vertex_queue_tent_cmp(void *a, void *b)
|
||||
{
|
||||
struct isis_vertex *va = a;
|
||||
struct isis_vertex *vb = b;
|
||||
|
||||
if (va->d_N < vb->d_N)
|
||||
return -1;
|
||||
|
||||
if (va->d_N > vb->d_N)
|
||||
return 1;
|
||||
|
||||
if (va->type < vb->type)
|
||||
return -1;
|
||||
|
||||
if (va->type > vb->type)
|
||||
return 1;
|
||||
|
||||
if (va->insert_counter < vb->insert_counter)
|
||||
return -1;
|
||||
|
||||
if (va->insert_counter > vb->insert_counter)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct skiplist *isis_vertex_queue_skiplist(void)
|
||||
{
|
||||
return skiplist_new(0, isis_vertex_queue_tent_cmp, NULL);
|
||||
}
|
||||
|
||||
static void isis_vertex_queue_init(struct isis_vertex_queue *queue,
|
||||
const char *name, bool ordered)
|
||||
{
|
||||
if (ordered) {
|
||||
queue->insert_counter = 1;
|
||||
queue->l.slist = isis_vertex_queue_skiplist();
|
||||
} else {
|
||||
queue->insert_counter = 0;
|
||||
queue->l.list = list_new();
|
||||
}
|
||||
queue->hash = hash_create(isis_vertex_queue_hash_key,
|
||||
isis_vertex_queue_hash_cmp, name);
|
||||
}
|
||||
|
||||
static void isis_vertex_del(struct isis_vertex *vertex);
|
||||
|
||||
static void isis_vertex_queue_clear(struct isis_vertex_queue *queue)
|
||||
{
|
||||
hash_clean(queue->hash, NULL);
|
||||
|
||||
if (queue->insert_counter) {
|
||||
struct isis_vertex *vertex;
|
||||
while (0 == skiplist_first(queue->l.slist, NULL,
|
||||
(void **)&vertex)) {
|
||||
isis_vertex_del(vertex);
|
||||
skiplist_delete_first(queue->l.slist);
|
||||
}
|
||||
queue->insert_counter = 1;
|
||||
} else {
|
||||
queue->l.list->del = (void (*)(void *))isis_vertex_del;
|
||||
list_delete_all_node(queue->l.list);
|
||||
queue->l.list->del = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void isis_vertex_queue_free(struct isis_vertex_queue *queue)
|
||||
{
|
||||
isis_vertex_queue_clear(queue);
|
||||
|
||||
hash_free(queue->hash);
|
||||
queue->hash = NULL;
|
||||
|
||||
if (queue->insert_counter) {
|
||||
skiplist_free(queue->l.slist);
|
||||
queue->l.slist = NULL;
|
||||
} else
|
||||
list_delete_and_null(&queue->l.list);
|
||||
}
|
||||
|
||||
static unsigned int isis_vertex_queue_count(struct isis_vertex_queue *queue)
|
||||
{
|
||||
return hashcount(queue->hash);
|
||||
}
|
||||
|
||||
static void isis_vertex_queue_append(struct isis_vertex_queue *queue,
|
||||
struct isis_vertex *vertex)
|
||||
{
|
||||
assert(!queue->insert_counter);
|
||||
|
||||
listnode_add(queue->l.list, vertex);
|
||||
|
||||
struct isis_vertex *inserted;
|
||||
|
||||
inserted = hash_get(queue->hash, vertex, hash_alloc_intern);
|
||||
assert(inserted == vertex);
|
||||
}
|
||||
|
||||
static void isis_vertex_queue_insert(struct isis_vertex_queue *queue,
|
||||
struct isis_vertex *vertex)
|
||||
{
|
||||
assert(queue->insert_counter);
|
||||
vertex->insert_counter = queue->insert_counter++;
|
||||
assert(queue->insert_counter != (uint64_t)-1);
|
||||
|
||||
skiplist_insert(queue->l.slist, vertex, vertex);
|
||||
|
||||
struct isis_vertex *inserted;
|
||||
inserted = hash_get(queue->hash, vertex, hash_alloc_intern);
|
||||
assert(inserted == vertex);
|
||||
}
|
||||
|
||||
static struct isis_vertex *
|
||||
isis_vertex_queue_pop(struct isis_vertex_queue *queue)
|
||||
{
|
||||
assert(queue->insert_counter);
|
||||
|
||||
struct isis_vertex *rv;
|
||||
|
||||
if (skiplist_first(queue->l.slist, NULL, (void **)&rv))
|
||||
return NULL;
|
||||
|
||||
skiplist_delete_first(queue->l.slist);
|
||||
hash_release(queue->hash, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void isis_vertex_queue_delete(struct isis_vertex_queue *queue,
|
||||
struct isis_vertex *vertex)
|
||||
{
|
||||
assert(queue->insert_counter);
|
||||
|
||||
skiplist_delete(queue->l.slist, vertex, vertex);
|
||||
hash_release(queue->hash, vertex);
|
||||
}
|
||||
|
||||
#define ALL_QUEUE_ELEMENTS_RO(queue, node, data) \
|
||||
ALL_LIST_ELEMENTS_RO((queue)->l.list, node, data)
|
||||
|
||||
|
||||
/* End of vertex queue definitions */
|
||||
|
||||
struct isis_spftree {
|
||||
struct isis_vertex_queue paths; /* the SPT */
|
||||
struct isis_vertex_queue tents; /* TENT */
|
||||
struct route_table *route_table;
|
||||
struct isis_area *area; /* back pointer to area */
|
||||
unsigned int runcount; /* number of runs since uptime */
|
||||
time_t last_run_timestamp; /* last run timestamp as wall time for display */
|
||||
time_t last_run_monotime; /* last run as monotime for scheduling */
|
||||
time_t last_run_duration; /* last run duration in msec */
|
||||
|
||||
uint16_t mtid;
|
||||
int family;
|
||||
int level;
|
||||
enum spf_tree_id tree_id;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* supports the given af ?
|
||||
*/
|
||||
@ -411,8 +162,7 @@ static const char *vtype2string(enum vertextype vtype)
|
||||
return NULL; /* Not reached */
|
||||
}
|
||||
|
||||
#define VID2STR_BUFFER SRCDEST2STR_BUFFER
|
||||
static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
|
||||
const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
|
||||
{
|
||||
if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) {
|
||||
return print_sys_hostname(vertex->N.id);
|
||||
@ -428,44 +178,26 @@ static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static void isis_vertex_id_init(struct isis_vertex *vertex, union isis_N *n,
|
||||
enum vertextype vtype)
|
||||
{
|
||||
vertex->type = vtype;
|
||||
|
||||
if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) {
|
||||
memcpy(vertex->N.id, n->id, ISIS_SYS_ID_LEN + 1);
|
||||
} else if (VTYPE_IP(vtype)) {
|
||||
memcpy(&vertex->N.ip, &n->ip, sizeof(n->ip));
|
||||
} else {
|
||||
flog_err(LIB_ERR_DEVELOPMENT, "Unknown Vertex Type");
|
||||
}
|
||||
}
|
||||
|
||||
static struct isis_vertex *isis_vertex_new(union isis_N *n,
|
||||
static struct isis_vertex *isis_vertex_new(struct isis_spftree *spftree,
|
||||
void *id,
|
||||
enum vertextype vtype)
|
||||
{
|
||||
struct isis_vertex *vertex;
|
||||
|
||||
vertex = XCALLOC(MTYPE_ISIS_VERTEX, sizeof(struct isis_vertex));
|
||||
|
||||
isis_vertex_id_init(vertex, n, vtype);
|
||||
isis_vertex_id_init(vertex, id, vtype);
|
||||
|
||||
vertex->Adj_N = list_new();
|
||||
vertex->parents = list_new();
|
||||
|
||||
return vertex;
|
||||
if (spftree->hopcount_metric) {
|
||||
vertex->firsthops = hash_create(isis_vertex_queue_hash_key,
|
||||
isis_vertex_queue_hash_cmp,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void isis_vertex_del(struct isis_vertex *vertex)
|
||||
{
|
||||
list_delete_and_null(&vertex->Adj_N);
|
||||
list_delete_and_null(&vertex->parents);
|
||||
|
||||
memset(vertex, 0, sizeof(struct isis_vertex));
|
||||
XFREE(MTYPE_ISIS_VERTEX, vertex);
|
||||
|
||||
return;
|
||||
return vertex;
|
||||
}
|
||||
|
||||
static void isis_vertex_adj_del(struct isis_vertex *vertex,
|
||||
@ -563,6 +295,9 @@ void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj)
|
||||
adj);
|
||||
}
|
||||
}
|
||||
|
||||
if (fabricd_spftree(area) != NULL)
|
||||
isis_spftree_adj_del(fabricd_spftree(area), adj);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -595,17 +330,13 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
|
||||
#ifdef EXTREME_DEBUG
|
||||
char buff[VID2STR_BUFFER];
|
||||
#endif /* EXTREME_DEBUG */
|
||||
union isis_N n;
|
||||
|
||||
memcpy(n.id, sysid, ISIS_SYS_ID_LEN);
|
||||
LSP_PSEUDO_ID(n.id) = 0;
|
||||
|
||||
lsp = isis_root_system_lsp(spftree->area, spftree->level, sysid);
|
||||
if (lsp == NULL)
|
||||
zlog_warn("ISIS-Spf: could not find own l%d LSP!",
|
||||
spftree->level);
|
||||
|
||||
vertex = isis_vertex_new(&n,
|
||||
vertex = isis_vertex_new(spftree, sysid,
|
||||
spftree->area->oldmetric
|
||||
? VTYPE_NONPSEUDO_IS
|
||||
: VTYPE_NONPSEUDO_TE_IS);
|
||||
@ -621,14 +352,24 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
|
||||
return vertex;
|
||||
}
|
||||
|
||||
static struct isis_vertex *isis_find_vertex(struct isis_vertex_queue *queue,
|
||||
union isis_N *n,
|
||||
enum vertextype vtype)
|
||||
static void vertex_add_parent_firsthop(struct hash_backet *backet, void *arg)
|
||||
{
|
||||
struct isis_vertex querier;
|
||||
struct isis_vertex *vertex = arg;
|
||||
struct isis_vertex *hop = backet->data;
|
||||
|
||||
isis_vertex_id_init(&querier, n, vtype);
|
||||
return hash_lookup(queue->hash, &querier);
|
||||
hash_get(vertex->firsthops, hop, hash_alloc_intern);
|
||||
}
|
||||
|
||||
static void vertex_update_firsthops(struct isis_vertex *vertex,
|
||||
struct isis_vertex *parent)
|
||||
{
|
||||
if (vertex->d_N <= 2)
|
||||
hash_get(vertex->firsthops, vertex, hash_alloc_intern);
|
||||
|
||||
if (vertex->d_N < 2 || !parent)
|
||||
return;
|
||||
|
||||
hash_iterate(parent->firsthops, vertex_add_parent_firsthop, vertex);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -649,7 +390,7 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
|
||||
|
||||
assert(isis_find_vertex(&spftree->paths, id, vtype) == NULL);
|
||||
assert(isis_find_vertex(&spftree->tents, id, vtype) == NULL);
|
||||
vertex = isis_vertex_new(id, vtype);
|
||||
vertex = isis_vertex_new(spftree, id, vtype);
|
||||
vertex->d_N = cost;
|
||||
vertex->depth = depth;
|
||||
|
||||
@ -657,6 +398,9 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
|
||||
listnode_add(vertex->parents, parent);
|
||||
}
|
||||
|
||||
if (spftree->hopcount_metric)
|
||||
vertex_update_firsthops(vertex, parent);
|
||||
|
||||
if (parent && parent->Adj_N && listcount(parent->Adj_N) > 0) {
|
||||
for (ALL_LIST_ELEMENTS_RO(parent->Adj_N, node, parent_adj))
|
||||
listnode_add(vertex->Adj_N, parent_adj);
|
||||
@ -722,6 +466,10 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
|
||||
|
||||
assert(spftree && parent);
|
||||
|
||||
if (spftree->hopcount_metric
|
||||
&& !VTYPE_IS(vtype))
|
||||
return;
|
||||
|
||||
struct prefix_pair p;
|
||||
if (vtype >= VTYPE_IPREACH_INTERNAL) {
|
||||
memcpy(&p, id, sizeof(p));
|
||||
@ -774,6 +522,8 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
|
||||
if (listnode_lookup(vertex->Adj_N, parent_adj)
|
||||
== NULL)
|
||||
listnode_add(vertex->Adj_N, parent_adj);
|
||||
if (spftree->hopcount_metric)
|
||||
vertex_update_firsthops(vertex, parent);
|
||||
/* 2) */
|
||||
if (listcount(vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
|
||||
remove_excess_adjs(vertex->Adj_N);
|
||||
@ -853,6 +603,9 @@ lspfragloop:
|
||||
for (r = (struct isis_oldstyle_reach *)
|
||||
lsp->tlvs->oldstyle_reach.head;
|
||||
r; r = r->next) {
|
||||
if (fabricd)
|
||||
continue;
|
||||
|
||||
/* C.2.6 a) */
|
||||
/* Two way connectivity */
|
||||
if (!memcmp(r->id, root_sysid, ISIS_SYS_ID_LEN))
|
||||
@ -889,7 +642,7 @@ lspfragloop:
|
||||
if (!pseudo_lsp
|
||||
&& !memcmp(er->id, null_sysid, ISIS_SYS_ID_LEN))
|
||||
continue;
|
||||
dist = cost + er->metric;
|
||||
dist = cost + (spftree->hopcount_metric ? 1 : er->metric);
|
||||
process_N(spftree,
|
||||
LSP_PSEUDO_ID(er->id) ? VTYPE_PSEUDO_TE_IS
|
||||
: VTYPE_NONPSEUDO_TE_IS,
|
||||
@ -897,7 +650,7 @@ lspfragloop:
|
||||
}
|
||||
}
|
||||
|
||||
if (!pseudo_lsp && spftree->family == AF_INET
|
||||
if (!fabricd && !pseudo_lsp && spftree->family == AF_INET
|
||||
&& spftree->mtid == ISIS_MT_IPV4_UNICAST) {
|
||||
struct isis_item_list *reachs[] = {
|
||||
&lsp->tlvs->oldstyle_ip_reach,
|
||||
@ -1037,7 +790,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
|
||||
/*
|
||||
* Add IP(v6) addresses of this circuit
|
||||
*/
|
||||
if (spftree->family == AF_INET) {
|
||||
if (spftree->family == AF_INET && !spftree->hopcount_metric) {
|
||||
memset(&ip_info, 0, sizeof(ip_info));
|
||||
ip_info.dest.family = AF_INET;
|
||||
for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, ipnode,
|
||||
@ -1050,7 +803,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
|
||||
&ip_info, NULL, 0, parent);
|
||||
}
|
||||
}
|
||||
if (spftree->family == AF_INET6) {
|
||||
if (spftree->family == AF_INET6 && !spftree->hopcount_metric) {
|
||||
memset(&ip_info, 0, sizeof(ip_info));
|
||||
ip_info.dest.family = AF_INET6;
|
||||
for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link,
|
||||
@ -1094,6 +847,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
|
||||
LSP_PSEUDO_ID(lsp_id) = 0;
|
||||
isis_spf_add_local(
|
||||
spftree, VTYPE_ES, lsp_id, adj,
|
||||
spftree->hopcount_metric ? 1 :
|
||||
circuit->te_metric
|
||||
[spftree->level - 1],
|
||||
parent);
|
||||
@ -1111,6 +865,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
|
||||
? VTYPE_NONPSEUDO_IS
|
||||
: VTYPE_NONPSEUDO_TE_IS,
|
||||
lsp_id, adj,
|
||||
spftree->hopcount_metric ? 1 :
|
||||
circuit->te_metric
|
||||
[spftree->level - 1],
|
||||
parent);
|
||||
@ -1180,10 +935,10 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
|
||||
circuit->circuit_id);
|
||||
continue;
|
||||
}
|
||||
isis_spf_process_lsp(
|
||||
spftree, lsp,
|
||||
circuit->te_metric[spftree->level - 1], 0,
|
||||
root_sysid, parent);
|
||||
isis_spf_process_lsp(spftree, lsp,
|
||||
spftree->hopcount_metric ?
|
||||
1 : circuit->te_metric[spftree->level - 1],
|
||||
0, root_sysid, parent);
|
||||
} else if (circuit->circ_type == CIRCUIT_T_P2P) {
|
||||
adj = circuit->u.p2p.neighbor;
|
||||
if (!adj || adj->adj_state != ISIS_ADJ_UP)
|
||||
@ -1196,6 +951,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
|
||||
LSP_PSEUDO_ID(lsp_id) = 0;
|
||||
isis_spf_add_local(
|
||||
spftree, VTYPE_ES, lsp_id, adj,
|
||||
spftree->hopcount_metric ? 1 :
|
||||
circuit->te_metric[spftree->level - 1],
|
||||
parent);
|
||||
break;
|
||||
@ -1215,6 +971,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
|
||||
? VTYPE_NONPSEUDO_IS
|
||||
: VTYPE_NONPSEUDO_TE_IS,
|
||||
lsp_id, adj,
|
||||
spftree->hopcount_metric ? 1 :
|
||||
circuit->te_metric
|
||||
[spftree->level - 1],
|
||||
parent);
|
||||
@ -1275,7 +1032,8 @@ static void add_to_paths(struct isis_spftree *spftree,
|
||||
}
|
||||
|
||||
static void init_spt(struct isis_spftree *spftree, int mtid, int level,
|
||||
int family, enum spf_tree_id tree_id)
|
||||
int family, enum spf_tree_id tree_id,
|
||||
bool hopcount_metric)
|
||||
{
|
||||
isis_vertex_queue_clear(&spftree->tents);
|
||||
isis_vertex_queue_clear(&spftree->paths);
|
||||
@ -1284,7 +1042,63 @@ static void init_spt(struct isis_spftree *spftree, int mtid, int level,
|
||||
spftree->level = level;
|
||||
spftree->family = family;
|
||||
spftree->tree_id = tree_id;
|
||||
return;
|
||||
spftree->hopcount_metric = hopcount_metric;
|
||||
}
|
||||
|
||||
static void isis_spf_loop(struct isis_spftree *spftree,
|
||||
uint8_t *root_sysid)
|
||||
{
|
||||
struct isis_vertex *vertex;
|
||||
struct isis_lsp *lsp;
|
||||
|
||||
while (isis_vertex_queue_count(&spftree->tents)) {
|
||||
vertex = isis_vertex_queue_pop(&spftree->tents);
|
||||
|
||||
#ifdef EXTREME_DEBUG
|
||||
zlog_debug(
|
||||
"ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS",
|
||||
print_sys_hostname(vertex->N.id),
|
||||
vtype2string(vertex->type), vertex->depth, vertex->d_N);
|
||||
#endif /* EXTREME_DEBUG */
|
||||
|
||||
add_to_paths(spftree, vertex);
|
||||
if (!VTYPE_IS(vertex->type))
|
||||
continue;
|
||||
|
||||
lsp = lsp_for_vertex(spftree, vertex);
|
||||
if (!lsp) {
|
||||
zlog_warn("ISIS-Spf: No LSP found for %s",
|
||||
rawlspid_print(vertex->N.id)); /* FIXME */
|
||||
continue;
|
||||
}
|
||||
|
||||
isis_spf_process_lsp(spftree, lsp, vertex->d_N, vertex->depth,
|
||||
root_sysid, vertex);
|
||||
}
|
||||
}
|
||||
|
||||
struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area,
|
||||
uint8_t *sysid,
|
||||
struct isis_spftree *spftree)
|
||||
{
|
||||
if (!spftree)
|
||||
spftree = isis_spftree_new(area);
|
||||
|
||||
init_spt(spftree, ISIS_MT_IPV4_UNICAST, ISIS_LEVEL2,
|
||||
AF_INET, SPFTREE_IPV4, true);
|
||||
if (!memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN)) {
|
||||
/* If we are running locally, initialize with information from adjacencies */
|
||||
struct isis_vertex *root = isis_spf_add_root(spftree, sysid);
|
||||
isis_spf_preload_tent(spftree, sysid, root);
|
||||
} else {
|
||||
isis_vertex_queue_insert(&spftree->tents, isis_vertex_new(
|
||||
spftree, sysid,
|
||||
VTYPE_NONPSEUDO_TE_IS));
|
||||
}
|
||||
|
||||
isis_spf_loop(spftree, sysid);
|
||||
|
||||
return spftree;
|
||||
}
|
||||
|
||||
static int isis_run_spf(struct isis_area *area, int level,
|
||||
@ -1292,11 +1106,8 @@ static int isis_run_spf(struct isis_area *area, int level,
|
||||
uint8_t *sysid, struct timeval *nowtv)
|
||||
{
|
||||
int retval = ISIS_OK;
|
||||
struct isis_vertex *vertex;
|
||||
struct isis_vertex *root_vertex;
|
||||
struct isis_spftree *spftree = area->spftree[tree_id][level - 1];
|
||||
uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
|
||||
struct isis_lsp *lsp;
|
||||
struct timeval time_now;
|
||||
unsigned long long start_time, end_time;
|
||||
uint16_t mtid = 0;
|
||||
@ -1330,7 +1141,7 @@ static int isis_run_spf(struct isis_area *area, int level,
|
||||
/*
|
||||
* C.2.5 Step 0
|
||||
*/
|
||||
init_spt(spftree, mtid, level, family, tree_id);
|
||||
init_spt(spftree, mtid, level, family, tree_id, false);
|
||||
/* a) */
|
||||
root_vertex = isis_spf_add_root(spftree, sysid);
|
||||
/* b) */
|
||||
@ -1350,32 +1161,7 @@ static int isis_run_spf(struct isis_area *area, int level,
|
||||
print_sys_hostname(sysid));
|
||||
}
|
||||
|
||||
while (isis_vertex_queue_count(&spftree->tents)) {
|
||||
vertex = isis_vertex_queue_pop(&spftree->tents);
|
||||
|
||||
#ifdef EXTREME_DEBUG
|
||||
zlog_debug(
|
||||
"ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS",
|
||||
print_sys_hostname(vertex->N.id),
|
||||
vtype2string(vertex->type), vertex->depth, vertex->d_N);
|
||||
#endif /* EXTREME_DEBUG */
|
||||
|
||||
add_to_paths(spftree, vertex);
|
||||
if (VTYPE_IS(vertex->type)) {
|
||||
memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
|
||||
LSP_FRAGMENT(lsp_id) = 0;
|
||||
lsp = lsp_search(lsp_id, area->lspdb[level - 1]);
|
||||
if (lsp && lsp->hdr.rem_lifetime != 0) {
|
||||
isis_spf_process_lsp(spftree, lsp, vertex->d_N,
|
||||
vertex->depth, sysid,
|
||||
vertex);
|
||||
} else {
|
||||
zlog_warn("ISIS-Spf: No LSP found for %s",
|
||||
rawlspid_print(lsp_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isis_spf_loop(spftree, sysid);
|
||||
out:
|
||||
spftree->runcount++;
|
||||
spftree->last_run_timestamp = time(NULL);
|
||||
@ -1446,6 +1232,8 @@ static int isis_run_spf_cb(struct thread *thread)
|
||||
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
|
||||
UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
|
||||
|
||||
fabricd_run_spf(area);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1617,12 +1405,18 @@ static void isis_print_spftree(struct vty *vty, int level,
|
||||
|
||||
DEFUN (show_isis_topology,
|
||||
show_isis_topology_cmd,
|
||||
"show isis topology [<level-1|level-2>]",
|
||||
SHOW_STR
|
||||
"IS-IS information\n"
|
||||
"show " PROTO_NAME " topology"
|
||||
#ifndef FABRICD
|
||||
" [<level-1|level-2>]"
|
||||
#endif
|
||||
, SHOW_STR
|
||||
PROTO_HELP
|
||||
"IS-IS paths to Intermediate Systems\n"
|
||||
#ifndef FABRICD
|
||||
"Paths to all level-1 routers in the area\n"
|
||||
"Paths to all level-2 routers in the domain\n")
|
||||
"Paths to all level-2 routers in the domain\n"
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int levels;
|
||||
struct listnode *node;
|
||||
@ -1660,6 +1454,13 @@ DEFUN (show_isis_topology,
|
||||
}
|
||||
}
|
||||
|
||||
if (fabricd_spftree(area)) {
|
||||
vty_out(vty,
|
||||
"IS-IS paths to level-2 routers with hop-by-hop metric\n");
|
||||
isis_print_paths(vty, &fabricd_spftree(area)->paths, isis->sysid);
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
|
@ -37,4 +37,7 @@ void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj);
|
||||
int isis_spf_schedule(struct isis_area *area, int level);
|
||||
void isis_spf_cmds_init(void);
|
||||
void isis_spf_print(struct isis_spftree *spftree, struct vty *vty);
|
||||
struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area,
|
||||
uint8_t *sysid,
|
||||
struct isis_spftree *spftree);
|
||||
#endif /* _ZEBRA_ISIS_SPF_H */
|
||||
|
362
isisd/isis_spf_private.h
Normal file
362
isisd/isis_spf_private.h
Normal file
@ -0,0 +1,362 @@
|
||||
/*
|
||||
* IS-IS Rout(e)ing protocol - isis_spf_private.h
|
||||
*
|
||||
* Copyright (C) 2001,2002 Sampo Saaristo
|
||||
* Tampere University of Technology
|
||||
* Institute of Communications Engineering
|
||||
* Copyright (C) 2017 Christian Franke <chris@opensourcerouting.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public Licenseas 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
|
||||
*/
|
||||
#ifndef ISIS_SPF_PRIVATE_H
|
||||
#define ISIS_SPF_PRIVATE_H
|
||||
|
||||
#include "hash.h"
|
||||
#include "jhash.h"
|
||||
#include "skiplist.h"
|
||||
#include "lib_errors.h"
|
||||
|
||||
enum vertextype {
|
||||
VTYPE_PSEUDO_IS = 1,
|
||||
VTYPE_PSEUDO_TE_IS,
|
||||
VTYPE_NONPSEUDO_IS,
|
||||
VTYPE_NONPSEUDO_TE_IS,
|
||||
VTYPE_ES,
|
||||
VTYPE_IPREACH_INTERNAL,
|
||||
VTYPE_IPREACH_EXTERNAL,
|
||||
VTYPE_IPREACH_TE,
|
||||
VTYPE_IP6REACH_INTERNAL,
|
||||
VTYPE_IP6REACH_EXTERNAL
|
||||
};
|
||||
|
||||
#define VTYPE_IS(t) ((t) >= VTYPE_PSEUDO_IS && (t) <= VTYPE_NONPSEUDO_TE_IS)
|
||||
#define VTYPE_ES(t) ((t) == VTYPE_ES)
|
||||
#define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL)
|
||||
|
||||
struct prefix_pair {
|
||||
struct prefix dest;
|
||||
struct prefix_ipv6 src;
|
||||
};
|
||||
|
||||
/*
|
||||
* Triple <N, d(N), {Adj(N)}>
|
||||
*/
|
||||
struct isis_vertex {
|
||||
enum vertextype type;
|
||||
union {
|
||||
uint8_t id[ISIS_SYS_ID_LEN + 1];
|
||||
struct prefix_pair ip;
|
||||
} N;
|
||||
uint32_t d_N; /* d(N) Distance from this IS */
|
||||
uint16_t depth; /* The depth in the imaginary tree */
|
||||
struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */
|
||||
struct list *parents; /* list of parents for ECMP */
|
||||
struct hash *firsthops; /* first two hops to neighbor */
|
||||
uint64_t insert_counter;
|
||||
};
|
||||
|
||||
/* Vertex Queue and associated functions */
|
||||
|
||||
struct isis_vertex_queue {
|
||||
union {
|
||||
struct skiplist *slist;
|
||||
struct list *list;
|
||||
} l;
|
||||
struct hash *hash;
|
||||
uint64_t insert_counter;
|
||||
};
|
||||
|
||||
__attribute__((__unused__))
|
||||
static unsigned isis_vertex_queue_hash_key(void *vp)
|
||||
{
|
||||
struct isis_vertex *vertex = vp;
|
||||
|
||||
if (VTYPE_IP(vertex->type)) {
|
||||
uint32_t key;
|
||||
|
||||
key = prefix_hash_key(&vertex->N.ip.dest);
|
||||
key = jhash_1word(prefix_hash_key(&vertex->N.ip.src), key);
|
||||
return key;
|
||||
}
|
||||
|
||||
return jhash(vertex->N.id, ISIS_SYS_ID_LEN + 1, 0x55aa5a5a);
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static int isis_vertex_queue_hash_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct isis_vertex *va = a, *vb = b;
|
||||
|
||||
if (va->type != vb->type)
|
||||
return 0;
|
||||
|
||||
if (VTYPE_IP(va->type)) {
|
||||
if (prefix_cmp(&va->N.ip.dest, &vb->N.ip.dest))
|
||||
return 0;
|
||||
|
||||
return prefix_cmp((struct prefix *)&va->N.ip.src,
|
||||
(struct prefix *)&vb->N.ip.src) == 0;
|
||||
}
|
||||
|
||||
return memcmp(va->N.id, vb->N.id, ISIS_SYS_ID_LEN + 1) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compares vertizes for sorting in the TENT list. Returns true
|
||||
* if candidate should be considered before current, false otherwise.
|
||||
*/
|
||||
__attribute__((__unused__))
|
||||
static int isis_vertex_queue_tent_cmp(void *a, void *b)
|
||||
{
|
||||
struct isis_vertex *va = a;
|
||||
struct isis_vertex *vb = b;
|
||||
|
||||
if (va->d_N < vb->d_N)
|
||||
return -1;
|
||||
|
||||
if (va->d_N > vb->d_N)
|
||||
return 1;
|
||||
|
||||
if (va->type < vb->type)
|
||||
return -1;
|
||||
|
||||
if (va->type > vb->type)
|
||||
return 1;
|
||||
|
||||
if (va->insert_counter < vb->insert_counter)
|
||||
return -1;
|
||||
|
||||
if (va->insert_counter > vb->insert_counter)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static struct skiplist *isis_vertex_queue_skiplist(void)
|
||||
{
|
||||
return skiplist_new(0, isis_vertex_queue_tent_cmp, NULL);
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static void isis_vertex_queue_init(struct isis_vertex_queue *queue,
|
||||
const char *name, bool ordered)
|
||||
{
|
||||
if (ordered) {
|
||||
queue->insert_counter = 1;
|
||||
queue->l.slist = isis_vertex_queue_skiplist();
|
||||
} else {
|
||||
queue->insert_counter = 0;
|
||||
queue->l.list = list_new();
|
||||
}
|
||||
queue->hash = hash_create(isis_vertex_queue_hash_key,
|
||||
isis_vertex_queue_hash_cmp, name);
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static void isis_vertex_del(struct isis_vertex *vertex)
|
||||
{
|
||||
list_delete_and_null(&vertex->Adj_N);
|
||||
list_delete_and_null(&vertex->parents);
|
||||
if (vertex->firsthops) {
|
||||
hash_clean(vertex->firsthops, NULL);
|
||||
hash_free(vertex->firsthops);
|
||||
vertex->firsthops = NULL;
|
||||
}
|
||||
|
||||
memset(vertex, 0, sizeof(struct isis_vertex));
|
||||
XFREE(MTYPE_ISIS_VERTEX, vertex);
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static void isis_vertex_queue_clear(struct isis_vertex_queue *queue)
|
||||
{
|
||||
hash_clean(queue->hash, NULL);
|
||||
|
||||
if (queue->insert_counter) {
|
||||
struct isis_vertex *vertex;
|
||||
while (0 == skiplist_first(queue->l.slist, NULL,
|
||||
(void **)&vertex)) {
|
||||
isis_vertex_del(vertex);
|
||||
skiplist_delete_first(queue->l.slist);
|
||||
}
|
||||
queue->insert_counter = 1;
|
||||
} else {
|
||||
queue->l.list->del = (void (*)(void *))isis_vertex_del;
|
||||
list_delete_all_node(queue->l.list);
|
||||
queue->l.list->del = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static void isis_vertex_queue_free(struct isis_vertex_queue *queue)
|
||||
{
|
||||
isis_vertex_queue_clear(queue);
|
||||
|
||||
hash_free(queue->hash);
|
||||
queue->hash = NULL;
|
||||
|
||||
if (queue->insert_counter) {
|
||||
skiplist_free(queue->l.slist);
|
||||
queue->l.slist = NULL;
|
||||
} else
|
||||
list_delete_and_null(&queue->l.list);
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static unsigned int isis_vertex_queue_count(struct isis_vertex_queue *queue)
|
||||
{
|
||||
return hashcount(queue->hash);
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static void isis_vertex_queue_append(struct isis_vertex_queue *queue,
|
||||
struct isis_vertex *vertex)
|
||||
{
|
||||
assert(!queue->insert_counter);
|
||||
|
||||
listnode_add(queue->l.list, vertex);
|
||||
|
||||
struct isis_vertex *inserted;
|
||||
|
||||
inserted = hash_get(queue->hash, vertex, hash_alloc_intern);
|
||||
assert(inserted == vertex);
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static struct isis_vertex *isis_vertex_queue_last(struct isis_vertex_queue *queue)
|
||||
{
|
||||
struct listnode *tail;
|
||||
|
||||
assert(!queue->insert_counter);
|
||||
tail = listtail(queue->l.list);
|
||||
assert(tail);
|
||||
return listgetdata(tail);
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static void isis_vertex_queue_insert(struct isis_vertex_queue *queue,
|
||||
struct isis_vertex *vertex)
|
||||
{
|
||||
assert(queue->insert_counter);
|
||||
vertex->insert_counter = queue->insert_counter++;
|
||||
assert(queue->insert_counter != (uint64_t)-1);
|
||||
|
||||
skiplist_insert(queue->l.slist, vertex, vertex);
|
||||
|
||||
struct isis_vertex *inserted;
|
||||
inserted = hash_get(queue->hash, vertex, hash_alloc_intern);
|
||||
assert(inserted == vertex);
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static struct isis_vertex *
|
||||
isis_vertex_queue_pop(struct isis_vertex_queue *queue)
|
||||
{
|
||||
assert(queue->insert_counter);
|
||||
|
||||
struct isis_vertex *rv;
|
||||
|
||||
if (skiplist_first(queue->l.slist, NULL, (void **)&rv))
|
||||
return NULL;
|
||||
|
||||
skiplist_delete_first(queue->l.slist);
|
||||
hash_release(queue->hash, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static void isis_vertex_queue_delete(struct isis_vertex_queue *queue,
|
||||
struct isis_vertex *vertex)
|
||||
{
|
||||
assert(queue->insert_counter);
|
||||
|
||||
skiplist_delete(queue->l.slist, vertex, vertex);
|
||||
hash_release(queue->hash, vertex);
|
||||
}
|
||||
|
||||
#define ALL_QUEUE_ELEMENTS_RO(queue, node, data) \
|
||||
ALL_LIST_ELEMENTS_RO((queue)->l.list, node, data)
|
||||
|
||||
/* End of vertex queue definitions */
|
||||
|
||||
struct isis_spftree {
|
||||
struct isis_vertex_queue paths; /* the SPT */
|
||||
struct isis_vertex_queue tents; /* TENT */
|
||||
struct route_table *route_table;
|
||||
struct isis_area *area; /* back pointer to area */
|
||||
unsigned int runcount; /* number of runs since uptime */
|
||||
time_t last_run_timestamp; /* last run timestamp as wall time for display */
|
||||
time_t last_run_monotime; /* last run as monotime for scheduling */
|
||||
time_t last_run_duration; /* last run duration in msec */
|
||||
|
||||
uint16_t mtid;
|
||||
int family;
|
||||
int level;
|
||||
enum spf_tree_id tree_id;
|
||||
bool hopcount_metric;
|
||||
};
|
||||
|
||||
__attribute__((__unused__))
|
||||
static void isis_vertex_id_init(struct isis_vertex *vertex, const void *id,
|
||||
enum vertextype vtype)
|
||||
{
|
||||
vertex->type = vtype;
|
||||
|
||||
if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) {
|
||||
memcpy(vertex->N.id, id, ISIS_SYS_ID_LEN + 1);
|
||||
} else if (VTYPE_IP(vtype)) {
|
||||
memcpy(&vertex->N.ip, id, sizeof(vertex->N.ip));
|
||||
} else {
|
||||
flog_err(LIB_ERR_DEVELOPMENT, "Unknown Vertex Type");
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static struct isis_vertex *isis_find_vertex(struct isis_vertex_queue *queue,
|
||||
const void *id,
|
||||
enum vertextype vtype)
|
||||
{
|
||||
struct isis_vertex querier;
|
||||
|
||||
isis_vertex_id_init(&querier, id, vtype);
|
||||
return hash_lookup(queue->hash, &querier);
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
static struct isis_lsp *lsp_for_vertex(struct isis_spftree *spftree,
|
||||
struct isis_vertex *vertex)
|
||||
{
|
||||
uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
|
||||
|
||||
assert(VTYPE_IS(vertex->type));
|
||||
|
||||
memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
|
||||
LSP_FRAGMENT(lsp_id) = 0;
|
||||
|
||||
dict_t *lspdb = spftree->area->lspdb[spftree->level - 1];
|
||||
struct isis_lsp *lsp = lsp_search(lsp_id, lspdb);
|
||||
|
||||
if (lsp && lsp->hdr.rem_lifetime != 0)
|
||||
return lsp;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define VID2STR_BUFFER SRCDEST2STR_BUFFER
|
||||
const char *vid2string(struct isis_vertex *vertex, char *buff, int size);
|
||||
|
||||
#endif
|
@ -67,17 +67,6 @@ const char *mode2text[] = {"Disable", "Area", "AS", "Emulate"};
|
||||
* Followings are control functions for MPLS-TE parameters management.
|
||||
*------------------------------------------------------------------------*/
|
||||
|
||||
/* Search MPLS TE Circuit context from Interface */
|
||||
static struct mpls_te_circuit *lookup_mpls_params_by_ifp(struct interface *ifp)
|
||||
{
|
||||
struct isis_circuit *circuit;
|
||||
|
||||
if ((circuit = circuit_scan_by_ifp(ifp)) == NULL)
|
||||
return NULL;
|
||||
|
||||
return circuit->mtc;
|
||||
}
|
||||
|
||||
/* Create new MPLS TE Circuit context */
|
||||
struct mpls_te_circuit *mpls_te_circuit_new()
|
||||
{
|
||||
@ -1085,6 +1074,18 @@ void isis_mpls_te_config_write_router(struct vty *vty)
|
||||
/*------------------------------------------------------------------------*
|
||||
* Followings are vty command functions.
|
||||
*------------------------------------------------------------------------*/
|
||||
#ifndef FABRICD
|
||||
|
||||
/* Search MPLS TE Circuit context from Interface */
|
||||
static struct mpls_te_circuit *lookup_mpls_params_by_ifp(struct interface *ifp)
|
||||
{
|
||||
struct isis_circuit *circuit;
|
||||
|
||||
if ((circuit = circuit_scan_by_ifp(ifp)) == NULL)
|
||||
return NULL;
|
||||
|
||||
return circuit->mtc;
|
||||
}
|
||||
|
||||
DEFUN (isis_mpls_te_on,
|
||||
isis_mpls_te_on_cmd,
|
||||
@ -1223,9 +1224,9 @@ DEFUN (no_isis_mpls_te_inter_as,
|
||||
|
||||
DEFUN (show_isis_mpls_te_router,
|
||||
show_isis_mpls_te_router_cmd,
|
||||
"show isis mpls-te router",
|
||||
"show " PROTO_NAME " mpls-te router",
|
||||
SHOW_STR
|
||||
ISIS_STR
|
||||
PROTO_HELP
|
||||
MPLS_TE_STR
|
||||
"Router information\n")
|
||||
{
|
||||
@ -1314,9 +1315,9 @@ static void show_mpls_te_sub(struct vty *vty, struct interface *ifp)
|
||||
|
||||
DEFUN (show_isis_mpls_te_interface,
|
||||
show_isis_mpls_te_interface_cmd,
|
||||
"show isis mpls-te interface [INTERFACE]",
|
||||
"show " PROTO_NAME " mpls-te interface [INTERFACE]",
|
||||
SHOW_STR
|
||||
ISIS_STR
|
||||
PROTO_HELP
|
||||
MPLS_TE_STR
|
||||
"Interface information\n"
|
||||
"Interface name\n")
|
||||
@ -1342,6 +1343,7 @@ DEFUN (show_isis_mpls_te_interface,
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize MPLS_TE */
|
||||
void isis_mpls_te_init(void)
|
||||
@ -1357,15 +1359,17 @@ void isis_mpls_te_init(void)
|
||||
isisMplsTE.cir_list = list_new();
|
||||
isisMplsTE.router_id.s_addr = 0;
|
||||
|
||||
#ifndef FABRICD
|
||||
/* Register new VTY commands */
|
||||
install_element(VIEW_NODE, &show_isis_mpls_te_router_cmd);
|
||||
install_element(VIEW_NODE, &show_isis_mpls_te_interface_cmd);
|
||||
|
||||
install_element(ISIS_NODE, &isis_mpls_te_on_cmd);
|
||||
install_element(ISIS_NODE, &no_isis_mpls_te_on_cmd);
|
||||
install_element(ISIS_NODE, &isis_mpls_te_router_addr_cmd);
|
||||
install_element(ISIS_NODE, &isis_mpls_te_inter_as_cmd);
|
||||
install_element(ISIS_NODE, &no_isis_mpls_te_inter_as_cmd);
|
||||
install_element(ROUTER_NODE, &isis_mpls_te_on_cmd);
|
||||
install_element(ROUTER_NODE, &no_isis_mpls_te_on_cmd);
|
||||
install_element(ROUTER_NODE, &isis_mpls_te_router_addr_cmd);
|
||||
install_element(ROUTER_NODE, &isis_mpls_te_inter_as_cmd);
|
||||
install_element(ROUTER_NODE, &no_isis_mpls_te_inter_as_cmd);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -107,6 +107,111 @@ static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX];
|
||||
/* Prototypes */
|
||||
static void append_item(struct isis_item_list *dest, struct isis_item *item);
|
||||
|
||||
/* Functions for Sub-TLV 3 SR Prefix-SID */
|
||||
|
||||
static struct isis_item *copy_item_prefix_sid(struct isis_item *i)
|
||||
{
|
||||
struct isis_prefix_sid *sid = (struct isis_prefix_sid *)i;
|
||||
struct isis_prefix_sid *rv = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*rv));
|
||||
|
||||
rv->flags = sid->flags;
|
||||
rv->algorithm = sid->algorithm;
|
||||
rv->value = sid->value;
|
||||
return (struct isis_item *)rv;
|
||||
}
|
||||
|
||||
static void format_item_prefix_sid(uint16_t mtid, struct isis_item *i,
|
||||
struct sbuf *buf, int indent)
|
||||
{
|
||||
struct isis_prefix_sid *sid = (struct isis_prefix_sid *)i;
|
||||
|
||||
sbuf_push(buf, indent, "SR Prefix-SID:\n");
|
||||
sbuf_push(buf, indent, " Flags:%s%s%s%s%s%s\n",
|
||||
sid->flags & ISIS_PREFIX_SID_READVERTISED ? " READVERTISED" : "",
|
||||
sid->flags & ISIS_PREFIX_SID_NODE ? " NODE" : "",
|
||||
sid->flags & ISIS_PREFIX_SID_NO_PHP ? " NO_PHP" : "",
|
||||
sid->flags & ISIS_PREFIX_SID_EXPLICIT_NULL ? " EXPLICIT-NULL" : "",
|
||||
sid->flags & ISIS_PREFIX_SID_VALUE ? " VALUE" : "",
|
||||
sid->flags & ISIS_PREFIX_SID_LOCAL ? " LOCAL" : "");
|
||||
sbuf_push(buf, indent, " Algorithm: %" PRIu8 "\n", sid->algorithm);
|
||||
if (sid->flags & ISIS_PREFIX_SID_VALUE) {
|
||||
sbuf_push(buf, indent, "Label: %" PRIu32 "\n", sid->value);
|
||||
} else {
|
||||
sbuf_push(buf, indent, "Index: %" PRIu32 "\n", sid->value);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_item_prefix_sid(struct isis_item *i)
|
||||
{
|
||||
XFREE(MTYPE_ISIS_SUBTLV, i);
|
||||
}
|
||||
|
||||
static int pack_item_prefix_sid(struct isis_item *i, struct stream *s)
|
||||
{
|
||||
struct isis_prefix_sid *sid = (struct isis_prefix_sid *)i;
|
||||
|
||||
uint8_t size = (sid->flags & ISIS_PREFIX_SID_VALUE) ? 5 : 6;
|
||||
|
||||
if (STREAM_WRITEABLE(s) < size)
|
||||
return 1;
|
||||
|
||||
stream_putc(s, sid->flags);
|
||||
stream_putc(s, sid->algorithm);
|
||||
|
||||
if (sid->flags & ISIS_PREFIX_SID_VALUE) {
|
||||
stream_put3(s, sid->value);
|
||||
} else {
|
||||
stream_putl(s, sid->value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unpack_item_prefix_sid(uint16_t mtid, uint8_t len, struct stream *s,
|
||||
struct sbuf *log, void *dest, int indent)
|
||||
{
|
||||
struct isis_subtlvs *subtlvs = dest;
|
||||
struct isis_prefix_sid sid = {
|
||||
};
|
||||
|
||||
sbuf_push(log, indent, "Unpacking SR Prefix-SID...\n");
|
||||
|
||||
if (len < 5) {
|
||||
sbuf_push(log, indent,
|
||||
"Not enough data left. (expected 5 or more bytes, got %" PRIu8 ")\n",
|
||||
len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sid.flags = stream_getc(s);
|
||||
if ((sid.flags & ISIS_PREFIX_SID_VALUE)
|
||||
!= (sid.flags & ISIS_PREFIX_SID_LOCAL)) {
|
||||
sbuf_push(log, indent, "Flags inplausible: Local Flag needs to match Value Flag\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sid.algorithm = stream_getc(s);
|
||||
|
||||
uint8_t expected_size = (sid.flags & ISIS_PREFIX_SID_VALUE) ? 5 : 6;
|
||||
if (len != expected_size) {
|
||||
sbuf_push(log, indent,
|
||||
"TLV size differs from expected size. "
|
||||
"(expected %u but got %" PRIu8 ")\n",
|
||||
expected_size, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sid.flags & ISIS_PREFIX_SID_VALUE) {
|
||||
sid.value = stream_get3(s);
|
||||
} else {
|
||||
sid.value = stream_getl(s);
|
||||
}
|
||||
|
||||
format_item_prefix_sid(mtid, (struct isis_item *)&sid, log, indent + 2);
|
||||
append_item(&subtlvs->prefix_sids, copy_item_prefix_sid((struct isis_item *)&sid));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Functions for Sub-TVL ??? IPv6 Source Prefix */
|
||||
|
||||
static struct prefix_ipv6 *copy_subtlv_ipv6_source_prefix(struct prefix_ipv6 *p)
|
||||
@ -198,14 +303,36 @@ static int unpack_subtlv_ipv6_source_prefix(enum isis_tlv_context context,
|
||||
memcpy(subtlvs->source_prefix, &p, sizeof(p));
|
||||
return 0;
|
||||
}
|
||||
static void init_item_list(struct isis_item_list *items);
|
||||
static struct isis_item *copy_item(enum isis_tlv_context context,
|
||||
enum isis_tlv_type type,
|
||||
struct isis_item *item);
|
||||
static void copy_items(enum isis_tlv_context context, enum isis_tlv_type type,
|
||||
struct isis_item_list *src, struct isis_item_list *dest);
|
||||
static void format_items_(uint16_t mtid, enum isis_tlv_context context,
|
||||
enum isis_tlv_type type, struct isis_item_list *items,
|
||||
struct sbuf *buf, int indent);
|
||||
#define format_items(...) format_items_(ISIS_MT_IPV4_UNICAST, __VA_ARGS__)
|
||||
static void free_items(enum isis_tlv_context context, enum isis_tlv_type type,
|
||||
struct isis_item_list *items);
|
||||
static int pack_items_(uint16_t mtid, enum isis_tlv_context context,
|
||||
enum isis_tlv_type type, struct isis_item_list *items,
|
||||
struct stream *s, struct isis_tlvs **fragment_tlvs,
|
||||
struct pack_order_entry *pe,
|
||||
struct isis_tlvs *(*new_fragment)(struct list *l),
|
||||
struct list *new_fragment_arg);
|
||||
#define pack_items(...) pack_items_(ISIS_MT_IPV4_UNICAST, __VA_ARGS__)
|
||||
|
||||
/* Functions related to subtlvs */
|
||||
|
||||
static struct isis_subtlvs *isis_alloc_subtlvs(void)
|
||||
static struct isis_subtlvs *isis_alloc_subtlvs(enum isis_tlv_context context)
|
||||
{
|
||||
struct isis_subtlvs *result;
|
||||
|
||||
result = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*result));
|
||||
result->context = context;
|
||||
|
||||
init_item_list(&result->prefix_sids);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -217,6 +344,11 @@ static struct isis_subtlvs *copy_subtlvs(struct isis_subtlvs *subtlvs)
|
||||
|
||||
struct isis_subtlvs *rv = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*rv));
|
||||
|
||||
rv->context = subtlvs->context;
|
||||
|
||||
copy_items(subtlvs->context, ISIS_SUBTLV_PREFIX_SID,
|
||||
&subtlvs->prefix_sids, &rv->prefix_sids);
|
||||
|
||||
rv->source_prefix =
|
||||
copy_subtlv_ipv6_source_prefix(subtlvs->source_prefix);
|
||||
return rv;
|
||||
@ -225,6 +357,9 @@ static struct isis_subtlvs *copy_subtlvs(struct isis_subtlvs *subtlvs)
|
||||
static void format_subtlvs(struct isis_subtlvs *subtlvs, struct sbuf *buf,
|
||||
int indent)
|
||||
{
|
||||
format_items(subtlvs->context, ISIS_SUBTLV_PREFIX_SID,
|
||||
&subtlvs->prefix_sids, buf, indent);
|
||||
|
||||
format_subtlv_ipv6_source_prefix(subtlvs->source_prefix, buf, indent);
|
||||
}
|
||||
|
||||
@ -233,6 +368,9 @@ static void isis_free_subtlvs(struct isis_subtlvs *subtlvs)
|
||||
if (!subtlvs)
|
||||
return;
|
||||
|
||||
free_items(subtlvs->context, ISIS_SUBTLV_PREFIX_SID,
|
||||
&subtlvs->prefix_sids);
|
||||
|
||||
XFREE(MTYPE_ISIS_SUBTLV, subtlvs->source_prefix);
|
||||
|
||||
XFREE(MTYPE_ISIS_SUBTLV, subtlvs);
|
||||
@ -248,6 +386,11 @@ static int pack_subtlvs(struct isis_subtlvs *subtlvs, struct stream *s)
|
||||
|
||||
stream_putc(s, 0); /* Put 0 as subtlvs length, filled in later */
|
||||
|
||||
rv = pack_items(subtlvs->context, ISIS_SUBTLV_PREFIX_SID,
|
||||
&subtlvs->prefix_sids, s, NULL, NULL, NULL, NULL);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
rv = pack_subtlv_ipv6_source_prefix(subtlvs->source_prefix, s);
|
||||
if (rv)
|
||||
return rv;
|
||||
@ -1135,6 +1278,7 @@ static void free_item_extended_ip_reach(struct isis_item *i)
|
||||
{
|
||||
struct isis_extended_ip_reach *item =
|
||||
(struct isis_extended_ip_reach *)i;
|
||||
isis_free_subtlvs(item->subtlvs);
|
||||
XFREE(MTYPE_ISIS_TLV, item);
|
||||
}
|
||||
|
||||
@ -1149,11 +1293,16 @@ static int pack_item_extended_ip_reach(struct isis_item *i, struct stream *s)
|
||||
|
||||
control = r->down ? ISIS_EXTENDED_IP_REACH_DOWN : 0;
|
||||
control |= r->prefix.prefixlen;
|
||||
control |= r->subtlvs ? ISIS_EXTENDED_IP_REACH_SUBTLV : 0;
|
||||
|
||||
stream_putc(s, control);
|
||||
|
||||
if (STREAM_WRITEABLE(s) < (unsigned)PSIZE(r->prefix.prefixlen))
|
||||
return 1;
|
||||
stream_put(s, &r->prefix.prefix.s_addr, PSIZE(r->prefix.prefixlen));
|
||||
|
||||
if (r->subtlvs)
|
||||
return pack_subtlvs(r->subtlvs, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1235,9 +1384,12 @@ static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len,
|
||||
len - 6 - PSIZE(rv->prefix.prefixlen));
|
||||
goto out;
|
||||
}
|
||||
sbuf_push(log, indent, "Skipping %" PRIu8 " bytes of subvls",
|
||||
subtlv_len);
|
||||
stream_forward_getp(s, subtlv_len);
|
||||
|
||||
rv->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IP_REACH);
|
||||
if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_IP_REACH, subtlv_len, s,
|
||||
log, rv->subtlvs, indent + 4)) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
append_item(items, (struct isis_item *)rv);
|
||||
@ -1329,6 +1481,126 @@ static int unpack_tlv_dynamic_hostname(enum isis_tlv_context context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Functions related to TLV 150 Spine-Leaf-Extension */
|
||||
|
||||
static struct isis_spine_leaf *copy_tlv_spine_leaf(
|
||||
const struct isis_spine_leaf *spine_leaf)
|
||||
{
|
||||
if (!spine_leaf)
|
||||
return NULL;
|
||||
|
||||
struct isis_spine_leaf *rv = XMALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
|
||||
memcpy(rv, spine_leaf, sizeof(*rv));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void format_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
|
||||
struct sbuf *buf, int indent)
|
||||
{
|
||||
if (!spine_leaf)
|
||||
return;
|
||||
|
||||
sbuf_push(buf, indent, "Spine-Leaf-Extension:\n");
|
||||
if (spine_leaf->has_tier) {
|
||||
if (spine_leaf->tier == ISIS_TIER_UNDEFINED) {
|
||||
sbuf_push(buf, indent, " Tier: undefined\n");
|
||||
} else {
|
||||
sbuf_push(buf, indent, " Tier: %" PRIu8 "\n",
|
||||
spine_leaf->tier);
|
||||
}
|
||||
}
|
||||
|
||||
sbuf_push(buf, indent, " Flags:%s%s%s\n",
|
||||
spine_leaf->is_leaf ? " LEAF" : "",
|
||||
spine_leaf->is_spine ? " SPINE" : "",
|
||||
spine_leaf->is_backup ? " BACKUP" : "");
|
||||
|
||||
}
|
||||
|
||||
static void free_tlv_spine_leaf(struct isis_spine_leaf *spine_leaf)
|
||||
{
|
||||
XFREE(MTYPE_ISIS_TLV, spine_leaf);
|
||||
}
|
||||
|
||||
#define ISIS_SPINE_LEAF_FLAG_TIER 0x08
|
||||
#define ISIS_SPINE_LEAF_FLAG_BACKUP 0x04
|
||||
#define ISIS_SPINE_LEAF_FLAG_SPINE 0x02
|
||||
#define ISIS_SPINE_LEAF_FLAG_LEAF 0x01
|
||||
|
||||
static int pack_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
|
||||
struct stream *s)
|
||||
{
|
||||
if (!spine_leaf)
|
||||
return 0;
|
||||
|
||||
uint8_t tlv_len = 2;
|
||||
|
||||
if (STREAM_WRITEABLE(s) < (unsigned)(2 + tlv_len))
|
||||
return 1;
|
||||
|
||||
stream_putc(s, ISIS_TLV_SPINE_LEAF_EXT);
|
||||
stream_putc(s, tlv_len);
|
||||
|
||||
uint16_t spine_leaf_flags = 0;
|
||||
|
||||
if (spine_leaf->has_tier) {
|
||||
spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_TIER;
|
||||
spine_leaf_flags |= spine_leaf->tier << 12;
|
||||
}
|
||||
|
||||
if (spine_leaf->is_leaf)
|
||||
spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_LEAF;
|
||||
|
||||
if (spine_leaf->is_spine)
|
||||
spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_SPINE;
|
||||
|
||||
if (spine_leaf->is_backup)
|
||||
spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_BACKUP;
|
||||
|
||||
stream_putw(s, spine_leaf_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unpack_tlv_spine_leaf(enum isis_tlv_context context,
|
||||
uint8_t tlv_type, uint8_t tlv_len,
|
||||
struct stream *s, struct sbuf *log,
|
||||
void *dest, int indent)
|
||||
{
|
||||
struct isis_tlvs *tlvs = dest;
|
||||
|
||||
sbuf_push(log, indent, "Unpacking Spine Leaf Extension TLV...\n");
|
||||
if (tlv_len < 2) {
|
||||
sbuf_push(log, indent, "WARNING: Unexepected TLV size\n");
|
||||
stream_forward_getp(s, tlv_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tlvs->spine_leaf) {
|
||||
sbuf_push(log, indent,
|
||||
"WARNING: Spine Leaf Extension TLV present multiple times.\n");
|
||||
stream_forward_getp(s, tlv_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tlvs->spine_leaf = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->spine_leaf));
|
||||
|
||||
uint16_t spine_leaf_flags = stream_getw(s);
|
||||
|
||||
if (spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_TIER) {
|
||||
tlvs->spine_leaf->has_tier = true;
|
||||
tlvs->spine_leaf->tier = spine_leaf_flags >> 12;
|
||||
}
|
||||
|
||||
tlvs->spine_leaf->is_leaf = spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_LEAF;
|
||||
tlvs->spine_leaf->is_spine = spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_SPINE;
|
||||
tlvs->spine_leaf->is_backup = spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_BACKUP;
|
||||
|
||||
stream_forward_getp(s, tlv_len - 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Functions related to TLV 240 P2P Three-Way Adjacency */
|
||||
|
||||
const char *isis_threeway_state_name(enum isis_threeway_state state)
|
||||
@ -1592,7 +1864,7 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s,
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv->subtlvs = isis_alloc_subtlvs();
|
||||
rv->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IPV6_REACH);
|
||||
if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_IPV6_REACH, subtlv_len, s,
|
||||
log, rv->subtlvs, indent + 4)) {
|
||||
goto out;
|
||||
@ -1713,6 +1985,114 @@ static int unpack_item_auth(uint16_t mtid, uint8_t len, struct stream *s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Functions related to TLV 13 Purge Originator */
|
||||
|
||||
static struct isis_purge_originator *copy_tlv_purge_originator(
|
||||
struct isis_purge_originator *poi)
|
||||
{
|
||||
if (!poi)
|
||||
return NULL;
|
||||
|
||||
struct isis_purge_originator *rv;
|
||||
|
||||
rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
|
||||
rv->sender_set = poi->sender_set;
|
||||
memcpy(rv->generator, poi->generator, sizeof(rv->generator));
|
||||
if (poi->sender_set)
|
||||
memcpy(rv->sender, poi->sender, sizeof(rv->sender));
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void format_tlv_purge_originator(struct isis_purge_originator *poi,
|
||||
struct sbuf *buf, int indent)
|
||||
{
|
||||
if (!poi)
|
||||
return;
|
||||
|
||||
sbuf_push(buf, indent, "Purge Originator Identification:\n");
|
||||
sbuf_push(buf, indent, " Generator: %s\n",
|
||||
isis_format_id(poi->generator, sizeof(poi->generator)));
|
||||
if (poi->sender_set) {
|
||||
sbuf_push(buf, indent, " Received-From: %s\n",
|
||||
isis_format_id(poi->sender, sizeof(poi->sender)));
|
||||
}
|
||||
}
|
||||
|
||||
static void free_tlv_purge_originator(struct isis_purge_originator *poi)
|
||||
{
|
||||
XFREE(MTYPE_ISIS_TLV, poi);
|
||||
}
|
||||
|
||||
static int pack_tlv_purge_originator(struct isis_purge_originator *poi,
|
||||
struct stream *s)
|
||||
{
|
||||
if (!poi)
|
||||
return 0;
|
||||
|
||||
uint8_t data_len = 1 + sizeof(poi->generator);
|
||||
|
||||
if (poi->sender_set)
|
||||
data_len += sizeof(poi->sender);
|
||||
|
||||
if (STREAM_WRITEABLE(s) < (unsigned)(2 + data_len))
|
||||
return 1;
|
||||
|
||||
stream_putc(s, ISIS_TLV_PURGE_ORIGINATOR);
|
||||
stream_putc(s, data_len);
|
||||
stream_putc(s, poi->sender_set ? 2 : 1);
|
||||
stream_put(s, poi->generator, sizeof(poi->generator));
|
||||
if (poi->sender_set)
|
||||
stream_put(s, poi->sender, sizeof(poi->sender));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unpack_tlv_purge_originator(enum isis_tlv_context context,
|
||||
uint8_t tlv_type, uint8_t tlv_len,
|
||||
struct stream *s, struct sbuf *log,
|
||||
void *dest, int indent)
|
||||
{
|
||||
struct isis_tlvs *tlvs = dest;
|
||||
struct isis_purge_originator poi = {};
|
||||
|
||||
sbuf_push(log, indent, "Unpacking Purge Originator Identification TLV...\n");
|
||||
if (tlv_len < 7) {
|
||||
sbuf_push(log, indent, "Not enough data left. (Expected at least 7 bytes, got %"
|
||||
PRIu8 ")\n", tlv_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t number_of_ids = stream_getc(s);
|
||||
|
||||
if (number_of_ids == 1) {
|
||||
poi.sender_set = false;
|
||||
} else if (number_of_ids == 2) {
|
||||
poi.sender_set = true;
|
||||
} else {
|
||||
sbuf_push(log, indent, "Got invalid value for number of system IDs: %"
|
||||
PRIu8 ")\n", number_of_ids);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (tlv_len != 1 + 6 * number_of_ids) {
|
||||
sbuf_push(log, indent, "Incorrect tlv len for number of IDs.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
stream_get(poi.generator, s, sizeof(poi.generator));
|
||||
if (poi.sender_set)
|
||||
stream_get(poi.sender, s, sizeof(poi.sender));
|
||||
|
||||
if (tlvs->purge_originator) {
|
||||
sbuf_push(log, indent,
|
||||
"WARNING: Purge originator present multiple times, ignoring.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
tlvs->purge_originator = copy_tlv_purge_originator(&poi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Functions relating to item TLVs */
|
||||
|
||||
static void init_item_list(struct isis_item_list *items)
|
||||
@ -1770,7 +2150,6 @@ static void format_items_(uint16_t mtid, enum isis_tlv_context context,
|
||||
for (i = items->head; i; i = i->next)
|
||||
format_item(mtid, context, type, i, buf, indent);
|
||||
}
|
||||
#define format_items(...) format_items_(ISIS_MT_IPV4_UNICAST, __VA_ARGS__)
|
||||
|
||||
static void free_item(enum isis_tlv_context tlv_context,
|
||||
enum isis_tlv_type tlv_type, struct isis_item *item)
|
||||
@ -1876,6 +2255,14 @@ top:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Multiple prefix-sids don't go into one TLV, so always break */
|
||||
if (type == ISIS_SUBTLV_PREFIX_SID
|
||||
&& (context == ISIS_CONTEXT_SUBTLV_IP_REACH
|
||||
|| context == ISIS_CONTEXT_SUBTLV_IPV6_REACH)) {
|
||||
item = item->next;
|
||||
break;
|
||||
}
|
||||
|
||||
if (len > 255) {
|
||||
if (!last_len) /* strange, not a single item fit */
|
||||
return 1;
|
||||
@ -2131,6 +2518,9 @@ struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
|
||||
copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH, &tlvs->isis_auth,
|
||||
&rv->isis_auth);
|
||||
|
||||
rv->purge_originator =
|
||||
copy_tlv_purge_originator(tlvs->purge_originator);
|
||||
|
||||
copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_AREA_ADDRESSES,
|
||||
&tlvs->area_addresses, &rv->area_addresses);
|
||||
|
||||
@ -2187,6 +2577,8 @@ struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
|
||||
|
||||
rv->threeway_adj = copy_tlv_threeway_adj(tlvs->threeway_adj);
|
||||
|
||||
rv->spine_leaf = copy_tlv_spine_leaf(tlvs->spine_leaf);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -2197,6 +2589,8 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
|
||||
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH, &tlvs->isis_auth, buf,
|
||||
indent);
|
||||
|
||||
format_tlv_purge_originator(tlvs->purge_originator, buf, indent);
|
||||
|
||||
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_AREA_ADDRESSES,
|
||||
&tlvs->area_addresses, buf, indent);
|
||||
|
||||
@ -2250,6 +2644,8 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
|
||||
&tlvs->mt_ipv6_reach, buf, indent);
|
||||
|
||||
format_tlv_threeway_adj(tlvs->threeway_adj, buf, indent);
|
||||
|
||||
format_tlv_spine_leaf(tlvs->spine_leaf, buf, indent);
|
||||
}
|
||||
|
||||
const char *isis_format_tlvs(struct isis_tlvs *tlvs)
|
||||
@ -2270,6 +2666,7 @@ void isis_free_tlvs(struct isis_tlvs *tlvs)
|
||||
return;
|
||||
|
||||
free_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH, &tlvs->isis_auth);
|
||||
free_tlv_purge_originator(tlvs->purge_originator);
|
||||
free_items(ISIS_CONTEXT_LSP, ISIS_TLV_AREA_ADDRESSES,
|
||||
&tlvs->area_addresses);
|
||||
free_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_ROUTER_INFO,
|
||||
@ -2301,6 +2698,7 @@ void isis_free_tlvs(struct isis_tlvs *tlvs)
|
||||
free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
|
||||
&tlvs->mt_ipv6_reach);
|
||||
free_tlv_threeway_adj(tlvs->threeway_adj);
|
||||
free_tlv_spine_leaf(tlvs->spine_leaf);
|
||||
|
||||
XFREE(MTYPE_ISIS_TLV, tlvs);
|
||||
}
|
||||
@ -2417,6 +2815,14 @@ static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = pack_tlv_purge_originator(tlvs->purge_originator, stream);
|
||||
if (rv)
|
||||
return rv;
|
||||
if (fragment_tlvs) {
|
||||
fragment_tlvs->purge_originator =
|
||||
copy_tlv_purge_originator(tlvs->purge_originator);
|
||||
}
|
||||
|
||||
rv = pack_tlv_protocols_supported(&tlvs->protocols_supported, stream);
|
||||
if (rv)
|
||||
return rv;
|
||||
@ -2480,6 +2886,14 @@ static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
|
||||
copy_tlv_threeway_adj(tlvs->threeway_adj);
|
||||
}
|
||||
|
||||
rv = pack_tlv_spine_leaf(tlvs->spine_leaf, stream);
|
||||
if (rv)
|
||||
return rv;
|
||||
if (fragment_tlvs) {
|
||||
fragment_tlvs->spine_leaf =
|
||||
copy_tlv_spine_leaf(tlvs->spine_leaf);
|
||||
}
|
||||
|
||||
for (size_t pack_idx = 0; pack_idx < array_size(pack_order);
|
||||
pack_idx++) {
|
||||
rv = handle_pack_entry(&pack_order[pack_idx], tlvs, stream,
|
||||
@ -2667,11 +3081,15 @@ int isis_unpack_tlvs(size_t avail_len, struct stream *stream,
|
||||
.name = _desc_, .unpack = unpack_subtlv_##_name_, \
|
||||
}
|
||||
|
||||
#define ITEM_SUBTLV_OPS(_name_, _desc_) \
|
||||
ITEM_TLV_OPS(_name_, _desc_)
|
||||
|
||||
ITEM_TLV_OPS(area_address, "TLV 1 Area Addresses");
|
||||
ITEM_TLV_OPS(oldstyle_reach, "TLV 2 IS Reachability");
|
||||
ITEM_TLV_OPS(lan_neighbor, "TLV 6 LAN Neighbors");
|
||||
ITEM_TLV_OPS(lsp_entry, "TLV 9 LSP Entries");
|
||||
ITEM_TLV_OPS(auth, "TLV 10 IS-IS Auth");
|
||||
TLV_OPS(purge_originator, "TLV 13 Purge Originator Identification");
|
||||
ITEM_TLV_OPS(extended_reach, "TLV 22 Extended Reachability");
|
||||
ITEM_TLV_OPS(oldstyle_ip_reach, "TLV 128/130 IP Reachability");
|
||||
TLV_OPS(protocols_supported, "TLV 129 Protocols Supported");
|
||||
@ -2679,11 +3097,13 @@ ITEM_TLV_OPS(ipv4_address, "TLV 132 IPv4 Interface Address");
|
||||
TLV_OPS(te_router_id, "TLV 134 TE Router ID");
|
||||
ITEM_TLV_OPS(extended_ip_reach, "TLV 135 Extended IP Reachability");
|
||||
TLV_OPS(dynamic_hostname, "TLV 137 Dynamic Hostname");
|
||||
TLV_OPS(spine_leaf, "TLV 150 Spine Leaf Extensions");
|
||||
ITEM_TLV_OPS(mt_router_info, "TLV 229 MT Router Information");
|
||||
TLV_OPS(threeway_adj, "TLV 240 P2P Three-Way Adjacency");
|
||||
ITEM_TLV_OPS(ipv6_address, "TLV 232 IPv6 Interface Address");
|
||||
ITEM_TLV_OPS(ipv6_reach, "TLV 236 IPv6 Reachability");
|
||||
|
||||
ITEM_SUBTLV_OPS(prefix_sid, "Sub-TLV 3 SR Prefix-SID");
|
||||
SUBTLV_OPS(ipv6_source_prefix, "Sub-TLV 22 IPv6 Source Prefix");
|
||||
|
||||
static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
|
||||
@ -2693,6 +3113,7 @@ static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
|
||||
[ISIS_TLV_LAN_NEIGHBORS] = &tlv_lan_neighbor_ops,
|
||||
[ISIS_TLV_LSP_ENTRY] = &tlv_lsp_entry_ops,
|
||||
[ISIS_TLV_AUTH] = &tlv_auth_ops,
|
||||
[ISIS_TLV_PURGE_ORIGINATOR] = &tlv_purge_originator_ops,
|
||||
[ISIS_TLV_EXTENDED_REACH] = &tlv_extended_reach_ops,
|
||||
[ISIS_TLV_MT_REACH] = &tlv_extended_reach_ops,
|
||||
[ISIS_TLV_OLDSTYLE_IP_REACH] = &tlv_oldstyle_ip_reach_ops,
|
||||
@ -2703,6 +3124,7 @@ static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
|
||||
[ISIS_TLV_EXTENDED_IP_REACH] = &tlv_extended_ip_reach_ops,
|
||||
[ISIS_TLV_MT_IP_REACH] = &tlv_extended_ip_reach_ops,
|
||||
[ISIS_TLV_DYNAMIC_HOSTNAME] = &tlv_dynamic_hostname_ops,
|
||||
[ISIS_TLV_SPINE_LEAF_EXT] = &tlv_spine_leaf_ops,
|
||||
[ISIS_TLV_MT_ROUTER_INFO] = &tlv_mt_router_info_ops,
|
||||
[ISIS_TLV_THREE_WAY_ADJ] = &tlv_threeway_adj_ops,
|
||||
[ISIS_TLV_IPV6_ADDRESS] = &tlv_ipv6_address_ops,
|
||||
@ -2710,8 +3132,11 @@ static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
|
||||
[ISIS_TLV_MT_IPV6_REACH] = &tlv_ipv6_reach_ops,
|
||||
},
|
||||
[ISIS_CONTEXT_SUBTLV_NE_REACH] = {},
|
||||
[ISIS_CONTEXT_SUBTLV_IP_REACH] = {},
|
||||
[ISIS_CONTEXT_SUBTLV_IP_REACH] = {
|
||||
[ISIS_SUBTLV_PREFIX_SID] = &tlv_prefix_sid_ops,
|
||||
},
|
||||
[ISIS_CONTEXT_SUBTLV_IPV6_REACH] = {
|
||||
[ISIS_SUBTLV_PREFIX_SID] = &tlv_prefix_sid_ops,
|
||||
[ISIS_SUBTLV_IPV6_SOURCE_PREFIX] = &subtlv_ipv6_source_prefix_ops,
|
||||
}
|
||||
};
|
||||
@ -3183,7 +3608,7 @@ void isis_tlvs_add_ipv6_dstsrc_reach(struct isis_tlvs *tlvs, uint16_t mtid,
|
||||
mtid);
|
||||
|
||||
struct isis_ipv6_reach *r = (struct isis_ipv6_reach*)last_item(l);
|
||||
r->subtlvs = isis_alloc_subtlvs();
|
||||
r->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IPV6_REACH);
|
||||
r->subtlvs->source_prefix = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*src));
|
||||
memcpy(r->subtlvs->source_prefix, src, sizeof(*src));
|
||||
}
|
||||
@ -3239,6 +3664,24 @@ void isis_tlvs_add_threeway_adj(struct isis_tlvs *tlvs,
|
||||
}
|
||||
}
|
||||
|
||||
void isis_tlvs_add_spine_leaf(struct isis_tlvs *tlvs, uint8_t tier,
|
||||
bool has_tier, bool is_leaf, bool is_spine,
|
||||
bool is_backup)
|
||||
{
|
||||
assert(!tlvs->spine_leaf);
|
||||
|
||||
tlvs->spine_leaf = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->spine_leaf));
|
||||
|
||||
if (has_tier) {
|
||||
tlvs->spine_leaf->tier = tier;
|
||||
}
|
||||
|
||||
tlvs->spine_leaf->has_tier = has_tier;
|
||||
tlvs->spine_leaf->is_leaf = is_leaf;
|
||||
tlvs->spine_leaf->is_spine = is_spine;
|
||||
tlvs->spine_leaf->is_backup = is_backup;
|
||||
}
|
||||
|
||||
struct isis_mt_router_info *
|
||||
isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid)
|
||||
{
|
||||
@ -3254,3 +3697,20 @@ isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void isis_tlvs_set_purge_originator(struct isis_tlvs *tlvs,
|
||||
const uint8_t *generator,
|
||||
const uint8_t *sender)
|
||||
{
|
||||
assert(!tlvs->purge_originator);
|
||||
|
||||
tlvs->purge_originator = XCALLOC(MTYPE_ISIS_TLV,
|
||||
sizeof(*tlvs->purge_originator));
|
||||
memcpy(tlvs->purge_originator->generator, generator,
|
||||
sizeof(tlvs->purge_originator->generator));
|
||||
if (sender) {
|
||||
tlvs->purge_originator->sender_set = true;
|
||||
memcpy(tlvs->purge_originator->sender, sender,
|
||||
sizeof(tlvs->purge_originator->sender));
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +83,8 @@ struct isis_extended_ip_reach {
|
||||
uint32_t metric;
|
||||
bool down;
|
||||
struct prefix_ipv4 prefix;
|
||||
|
||||
struct isis_subtlvs *subtlvs;
|
||||
};
|
||||
|
||||
struct isis_ipv6_reach;
|
||||
@ -103,6 +105,17 @@ struct isis_protocols_supported {
|
||||
uint8_t *protocols;
|
||||
};
|
||||
|
||||
#define ISIS_TIER_UNDEFINED 15
|
||||
|
||||
struct isis_spine_leaf {
|
||||
uint8_t tier;
|
||||
|
||||
bool has_tier;
|
||||
bool is_leaf;
|
||||
bool is_spine;
|
||||
bool is_backup;
|
||||
};
|
||||
|
||||
enum isis_threeway_state {
|
||||
ISIS_THREEWAY_DOWN = 2,
|
||||
ISIS_THREEWAY_INITIALIZING = 1,
|
||||
@ -176,6 +189,13 @@ struct isis_item_list {
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
struct isis_purge_originator {
|
||||
bool sender_set;
|
||||
|
||||
uint8_t generator[6];
|
||||
uint8_t sender[6];
|
||||
};
|
||||
|
||||
RB_HEAD(isis_mt_item_list, isis_item_list);
|
||||
|
||||
struct isis_item_list *isis_get_mt_items(struct isis_mt_item_list *m,
|
||||
@ -185,6 +205,7 @@ struct isis_item_list *isis_lookup_mt_items(struct isis_mt_item_list *m,
|
||||
|
||||
struct isis_tlvs {
|
||||
struct isis_item_list isis_auth;
|
||||
struct isis_purge_originator *purge_originator;
|
||||
struct isis_item_list area_addresses;
|
||||
struct isis_item_list oldstyle_reach;
|
||||
struct isis_item_list lan_neighbor;
|
||||
@ -205,11 +226,24 @@ struct isis_tlvs {
|
||||
struct isis_item_list ipv6_reach;
|
||||
struct isis_mt_item_list mt_ipv6_reach;
|
||||
struct isis_threeway_adj *threeway_adj;
|
||||
struct isis_spine_leaf *spine_leaf;
|
||||
};
|
||||
|
||||
struct isis_subtlvs {
|
||||
/* draft-baker-ipv6-isis-dst-src-routing-06 */
|
||||
struct prefix_ipv6 *source_prefix;
|
||||
#define ISIS_PREFIX_SID_READVERTISED 0x80
|
||||
#define ISIS_PREFIX_SID_NODE 0x40
|
||||
#define ISIS_PREFIX_SID_NO_PHP 0x20
|
||||
#define ISIS_PREFIX_SID_EXPLICIT_NULL 0x10
|
||||
#define ISIS_PREFIX_SID_VALUE 0x08
|
||||
#define ISIS_PREFIX_SID_LOCAL 0x04
|
||||
|
||||
struct isis_prefix_sid;
|
||||
struct isis_prefix_sid {
|
||||
struct isis_prefix_sid *next;
|
||||
|
||||
uint8_t flags;
|
||||
uint8_t algorithm;
|
||||
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
enum isis_tlv_context {
|
||||
@ -220,6 +254,15 @@ enum isis_tlv_context {
|
||||
ISIS_CONTEXT_MAX
|
||||
};
|
||||
|
||||
struct isis_subtlvs {
|
||||
enum isis_tlv_context context;
|
||||
|
||||
/* draft-baker-ipv6-isis-dst-src-routing-06 */
|
||||
struct prefix_ipv6 *source_prefix;
|
||||
/* draft-ietf-isis-segment-routing-extensions-16 */
|
||||
struct isis_item_list prefix_sids;
|
||||
};
|
||||
|
||||
enum isis_tlv_type {
|
||||
ISIS_TLV_AREA_ADDRESSES = 1,
|
||||
ISIS_TLV_OLDSTYLE_REACH = 2,
|
||||
@ -227,6 +270,7 @@ enum isis_tlv_type {
|
||||
ISIS_TLV_PADDING = 8,
|
||||
ISIS_TLV_LSP_ENTRY = 9,
|
||||
ISIS_TLV_AUTH = 10,
|
||||
ISIS_TLV_PURGE_ORIGINATOR = 13,
|
||||
ISIS_TLV_EXTENDED_REACH = 22,
|
||||
|
||||
ISIS_TLV_OLDSTYLE_IP_REACH = 128,
|
||||
@ -236,6 +280,7 @@ enum isis_tlv_type {
|
||||
ISIS_TLV_TE_ROUTER_ID = 134,
|
||||
ISIS_TLV_EXTENDED_IP_REACH = 135,
|
||||
ISIS_TLV_DYNAMIC_HOSTNAME = 137,
|
||||
ISIS_TLV_SPINE_LEAF_EXT = 150,
|
||||
ISIS_TLV_MT_REACH = 222,
|
||||
ISIS_TLV_MT_ROUTER_INFO = 229,
|
||||
ISIS_TLV_IPV6_ADDRESS = 232,
|
||||
@ -245,6 +290,7 @@ enum isis_tlv_type {
|
||||
ISIS_TLV_THREE_WAY_ADJ = 240,
|
||||
ISIS_TLV_MAX = 256,
|
||||
|
||||
ISIS_SUBTLV_PREFIX_SID = 3,
|
||||
ISIS_SUBTLV_IPV6_SOURCE_PREFIX = 22
|
||||
};
|
||||
|
||||
@ -331,6 +377,14 @@ void isis_tlvs_add_threeway_adj(struct isis_tlvs *tlvs,
|
||||
const uint8_t *neighbor_id,
|
||||
uint32_t neighbor_circuit_id);
|
||||
|
||||
void isis_tlvs_add_spine_leaf(struct isis_tlvs *tlvs, uint8_t tier,
|
||||
bool has_tier, bool is_leaf, bool is_spine,
|
||||
bool is_backup);
|
||||
|
||||
struct isis_mt_router_info *
|
||||
isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid);
|
||||
|
||||
void isis_tlvs_set_purge_originator(struct isis_tlvs *tlvs,
|
||||
const uint8_t *generator,
|
||||
const uint8_t *sender);
|
||||
#endif
|
||||
|
182
isisd/isis_tx_queue.c
Normal file
182
isisd/isis_tx_queue.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* IS-IS Rout(e)ing protocol - LSP TX Queuing logic
|
||||
*
|
||||
* Copyright (C) 2018 Christian Franke
|
||||
*
|
||||
* This file is part of FreeRangeRouting (FRR)
|
||||
*
|
||||
* FRR 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, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* FRR 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>
|
||||
|
||||
#include "hash.h"
|
||||
#include "jhash.h"
|
||||
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_memory.h"
|
||||
#include "isisd/isis_flags.h"
|
||||
#include "dict.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
#include "isisd/isis_tx_queue.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(ISISD, TX_QUEUE, "ISIS TX Queue")
|
||||
DEFINE_MTYPE_STATIC(ISISD, TX_QUEUE_ENTRY, "ISIS TX Queue Entry")
|
||||
|
||||
struct isis_tx_queue {
|
||||
void *arg;
|
||||
void (*send_event)(void *arg, struct isis_lsp *, enum isis_tx_type);
|
||||
struct hash *hash;
|
||||
};
|
||||
|
||||
struct isis_tx_queue_entry {
|
||||
struct isis_lsp *lsp;
|
||||
enum isis_tx_type type;
|
||||
struct thread *retry;
|
||||
struct isis_tx_queue *queue;
|
||||
};
|
||||
|
||||
static unsigned tx_queue_hash_key(void *p)
|
||||
{
|
||||
struct isis_tx_queue_entry *e = p;
|
||||
|
||||
uint32_t id_key = jhash(e->lsp->hdr.lsp_id,
|
||||
ISIS_SYS_ID_LEN + 2, 0x55aa5a5a);
|
||||
|
||||
return jhash_1word(e->lsp->level, id_key);
|
||||
}
|
||||
|
||||
static int tx_queue_hash_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct isis_tx_queue_entry *ea = a, *eb = b;
|
||||
|
||||
if (ea->lsp->level != eb->lsp->level)
|
||||
return 0;
|
||||
|
||||
if (memcmp(ea->lsp->hdr.lsp_id, eb->lsp->hdr.lsp_id,
|
||||
ISIS_SYS_ID_LEN + 2))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct isis_tx_queue *isis_tx_queue_new(void *arg,
|
||||
void(*send_event)(void *arg,
|
||||
struct isis_lsp *,
|
||||
enum isis_tx_type))
|
||||
{
|
||||
struct isis_tx_queue *rv = XCALLOC(MTYPE_TX_QUEUE, sizeof(*rv));
|
||||
|
||||
rv->arg = arg;
|
||||
rv->send_event = send_event;
|
||||
|
||||
rv->hash = hash_create(tx_queue_hash_key, tx_queue_hash_cmp, NULL);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void tx_queue_element_free(void *element)
|
||||
{
|
||||
struct isis_tx_queue_entry *e = element;
|
||||
|
||||
if (e->retry)
|
||||
thread_cancel(e->retry);
|
||||
|
||||
XFREE(MTYPE_TX_QUEUE_ENTRY, e);
|
||||
}
|
||||
|
||||
void isis_tx_queue_free(struct isis_tx_queue *queue)
|
||||
{
|
||||
hash_clean(queue->hash, tx_queue_element_free);
|
||||
hash_free(queue->hash);
|
||||
XFREE(MTYPE_TX_QUEUE, queue);
|
||||
}
|
||||
|
||||
static struct isis_tx_queue_entry *tx_queue_find(struct isis_tx_queue *queue,
|
||||
struct isis_lsp *lsp)
|
||||
{
|
||||
struct isis_tx_queue_entry e = {
|
||||
.lsp = lsp
|
||||
};
|
||||
|
||||
return hash_lookup(queue->hash, &e);
|
||||
}
|
||||
|
||||
static int tx_queue_send_event(struct thread *thread)
|
||||
{
|
||||
struct isis_tx_queue_entry *e = THREAD_ARG(thread);
|
||||
struct isis_tx_queue *queue = e->queue;
|
||||
|
||||
e->retry = NULL;
|
||||
thread_add_timer(master, tx_queue_send_event, e, 5, &e->retry);
|
||||
|
||||
queue->send_event(queue->arg, e->lsp, e->type);
|
||||
/* Don't access e here anymore, send_event might have destroyed it */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isis_tx_queue_add(struct isis_tx_queue *queue,
|
||||
struct isis_lsp *lsp,
|
||||
enum isis_tx_type type)
|
||||
{
|
||||
if (!queue)
|
||||
return;
|
||||
|
||||
struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp);
|
||||
if (!e) {
|
||||
e = XCALLOC(MTYPE_TX_QUEUE_ENTRY, sizeof(*e));
|
||||
e->lsp = lsp;
|
||||
e->queue = queue;
|
||||
|
||||
struct isis_tx_queue_entry *inserted;
|
||||
inserted = hash_get(queue->hash, e, hash_alloc_intern);
|
||||
assert(inserted == e);
|
||||
}
|
||||
|
||||
e->type = type;
|
||||
|
||||
if (e->retry)
|
||||
thread_cancel(e->retry);
|
||||
thread_add_event(master, tx_queue_send_event, e, 0, &e->retry);
|
||||
}
|
||||
|
||||
void isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp)
|
||||
{
|
||||
if (!queue)
|
||||
return;
|
||||
|
||||
struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp);
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
if (e->retry)
|
||||
thread_cancel(e->retry);
|
||||
|
||||
hash_release(queue->hash, e);
|
||||
XFREE(MTYPE_TX_QUEUE_ENTRY, e);
|
||||
}
|
||||
|
||||
unsigned long isis_tx_queue_len(struct isis_tx_queue *queue)
|
||||
{
|
||||
if (!queue)
|
||||
return 0;
|
||||
|
||||
return hashcount(queue->hash);
|
||||
}
|
||||
|
||||
void isis_tx_queue_clean(struct isis_tx_queue *queue)
|
||||
{
|
||||
hash_clean(queue->hash, tx_queue_element_free);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* IS-IS Rout(e)ing protocol - LSP Hash
|
||||
* IS-IS Rout(e)ing protocol - LSP TX Queuing logic
|
||||
*
|
||||
* Copyright (C) 2017 Christian Franke
|
||||
* Copyright (C) 2018 Christian Franke
|
||||
*
|
||||
* This file is part of FreeRangeRouting (FRR)
|
||||
*
|
||||
@ -19,16 +19,31 @@
|
||||
* 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
|
||||
*/
|
||||
#ifndef ISIS_LSP_HASH_H
|
||||
#define ISIS_LSP_HASH_H
|
||||
#ifndef ISIS_TX_QUEUE_H
|
||||
#define ISIS_TX_QUEUE_H
|
||||
|
||||
struct isis_lsp_hash;
|
||||
enum isis_tx_type {
|
||||
TX_LSP_NORMAL = 0,
|
||||
TX_LSP_CIRCUIT_SCOPED
|
||||
};
|
||||
|
||||
struct isis_tx_queue;
|
||||
|
||||
struct isis_tx_queue *isis_tx_queue_new(void *arg,
|
||||
void(*send_event)(void *arg,
|
||||
struct isis_lsp *,
|
||||
enum isis_tx_type));
|
||||
|
||||
void isis_tx_queue_free(struct isis_tx_queue *queue);
|
||||
|
||||
void isis_tx_queue_add(struct isis_tx_queue *queue,
|
||||
struct isis_lsp *lsp,
|
||||
enum isis_tx_type type);
|
||||
|
||||
void isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp);
|
||||
|
||||
unsigned long isis_tx_queue_len(struct isis_tx_queue *queue);
|
||||
|
||||
void isis_tx_queue_clean(struct isis_tx_queue *queue);
|
||||
|
||||
struct isis_lsp_hash *isis_lsp_hash_new(void);
|
||||
void isis_lsp_hash_clean(struct isis_lsp_hash *ih);
|
||||
void isis_lsp_hash_free(struct isis_lsp_hash *ih);
|
||||
struct isis_lsp *isis_lsp_hash_lookup(struct isis_lsp_hash *ih,
|
||||
struct isis_lsp *lsp);
|
||||
void isis_lsp_hash_add(struct isis_lsp_hash *ih, struct isis_lsp *lsp);
|
||||
void isis_lsp_hash_release(struct isis_lsp_hash *ih, struct isis_lsp *lsp);
|
||||
#endif
|
2165
isisd/isis_vty.c
2165
isisd/isis_vty.c
File diff suppressed because it is too large
Load Diff
960
isisd/isis_vty_common.c
Normal file
960
isisd/isis_vty_common.c
Normal file
@ -0,0 +1,960 @@
|
||||
/*
|
||||
* IS-IS Rout(e)ing protocol - isis_vty_common.c
|
||||
*
|
||||
* This file contains the CLI that is shared between OpenFabric and IS-IS
|
||||
*
|
||||
* Copyright (C) 2001,2002 Sampo Saaristo
|
||||
* Tampere University of Technology
|
||||
* Institute of Communications Engineering
|
||||
* Copyright (C) 2016 David Lamparter, for NetDEF, Inc.
|
||||
* Copyright (C) 2018 Christian Franke, for NetDEF, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public Licenseas 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>
|
||||
|
||||
#include "command.h"
|
||||
#include "spf_backoff.h"
|
||||
|
||||
#include "isis_circuit.h"
|
||||
#include "isis_csm.h"
|
||||
#include "isis_misc.h"
|
||||
#include "isis_mt.h"
|
||||
#include "isisd.h"
|
||||
#include "isis_vty_common.h"
|
||||
|
||||
struct isis_circuit *isis_circuit_lookup(struct vty *vty)
|
||||
{
|
||||
struct interface *ifp = VTY_GET_CONTEXT(interface);
|
||||
struct isis_circuit *circuit;
|
||||
|
||||
if (!ifp) {
|
||||
vty_out(vty, "Invalid interface \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
circuit = circuit_scan_by_ifp(ifp);
|
||||
if (!circuit) {
|
||||
vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return circuit;
|
||||
}
|
||||
|
||||
DEFUN (ip_router_isis,
|
||||
ip_router_isis_cmd,
|
||||
"ip router " PROTO_NAME " WORD",
|
||||
"Interface Internet Protocol config commands\n"
|
||||
"IP router interface commands\n"
|
||||
PROTO_HELP
|
||||
"Routing process tag\n")
|
||||
{
|
||||
int idx_afi = 0;
|
||||
int idx_word = 3;
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct isis_circuit *circuit;
|
||||
struct isis_area *area;
|
||||
const char *af = argv[idx_afi]->arg;
|
||||
const char *area_tag = argv[idx_word]->arg;
|
||||
|
||||
/* Prevent more than one area per circuit */
|
||||
circuit = circuit_scan_by_ifp(ifp);
|
||||
if (circuit && circuit->area) {
|
||||
if (strcmp(circuit->area->area_tag, area_tag)) {
|
||||
vty_out(vty, "ISIS circuit is already defined on %s\n",
|
||||
circuit->area->area_tag);
|
||||
return CMD_ERR_NOTHING_TODO;
|
||||
}
|
||||
}
|
||||
|
||||
area = isis_area_lookup(area_tag);
|
||||
if (!area)
|
||||
area = isis_area_create(area_tag);
|
||||
|
||||
if (!circuit || !circuit->area) {
|
||||
circuit = isis_circuit_create(area, ifp);
|
||||
|
||||
if (circuit->state != C_STATE_CONF
|
||||
&& circuit->state != C_STATE_UP) {
|
||||
vty_out(vty,
|
||||
"Couldn't bring up interface, please check log.\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router;
|
||||
if (af[2] != '\0')
|
||||
ipv6 = true;
|
||||
else
|
||||
ip = true;
|
||||
|
||||
isis_circuit_af_set(circuit, ip, ipv6);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ip6_router_isis,
|
||||
ip6_router_isis_cmd,
|
||||
"ipv6 router " PROTO_NAME " WORD",
|
||||
"Interface Internet Protocol config commands\n"
|
||||
"IP router interface commands\n"
|
||||
PROTO_HELP
|
||||
"Routing process tag\n")
|
||||
{
|
||||
return ip_router_isis(self, vty, argc, argv);
|
||||
}
|
||||
|
||||
DEFUN (no_ip_router_isis,
|
||||
no_ip_router_isis_cmd,
|
||||
"no <ip|ipv6> router " PROTO_NAME " WORD",
|
||||
NO_STR
|
||||
"Interface Internet Protocol config commands\n"
|
||||
"IP router interface commands\n"
|
||||
"IP router interface commands\n"
|
||||
PROTO_HELP
|
||||
"Routing process tag\n")
|
||||
{
|
||||
int idx_afi = 1;
|
||||
int idx_word = 4;
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct isis_area *area;
|
||||
struct isis_circuit *circuit;
|
||||
const char *af = argv[idx_afi]->arg;
|
||||
const char *area_tag = argv[idx_word]->arg;
|
||||
|
||||
area = isis_area_lookup(area_tag);
|
||||
if (!area) {
|
||||
vty_out(vty, "Can't find ISIS instance %s\n",
|
||||
area_tag);
|
||||
return CMD_ERR_NO_MATCH;
|
||||
}
|
||||
|
||||
circuit = circuit_lookup_by_ifp(ifp, area->circuit_list);
|
||||
if (!circuit) {
|
||||
vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name);
|
||||
return CMD_ERR_NO_MATCH;
|
||||
}
|
||||
|
||||
bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router;
|
||||
if (af[2] != '\0')
|
||||
ipv6 = false;
|
||||
else
|
||||
ip = false;
|
||||
|
||||
isis_circuit_af_set(circuit, ip, ipv6);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_passive,
|
||||
isis_passive_cmd,
|
||||
PROTO_NAME " passive",
|
||||
PROTO_HELP
|
||||
"Configure the passive mode for interface\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
CMD_FERR_RETURN(isis_circuit_passive_set(circuit, 1),
|
||||
"Cannot set passive: $ERR");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_passive,
|
||||
no_isis_passive_cmd,
|
||||
"no " PROTO_NAME " passive",
|
||||
NO_STR
|
||||
PROTO_HELP
|
||||
"Configure the passive mode for interface\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
CMD_FERR_RETURN(isis_circuit_passive_set(circuit, 0),
|
||||
"Cannot set no passive: $ERR");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_passwd,
|
||||
isis_passwd_cmd,
|
||||
PROTO_NAME " password <md5|clear> WORD",
|
||||
PROTO_HELP
|
||||
"Configure the authentication password for a circuit\n"
|
||||
"HMAC-MD5 authentication\n"
|
||||
"Cleartext password\n"
|
||||
"Circuit password\n")
|
||||
{
|
||||
int idx_encryption = 2;
|
||||
int idx_word = 3;
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
ferr_r rv;
|
||||
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
if (argv[idx_encryption]->arg[0] == 'm')
|
||||
rv = isis_circuit_passwd_hmac_md5_set(circuit,
|
||||
argv[idx_word]->arg);
|
||||
else
|
||||
rv = isis_circuit_passwd_cleartext_set(circuit,
|
||||
argv[idx_word]->arg);
|
||||
|
||||
CMD_FERR_RETURN(rv, "Failed to set circuit password: $ERR");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_passwd,
|
||||
no_isis_passwd_cmd,
|
||||
"no " PROTO_NAME " password [<md5|clear> WORD]",
|
||||
NO_STR
|
||||
PROTO_HELP
|
||||
"Configure the authentication password for a circuit\n"
|
||||
"HMAC-MD5 authentication\n"
|
||||
"Cleartext password\n"
|
||||
"Circuit password\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
CMD_FERR_RETURN(isis_circuit_passwd_unset(circuit),
|
||||
"Failed to unset circuit password: $ERR");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_metric,
|
||||
isis_metric_cmd,
|
||||
PROTO_NAME " metric (0-16777215)",
|
||||
PROTO_HELP
|
||||
"Set default metric for circuit\n"
|
||||
"Default metric value\n")
|
||||
{
|
||||
int idx_number = 2;
|
||||
int met;
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
met = atoi(argv[idx_number]->arg);
|
||||
|
||||
/* RFC3787 section 5.1 */
|
||||
if (circuit->area && circuit->area->oldmetric == 1
|
||||
&& met > MAX_NARROW_LINK_METRIC) {
|
||||
vty_out(vty,
|
||||
"Invalid metric %d - should be <0-63> "
|
||||
"when narrow metric type enabled\n",
|
||||
met);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* RFC4444 */
|
||||
if (circuit->area && circuit->area->newmetric == 1
|
||||
&& met > MAX_WIDE_LINK_METRIC) {
|
||||
vty_out(vty,
|
||||
"Invalid metric %d - should be <0-16777215> "
|
||||
"when wide metric type enabled\n",
|
||||
met);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
CMD_FERR_RETURN(isis_circuit_metric_set(circuit, IS_LEVEL_1, met),
|
||||
"Failed to set L1 metric: $ERR");
|
||||
CMD_FERR_RETURN(isis_circuit_metric_set(circuit, IS_LEVEL_2, met),
|
||||
"Failed to set L2 metric: $ERR");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_metric,
|
||||
no_isis_metric_cmd,
|
||||
"no " PROTO_NAME " metric [(0-16777215)]",
|
||||
NO_STR
|
||||
PROTO_HELP
|
||||
"Set default metric for circuit\n"
|
||||
"Default metric value\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
CMD_FERR_RETURN(isis_circuit_metric_set(circuit, IS_LEVEL_1,
|
||||
DEFAULT_CIRCUIT_METRIC),
|
||||
"Failed to set L1 metric: $ERR");
|
||||
CMD_FERR_RETURN(isis_circuit_metric_set(circuit, IS_LEVEL_2,
|
||||
DEFAULT_CIRCUIT_METRIC),
|
||||
"Failed to set L2 metric: $ERR");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_hello_interval,
|
||||
isis_hello_interval_cmd,
|
||||
PROTO_NAME " hello-interval (1-600)",
|
||||
PROTO_HELP
|
||||
"Set Hello interval\n"
|
||||
"Holdtime 1 seconds, interval depends on multiplier\n")
|
||||
{
|
||||
uint32_t interval = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->hello_interval[0] = interval;
|
||||
circuit->hello_interval[1] = interval;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_hello_interval,
|
||||
no_isis_hello_interval_cmd,
|
||||
"no " PROTO_NAME " hello-interval [(1-600)]",
|
||||
NO_STR
|
||||
PROTO_HELP
|
||||
"Set Hello interval\n"
|
||||
"Holdtime 1 second, interval depends on multiplier\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL;
|
||||
circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_hello_multiplier,
|
||||
isis_hello_multiplier_cmd,
|
||||
PROTO_NAME " hello-multiplier (2-100)",
|
||||
PROTO_HELP
|
||||
"Set multiplier for Hello holding time\n"
|
||||
"Hello multiplier value\n")
|
||||
{
|
||||
uint16_t mult = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->hello_multiplier[0] = mult;
|
||||
circuit->hello_multiplier[1] = mult;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_hello_multiplier,
|
||||
no_isis_hello_multiplier_cmd,
|
||||
"no " PROTO_NAME " hello-multiplier [(2-100)]",
|
||||
NO_STR
|
||||
PROTO_HELP
|
||||
"Set multiplier for Hello holding time\n"
|
||||
"Hello multiplier value\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER;
|
||||
circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (csnp_interval,
|
||||
csnp_interval_cmd,
|
||||
PROTO_NAME " csnp-interval (1-600)",
|
||||
PROTO_HELP
|
||||
"Set CSNP interval in seconds\n"
|
||||
"CSNP interval value\n")
|
||||
{
|
||||
uint16_t interval = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->csnp_interval[0] = interval;
|
||||
circuit->csnp_interval[1] = interval;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_csnp_interval,
|
||||
no_csnp_interval_cmd,
|
||||
"no " PROTO_NAME " csnp-interval [(1-600)]",
|
||||
NO_STR
|
||||
PROTO_HELP
|
||||
"Set CSNP interval in seconds\n"
|
||||
"CSNP interval value\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL;
|
||||
circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (psnp_interval,
|
||||
psnp_interval_cmd,
|
||||
PROTO_NAME " psnp-interval (1-120)",
|
||||
PROTO_HELP
|
||||
"Set PSNP interval in seconds\n"
|
||||
"PSNP interval value\n")
|
||||
{
|
||||
uint16_t interval = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->psnp_interval[0] = interval;
|
||||
circuit->psnp_interval[1] = interval;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_psnp_interval,
|
||||
no_psnp_interval_cmd,
|
||||
"no " PROTO_NAME " psnp-interval [(1-120)]",
|
||||
NO_STR
|
||||
PROTO_HELP
|
||||
"Set PSNP interval in seconds\n"
|
||||
"PSNP interval value\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL;
|
||||
circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (circuit_topology,
|
||||
circuit_topology_cmd,
|
||||
PROTO_NAME " topology " ISIS_MT_NAMES,
|
||||
PROTO_HELP
|
||||
"Configure interface IS-IS topologies\n"
|
||||
ISIS_MT_DESCRIPTIONS)
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
const char *arg = argv[2]->arg;
|
||||
uint16_t mtid = isis_str2mtid(arg);
|
||||
|
||||
if (circuit->area && circuit->area->oldmetric) {
|
||||
vty_out(vty,
|
||||
"Multi topology IS-IS can only be used with wide metrics\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (mtid == (uint16_t)-1) {
|
||||
vty_out(vty, "Don't know topology '%s'\n", arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return isis_circuit_mt_enabled_set(circuit, mtid, true);
|
||||
}
|
||||
|
||||
DEFUN (no_circuit_topology,
|
||||
no_circuit_topology_cmd,
|
||||
"no " PROTO_NAME " topology " ISIS_MT_NAMES,
|
||||
NO_STR
|
||||
PROTO_HELP
|
||||
"Configure interface IS-IS topologies\n"
|
||||
ISIS_MT_DESCRIPTIONS)
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
const char *arg = argv[3]->arg;
|
||||
uint16_t mtid = isis_str2mtid(arg);
|
||||
|
||||
if (circuit->area && circuit->area->oldmetric) {
|
||||
vty_out(vty,
|
||||
"Multi topology IS-IS can only be used with wide metrics\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (mtid == (uint16_t)-1) {
|
||||
vty_out(vty, "Don't know topology '%s'\n", arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return isis_circuit_mt_enabled_set(circuit, mtid, false);
|
||||
}
|
||||
|
||||
DEFUN (set_overload_bit,
|
||||
set_overload_bit_cmd,
|
||||
"set-overload-bit",
|
||||
"Set overload bit to avoid any transit traffic\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
isis_area_overload_bit_set(area, true);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_set_overload_bit,
|
||||
no_set_overload_bit_cmd,
|
||||
"no set-overload-bit",
|
||||
"Reset overload bit to accept transit traffic\n"
|
||||
"Reset overload bit\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
isis_area_overload_bit_set(area, false);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int isis_vty_lsp_mtu_set(struct vty *vty, unsigned int lsp_mtu)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
struct listnode *node;
|
||||
struct isis_circuit *circuit;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
|
||||
if (circuit->state != C_STATE_INIT
|
||||
&& circuit->state != C_STATE_UP)
|
||||
continue;
|
||||
if (lsp_mtu > isis_circuit_pdu_size(circuit)) {
|
||||
vty_out(vty,
|
||||
"ISIS area contains circuit %s, which has a maximum PDU size of %zu.\n",
|
||||
circuit->interface->name,
|
||||
isis_circuit_pdu_size(circuit));
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
isis_area_lsp_mtu_set(area, lsp_mtu);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (area_lsp_mtu,
|
||||
area_lsp_mtu_cmd,
|
||||
"lsp-mtu (128-4352)",
|
||||
"Configure the maximum size of generated LSPs\n"
|
||||
"Maximum size of generated LSPs\n")
|
||||
{
|
||||
int idx_number = 1;
|
||||
unsigned int lsp_mtu;
|
||||
|
||||
lsp_mtu = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
|
||||
return isis_vty_lsp_mtu_set(vty, lsp_mtu);
|
||||
}
|
||||
|
||||
DEFUN (no_area_lsp_mtu,
|
||||
no_area_lsp_mtu_cmd,
|
||||
"no lsp-mtu [(128-4352)]",
|
||||
NO_STR
|
||||
"Configure the maximum size of generated LSPs\n"
|
||||
"Maximum size of generated LSPs\n")
|
||||
{
|
||||
return isis_vty_lsp_mtu_set(vty, DEFAULT_LSP_MTU);
|
||||
}
|
||||
|
||||
DEFUN (area_purge_originator,
|
||||
area_purge_originator_cmd,
|
||||
"[no] purge-originator",
|
||||
NO_STR
|
||||
"Use the RFC 6232 purge-originator\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
area->purge_originator = !!strcmp(argv[0]->text, "no");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int isis_vty_lsp_gen_interval_set(struct vty *vty, int level, uint16_t interval)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
int lvl;
|
||||
|
||||
for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) {
|
||||
if (!(lvl & level))
|
||||
continue;
|
||||
|
||||
if (interval >= area->lsp_refresh[lvl - 1]) {
|
||||
vty_out(vty,
|
||||
"LSP gen interval %us must be less than "
|
||||
"the LSP refresh interval %us\n",
|
||||
interval, area->lsp_refresh[lvl - 1]);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) {
|
||||
if (!(lvl & level))
|
||||
continue;
|
||||
area->lsp_gen_interval[lvl - 1] = interval;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (lsp_gen_interval,
|
||||
lsp_gen_interval_cmd,
|
||||
"lsp-gen-interval (1-120)",
|
||||
"Minimum interval between regenerating same LSP\n"
|
||||
"Minimum interval in seconds\n")
|
||||
{
|
||||
uint16_t interval = atoi(argv[1]->arg);
|
||||
|
||||
return isis_vty_lsp_gen_interval_set(vty, IS_LEVEL_1_AND_2, interval);
|
||||
}
|
||||
|
||||
DEFUN (no_lsp_gen_interval,
|
||||
no_lsp_gen_interval_cmd,
|
||||
"no lsp-gen-interval [(1-120)]",
|
||||
NO_STR
|
||||
"Minimum interval between regenerating same LSP\n"
|
||||
"Minimum interval in seconds\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
return isis_vty_lsp_gen_interval_set(vty, IS_LEVEL_1_AND_2,
|
||||
DEFAULT_MIN_LSP_GEN_INTERVAL);
|
||||
}
|
||||
|
||||
DEFUN (spf_interval,
|
||||
spf_interval_cmd,
|
||||
"spf-interval (1-120)",
|
||||
"Minimum interval between SPF calculations\n"
|
||||
"Minimum interval between consecutive SPFs in seconds\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
uint16_t interval = atoi(argv[1]->arg);
|
||||
|
||||
area->min_spf_interval[0] = interval;
|
||||
area->min_spf_interval[1] = interval;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_spf_interval,
|
||||
no_spf_interval_cmd,
|
||||
"no spf-interval [(1-120)]",
|
||||
NO_STR
|
||||
"Minimum interval between SPF calculations\n"
|
||||
"Minimum interval between consecutive SPFs in seconds\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
|
||||
area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_spf_delay_ietf,
|
||||
no_spf_delay_ietf_cmd,
|
||||
"no spf-delay-ietf",
|
||||
NO_STR
|
||||
"IETF SPF delay algorithm\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
spf_backoff_free(area->spf_delay_ietf[0]);
|
||||
spf_backoff_free(area->spf_delay_ietf[1]);
|
||||
area->spf_delay_ietf[0] = NULL;
|
||||
area->spf_delay_ietf[1] = NULL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (spf_delay_ietf,
|
||||
spf_delay_ietf_cmd,
|
||||
"spf-delay-ietf init-delay (0-60000) short-delay (0-60000) long-delay (0-60000) holddown (0-60000) time-to-learn (0-60000)",
|
||||
"IETF SPF delay algorithm\n"
|
||||
"Delay used while in QUIET state\n"
|
||||
"Delay used while in QUIET state in milliseconds\n"
|
||||
"Delay used while in SHORT_WAIT state\n"
|
||||
"Delay used while in SHORT_WAIT state in milliseconds\n"
|
||||
"Delay used while in LONG_WAIT\n"
|
||||
"Delay used while in LONG_WAIT state in milliseconds\n"
|
||||
"Time with no received IGP events before considering IGP stable\n"
|
||||
"Time with no received IGP events before considering IGP stable (in milliseconds)\n"
|
||||
"Maximum duration needed to learn all the events related to a single failure\n"
|
||||
"Maximum duration needed to learn all the events related to a single failure (in milliseconds)\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
long init_delay = atol(argv[2]->arg);
|
||||
long short_delay = atol(argv[4]->arg);
|
||||
long long_delay = atol(argv[6]->arg);
|
||||
long holddown = atol(argv[8]->arg);
|
||||
long timetolearn = atol(argv[10]->arg);
|
||||
|
||||
size_t bufsiz = strlen(area->area_tag) + sizeof("IS-IS Lx");
|
||||
char *buf = XCALLOC(MTYPE_TMP, bufsiz);
|
||||
|
||||
snprintf(buf, bufsiz, "IS-IS %s L1", area->area_tag);
|
||||
spf_backoff_free(area->spf_delay_ietf[0]);
|
||||
area->spf_delay_ietf[0] =
|
||||
spf_backoff_new(master, buf, init_delay, short_delay,
|
||||
long_delay, holddown, timetolearn);
|
||||
|
||||
snprintf(buf, bufsiz, "IS-IS %s L2", area->area_tag);
|
||||
spf_backoff_free(area->spf_delay_ietf[1]);
|
||||
area->spf_delay_ietf[1] =
|
||||
spf_backoff_new(master, buf, init_delay, short_delay,
|
||||
long_delay, holddown, timetolearn);
|
||||
|
||||
XFREE(MTYPE_TMP, buf);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int isis_vty_max_lsp_lifetime_set(struct vty *vty, int level, uint16_t interval)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
int lvl;
|
||||
uint16_t refresh_interval = interval - 300;
|
||||
int set_refresh_interval[ISIS_LEVELS] = {0, 0};
|
||||
|
||||
for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) {
|
||||
if (!(lvl & level))
|
||||
continue;
|
||||
|
||||
if (refresh_interval < area->lsp_refresh[lvl - 1]) {
|
||||
vty_out(vty,
|
||||
"Level %d Max LSP lifetime %us must be 300s greater than "
|
||||
"the configured LSP refresh interval %us\n",
|
||||
lvl, interval, area->lsp_refresh[lvl - 1]);
|
||||
vty_out(vty,
|
||||
"Automatically reducing level %d LSP refresh interval "
|
||||
"to %us\n",
|
||||
lvl, refresh_interval);
|
||||
set_refresh_interval[lvl - 1] = 1;
|
||||
|
||||
if (refresh_interval
|
||||
<= area->lsp_gen_interval[lvl - 1]) {
|
||||
vty_out(vty,
|
||||
"LSP refresh interval %us must be greater than "
|
||||
"the configured LSP gen interval %us\n",
|
||||
refresh_interval,
|
||||
area->lsp_gen_interval[lvl - 1]);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) {
|
||||
if (!(lvl & level))
|
||||
continue;
|
||||
isis_area_max_lsp_lifetime_set(area, lvl, interval);
|
||||
if (set_refresh_interval[lvl - 1])
|
||||
isis_area_lsp_refresh_set(area, lvl, refresh_interval);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (max_lsp_lifetime,
|
||||
max_lsp_lifetime_cmd,
|
||||
"max-lsp-lifetime (350-65535)",
|
||||
"Maximum LSP lifetime\n"
|
||||
"LSP lifetime in seconds\n")
|
||||
{
|
||||
int lifetime = atoi(argv[1]->arg);
|
||||
|
||||
return isis_vty_max_lsp_lifetime_set(vty, IS_LEVEL_1_AND_2, lifetime);
|
||||
}
|
||||
|
||||
|
||||
DEFUN (no_max_lsp_lifetime,
|
||||
no_max_lsp_lifetime_cmd,
|
||||
"no max-lsp-lifetime [(350-65535)]",
|
||||
NO_STR
|
||||
"Maximum LSP lifetime\n"
|
||||
"LSP lifetime in seconds\n")
|
||||
{
|
||||
return isis_vty_max_lsp_lifetime_set(vty, IS_LEVEL_1_AND_2,
|
||||
DEFAULT_LSP_LIFETIME);
|
||||
}
|
||||
|
||||
int isis_vty_lsp_refresh_set(struct vty *vty, int level, uint16_t interval)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
int lvl;
|
||||
|
||||
for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) {
|
||||
if (!(lvl & level))
|
||||
continue;
|
||||
if (interval <= area->lsp_gen_interval[lvl - 1]) {
|
||||
vty_out(vty,
|
||||
"LSP refresh interval %us must be greater than "
|
||||
"the configured LSP gen interval %us\n",
|
||||
interval, area->lsp_gen_interval[lvl - 1]);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if (interval > (area->max_lsp_lifetime[lvl - 1] - 300)) {
|
||||
vty_out(vty,
|
||||
"LSP refresh interval %us must be less than "
|
||||
"the configured LSP lifetime %us less 300\n",
|
||||
interval, area->max_lsp_lifetime[lvl - 1]);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) {
|
||||
if (!(lvl & level))
|
||||
continue;
|
||||
isis_area_lsp_refresh_set(area, lvl, interval);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (lsp_refresh_interval,
|
||||
lsp_refresh_interval_cmd,
|
||||
"lsp-refresh-interval (1-65235)",
|
||||
"LSP refresh interval\n"
|
||||
"LSP refresh interval in seconds\n")
|
||||
{
|
||||
unsigned int interval = atoi(argv[1]->arg);
|
||||
return isis_vty_lsp_refresh_set(vty, IS_LEVEL_1_AND_2, interval);
|
||||
}
|
||||
|
||||
DEFUN (no_lsp_refresh_interval,
|
||||
no_lsp_refresh_interval_cmd,
|
||||
"no lsp-refresh-interval [(1-65235)]",
|
||||
NO_STR
|
||||
"LSP refresh interval\n"
|
||||
"LSP refresh interval in seconds\n")
|
||||
{
|
||||
return isis_vty_lsp_refresh_set(vty, IS_LEVEL_1_AND_2,
|
||||
DEFAULT_MAX_LSP_GEN_INTERVAL);
|
||||
}
|
||||
|
||||
int isis_vty_password_set(struct vty *vty, int argc,
|
||||
struct cmd_token *argv[], int level)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
int idx_algo = 1;
|
||||
int idx_password = 2;
|
||||
int idx_snp_auth = 5;
|
||||
uint8_t snp_auth = 0;
|
||||
|
||||
const char *passwd = argv[idx_password]->arg;
|
||||
if (strlen(passwd) > 254) {
|
||||
vty_out(vty, "Too long area password (>254)\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (argc > idx_snp_auth) {
|
||||
snp_auth = SNP_AUTH_SEND;
|
||||
if (strmatch(argv[idx_snp_auth]->text, "validate"))
|
||||
snp_auth |= SNP_AUTH_RECV;
|
||||
}
|
||||
|
||||
if (strmatch(argv[idx_algo]->text, "clear")) {
|
||||
return isis_area_passwd_cleartext_set(area, level,
|
||||
passwd, snp_auth);
|
||||
} else if (strmatch(argv[idx_algo]->text, "md5")) {
|
||||
return isis_area_passwd_hmac_md5_set(area, level,
|
||||
passwd, snp_auth);
|
||||
}
|
||||
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
DEFUN (domain_passwd,
|
||||
domain_passwd_cmd,
|
||||
"domain-password <clear|md5> WORD [authenticate snp <send-only|validate>]",
|
||||
"Set the authentication password for a routing domain\n"
|
||||
"Authentication type\n"
|
||||
"Authentication type\n"
|
||||
"Level-wide password\n"
|
||||
"Authentication\n"
|
||||
"SNP PDUs\n"
|
||||
"Send but do not check PDUs on receiving\n"
|
||||
"Send and check PDUs on receiving\n")
|
||||
{
|
||||
return isis_vty_password_set(vty, argc, argv, IS_LEVEL_2);
|
||||
}
|
||||
|
||||
DEFUN (no_domain_passwd,
|
||||
no_domain_passwd_cmd,
|
||||
"no domain-password",
|
||||
NO_STR
|
||||
"Set the authentication password for a routing domain\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
return isis_area_passwd_unset(area, IS_LEVEL_2);
|
||||
}
|
||||
|
||||
void isis_vty_init(void)
|
||||
{
|
||||
install_element(INTERFACE_NODE, &ip_router_isis_cmd);
|
||||
install_element(INTERFACE_NODE, &ip6_router_isis_cmd);
|
||||
install_element(INTERFACE_NODE, &no_ip_router_isis_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_passive_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_passive_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_passwd_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_passwd_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_metric_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_metric_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_hello_interval_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_hello_interval_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_hello_multiplier_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_hello_multiplier_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &csnp_interval_cmd);
|
||||
install_element(INTERFACE_NODE, &no_csnp_interval_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &psnp_interval_cmd);
|
||||
install_element(INTERFACE_NODE, &no_psnp_interval_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &circuit_topology_cmd);
|
||||
install_element(INTERFACE_NODE, &no_circuit_topology_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &set_overload_bit_cmd);
|
||||
install_element(ROUTER_NODE, &no_set_overload_bit_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &area_lsp_mtu_cmd);
|
||||
install_element(ROUTER_NODE, &no_area_lsp_mtu_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &area_purge_originator_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &lsp_gen_interval_cmd);
|
||||
install_element(ROUTER_NODE, &no_lsp_gen_interval_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &spf_interval_cmd);
|
||||
install_element(ROUTER_NODE, &no_spf_interval_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &max_lsp_lifetime_cmd);
|
||||
install_element(ROUTER_NODE, &no_max_lsp_lifetime_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &lsp_refresh_interval_cmd);
|
||||
install_element(ROUTER_NODE, &no_lsp_refresh_interval_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &domain_passwd_cmd);
|
||||
install_element(ROUTER_NODE, &no_domain_passwd_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &spf_delay_ietf_cmd);
|
||||
install_element(ROUTER_NODE, &no_spf_delay_ietf_cmd);
|
||||
|
||||
isis_vty_daemon_init();
|
||||
}
|
38
isisd/isis_vty_common.h
Normal file
38
isisd/isis_vty_common.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* IS-IS Rout(e)ing protocol - isis_vty_common.h
|
||||
*
|
||||
* Copyright (C) 2001,2002 Sampo Saaristo
|
||||
* Tampere University of Technology
|
||||
* Institute of Communications Engineering
|
||||
* Copyright (C) 2016 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public Licenseas 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
|
||||
*/
|
||||
|
||||
#ifndef ISIS_VTY_COMMON_H
|
||||
#define ISIS_VTY_COMMON_H
|
||||
|
||||
struct isis_circuit *isis_circuit_lookup(struct vty *vty);
|
||||
|
||||
int isis_vty_max_lsp_lifetime_set(struct vty *vty, int level, uint16_t interval);
|
||||
int isis_vty_lsp_refresh_set(struct vty *vty, int level, uint16_t interval);
|
||||
int isis_vty_lsp_gen_interval_set(struct vty *vty, int level, uint16_t interval);
|
||||
int isis_vty_password_set(struct vty *vty, int argc,
|
||||
struct cmd_token *argv[], int level);
|
||||
|
||||
void isis_vty_daemon_init(void);
|
||||
void isis_vty_init(void);
|
||||
|
||||
#endif
|
94
isisd/isis_vty_fabricd.c
Normal file
94
isisd/isis_vty_fabricd.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* IS-IS Rout(e)ing protocol - isis_vty_fabricd.c
|
||||
*
|
||||
* This file contains the CLI that is specific to OpenFabric
|
||||
*
|
||||
* Copyright (C) 2018 Christian Franke, for NetDEF, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public Licenseas 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>
|
||||
|
||||
#include "command.h"
|
||||
|
||||
#include "isisd.h"
|
||||
#include "isis_vty_common.h"
|
||||
#include "fabricd.h"
|
||||
#include "isis_tlvs.h"
|
||||
|
||||
DEFUN (fabric_tier,
|
||||
fabric_tier_cmd,
|
||||
"fabric-tier (0-14)",
|
||||
"Statically configure the tier to advertise\n"
|
||||
"Tier to advertise\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
uint8_t tier = atoi(argv[1]->arg);
|
||||
|
||||
fabricd_configure_tier(area, tier);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_fabric_tier,
|
||||
no_fabric_tier_cmd,
|
||||
"no fabric-tier [(0-14)]",
|
||||
NO_STR
|
||||
"Statically configure the tier to advertise\n"
|
||||
"Tier to advertise\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
fabricd_configure_tier(area, ISIS_TIER_UNDEFINED);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (debug_fabric_flooding,
|
||||
debug_fabric_flooding_cmd,
|
||||
"debug openfabric flooding",
|
||||
DEBUG_STR
|
||||
PROTO_HELP
|
||||
"Flooding optimization algorithm\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_FABRICD_FLOODING;
|
||||
print_debug(vty, DEBUG_FABRICD_FLOODING, 1);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_fabric_flooding,
|
||||
no_debug_fabric_flooding_cmd,
|
||||
"no debug openfabric flooding",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
PROTO_HELP
|
||||
"Flooding optimization algorithm\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_FABRICD_FLOODING;
|
||||
print_debug(vty, DEBUG_FABRICD_FLOODING, 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void isis_vty_daemon_init(void)
|
||||
{
|
||||
install_element(ROUTER_NODE, &fabric_tier_cmd);
|
||||
install_element(ROUTER_NODE, &no_fabric_tier_cmd);
|
||||
install_element(ENABLE_NODE, &debug_fabric_flooding_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_fabric_flooding_cmd);
|
||||
install_element(CONFIG_NODE, &debug_fabric_flooding_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_fabric_flooding_cmd);
|
||||
}
|
858
isisd/isis_vty_isisd.c
Normal file
858
isisd/isis_vty_isisd.c
Normal file
@ -0,0 +1,858 @@
|
||||
/*
|
||||
* IS-IS Rout(e)ing protocol - isis_vty_isisd.c
|
||||
*
|
||||
* This file contains the CLI that is specific to IS-IS
|
||||
*
|
||||
* Copyright (C) 2001,2002 Sampo Saaristo
|
||||
* Tampere University of Technology
|
||||
* Institute of Communications Engineering
|
||||
* Copyright (C) 2016 David Lamparter, for NetDEF, Inc.
|
||||
* Copyright (C) 2018 Christian Franke, for NetDEF, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public Licenseas 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>
|
||||
|
||||
#include "command.h"
|
||||
|
||||
#include "isis_circuit.h"
|
||||
#include "isis_csm.h"
|
||||
#include "isis_misc.h"
|
||||
#include "isis_mt.h"
|
||||
#include "isisd.h"
|
||||
#include "isis_vty_common.h"
|
||||
|
||||
static int level_for_arg(const char *arg)
|
||||
{
|
||||
if (!strcmp(arg, "level-1"))
|
||||
return IS_LEVEL_1;
|
||||
else
|
||||
return IS_LEVEL_2;
|
||||
}
|
||||
|
||||
DEFUN (isis_circuit_type,
|
||||
isis_circuit_type_cmd,
|
||||
"isis circuit-type <level-1|level-1-2|level-2-only>",
|
||||
"IS-IS routing protocol\n"
|
||||
"Configure circuit type for interface\n"
|
||||
"Level-1 only adjacencies are formed\n"
|
||||
"Level-1-2 adjacencies are formed\n"
|
||||
"Level-2 only adjacencies are formed\n")
|
||||
{
|
||||
int idx_level = 2;
|
||||
int is_type;
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
is_type = string2circuit_t(argv[idx_level]->arg);
|
||||
if (!is_type) {
|
||||
vty_out(vty, "Unknown circuit-type \n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (circuit->state == C_STATE_UP
|
||||
&& circuit->area->is_type != IS_LEVEL_1_AND_2
|
||||
&& circuit->area->is_type != is_type) {
|
||||
vty_out(vty, "Invalid circuit level for area %s.\n",
|
||||
circuit->area->area_tag);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
isis_circuit_is_type_set(circuit, is_type);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_circuit_type,
|
||||
no_isis_circuit_type_cmd,
|
||||
"no isis circuit-type <level-1|level-1-2|level-2-only>",
|
||||
NO_STR
|
||||
"IS-IS routing protocol\n"
|
||||
"Configure circuit type for interface\n"
|
||||
"Level-1 only adjacencies are formed\n"
|
||||
"Level-1-2 adjacencies are formed\n"
|
||||
"Level-2 only adjacencies are formed\n")
|
||||
{
|
||||
int is_type;
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
/*
|
||||
* Set the circuits level to its default value
|
||||
*/
|
||||
if (circuit->state == C_STATE_UP)
|
||||
is_type = circuit->area->is_type;
|
||||
else
|
||||
is_type = IS_LEVEL_1_AND_2;
|
||||
isis_circuit_is_type_set(circuit, is_type);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_network,
|
||||
isis_network_cmd,
|
||||
"isis network point-to-point",
|
||||
"IS-IS routing protocol\n"
|
||||
"Set network type\n"
|
||||
"point-to-point network type\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) {
|
||||
vty_out(vty,
|
||||
"isis network point-to-point is valid only on broadcast interfaces\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_network,
|
||||
no_isis_network_cmd,
|
||||
"no isis network point-to-point",
|
||||
NO_STR
|
||||
"IS-IS routing protocol\n"
|
||||
"Set network type for circuit\n"
|
||||
"point-to-point network type\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) {
|
||||
vty_out(vty,
|
||||
"isis network point-to-point is valid only on broadcast interfaces\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_priority,
|
||||
isis_priority_cmd,
|
||||
"isis priority (0-127)",
|
||||
"IS-IS routing protocol\n"
|
||||
"Set priority for Designated Router election\n"
|
||||
"Priority value\n")
|
||||
{
|
||||
uint8_t prio = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->priority[0] = prio;
|
||||
circuit->priority[1] = prio;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_priority,
|
||||
no_isis_priority_cmd,
|
||||
"no isis priority [(0-127)]",
|
||||
NO_STR
|
||||
"IS-IS routing protocol\n"
|
||||
"Set priority for Designated Router election\n"
|
||||
"Priority value\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->priority[0] = DEFAULT_PRIORITY;
|
||||
circuit->priority[1] = DEFAULT_PRIORITY;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_priority_level,
|
||||
isis_priority_level_cmd,
|
||||
"isis priority (0-127) <level-1|level-2>",
|
||||
"IS-IS routing protocol\n"
|
||||
"Set priority for Designated Router election\n"
|
||||
"Priority value\n"
|
||||
"Specify priority for level-1 routing\n"
|
||||
"Specify priority for level-2 routing\n")
|
||||
{
|
||||
uint8_t prio = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->priority[level_for_arg(argv[3]->text)] = prio;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_priority_level,
|
||||
no_isis_priority_level_cmd,
|
||||
"no isis priority [(0-127)] <level-1|level-2>",
|
||||
NO_STR
|
||||
"IS-IS routing protocol\n"
|
||||
"Set priority for Designated Router election\n"
|
||||
"Priority value\n"
|
||||
"Specify priority for level-1 routing\n"
|
||||
"Specify priority for level-2 routing\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
int level = level_for_arg(argv[argc - 1]->text);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->priority[level] = DEFAULT_PRIORITY;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_metric_level,
|
||||
isis_metric_level_cmd,
|
||||
"isis metric (0-16777215) <level-1|level-2>",
|
||||
"IS-IS routing protocol\n"
|
||||
"Set default metric for circuit\n"
|
||||
"Default metric value\n"
|
||||
"Specify metric for level-1 routing\n"
|
||||
"Specify metric for level-2 routing\n")
|
||||
{
|
||||
uint32_t met = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
CMD_FERR_RETURN(isis_circuit_metric_set(circuit,
|
||||
level_for_arg(argv[3]->text),
|
||||
met),
|
||||
"Failed to set metric: $ERR");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_metric_level,
|
||||
no_isis_metric_level_cmd,
|
||||
"no isis metric [(0-16777215)] <level-1|level-2>",
|
||||
NO_STR
|
||||
"IS-IS routing protocol\n"
|
||||
"Set default metric for circuit\n"
|
||||
"Default metric value\n"
|
||||
"Specify metric for level-1 routing\n"
|
||||
"Specify metric for level-2 routing\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
int level = level_for_arg(argv[argc - 1]->text);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
CMD_FERR_RETURN(isis_circuit_metric_set(circuit, level,
|
||||
DEFAULT_CIRCUIT_METRIC),
|
||||
"Failed to set L1 metric: $ERR");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_hello_interval_level,
|
||||
isis_hello_interval_level_cmd,
|
||||
"isis hello-interval (1-600) <level-1|level-2>",
|
||||
"IS-IS routing protocol\n"
|
||||
"Set Hello interval\n"
|
||||
"Holdtime 1 second, interval depends on multiplier\n"
|
||||
"Specify hello-interval for level-1 IIHs\n"
|
||||
"Specify hello-interval for level-2 IIHs\n")
|
||||
{
|
||||
uint32_t interval = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->hello_interval[level_for_arg(argv[3]->text)] = interval;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_hello_interval_level,
|
||||
no_isis_hello_interval_level_cmd,
|
||||
"no isis hello-interval [(1-600)] <level-1|level-2>",
|
||||
NO_STR
|
||||
"IS-IS routing protocol\n"
|
||||
"Set Hello interval\n"
|
||||
"Holdtime 1 second, interval depends on multiplier\n"
|
||||
"Specify hello-interval for level-1 IIHs\n"
|
||||
"Specify hello-interval for level-2 IIHs\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
int level = level_for_arg(argv[argc - 1]->text);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->hello_interval[level] = DEFAULT_HELLO_INTERVAL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_hello_multiplier_level,
|
||||
isis_hello_multiplier_level_cmd,
|
||||
"isis hello-multiplier (2-100) <level-1|level-2>",
|
||||
"IS-IS routing protocol\n"
|
||||
"Set multiplier for Hello holding time\n"
|
||||
"Hello multiplier value\n"
|
||||
"Specify hello multiplier for level-1 IIHs\n"
|
||||
"Specify hello multiplier for level-2 IIHs\n")
|
||||
{
|
||||
uint16_t mult = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->hello_multiplier[level_for_arg(argv[3]->text)] = mult;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_hello_multiplier_level,
|
||||
no_isis_hello_multiplier_level_cmd,
|
||||
"no isis hello-multiplier [(2-100)] <level-1|level-2>",
|
||||
NO_STR
|
||||
"IS-IS routing protocol\n"
|
||||
"Set multiplier for Hello holding time\n"
|
||||
"Hello multiplier value\n"
|
||||
"Specify hello multiplier for level-1 IIHs\n"
|
||||
"Specify hello multiplier for level-2 IIHs\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
int level = level_for_arg(argv[argc - 1]->text);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->hello_multiplier[level] = DEFAULT_HELLO_MULTIPLIER;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_threeway_adj,
|
||||
isis_threeway_adj_cmd,
|
||||
"[no] isis three-way-handshake",
|
||||
NO_STR
|
||||
"IS-IS commands\n"
|
||||
"Enable/Disable three-way handshake\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->disable_threeway_adj = !strcmp(argv[0]->text, "no");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (isis_hello_padding,
|
||||
isis_hello_padding_cmd,
|
||||
"isis hello padding",
|
||||
"IS-IS routing protocol\n"
|
||||
"Add padding to IS-IS hello packets\n"
|
||||
"Pad hello packets\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->pad_hellos = 1;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_isis_hello_padding,
|
||||
no_isis_hello_padding_cmd,
|
||||
"no isis hello padding",
|
||||
NO_STR
|
||||
"IS-IS routing protocol\n"
|
||||
"Add padding to IS-IS hello packets\n"
|
||||
"Pad hello packets\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->pad_hellos = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (csnp_interval_level,
|
||||
csnp_interval_level_cmd,
|
||||
"isis csnp-interval (1-600) <level-1|level-2>",
|
||||
"IS-IS routing protocol\n"
|
||||
"Set CSNP interval in seconds\n"
|
||||
"CSNP interval value\n"
|
||||
"Specify interval for level-1 CSNPs\n"
|
||||
"Specify interval for level-2 CSNPs\n")
|
||||
{
|
||||
uint16_t interval = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->csnp_interval[level_for_arg(argv[3]->text)] = interval;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_csnp_interval_level,
|
||||
no_csnp_interval_level_cmd,
|
||||
"no isis csnp-interval [(1-600)] <level-1|level-2>",
|
||||
NO_STR
|
||||
"IS-IS routing protocol\n"
|
||||
"Set CSNP interval in seconds\n"
|
||||
"CSNP interval value\n"
|
||||
"Specify interval for level-1 CSNPs\n"
|
||||
"Specify interval for level-2 CSNPs\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
int level = level_for_arg(argv[argc - 1]->text);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->csnp_interval[level] = DEFAULT_CSNP_INTERVAL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (psnp_interval_level,
|
||||
psnp_interval_level_cmd,
|
||||
"isis psnp-interval (1-120) <level-1|level-2>",
|
||||
"IS-IS routing protocol\n"
|
||||
"Set PSNP interval in seconds\n"
|
||||
"PSNP interval value\n"
|
||||
"Specify interval for level-1 PSNPs\n"
|
||||
"Specify interval for level-2 PSNPs\n")
|
||||
{
|
||||
uint16_t interval = atoi(argv[2]->arg);
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->psnp_interval[level_for_arg(argv[3]->text)] = (uint16_t)interval;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_psnp_interval_level,
|
||||
no_psnp_interval_level_cmd,
|
||||
"no isis psnp-interval [(1-120)] <level-1|level-2>",
|
||||
NO_STR
|
||||
"IS-IS routing protocol\n"
|
||||
"Set PSNP interval in seconds\n"
|
||||
"PSNP interval value\n"
|
||||
"Specify interval for level-1 PSNPs\n"
|
||||
"Specify interval for level-2 PSNPs\n")
|
||||
{
|
||||
struct isis_circuit *circuit = isis_circuit_lookup(vty);
|
||||
int level = level_for_arg(argv[argc - 1]->text);
|
||||
if (!circuit)
|
||||
return CMD_ERR_NO_MATCH;
|
||||
|
||||
circuit->psnp_interval[level] = DEFAULT_PSNP_INTERVAL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area)
|
||||
{
|
||||
struct isis_circuit *circuit;
|
||||
struct listnode *node;
|
||||
|
||||
if (!vty)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
if (!area) {
|
||||
vty_out(vty, "ISIS area is invalid\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
|
||||
if ((area->is_type & IS_LEVEL_1)
|
||||
&& (circuit->is_type & IS_LEVEL_1)
|
||||
&& (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC)) {
|
||||
vty_out(vty, "ISIS circuit %s metric is invalid\n",
|
||||
circuit->interface->name);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if ((area->is_type & IS_LEVEL_2)
|
||||
&& (circuit->is_type & IS_LEVEL_2)
|
||||
&& (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) {
|
||||
vty_out(vty, "ISIS circuit %s metric is invalid\n",
|
||||
circuit->interface->name);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (metric_style,
|
||||
metric_style_cmd,
|
||||
"metric-style <narrow|transition|wide>",
|
||||
"Use old-style (ISO 10589) or new-style packet formats\n"
|
||||
"Use old style of TLVs with narrow metric\n"
|
||||
"Send and accept both styles of TLVs during transition\n"
|
||||
"Use new style of TLVs to carry wider metric\n")
|
||||
{
|
||||
int idx_metric_style = 1;
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
int ret;
|
||||
|
||||
if (strncmp(argv[idx_metric_style]->arg, "w", 1) == 0) {
|
||||
isis_area_metricstyle_set(area, false, true);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (area_is_mt(area)) {
|
||||
vty_out(vty,
|
||||
"Narrow metrics cannot be used while multi topology IS-IS is active\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
ret = validate_metric_style_narrow(vty, area);
|
||||
if (ret != CMD_SUCCESS)
|
||||
return ret;
|
||||
|
||||
if (strncmp(argv[idx_metric_style]->arg, "t", 1) == 0)
|
||||
isis_area_metricstyle_set(area, true, true);
|
||||
else if (strncmp(argv[idx_metric_style]->arg, "n", 1) == 0)
|
||||
isis_area_metricstyle_set(area, true, false);
|
||||
return CMD_SUCCESS;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_metric_style,
|
||||
no_metric_style_cmd,
|
||||
"no metric-style",
|
||||
NO_STR
|
||||
"Use old-style (ISO 10589) or new-style packet formats\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
int ret;
|
||||
|
||||
if (area_is_mt(area)) {
|
||||
vty_out(vty,
|
||||
"Narrow metrics cannot be used while multi topology IS-IS is active\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
ret = validate_metric_style_narrow(vty, area);
|
||||
if (ret != CMD_SUCCESS)
|
||||
return ret;
|
||||
|
||||
isis_area_metricstyle_set(area, true, false);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (set_attached_bit,
|
||||
set_attached_bit_cmd,
|
||||
"set-attached-bit",
|
||||
"Set attached bit to identify as L1/L2 router for inter-area traffic\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
isis_area_attached_bit_set(area, true);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_set_attached_bit,
|
||||
no_set_attached_bit_cmd,
|
||||
"no set-attached-bit",
|
||||
NO_STR
|
||||
"Reset attached bit\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
isis_area_attached_bit_set(area, false);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (dynamic_hostname,
|
||||
dynamic_hostname_cmd,
|
||||
"hostname dynamic",
|
||||
"Dynamic hostname for IS-IS\n"
|
||||
"Dynamic hostname\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
isis_area_dynhostname_set(area, true);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_dynamic_hostname,
|
||||
no_dynamic_hostname_cmd,
|
||||
"no hostname dynamic",
|
||||
NO_STR
|
||||
"Dynamic hostname for IS-IS\n"
|
||||
"Dynamic hostname\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
isis_area_dynhostname_set(area, false);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (is_type,
|
||||
is_type_cmd,
|
||||
"is-type <level-1|level-1-2|level-2-only>",
|
||||
"IS Level for this routing process (OSI only)\n"
|
||||
"Act as a station router only\n"
|
||||
"Act as both a station router and an area router\n"
|
||||
"Act as an area router only\n")
|
||||
{
|
||||
int idx_level = 1;
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
int type;
|
||||
|
||||
type = string2circuit_t(argv[idx_level]->arg);
|
||||
if (!type) {
|
||||
vty_out(vty, "Unknown IS level \n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
isis_area_is_type_set(area, type);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_is_type,
|
||||
no_is_type_cmd,
|
||||
"no is-type <level-1|level-1-2|level-2-only>",
|
||||
NO_STR
|
||||
"IS Level for this routing process (OSI only)\n"
|
||||
"Act as a station router only\n"
|
||||
"Act as both a station router and an area router\n"
|
||||
"Act as an area router only\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
int type;
|
||||
|
||||
/*
|
||||
* Put the is-type back to defaults:
|
||||
* - level-1-2 on first area
|
||||
* - level-1 for the rest
|
||||
*/
|
||||
if (listgetdata(listhead(isis->area_list)) == area)
|
||||
type = IS_LEVEL_1_AND_2;
|
||||
else
|
||||
type = IS_LEVEL_1;
|
||||
|
||||
isis_area_is_type_set(area, type);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (lsp_gen_interval_level,
|
||||
lsp_gen_interval_level_cmd,
|
||||
"lsp-gen-interval <level-1|level-2> (1-120)",
|
||||
"Minimum interval between regenerating same LSP\n"
|
||||
"Set interval for level 1 only\n"
|
||||
"Set interval for level 2 only\n"
|
||||
"Minimum interval in seconds\n")
|
||||
{
|
||||
uint16_t interval = atoi(argv[2]->arg);
|
||||
|
||||
return isis_vty_lsp_gen_interval_set(vty, level_for_arg(argv[1]->text),
|
||||
interval);
|
||||
}
|
||||
|
||||
DEFUN (no_lsp_gen_interval_level,
|
||||
no_lsp_gen_interval_level_cmd,
|
||||
"no lsp-gen-interval <level-1|level-2> [(1-120)]",
|
||||
NO_STR
|
||||
"Minimum interval between regenerating same LSP\n"
|
||||
"Set interval for level 1 only\n"
|
||||
"Set interval for level 2 only\n"
|
||||
"Minimum interval in seconds\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
return isis_vty_lsp_gen_interval_set(vty, level_for_arg(argv[2]->text),
|
||||
DEFAULT_MIN_LSP_GEN_INTERVAL);
|
||||
}
|
||||
|
||||
DEFUN (max_lsp_lifetime_level,
|
||||
max_lsp_lifetime_level_cmd,
|
||||
"max-lsp-lifetime <level-1|level-2> (350-65535)",
|
||||
"Maximum LSP lifetime\n"
|
||||
"Maximum LSP lifetime for Level 1 only\n"
|
||||
"Maximum LSP lifetime for Level 2 only\n"
|
||||
"LSP lifetime in seconds\n")
|
||||
{
|
||||
uint16_t lifetime = atoi(argv[2]->arg);
|
||||
|
||||
return isis_vty_max_lsp_lifetime_set(vty, level_for_arg(argv[1]->text),
|
||||
lifetime);
|
||||
}
|
||||
|
||||
DEFUN (no_max_lsp_lifetime_level,
|
||||
no_max_lsp_lifetime_level_cmd,
|
||||
"no max-lsp-lifetime <level-1|level-2> [(350-65535)]",
|
||||
NO_STR
|
||||
"Maximum LSP lifetime\n"
|
||||
"Maximum LSP lifetime for Level 1 only\n"
|
||||
"Maximum LSP lifetime for Level 2 only\n"
|
||||
"LSP lifetime in seconds\n")
|
||||
{
|
||||
return isis_vty_max_lsp_lifetime_set(vty, level_for_arg(argv[1]->text),
|
||||
DEFAULT_LSP_LIFETIME);
|
||||
}
|
||||
|
||||
DEFUN (spf_interval_level,
|
||||
spf_interval_level_cmd,
|
||||
"spf-interval <level-1|level-2> (1-120)",
|
||||
"Minimum interval between SPF calculations\n"
|
||||
"Set interval for level 1 only\n"
|
||||
"Set interval for level 2 only\n"
|
||||
"Minimum interval between consecutive SPFs in seconds\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
uint16_t interval = atoi(argv[2]->arg);
|
||||
|
||||
area->min_spf_interval[level_for_arg(argv[1]->text)] = interval;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_spf_interval_level,
|
||||
no_spf_interval_level_cmd,
|
||||
"no spf-interval <level-1|level-2> [(1-120)]",
|
||||
NO_STR
|
||||
"Minimum interval between SPF calculations\n"
|
||||
"Set interval for level 1 only\n"
|
||||
"Set interval for level 2 only\n"
|
||||
"Minimum interval between consecutive SPFs in seconds\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
int level = level_for_arg(argv[1]->text);
|
||||
|
||||
area->min_spf_interval[level] = MINIMUM_SPF_INTERVAL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (lsp_refresh_interval_level,
|
||||
lsp_refresh_interval_level_cmd,
|
||||
"lsp-refresh-interval <level-1|level-2> (1-65235)",
|
||||
"LSP refresh interval\n"
|
||||
"LSP refresh interval for Level 1 only\n"
|
||||
"LSP refresh interval for Level 2 only\n"
|
||||
"LSP refresh interval in seconds\n")
|
||||
{
|
||||
uint16_t interval = atoi(argv[2]->arg);
|
||||
return isis_vty_lsp_refresh_set(vty, level_for_arg(argv[1]->text),
|
||||
interval);
|
||||
}
|
||||
|
||||
DEFUN (no_lsp_refresh_interval_level,
|
||||
no_lsp_refresh_interval_level_cmd,
|
||||
"no lsp-refresh-interval <level-1|level-2> [(1-65235)]",
|
||||
NO_STR
|
||||
"LSP refresh interval\n"
|
||||
"LSP refresh interval for Level 1 only\n"
|
||||
"LSP refresh interval for Level 2 only\n"
|
||||
"LSP refresh interval in seconds\n")
|
||||
{
|
||||
return isis_vty_lsp_refresh_set(vty, level_for_arg(argv[2]->text),
|
||||
DEFAULT_MAX_LSP_GEN_INTERVAL);
|
||||
}
|
||||
|
||||
DEFUN (area_passwd,
|
||||
area_passwd_cmd,
|
||||
"area-password <clear|md5> WORD [authenticate snp <send-only|validate>]",
|
||||
"Configure the authentication password for an area\n"
|
||||
"Authentication type\n"
|
||||
"Authentication type\n"
|
||||
"Area password\n"
|
||||
"Authentication\n"
|
||||
"SNP PDUs\n"
|
||||
"Send but do not check PDUs on receiving\n"
|
||||
"Send and check PDUs on receiving\n")
|
||||
{
|
||||
return isis_vty_password_set(vty, argc, argv, IS_LEVEL_1);
|
||||
}
|
||||
|
||||
DEFUN (no_area_passwd,
|
||||
no_area_passwd_cmd,
|
||||
"no area-password",
|
||||
NO_STR
|
||||
"Configure the authentication password for an area\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(isis_area, area);
|
||||
|
||||
return isis_area_passwd_unset(area, IS_LEVEL_1);
|
||||
}
|
||||
|
||||
void isis_vty_daemon_init(void)
|
||||
{
|
||||
install_element(INTERFACE_NODE, &isis_circuit_type_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_circuit_type_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_network_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_network_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_priority_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_priority_cmd);
|
||||
install_element(INTERFACE_NODE, &isis_priority_level_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_priority_level_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_metric_level_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_metric_level_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_hello_interval_level_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_hello_interval_level_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_hello_multiplier_level_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_hello_multiplier_level_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_threeway_adj_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &isis_hello_padding_cmd);
|
||||
install_element(INTERFACE_NODE, &no_isis_hello_padding_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &csnp_interval_level_cmd);
|
||||
install_element(INTERFACE_NODE, &no_csnp_interval_level_cmd);
|
||||
|
||||
install_element(INTERFACE_NODE, &psnp_interval_level_cmd);
|
||||
install_element(INTERFACE_NODE, &no_psnp_interval_level_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &metric_style_cmd);
|
||||
install_element(ROUTER_NODE, &no_metric_style_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &set_attached_bit_cmd);
|
||||
install_element(ROUTER_NODE, &no_set_attached_bit_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &dynamic_hostname_cmd);
|
||||
install_element(ROUTER_NODE, &no_dynamic_hostname_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &is_type_cmd);
|
||||
install_element(ROUTER_NODE, &no_is_type_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &lsp_gen_interval_level_cmd);
|
||||
install_element(ROUTER_NODE, &no_lsp_gen_interval_level_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &max_lsp_lifetime_level_cmd);
|
||||
install_element(ROUTER_NODE, &no_max_lsp_lifetime_level_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &spf_interval_level_cmd);
|
||||
install_element(ROUTER_NODE, &no_spf_interval_level_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &lsp_refresh_interval_level_cmd);
|
||||
install_element(ROUTER_NODE, &no_lsp_refresh_interval_level_cmd);
|
||||
|
||||
install_element(ROUTER_NODE, &area_passwd_cmd);
|
||||
install_element(ROUTER_NODE, &no_area_passwd_cmd);
|
||||
}
|
@ -261,8 +261,10 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
|
||||
return;
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
if (fabricd)
|
||||
api.flags |= ZEBRA_FLAG_ONLINK;
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_ISIS;
|
||||
api.type = PROTO_TYPE;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *prefix;
|
||||
if (src_p && src_p->prefixlen) {
|
||||
@ -337,7 +339,7 @@ static void isis_zebra_route_del_route(struct prefix *prefix,
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_ISIS;
|
||||
api.type = PROTO_TYPE;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *prefix;
|
||||
if (src_p && src_p->prefixlen) {
|
||||
@ -378,7 +380,7 @@ static int isis_zebra_read(int command, struct zclient *zclient,
|
||||
*/
|
||||
if (api.prefix.prefixlen == 0
|
||||
&& api.src_prefix.prefixlen == 0
|
||||
&& api.type == ZEBRA_ROUTE_ISIS) {
|
||||
&& api.type == PROTO_TYPE) {
|
||||
command = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
|
||||
}
|
||||
|
||||
@ -424,7 +426,7 @@ static void isis_zebra_connected(struct zclient *zclient)
|
||||
void isis_zebra_init(struct thread_master *master)
|
||||
{
|
||||
zclient = zclient_new_notify(master, &zclient_options_default);
|
||||
zclient_init(zclient, ZEBRA_ROUTE_ISIS, 0, &isisd_privs);
|
||||
zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
|
||||
zclient->zebra_connected = isis_zebra_connected;
|
||||
zclient->router_id_update = isis_router_id_update_zebra;
|
||||
zclient->interface_add = isis_zebra_if_add;
|
||||
|
276
isisd/isisd.c
276
isisd/isisd.c
@ -56,6 +56,7 @@
|
||||
#include "isisd/isis_events.h"
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/fabricd.h"
|
||||
|
||||
struct isis *isis = NULL;
|
||||
|
||||
@ -95,6 +96,7 @@ void isis_new(unsigned long process_id)
|
||||
*/
|
||||
/* isis->debugs = 0xFFFF; */
|
||||
isisMplsTE.status = disable; /* Only support TE metric */
|
||||
|
||||
QOBJ_REG(isis, isis);
|
||||
}
|
||||
|
||||
@ -105,10 +107,13 @@ struct isis_area *isis_area_create(const char *area_tag)
|
||||
area = XCALLOC(MTYPE_ISIS_AREA, sizeof(struct isis_area));
|
||||
|
||||
/*
|
||||
* The first instance is level-1-2 rest are level-1, unless otherwise
|
||||
* configured
|
||||
* Fabricd runs only as level-2.
|
||||
* For IS-IS, the first instance is level-1-2 rest are level-1,
|
||||
* unless otherwise configured
|
||||
*/
|
||||
if (listcount(isis->area_list) > 0)
|
||||
if (fabricd) {
|
||||
area->is_type = IS_LEVEL_2;
|
||||
} else if (listcount(isis->area_list) > 0)
|
||||
area->is_type = IS_LEVEL_1;
|
||||
else
|
||||
area->is_type = IS_LEVEL_1_AND_2;
|
||||
@ -153,6 +158,8 @@ struct isis_area *isis_area_create(const char *area_tag)
|
||||
listnode_add(isis->area_list, area);
|
||||
area->isis = isis;
|
||||
|
||||
if (fabricd)
|
||||
area->fabricd = fabricd_new(area);
|
||||
QOBJ_REG(area, isis_area);
|
||||
|
||||
return area;
|
||||
@ -179,7 +186,7 @@ int isis_area_get(struct vty *vty, const char *area_tag)
|
||||
area = isis_area_lookup(area_tag);
|
||||
|
||||
if (area) {
|
||||
VTY_PUSH_CONTEXT(ISIS_NODE, area);
|
||||
VTY_PUSH_CONTEXT(ROUTER_NODE, area);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -188,7 +195,7 @@ int isis_area_get(struct vty *vty, const char *area_tag)
|
||||
if (isis->debugs & DEBUG_EVENTS)
|
||||
zlog_debug("New IS-IS area instance %s", area->area_tag);
|
||||
|
||||
VTY_PUSH_CONTEXT(ISIS_NODE, area);
|
||||
VTY_PUSH_CONTEXT(ROUTER_NODE, area);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -209,6 +216,9 @@ int isis_area_destroy(struct vty *vty, const char *area_tag)
|
||||
|
||||
QOBJ_UNREG(area);
|
||||
|
||||
if (fabricd)
|
||||
fabricd_finish(area->fabricd);
|
||||
|
||||
if (area->circuit_list) {
|
||||
for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode,
|
||||
circuit)) {
|
||||
@ -463,9 +473,9 @@ int show_isis_interface_common(struct vty *vty, const char *ifname, char detail)
|
||||
|
||||
DEFUN (show_isis_interface,
|
||||
show_isis_interface_cmd,
|
||||
"show isis interface",
|
||||
"show " PROTO_NAME " interface",
|
||||
SHOW_STR
|
||||
"ISIS network information\n"
|
||||
PROTO_HELP
|
||||
"ISIS interface\n")
|
||||
{
|
||||
return show_isis_interface_common(vty, NULL, ISIS_UI_LEVEL_BRIEF);
|
||||
@ -473,9 +483,9 @@ DEFUN (show_isis_interface,
|
||||
|
||||
DEFUN (show_isis_interface_detail,
|
||||
show_isis_interface_detail_cmd,
|
||||
"show isis interface detail",
|
||||
"show " PROTO_NAME " interface detail",
|
||||
SHOW_STR
|
||||
"ISIS network information\n"
|
||||
PROTO_HELP
|
||||
"ISIS interface\n"
|
||||
"show detailed information\n")
|
||||
{
|
||||
@ -484,9 +494,9 @@ DEFUN (show_isis_interface_detail,
|
||||
|
||||
DEFUN (show_isis_interface_arg,
|
||||
show_isis_interface_arg_cmd,
|
||||
"show isis interface WORD",
|
||||
"show " PROTO_NAME " interface WORD",
|
||||
SHOW_STR
|
||||
"ISIS network information\n"
|
||||
PROTO_HELP
|
||||
"ISIS interface\n"
|
||||
"ISIS interface name\n")
|
||||
{
|
||||
@ -634,9 +644,9 @@ int clear_isis_neighbor_common(struct vty *vty, const char *id)
|
||||
|
||||
DEFUN (show_isis_neighbor,
|
||||
show_isis_neighbor_cmd,
|
||||
"show isis neighbor",
|
||||
"show " PROTO_NAME " neighbor",
|
||||
SHOW_STR
|
||||
"ISIS network information\n"
|
||||
PROTO_HELP
|
||||
"ISIS neighbor adjacencies\n")
|
||||
{
|
||||
return show_isis_neighbor_common(vty, NULL, ISIS_UI_LEVEL_BRIEF);
|
||||
@ -644,9 +654,9 @@ DEFUN (show_isis_neighbor,
|
||||
|
||||
DEFUN (show_isis_neighbor_detail,
|
||||
show_isis_neighbor_detail_cmd,
|
||||
"show isis neighbor detail",
|
||||
"show " PROTO_NAME " neighbor detail",
|
||||
SHOW_STR
|
||||
"ISIS network information\n"
|
||||
PROTO_HELP
|
||||
"ISIS neighbor adjacencies\n"
|
||||
"show detailed information\n")
|
||||
{
|
||||
@ -655,9 +665,9 @@ DEFUN (show_isis_neighbor_detail,
|
||||
|
||||
DEFUN (show_isis_neighbor_arg,
|
||||
show_isis_neighbor_arg_cmd,
|
||||
"show isis neighbor WORD",
|
||||
"show " PROTO_NAME " neighbor WORD",
|
||||
SHOW_STR
|
||||
"ISIS network information\n"
|
||||
PROTO_HELP
|
||||
"ISIS neighbor adjacencies\n"
|
||||
"System id\n")
|
||||
{
|
||||
@ -668,19 +678,19 @@ DEFUN (show_isis_neighbor_arg,
|
||||
|
||||
DEFUN (clear_isis_neighbor,
|
||||
clear_isis_neighbor_cmd,
|
||||
"clear isis neighbor",
|
||||
"clear " PROTO_NAME " neighbor",
|
||||
CLEAR_STR
|
||||
"Reset ISIS network information\n"
|
||||
"Reset ISIS neighbor adjacencies\n")
|
||||
PROTO_HELP
|
||||
"ISIS neighbor adjacencies\n")
|
||||
{
|
||||
return clear_isis_neighbor_common(vty, NULL);
|
||||
}
|
||||
|
||||
DEFUN (clear_isis_neighbor_arg,
|
||||
clear_isis_neighbor_arg_cmd,
|
||||
"clear isis neighbor WORD",
|
||||
"clear " PROTO_NAME " neighbor WORD",
|
||||
CLEAR_STR
|
||||
"ISIS network information\n"
|
||||
PROTO_HELP
|
||||
"ISIS neighbor adjacencies\n"
|
||||
"System id\n")
|
||||
{
|
||||
@ -734,16 +744,18 @@ void print_debug(struct vty *vty, int flags, int onoff)
|
||||
vty_out(vty, "IS-IS LSP generation debugging is %s\n", onoffs);
|
||||
if (flags & DEBUG_LSP_SCHED)
|
||||
vty_out(vty, "IS-IS LSP scheduling debugging is %s\n", onoffs);
|
||||
if (flags & DEBUG_FABRICD_FLOODING)
|
||||
vty_out(vty, "OpenFabric Flooding debugging is %s\n", onoffs);
|
||||
}
|
||||
|
||||
DEFUN_NOSH (show_debugging,
|
||||
show_debugging_isis_cmd,
|
||||
"show debugging [isis]",
|
||||
"show debugging [" PROTO_NAME "]",
|
||||
SHOW_STR
|
||||
"State of each debugging option\n"
|
||||
ISIS_STR)
|
||||
PROTO_HELP)
|
||||
{
|
||||
vty_out(vty, "IS-IS debugging status:\n");
|
||||
vty_out(vty, PROTO_NAME " debugging status:\n");
|
||||
|
||||
if (isis->debugs)
|
||||
print_debug(vty, isis->debugs, 1);
|
||||
@ -760,59 +772,63 @@ static int config_write_debug(struct vty *vty)
|
||||
int flags = isis->debugs;
|
||||
|
||||
if (flags & DEBUG_ADJ_PACKETS) {
|
||||
vty_out(vty, "debug isis adj-packets\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " adj-packets\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_CHECKSUM_ERRORS) {
|
||||
vty_out(vty, "debug isis checksum-errors\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " checksum-errors\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_LOCAL_UPDATES) {
|
||||
vty_out(vty, "debug isis local-updates\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " local-updates\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_PROTOCOL_ERRORS) {
|
||||
vty_out(vty, "debug isis protocol-errors\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " protocol-errors\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_SNP_PACKETS) {
|
||||
vty_out(vty, "debug isis snp-packets\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " snp-packets\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_SPF_EVENTS) {
|
||||
vty_out(vty, "debug isis spf-events\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " spf-events\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_SPF_STATS) {
|
||||
vty_out(vty, "debug isis spf-statistics\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " spf-statistics\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_SPF_TRIGGERS) {
|
||||
vty_out(vty, "debug isis spf-triggers\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " spf-triggers\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_UPDATE_PACKETS) {
|
||||
vty_out(vty, "debug isis update-packets\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " update-packets\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_RTE_EVENTS) {
|
||||
vty_out(vty, "debug isis route-events\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " route-events\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_EVENTS) {
|
||||
vty_out(vty, "debug isis events\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " events\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_PACKET_DUMP) {
|
||||
vty_out(vty, "debug isis packet-dump\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " packet-dump\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_LSP_GEN) {
|
||||
vty_out(vty, "debug isis lsp-gen\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " lsp-gen\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_LSP_SCHED) {
|
||||
vty_out(vty, "debug isis lsp-sched\n");
|
||||
vty_out(vty, "debug " PROTO_NAME " lsp-sched\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_FABRICD_FLOODING) {
|
||||
vty_out(vty, "debug " PROTO_NAME " flooding\n");
|
||||
write++;
|
||||
}
|
||||
write += spf_backoff_write_config(vty);
|
||||
@ -822,9 +838,9 @@ static int config_write_debug(struct vty *vty)
|
||||
|
||||
DEFUN (debug_isis_adj,
|
||||
debug_isis_adj_cmd,
|
||||
"debug isis adj-packets",
|
||||
"debug " PROTO_NAME " adj-packets",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Adjacency related packets\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_ADJ_PACKETS;
|
||||
@ -835,10 +851,10 @@ DEFUN (debug_isis_adj,
|
||||
|
||||
DEFUN (no_debug_isis_adj,
|
||||
no_debug_isis_adj_cmd,
|
||||
"no debug isis adj-packets",
|
||||
"no debug " PROTO_NAME " adj-packets",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Adjacency related packets\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_ADJ_PACKETS;
|
||||
@ -849,9 +865,9 @@ DEFUN (no_debug_isis_adj,
|
||||
|
||||
DEFUN (debug_isis_csum,
|
||||
debug_isis_csum_cmd,
|
||||
"debug isis checksum-errors",
|
||||
"debug " PROTO_NAME " checksum-errors",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS LSP checksum errors\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_CHECKSUM_ERRORS;
|
||||
@ -862,10 +878,10 @@ DEFUN (debug_isis_csum,
|
||||
|
||||
DEFUN (no_debug_isis_csum,
|
||||
no_debug_isis_csum_cmd,
|
||||
"no debug isis checksum-errors",
|
||||
"no debug " PROTO_NAME " checksum-errors",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS LSP checksum errors\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_CHECKSUM_ERRORS;
|
||||
@ -876,9 +892,9 @@ DEFUN (no_debug_isis_csum,
|
||||
|
||||
DEFUN (debug_isis_lupd,
|
||||
debug_isis_lupd_cmd,
|
||||
"debug isis local-updates",
|
||||
"debug " PROTO_NAME " local-updates",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS local update packets\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_LOCAL_UPDATES;
|
||||
@ -889,10 +905,10 @@ DEFUN (debug_isis_lupd,
|
||||
|
||||
DEFUN (no_debug_isis_lupd,
|
||||
no_debug_isis_lupd_cmd,
|
||||
"no debug isis local-updates",
|
||||
"no debug " PROTO_NAME " local-updates",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS local update packets\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_LOCAL_UPDATES;
|
||||
@ -903,9 +919,9 @@ DEFUN (no_debug_isis_lupd,
|
||||
|
||||
DEFUN (debug_isis_err,
|
||||
debug_isis_err_cmd,
|
||||
"debug isis protocol-errors",
|
||||
"debug " PROTO_NAME " protocol-errors",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS LSP protocol errors\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_PROTOCOL_ERRORS;
|
||||
@ -916,10 +932,10 @@ DEFUN (debug_isis_err,
|
||||
|
||||
DEFUN (no_debug_isis_err,
|
||||
no_debug_isis_err_cmd,
|
||||
"no debug isis protocol-errors",
|
||||
"no debug " PROTO_NAME " protocol-errors",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS LSP protocol errors\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_PROTOCOL_ERRORS;
|
||||
@ -930,9 +946,9 @@ DEFUN (no_debug_isis_err,
|
||||
|
||||
DEFUN (debug_isis_snp,
|
||||
debug_isis_snp_cmd,
|
||||
"debug isis snp-packets",
|
||||
"debug " PROTO_NAME " snp-packets",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS CSNP/PSNP packets\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_SNP_PACKETS;
|
||||
@ -943,10 +959,10 @@ DEFUN (debug_isis_snp,
|
||||
|
||||
DEFUN (no_debug_isis_snp,
|
||||
no_debug_isis_snp_cmd,
|
||||
"no debug isis snp-packets",
|
||||
"no debug " PROTO_NAME " snp-packets",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS CSNP/PSNP packets\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_SNP_PACKETS;
|
||||
@ -957,9 +973,9 @@ DEFUN (no_debug_isis_snp,
|
||||
|
||||
DEFUN (debug_isis_upd,
|
||||
debug_isis_upd_cmd,
|
||||
"debug isis update-packets",
|
||||
"debug " PROTO_NAME " update-packets",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Update related packets\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_UPDATE_PACKETS;
|
||||
@ -970,10 +986,10 @@ DEFUN (debug_isis_upd,
|
||||
|
||||
DEFUN (no_debug_isis_upd,
|
||||
no_debug_isis_upd_cmd,
|
||||
"no debug isis update-packets",
|
||||
"no debug " PROTO_NAME " update-packets",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Update related packets\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_UPDATE_PACKETS;
|
||||
@ -984,9 +1000,9 @@ DEFUN (no_debug_isis_upd,
|
||||
|
||||
DEFUN (debug_isis_spfevents,
|
||||
debug_isis_spfevents_cmd,
|
||||
"debug isis spf-events",
|
||||
"debug " PROTO_NAME " spf-events",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Shortest Path First Events\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_SPF_EVENTS;
|
||||
@ -997,10 +1013,10 @@ DEFUN (debug_isis_spfevents,
|
||||
|
||||
DEFUN (no_debug_isis_spfevents,
|
||||
no_debug_isis_spfevents_cmd,
|
||||
"no debug isis spf-events",
|
||||
"no debug " PROTO_NAME " spf-events",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Shortest Path First Events\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_SPF_EVENTS;
|
||||
@ -1011,9 +1027,9 @@ DEFUN (no_debug_isis_spfevents,
|
||||
|
||||
DEFUN (debug_isis_spfstats,
|
||||
debug_isis_spfstats_cmd,
|
||||
"debug isis spf-statistics ",
|
||||
"debug " PROTO_NAME " spf-statistics ",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS SPF Timing and Statistic Data\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_SPF_STATS;
|
||||
@ -1024,10 +1040,10 @@ DEFUN (debug_isis_spfstats,
|
||||
|
||||
DEFUN (no_debug_isis_spfstats,
|
||||
no_debug_isis_spfstats_cmd,
|
||||
"no debug isis spf-statistics",
|
||||
"no debug " PROTO_NAME " spf-statistics",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS SPF Timing and Statistic Data\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_SPF_STATS;
|
||||
@ -1038,9 +1054,9 @@ DEFUN (no_debug_isis_spfstats,
|
||||
|
||||
DEFUN (debug_isis_spftrigg,
|
||||
debug_isis_spftrigg_cmd,
|
||||
"debug isis spf-triggers",
|
||||
"debug " PROTO_NAME " spf-triggers",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS SPF triggering events\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_SPF_TRIGGERS;
|
||||
@ -1051,10 +1067,10 @@ DEFUN (debug_isis_spftrigg,
|
||||
|
||||
DEFUN (no_debug_isis_spftrigg,
|
||||
no_debug_isis_spftrigg_cmd,
|
||||
"no debug isis spf-triggers",
|
||||
"no debug " PROTO_NAME " spf-triggers",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS SPF triggering events\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_SPF_TRIGGERS;
|
||||
@ -1065,9 +1081,9 @@ DEFUN (no_debug_isis_spftrigg,
|
||||
|
||||
DEFUN (debug_isis_rtevents,
|
||||
debug_isis_rtevents_cmd,
|
||||
"debug isis route-events",
|
||||
"debug " PROTO_NAME " route-events",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Route related events\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_RTE_EVENTS;
|
||||
@ -1078,10 +1094,10 @@ DEFUN (debug_isis_rtevents,
|
||||
|
||||
DEFUN (no_debug_isis_rtevents,
|
||||
no_debug_isis_rtevents_cmd,
|
||||
"no debug isis route-events",
|
||||
"no debug " PROTO_NAME " route-events",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Route related events\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_RTE_EVENTS;
|
||||
@ -1092,9 +1108,9 @@ DEFUN (no_debug_isis_rtevents,
|
||||
|
||||
DEFUN (debug_isis_events,
|
||||
debug_isis_events_cmd,
|
||||
"debug isis events",
|
||||
"debug " PROTO_NAME " events",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Events\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_EVENTS;
|
||||
@ -1105,10 +1121,10 @@ DEFUN (debug_isis_events,
|
||||
|
||||
DEFUN (no_debug_isis_events,
|
||||
no_debug_isis_events_cmd,
|
||||
"no debug isis events",
|
||||
"no debug " PROTO_NAME " events",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Events\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_EVENTS;
|
||||
@ -1119,9 +1135,9 @@ DEFUN (no_debug_isis_events,
|
||||
|
||||
DEFUN (debug_isis_packet_dump,
|
||||
debug_isis_packet_dump_cmd,
|
||||
"debug isis packet-dump",
|
||||
"debug " PROTO_NAME " packet-dump",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS packet dump\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_PACKET_DUMP;
|
||||
@ -1132,10 +1148,10 @@ DEFUN (debug_isis_packet_dump,
|
||||
|
||||
DEFUN (no_debug_isis_packet_dump,
|
||||
no_debug_isis_packet_dump_cmd,
|
||||
"no debug isis packet-dump",
|
||||
"no debug " PROTO_NAME " packet-dump",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS packet dump\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_PACKET_DUMP;
|
||||
@ -1146,9 +1162,9 @@ DEFUN (no_debug_isis_packet_dump,
|
||||
|
||||
DEFUN (debug_isis_lsp_gen,
|
||||
debug_isis_lsp_gen_cmd,
|
||||
"debug isis lsp-gen",
|
||||
"debug " PROTO_NAME " lsp-gen",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS generation of own LSPs\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_LSP_GEN;
|
||||
@ -1159,10 +1175,10 @@ DEFUN (debug_isis_lsp_gen,
|
||||
|
||||
DEFUN (no_debug_isis_lsp_gen,
|
||||
no_debug_isis_lsp_gen_cmd,
|
||||
"no debug isis lsp-gen",
|
||||
"no debug " PROTO_NAME " lsp-gen",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS generation of own LSPs\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_LSP_GEN;
|
||||
@ -1173,9 +1189,9 @@ DEFUN (no_debug_isis_lsp_gen,
|
||||
|
||||
DEFUN (debug_isis_lsp_sched,
|
||||
debug_isis_lsp_sched_cmd,
|
||||
"debug isis lsp-sched",
|
||||
"debug " PROTO_NAME " lsp-sched",
|
||||
DEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS scheduling of LSP generation\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_LSP_SCHED;
|
||||
@ -1186,10 +1202,10 @@ DEFUN (debug_isis_lsp_sched,
|
||||
|
||||
DEFUN (no_debug_isis_lsp_sched,
|
||||
no_debug_isis_lsp_sched_cmd,
|
||||
"no debug isis lsp-sched",
|
||||
"no debug " PROTO_NAME " lsp-sched",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS scheduling of LSP generation\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_LSP_SCHED;
|
||||
@ -1200,9 +1216,9 @@ DEFUN (no_debug_isis_lsp_sched,
|
||||
|
||||
DEFUN (show_hostname,
|
||||
show_hostname_cmd,
|
||||
"show isis hostname",
|
||||
"show " PROTO_NAME " hostname",
|
||||
SHOW_STR
|
||||
"IS-IS information\n"
|
||||
PROTO_HELP
|
||||
"IS-IS Dynamic hostname mapping\n")
|
||||
{
|
||||
dynhn_print_all(vty);
|
||||
@ -1212,10 +1228,10 @@ DEFUN (show_hostname,
|
||||
|
||||
DEFUN (show_isis_spf_ietf,
|
||||
show_isis_spf_ietf_cmd,
|
||||
"show isis spf-delay-ietf",
|
||||
"show " PROTO_NAME " spf-delay-ietf",
|
||||
SHOW_STR
|
||||
"IS-IS information\n"
|
||||
"IS-IS SPF delay IETF information\n")
|
||||
PROTO_HELP
|
||||
"SPF delay IETF information\n")
|
||||
{
|
||||
if (!isis) {
|
||||
vty_out(vty, "ISIS is not running\n");
|
||||
@ -1261,15 +1277,15 @@ DEFUN (show_isis_spf_ietf,
|
||||
|
||||
DEFUN (show_isis_summary,
|
||||
show_isis_summary_cmd,
|
||||
"show isis summary",
|
||||
SHOW_STR "IS-IS information\n" "IS-IS summary\n")
|
||||
"show " PROTO_NAME " summary",
|
||||
SHOW_STR PROTO_HELP "summary\n")
|
||||
{
|
||||
struct listnode *node, *node2;
|
||||
struct isis_area *area;
|
||||
int level;
|
||||
|
||||
if (isis == NULL) {
|
||||
vty_out(vty, "ISIS is not running\n");
|
||||
vty_out(vty, PROTO_NAME " is not running\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1289,6 +1305,14 @@ DEFUN (show_isis_summary,
|
||||
vty_out(vty, "Area %s:\n",
|
||||
area->area_tag ? area->area_tag : "null");
|
||||
|
||||
if (fabricd) {
|
||||
uint8_t tier = fabricd_tier(area);
|
||||
if (tier == ISIS_TIER_UNDEFINED)
|
||||
vty_out(vty, " Tier: undefined\n");
|
||||
else
|
||||
vty_out(vty, " Tier: %" PRIu8 "\n", tier);
|
||||
}
|
||||
|
||||
if (listcount(area->area_addrs) > 0) {
|
||||
struct area_addr *area_addr;
|
||||
for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node2,
|
||||
@ -1471,10 +1495,10 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level)
|
||||
|
||||
DEFUN (show_database,
|
||||
show_database_cmd,
|
||||
"show isis database [detail] [WORD]",
|
||||
"show " PROTO_NAME " database [detail] [WORD]",
|
||||
SHOW_STR
|
||||
"IS-IS information\n"
|
||||
"IS-IS link state database\n"
|
||||
PROTO_HELP
|
||||
"Link state database\n"
|
||||
"Detailed information\n"
|
||||
"LSP ID\n")
|
||||
{
|
||||
@ -1491,9 +1515,9 @@ DEFUN (show_database,
|
||||
*/
|
||||
DEFUN_NOSH (router_isis,
|
||||
router_isis_cmd,
|
||||
"router isis WORD",
|
||||
"router " PROTO_NAME " WORD",
|
||||
ROUTER_STR
|
||||
"ISO IS-IS\n"
|
||||
PROTO_HELP
|
||||
"ISO Routing area tag\n")
|
||||
{
|
||||
int idx_word = 2;
|
||||
@ -1505,8 +1529,11 @@ DEFUN_NOSH (router_isis,
|
||||
*/
|
||||
DEFUN (no_router_isis,
|
||||
no_router_isis_cmd,
|
||||
"no router isis WORD",
|
||||
"no\n" ROUTER_STR "ISO IS-IS\n" "ISO Routing area tag\n")
|
||||
"no router " PROTO_NAME " WORD",
|
||||
NO_STR
|
||||
ROUTER_STR
|
||||
PROTO_HELP
|
||||
"ISO Routing area tag\n")
|
||||
{
|
||||
int idx_word = 3;
|
||||
return isis_area_destroy(vty, argv[idx_word]->arg);
|
||||
@ -1869,7 +1896,7 @@ int isis_config_write(struct vty *vty)
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
|
||||
/* ISIS - Area name */
|
||||
vty_out(vty, "router isis %s\n", area->area_tag);
|
||||
vty_out(vty, "router " PROTO_NAME " %s\n", area->area_tag);
|
||||
write++;
|
||||
/* ISIS - Net */
|
||||
if (listcount(area->area_addrs) > 0) {
|
||||
@ -1893,6 +1920,7 @@ int isis_config_write(struct vty *vty)
|
||||
write++;
|
||||
}
|
||||
/* ISIS - Metric-Style - when true displays wide */
|
||||
if (!fabricd) {
|
||||
if (area->newmetric) {
|
||||
if (!area->oldmetric)
|
||||
vty_out(vty, " metric-style wide\n");
|
||||
@ -1904,12 +1932,14 @@ int isis_config_write(struct vty *vty)
|
||||
vty_out(vty, " metric-style narrow\n");
|
||||
write++;
|
||||
}
|
||||
}
|
||||
/* ISIS - overload-bit */
|
||||
if (area->overload_bit) {
|
||||
vty_out(vty, " set-overload-bit\n");
|
||||
write++;
|
||||
}
|
||||
/* ISIS - Area is-type (level-1-2 is default) */
|
||||
if (!fabricd) {
|
||||
if (area->is_type == IS_LEVEL_1) {
|
||||
vty_out(vty, " is-type level-1\n");
|
||||
write++;
|
||||
@ -1917,6 +1947,7 @@ int isis_config_write(struct vty *vty)
|
||||
vty_out(vty, " is-type level-2-only\n");
|
||||
write++;
|
||||
}
|
||||
}
|
||||
write += isis_redist_config_write(vty, area, AF_INET);
|
||||
write += isis_redist_config_write(vty, area, AF_INET6);
|
||||
/* ISIS - Lsp generation interval */
|
||||
@ -1998,6 +2029,10 @@ int isis_config_write(struct vty *vty)
|
||||
vty_out(vty, " lsp-mtu %u\n", area->lsp_mtu);
|
||||
write++;
|
||||
}
|
||||
if (area->purge_originator) {
|
||||
vty_out(vty, " purge-originator\n");
|
||||
write++;
|
||||
}
|
||||
|
||||
/* Minimum SPF interval. */
|
||||
if (area->min_spf_interval[0]
|
||||
@ -2116,6 +2151,7 @@ int isis_config_write(struct vty *vty)
|
||||
}
|
||||
|
||||
write += area_write_mt_settings(area, vty);
|
||||
write += fabricd_write_settings(area, vty);
|
||||
}
|
||||
isis_mpls_te_config_write_router(vty);
|
||||
}
|
||||
@ -2123,12 +2159,12 @@ int isis_config_write(struct vty *vty)
|
||||
return write;
|
||||
}
|
||||
|
||||
struct cmd_node isis_node = {ISIS_NODE, "%s(config-router)# ", 1};
|
||||
struct cmd_node router_node = {ROUTER_NODE, "%s(config-router)# ", 1};
|
||||
|
||||
void isis_init()
|
||||
{
|
||||
/* Install IS-IS top node */
|
||||
install_node(&isis_node, isis_config_write);
|
||||
install_node(&router_node, isis_config_write);
|
||||
|
||||
install_element(VIEW_NODE, &show_isis_summary_cmd);
|
||||
|
||||
@ -2212,16 +2248,16 @@ void isis_init()
|
||||
install_element(CONFIG_NODE, &router_isis_cmd);
|
||||
install_element(CONFIG_NODE, &no_router_isis_cmd);
|
||||
|
||||
install_default(ISIS_NODE);
|
||||
install_default(ROUTER_NODE);
|
||||
|
||||
install_element(ISIS_NODE, &net_cmd);
|
||||
install_element(ISIS_NODE, &no_net_cmd);
|
||||
install_element(ROUTER_NODE, &net_cmd);
|
||||
install_element(ROUTER_NODE, &no_net_cmd);
|
||||
|
||||
install_element(ISIS_NODE, &isis_topology_cmd);
|
||||
install_element(ISIS_NODE, &no_isis_topology_cmd);
|
||||
install_element(ROUTER_NODE, &isis_topology_cmd);
|
||||
install_element(ROUTER_NODE, &no_isis_topology_cmd);
|
||||
|
||||
install_element(ISIS_NODE, &log_adj_changes_cmd);
|
||||
install_element(ISIS_NODE, &no_log_adj_changes_cmd);
|
||||
install_element(ROUTER_NODE, &log_adj_changes_cmd);
|
||||
install_element(ROUTER_NODE, &no_log_adj_changes_cmd);
|
||||
|
||||
spf_backoff_cmd_init();
|
||||
}
|
||||
|
@ -33,12 +33,32 @@
|
||||
#include "isis_memory.h"
|
||||
#include "qobj.h"
|
||||
|
||||
#ifdef FABRICD
|
||||
static const bool fabricd = true;
|
||||
#define PROTO_TYPE ZEBRA_ROUTE_OPENFABRIC
|
||||
#define PROTO_NAME "openfabric"
|
||||
#define PROTO_HELP "OpenFabric routing protocol\n"
|
||||
#define PROTO_REDIST_STR FRR_REDIST_STR_FABRICD
|
||||
#define PROTO_REDIST_HELP FRR_REDIST_HELP_STR_FABRICD
|
||||
#define ROUTER_NODE OPENFABRIC_NODE
|
||||
#else
|
||||
static const bool fabricd = false;
|
||||
#define PROTO_TYPE ZEBRA_ROUTE_ISIS
|
||||
#define PROTO_NAME "isis"
|
||||
#define PROTO_HELP "IS-IS routing protocol\n"
|
||||
#define PROTO_REDIST_STR FRR_REDIST_STR_ISISD
|
||||
#define PROTO_REDIST_HELP FRR_REDIST_HELP_STR_ISISD
|
||||
#define ROUTER_NODE ISIS_NODE
|
||||
#endif
|
||||
|
||||
extern struct zebra_privs_t isisd_privs;
|
||||
|
||||
/* uncomment if you are a developer in bug hunt */
|
||||
/* #define EXTREME_DEBUG */
|
||||
/* #define EXTREME_DICT_DEBUG */
|
||||
|
||||
struct fabricd;
|
||||
|
||||
struct isis {
|
||||
unsigned long process_id;
|
||||
int sysid_set;
|
||||
@ -93,6 +113,8 @@ struct isis_area {
|
||||
*/
|
||||
int lsp_regenerate_pending[ISIS_LEVELS];
|
||||
|
||||
struct fabricd *fabricd;
|
||||
|
||||
/*
|
||||
* Configurables
|
||||
*/
|
||||
@ -126,6 +148,7 @@ struct isis_area {
|
||||
/* multi topology settings */
|
||||
struct list *mt_settings;
|
||||
int ipv6_circuits;
|
||||
bool purge_originator;
|
||||
/* Counters */
|
||||
uint32_t circuit_state_changes;
|
||||
struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT]
|
||||
@ -168,7 +191,6 @@ int isis_area_passwd_cleartext_set(struct isis_area *area, int level,
|
||||
const char *passwd, uint8_t snp_auth);
|
||||
int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level,
|
||||
const char *passwd, uint8_t snp_auth);
|
||||
void isis_vty_init(void);
|
||||
|
||||
/* Master of threads. */
|
||||
extern struct thread_master *master;
|
||||
@ -188,6 +210,7 @@ extern struct thread_master *master;
|
||||
#define DEBUG_PACKET_DUMP (1<<12)
|
||||
#define DEBUG_LSP_GEN (1<<13)
|
||||
#define DEBUG_LSP_SCHED (1<<14)
|
||||
#define DEBUG_FABRICD_FLOODING (1<<15)
|
||||
|
||||
#define lsp_debug(...) \
|
||||
do { \
|
||||
|
103
isisd/subdir.am
103
isisd/subdir.am
@ -6,35 +6,23 @@ if ISISD
|
||||
noinst_LIBRARIES += isisd/libisis.a
|
||||
sbin_PROGRAMS += isisd/isisd
|
||||
dist_examples_DATA += isisd/isisd.conf.sample
|
||||
vtysh_scan += \
|
||||
$(top_srcdir)/isisd/isis_redist.c \
|
||||
$(top_srcdir)/isisd/isis_spf.c \
|
||||
$(top_srcdir)/isisd/isis_te.c \
|
||||
$(top_srcdir)/isisd/isis_vty_common.c \
|
||||
$(top_srcdir)/isisd/isis_vty_fabricd.c \
|
||||
$(top_srcdir)/isisd/isis_vty_isisd.c \
|
||||
$(top_srcdir)/isisd/isisd.c \
|
||||
# end
|
||||
man8 += $(MANBUILD)/isisd.8
|
||||
endif
|
||||
|
||||
isisd_libisis_a_SOURCES = \
|
||||
isisd/dict.c \
|
||||
isisd/isis_adjacency.c \
|
||||
isisd/isis_circuit.c \
|
||||
isisd/isis_csm.c \
|
||||
isisd/isis_dr.c \
|
||||
isisd/isis_dynhn.c \
|
||||
isisd/isis_errors.c \
|
||||
isisd/isis_events.c \
|
||||
isisd/isis_flags.c \
|
||||
isisd/isis_lsp.c \
|
||||
isisd/isis_lsp_hash.c \
|
||||
isisd/isis_memory.c \
|
||||
isisd/isis_misc.c \
|
||||
isisd/isis_mt.c \
|
||||
isisd/isis_pdu.c \
|
||||
isisd/isis_redist.c \
|
||||
isisd/isis_route.c \
|
||||
isisd/isis_routemap.c \
|
||||
isisd/isis_spf.c \
|
||||
isisd/isis_te.c \
|
||||
isisd/isis_tlvs.c \
|
||||
isisd/isis_vty.c \
|
||||
isisd/isis_zebra.c \
|
||||
isisd/isisd.c \
|
||||
isisd/iso_checksum.c \
|
||||
# end
|
||||
if FABRICD
|
||||
noinst_LIBRARIES += isisd/libfabric.a
|
||||
sbin_PROGRAMS += isisd/fabricd
|
||||
dist_examples_DATA += isisd/fabricd.conf.sample
|
||||
endif
|
||||
|
||||
noinst_HEADERS += \
|
||||
isisd/dict.h \
|
||||
@ -49,7 +37,6 @@ noinst_HEADERS += \
|
||||
isisd/isis_events.h \
|
||||
isisd/isis_flags.h \
|
||||
isisd/isis_lsp.h \
|
||||
isisd/isis_lsp_hash.h \
|
||||
isisd/isis_memory.h \
|
||||
isisd/isis_misc.h \
|
||||
isisd/isis_mt.h \
|
||||
@ -59,17 +46,73 @@ noinst_HEADERS += \
|
||||
isisd/isis_route.h \
|
||||
isisd/isis_routemap.h \
|
||||
isisd/isis_spf.h \
|
||||
isisd/isis_spf_private.h \
|
||||
isisd/isis_te.h \
|
||||
isisd/isis_tlvs.h \
|
||||
isisd/isis_tx_queue.h \
|
||||
isisd/isis_vty_common.h \
|
||||
isisd/isis_zebra.h \
|
||||
isisd/isisd.h \
|
||||
isisd/iso_checksum.h \
|
||||
isisd/fabricd.h \
|
||||
# end
|
||||
|
||||
isisd_isisd_LDADD = isisd/libisis.a lib/libfrr.la @LIBCAP@
|
||||
isisd_isisd_SOURCES = \
|
||||
LIBISIS_SOURCES = \
|
||||
isisd/dict.c \
|
||||
isisd/isis_adjacency.c \
|
||||
isisd/isis_circuit.c \
|
||||
isisd/isis_csm.c \
|
||||
isisd/isis_dr.c \
|
||||
isisd/isis_dynhn.c \
|
||||
isisd/isis_errors.c \
|
||||
isisd/isis_events.c \
|
||||
isisd/isis_flags.c \
|
||||
isisd/isis_lsp.c \
|
||||
isisd/isis_memory.c \
|
||||
isisd/isis_misc.c \
|
||||
isisd/isis_mt.c \
|
||||
isisd/isis_pdu.c \
|
||||
isisd/isis_redist.c \
|
||||
isisd/isis_route.c \
|
||||
isisd/isis_routemap.c \
|
||||
isisd/isis_spf.c \
|
||||
isisd/isis_te.c \
|
||||
isisd/isis_tlvs.c \
|
||||
isisd/isis_tx_queue.c \
|
||||
isisd/isis_vty_common.c \
|
||||
isisd/isis_zebra.c \
|
||||
isisd/isisd.c \
|
||||
isisd/iso_checksum.c \
|
||||
isisd/fabricd.c \
|
||||
# end
|
||||
|
||||
ISIS_SOURCES = \
|
||||
isisd/isis_bpf.c \
|
||||
isisd/isis_dlpi.c \
|
||||
isisd/isis_main.c \
|
||||
isisd/isis_pfpacket.c \
|
||||
# end
|
||||
|
||||
ISIS_LDADD_COMMON = lib/libfrr.la @LIBCAP@
|
||||
|
||||
# Building isisd
|
||||
|
||||
isisd_libisis_a_SOURCES = \
|
||||
$(LIBISIS_SOURCES) \
|
||||
isisd/isis_vty_isisd.c \
|
||||
#end
|
||||
isisd_isisd_LDADD = isisd/libisis.a $(ISIS_LDADD_COMMON)
|
||||
isisd_isisd_SOURCES = $(ISIS_SOURCES)
|
||||
|
||||
# Building fabricd
|
||||
|
||||
FABRICD_CPPFLAGS = -DFABRICD=1 $(AM_CPPFLAGS)
|
||||
|
||||
isisd_libfabric_a_SOURCES = \
|
||||
$(LIBISIS_SOURCES) \
|
||||
isisd/isis_vty_fabricd.c \
|
||||
#end
|
||||
isisd_libfabric_a_CPPFLAGS = $(FABRICD_CPPFLAGS)
|
||||
isisd_fabricd_LDADD = isisd/libfabric.a $(ISIS_LDADD_COMMON)
|
||||
isisd_fabricd_SOURCES = $(ISIS_SOURCES)
|
||||
isisd_fabricd_CPPFLAGS = $(FABRICD_CPPFLAGS)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user