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:
David Lamparter 2018-09-12 21:58:39 +02:00
commit e991eff5b5
245 changed files with 6961 additions and 7477 deletions

136
.gitignore vendored
View File

@ -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

View File

@ -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>

View File

@ -1,4 +0,0 @@
ChangeLog information for FRRouting is for now recorded in source-code
management system. Please see:
http://www.frrouting.org/

View File

@ -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 \
-I$(top_builddir) -I$(top_builddir)/include -I$(top_builddir)/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:

2574
NEWS

File diff suppressed because it is too large Load Diff

16
README
View File

@ -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
View 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
```

View File

@ -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"

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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 = \

View File

@ -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
View File

@ -1,3 +1,2 @@
# ignore binary files
*.a
bfdd

View File

@ -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;

View File

@ -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:

View File

@ -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
View File

@ -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
View File

@ -0,0 +1,10 @@
all: ALWAYS
@$(MAKE) -s -C .. bgpd/bgpd
%: ALWAYS
@$(MAKE) -s -C .. bgpd/$@
Makefile:
#nothing
ALWAYS:
.PHONY: ALWAYS makefiles
.SUFFIXES:

View File

@ -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

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -24,8 +24,6 @@
/* TBD remove unneeded includes */
#include <errno.h>
#include "lib/zebra.h"
#include "lib/prefix.h"
#include "lib/agg_table.h"

View File

@ -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"

View File

@ -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"

View 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:

View File

@ -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)

View File

@ -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"

View 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

View 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:

View File

@ -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 =

View File

@ -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>

View 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
View 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

View File

@ -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

View File

@ -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])
])
AC_LANG_POP(C)
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"
])
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
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

View File

@ -1,5 +1,3 @@
AUTHORS
NEWS
README
README.md
doc/user/*.rst
doc/figures/*.png

6
doc/.gitignore vendored
View File

@ -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

View File

@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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

View 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

View File

@ -450,8 +450,6 @@ is no ordering requirement)
.. code-block:: make
include ../common.am
# ...
# if linked into a LTLIBRARY (.la/.so):

View File

@ -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.

View File

@ -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
View 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

View File

@ -10,6 +10,7 @@
bgpd
eigrpd
isisd
fabricd
ldpd
nhrpd
ospf6d

View File

@ -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
View File

@ -1,5 +0,0 @@
.arch-ids
.arch-inventory
*~
*.loT

404
doc/user/fabricd.rst Normal file
View 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

View File

@ -42,6 +42,7 @@ Protocols
bfd
bgp
babeld
fabricd
ldpd
eigrpd
isisd

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -1,18 +1,2 @@
!Makefile
Makefile.in
*.o
*.a
eigrpd
eigrpd.conf
tags
TAGS
.deps
.nfs*
*.lo
*.la
*.libs
.arch-inventory
.arch-ids
*~
*.loT

View File

@ -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"

View File

@ -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
View File

@ -1,15 +0,0 @@
!Makefile
Makefile.in
*.o
tags
TAGS
.deps
.nfs*
*.lo
*.la
*.a
*.libs
.arch-inventory
.arch-ids
*~
*.loT

View File

@ -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
View File

@ -1,6 +0,0 @@
Makefile
Makefile.in
.nfs*
*~
*.loT

14
isisd/.gitignore vendored
View File

@ -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
View 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
View 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
View 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

View File

@ -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);

View File

@ -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);

View File

@ -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) {
for (dnode = dict_first(area->lspdb[level - 1]);
dnode != NULL; dnode = dnode_next) {
dnode_next = dict_next(
area->lspdb[level - 1], dnode);
lsp = dnode_get(dnode);
if (is_set) {
ISIS_SET_FLAG(lsp->SRMflags,
circuit);
} else {
ISIS_CLEAR_FLAG(lsp->SRMflags,
circuit);
}
}
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 = dict_next(area->lspdb[level - 1], dnode)) {
lsp = dnode_get(dnode);
if (is_set) {
isis_tx_queue_add(circuit->tx_queue, lsp,
TX_LSP_NORMAL);
} else {
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,33 +950,35 @@ 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 (circuit->is_type == IS_LEVEL_1) {
vty_out(vty, " isis circuit-type level-1\n");
write++;
} else {
if (circuit->is_type == IS_LEVEL_2) {
vty_out(vty,
" isis circuit-type level-2-only\n");
if (!fabricd) {
if (circuit->is_type == IS_LEVEL_1) {
vty_out(vty, " " PROTO_NAME " circuit-type level-1\n");
write++;
} else {
if (circuit->is_type == IS_LEVEL_2) {
vty_out(vty,
" " PROTO_NAME " circuit-type level-2-only\n");
write++;
}
}
}
@ -992,7 +987,7 @@ int isis_interface_config_write(struct vty *vty)
== 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;
}

View File

@ -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 */

View File

@ -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;
}
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);
if (fabricd_init_c) {
fabricd_sync_incomplete |=
ISIS_CHECK_FLAG(lsp->SSNflags,
fabricd_init_c);
}
}
}
}
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);
struct list *circuit_list = lsp->area->circuit_list;
for (ALL_LIST_ELEMENTS_RO(circuit_list, node, 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);
}
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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();

View File

@ -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++;
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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,7 +629,10 @@ DEFUN (no_isis_redistribute,
if (type < 0)
return CMD_WARNING_CONFIG_FAILED;
level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
if (fabricd)
level = 2;
else
level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
isis_redist_unset(area, level, family, type);
return 0;
@ -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,7 +674,10 @@ DEFUN (isis_default_originate,
if (family < 0)
return CMD_WARNING_CONFIG_FAILED;
level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
if (fabricd)
level = 2;
else
level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2;
if ((area->is_type & level) != level) {
vty_out(vty, "Node is not a level-%d IS\n", 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);
}

View File

@ -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,46 +178,28 @@ 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();
if (spftree->hopcount_metric) {
vertex->firsthops = hash_create(isis_vertex_queue_hash_key,
isis_vertex_queue_hash_cmp,
NULL);
}
return vertex;
}
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;
}
static void isis_vertex_adj_del(struct isis_vertex *vertex,
struct isis_adjacency *adj)
{
@ -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");
}

View File

@ -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
View 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

View File

@ -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;
}

View File

@ -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));
}
}

View File

@ -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
View 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);
}

View File

@ -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

File diff suppressed because it is too large Load Diff

960
isisd/isis_vty_common.c Normal file
View 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
View 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
View 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
View 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);
}

View File

@ -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;

View File

@ -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,16 +1920,18 @@ int isis_config_write(struct vty *vty)
write++;
}
/* ISIS - Metric-Style - when true displays wide */
if (area->newmetric) {
if (!area->oldmetric)
vty_out(vty, " metric-style wide\n");
else
vty_out(vty,
" metric-style transition\n");
write++;
} else {
vty_out(vty, " metric-style narrow\n");
write++;
if (!fabricd) {
if (area->newmetric) {
if (!area->oldmetric)
vty_out(vty, " metric-style wide\n");
else
vty_out(vty,
" metric-style transition\n");
write++;
} else {
vty_out(vty, " metric-style narrow\n");
write++;
}
}
/* ISIS - overload-bit */
if (area->overload_bit) {
@ -1910,12 +1939,14 @@ int isis_config_write(struct vty *vty)
write++;
}
/* ISIS - Area is-type (level-1-2 is default) */
if (area->is_type == IS_LEVEL_1) {
vty_out(vty, " is-type level-1\n");
write++;
} else if (area->is_type == IS_LEVEL_2) {
vty_out(vty, " is-type level-2-only\n");
write++;
if (!fabricd) {
if (area->is_type == IS_LEVEL_1) {
vty_out(vty, " is-type level-1\n");
write++;
} else if (area->is_type == IS_LEVEL_2) {
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);
@ -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();
}

View File

@ -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 { \

View File

@ -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