]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #2985 from patrasar/Fix_1636
authorDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 11 Sep 2018 13:16:24 +0000 (09:16 -0400)
committerGitHub <noreply@github.com>
Tue, 11 Sep 2018 13:16:24 +0000 (09:16 -0400)
pimd: create a new command "ip pim" configuring pim sm

251 files changed:
.gitignore
AUTHORS [deleted file]
ChangeLog [deleted file]
Makefile.am
NEWS [deleted file]
README [deleted file]
README.md [new file with mode: 0644]
babeld/babel_filter.c
babeld/kernel.c
babeld/neighbour.c
babeld/net.c
babeld/resend.c
babeld/source.c
babeld/subdir.am
babeld/util.c
bfdd/.gitignore
bfdd/bfd.c
bfdd/bfd.h
bfdd/bfd_packet.c
bfdd/bfdctl.h
bfdd/bfdd.c
bfdd/bfdd_vty.c
bfdd/bsd.c
bfdd/config.c
bfdd/event.c
bfdd/linux.c
bfdd/ptm_adapter.c
bfdd/subdir.am
bgpd/.gitignore
bgpd/Makefile [new file with mode: 0644]
bgpd/Makefile.am [deleted file]
bgpd/bgp_flowspec.c
bgpd/bgp_route.c
bgpd/bgp_rpki.c
bgpd/rfapi/rfapi.c
bgpd/rfapi/rfapi_ap.c
bgpd/rfapi/rfapi_descriptor_rfp_utils.c
bgpd/rfapi/rfapi_import.c
bgpd/rfapi/rfapi_monitor.c
bgpd/rfapi/rfapi_rib.c
bgpd/rfapi/rfapi_vty.c
bgpd/rfp-example/librfp/Makefile [new file with mode: 0644]
bgpd/rfp-example/librfp/Makefile.am [deleted file]
bgpd/rfp-example/librfp/rfp_example.c
bgpd/rfp-example/librfp/subdir.am [new file with mode: 0644]
bgpd/rfp-example/rfptest/Makefile [new file with mode: 0644]
bgpd/rfp-example/rfptest/Makefile.am [deleted file]
bgpd/rfp-example/rfptest/rfptest.c
bgpd/rfp-example/rfptest/subdir.am [new file with mode: 0644]
bgpd/subdir.am [new file with mode: 0644]
common.am [deleted file]
configure.ac
debianpkg/frr-doc.docs
doc/.gitignore
doc/developer/building-frr-for-centos6.rst
doc/developer/building-frr-for-centos7.rst
doc/developer/building-frr-for-fedora24.rst
doc/developer/cli.rst
doc/manpages/common-options.rst
doc/manpages/conf.py
doc/manpages/fabricd.rst [new file with mode: 0644]
doc/manpages/index.rst
doc/manpages/subdir.am
doc/mpls/.gitignore [deleted file]
doc/user/fabricd.rst [new file with mode: 0644]
doc/user/index.rst
doc/user/installation.rst
doc/user/isisd.rst
doc/user/setup.rst
doc/user/sharp.rst
doc/user/subdir.am
eigrpd/.gitignore
eigrpd/eigrp_fsm.c
eigrpd/eigrp_vty.c
eigrpd/subdir.am
fpm/.gitignore [deleted file]
fpm/subdir.am
init/.gitignore [deleted file]
isisd/.gitignore
isisd/fabricd.c [new file with mode: 0644]
isisd/fabricd.conf.sample [new file with mode: 0644]
isisd/fabricd.h [new file with mode: 0644]
isisd/isis_adjacency.c
isisd/isis_bpf.c
isisd/isis_circuit.c
isisd/isis_circuit.h
isisd/isis_lsp.c
isisd/isis_lsp.h
isisd/isis_lsp_hash.c [deleted file]
isisd/isis_lsp_hash.h [deleted file]
isisd/isis_main.c
isisd/isis_mt.c
isisd/isis_pdu.c
isisd/isis_pdu.h
isisd/isis_redist.c
isisd/isis_spf.c
isisd/isis_spf.h
isisd/isis_spf_private.h [new file with mode: 0644]
isisd/isis_te.c
isisd/isis_tlvs.c
isisd/isis_tlvs.h
isisd/isis_tx_queue.c [new file with mode: 0644]
isisd/isis_tx_queue.h [new file with mode: 0644]
isisd/isis_vty.c [deleted file]
isisd/isis_vty_common.c [new file with mode: 0644]
isisd/isis_vty_common.h [new file with mode: 0644]
isisd/isis_vty_fabricd.c [new file with mode: 0644]
isisd/isis_vty_isisd.c [new file with mode: 0644]
isisd/isis_zebra.c
isisd/isisd.c
isisd/isisd.h
isisd/subdir.am
ldpd/.gitignore
ldpd/lde.c
ldpd/pfkey.c
ldpd/subdir.am
lib/.gitignore
lib/command.c
lib/command.h
lib/command_lex.l
lib/csv.c
lib/defun_lex.l
lib/ferr.c
lib/frr_pthread.c
lib/frr_pthread.h
lib/frrstr.c
lib/grammar_sandbox.c
lib/grammar_sandbox_main.c
lib/hook.c
lib/if.c
lib/imsg-buffer.c
lib/imsg.c
lib/lib_errors.c
lib/log.c
lib/memory.c
lib/memory_vty.c
lib/openbsd-tree.c
lib/ptm_lib.c
lib/queue.h
lib/route_types.txt
lib/skiplist.c
lib/stream.c
lib/strlcat.c
lib/strlcpy.c
lib/subdir.am
lib/vty.c
lib/zebra.h
m4/.gitignore
m4/pkg.m4
nhrpd/.gitignore
nhrpd/linux.c
nhrpd/netlink_arp.c
nhrpd/netlink_gre.c
nhrpd/nhrp_event.c
nhrpd/nhrp_interface.c
nhrpd/nhrp_main.c
nhrpd/nhrp_packet.c
nhrpd/nhrp_peer.c
nhrpd/nhrp_route.c
nhrpd/nhrp_shortcut.c
nhrpd/resolver.c
nhrpd/subdir.am
nhrpd/vici.c
nhrpd/zbuf.c
nhrpd/znl.c
ospf6d/.gitignore
ospf6d/ospf6_asbr.c
ospf6d/ospf6_lsa.c
ospf6d/ospf6_lsa.h
ospf6d/ospf6_neighbor.c
ospf6d/ospf6_route.c
ospf6d/ospf6_top.c
ospf6d/subdir.am
ospfclient/.gitignore
ospfclient/subdir.am
ospfd/.gitignore
ospfd/ospf_snmp.c
ospfd/ospf_sr.c
ospfd/subdir.am
pbrd/.gitignore
pbrd/subdir.am
pimd/.gitignore
pimd/mtracebis.c
pimd/mtracebis_netlink.c
pimd/mtracebis_routeget.c
pimd/pim_igmp_mtrace.c
pimd/pim_igmp_stats.c
pimd/subdir.am
pkgsrc/.gitignore
ports/.gitignore [deleted file]
ports/files/.gitignore [deleted file]
ports/pkg/.gitignore [deleted file]
python/clidef.py
qpb/.gitignore [deleted file]
qpb/qpb_allocator.c
qpb/subdir.am
redhat/.gitignore
redhat/README.rpm_build.md
redhat/daemons
redhat/frr.init
redhat/frr.logrotate
redhat/frr.spec.in
ripd/.gitignore
ripd/subdir.am
ripngd/.gitignore
ripngd/subdir.am
sharpd/.gitignore
sharpd/sharp_vty.c
sharpd/sharp_zebra.c
sharpd/subdir.am
snapcraft/.gitignore
solaris/.gitignore
staticd/static_vty.c
staticd/subdir.am
tests/.gitignore
tests/Makefile [new file with mode: 0644]
tests/Makefile.am [deleted file]
tests/helpers/python/frrtest.py
tests/isisd/test_fuzz_isis_tlv.c
tests/isisd/test_fuzz_isis_tlv_tests.h.gz
tests/isisd/test_isis_vertex_queue.c
tests/lib/cli/test_cli.c
tests/lib/cli/test_cli.py
tests/ospf6d/test_lsdb.c
tests/subdir.am [new file with mode: 0644]
tests/test_lblmgr.c
tools/.gitignore
tools/etc/iproute2/rt_protos.d/frr.conf
tools/frr
tools/permutations.c
tools/start-stop-daemon.c
vtysh/.gitignore
vtysh/Makefile [new file with mode: 0644]
vtysh/Makefile.am [deleted file]
vtysh/extract.pl.in
vtysh/subdir.am [new file with mode: 0644]
vtysh/vtysh.c
vtysh/vtysh.h
vtysh/vtysh_config.c
vtysh/vtysh_main.c
watchfrr/.gitignore
watchfrr/subdir.am
zebra/.gitignore
zebra/if_ioctl_solaris.c
zebra/rt_netlink.c
zebra/rt_netlink.h
zebra/rtread_getmsg.c
zebra/subdir.am
zebra/zebra_fpm_protobuf.c
zebra/zebra_rib.c
zebra/zebra_vxlan.c

index c5fd0ced9b34a10e1ccaac706ca5a8321ea383ef..8c62f05539e483d457055b83567920e575f12843 100644 (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
+.libs
+
+### build outputs
+
+*.o
+*.lo
+*.a
+*.la
+*.so
+*.loT
+*.pb.h
+*.pb-c.h
+*.pb-c.c
+*_clippy.c
+
+### dist
+
 *.tar.?z
+*.tar.?z.asc
+*.tar.asc
+*.deb
+*.ddeb
+*.dsc
+*.changes
+
+### other garbage
+
 .nfs*
-libtool
-.libs
 .arch-inventory
 .arch-ids
 {arch}
 build
+.cache
 .msg
 .rebase-*
 *~
-*.o
-*.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/
-*.deb
-*.ddeb
-*.dsc
-*.changes
-*.pyc
+*.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
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644 (file)
index 61867a8..0000000
--- a/AUTHORS
+++ /dev/null
@@ -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>
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644 (file)
index ec7e6cd..0000000
--- a/ChangeLog
+++ /dev/null
@@ -1,4 +0,0 @@
-ChangeLog information for FRRouting is for now recorded in source-code
-management system. Please see:
-
-       http://www.frrouting.org/
index b9003b8358474f23b14a9f01336fe5cf2c9227ed..fb052a8dea721ae605f48d4b847e63b08c9857e3 100644 (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:
diff --git a/NEWS b/NEWS
deleted file mode 100644 (file)
index 8f9dd7a..0000000
--- a/NEWS
+++ /dev/null
@@ -1,2574 +0,0 @@
-Note: this file lists major user-visible changes only.
-
-* Changes in Quagga 0.99.24
-
-User-visible changes:
-- [pimd] New daemon: pimd provides IPv4 PIM-SSM multicast routing.
-- [bgpd] New feature: "next-hop-self all" to override nexthop on iBGP route
-    reflector setups.
-- [bgpd] route-maps have a new action "set ipv6 next-hop peer-address"
-- [bgpd] route-maps have a new action "set as-path prepend last-as"
-- [bgpd] Update validity checking (particularly MP-BGP / IPv6 routes) was
-    touched up significantly.  Please report possible bugs.
-- [ripd] New feature: RIP for IPv4 now supports equal-cost multipath (ECMP)
-- [zebra] Multicast RIB support has been extended.  It still is IPv4 only.
-- [zebra] "no link-detect" is now printed in configurations since it won't
-    be the default anymore soon.  To retain current behaviour, re-save your
-    configuration after updating to 0.99.24.
-
-Distributor-visible changes:
-- --enable-pimd is added to enable pimd.  It is considered experimental, though
-    unless the distribution target is embedded systems with little flash, there
-    is no reason to not include it in packages.
-- --disable-ipv6 no longer exists as an option.  It's 2015, your C library
-    really needs to have IPv6 support by now.
-- --disable-netlink no longer exists as an option.  It didn't work anyway.
-- --disable-solaris no longer exists as an option.  It only controlled some
-    init scripts.
-- --enable-isisd is now the default.
-- mrlg.cgi is no longer included (it was severely outdated).  It can be found
-    independently at http://mrlg.op-sec.us/
-- build on Linux with the musl C library should now work
-
-* Changes in Quagga 0.99.23
-
-Known issues:
-- [bgpd] setting an extcommunity in a route map on a route that already has
-  an extcommunity attribute will cause bgpd to crash.  This issue will be
-  fixed in a followup minor release.
-
-User-visible changes:
-- [lib] Performance enhancements on hashes and timers.
-- [bgpd] New feature: iBGP TTL security.
-- [bgpd] New feature: relaxed bestpath criteria for multipath and improved
-  display of multipath routes in "show ip bgp".  Scripts parsing this output
-  may need to be updated.
-- [bgpd] Multiprotocol peerings over IPv6 now try to find a more appropriate
-  IPv4 nexthop by looking at the interface.
-- [ospf6d] A large amount of changes has been merged for ospf6d.  Careful
-  evaluation prior to deployment is recommended.
-- [zebra] Recursive route support has been overhauled.  Scripts parsing
-  "show ip route" output may need adaptation.
-- [zebra] IPv6 address management has been improved regarding tentative
-  addresses.  This is visible in that a freshly configured address will not
-  immediately be marked as usable.
-- [*] a lot of bugs have been fixed, please refer to the git log
-
-* Changes in Quagga 0.99.22
-
-- [bgpd] The semantics of default-originate route-map have changed.
-  The route-map is now used to advertise the default route conditionally.
-  The old behaviour which allowed to set attributes on the originated
-  default route is no longer supported.
-- [bgpd] There is now a replace-as option to neighbor ... local-as ...
-  no-prepend.  For details, refer to the user documentation.
-- [zebra] An FPM interface has been added.  This provides an alternate
-  interface to routing information and is geared at OpenFlow & co.
-- [snmp] AgentX is now supported;  the old smux backend is considered
-  deprecated.  ospf6d has also had OSPFV3-MIB added.
-- [*] several issues with configuration save/load/apply have been fixed,
-  in particular on ospf "max-metric router-lsa administrative" and
-  "distribute-list", bgpd "no neighbor activate", isisd "metric-style",
-- [*] a lot of bugs have been fixed, please refer to the git log
-
-* Changes in Quagga 0.99.21
-
-- [bgpd] BGP multipath support has been merged
-- [bgpd] SAFI (Multicast topology) support has been extended to propagate
-  the topology to zebra.
-- [bgpd] AS path limit functionality has been removed
-- [babeld] a new routing daemon implementing the BABEL ad-hoc mesh routing
-  protocol has been merged.
-- [isisd] a major overhaul has been picked up. Please note that isisd is
-  STILL NOT SUITABLE FOR PRODUCTION USE.
-- [*] a lot of bugs have been fixed, please refer to the git log
-
-* Changes in Quagga 0.99.10
-
-- [bgpd] 4-byte AS support added
-- [bgpd] MRT format changes to version 2. Those relying on
-  bgpd MRT table dumps may need to update their tools.
-- [bgpd] Added new route-map set statement: "as-path exclude"
-- Zebra RIB updates queue has evolved into a multi-level
-  structure to address RIB consistency issues.
-
-* Changes in Quagga 0.99.2
-
-- [bgpd] Work queues added to bgpd to split up update processing,
-  particularly beneficial when a peer session goes down. AS_PATH
-  parsing rewritten to be clearer, more robust and ready for 4-byte.
-
-- [ripd] Simple authentication is no longer the default authentication
-  mode for ripd. The default is now no-authentication. Any setups which
-  used simple authentication will probably need to update their
-  configuration manually.
-
-- [ospfd] 1s dead-interval with sub-second Hellos feature added.
-  SPF timers now specified in milliseconds, and with adaptive
-  hold-time support. RFC3137 Stub-router support added. Default ABR
-  type is now 'cisco'.
-
-- Solaris least privileges support added.
-
-* Changes in Quagga 0.99.1
-
-- Zserv is now buffered via threads and non-blocking in most cases for both
-  clients and zebra, which should improve responsiveness of daemons when
-  they must send many messages to zebra.
-
-- 'show thread cpu' now displays both cpu+system and wall-clock time,
-  where getrusage() is available.
-
-- Background threads added and workqueue API added, with a
-  'show work-queues' command. Thread scheduling improved slightly.
-
-- Zebra now has a work-queue for RIB processing. See 'show work-queues' in
-  the zebra daemon vty.
-
-- Support for interface renaming on Linux netlink systems.
-
-- GNU Zebra bgpd merges, including BGP Graceful-restart and "match ip
-  route-source" command.
-
-- Automatic logging of backtraces should daemons crash to assist in
-  diagnosis. See the documentation for more information on configuring
-  logging correctly, and set --enable-gcc-rdynamic if compiling with gcc.
-
-* Changes in Quagga 0.98.0
-
-- Logging facilities upgraded.  One can now specify a severity level
-  for each logging destination.  And a new "show logging" command gives
-  thorough information on the current logging system configuration.
-
-- Watchquagga daemon added.  This is not well tested yet.  Please try
-  monitor mode first before enabling restart features.  It is important
-  to make sure that the various timers are configured with appropriate
-  values for your site.
-
-- BGP route-server support added. See the texinfo documentation.
-
-- OSPF API initialisation is disabled by default even if compiled in. You
-  can enable it with -a/--apiserver command line switch.
-
-- "write-config integrated" vtysh command replaced with "service
-  integrated-vtysh-config" command.
-
-- Router id is now handled by zebra daemon and all daemons receive changes
-  from it. Router id can be overriden in daemons' configurations of course.
-  To fix common router id in zebra daemon you can either install non-127
-  address on loopback or use "router-id x.x.x.x" command.
-
-- "secondary" keyword is removed from ip address configuration. All
-  supported OS'es have their own vision what's secondary address and
-  how to handle it.
-
-- Zebra no longer enables forwarding by default. If you rely on zebra to
-  enable forwarding make sure to add '<ip|ip6> forwarding' statements
-  to your zebra configuration file.
-
-- All libraries are built and used shared, on platforms where libtool
-  supports shared libraries.
-
-- Router advertisement syntax is changed. In usual cases (if you didn't do
-  any fancy stuff) it's enough to change lines in configuration from:
-  "ipv6 nd prefix-advertisement X:X:X:X::/X 2592000 604800 autoconfig on-link"
-  to:
-  "ipv6 nd prefix X:X:X:X::/X"
-
-  All router advertisement options are documented in texi documentation.
-
-- --enable-nssa configure switch is removed. NSSA support is stable enough.
-
-- Daemons don't look at current directory for config file any more.
-
-* Changes in Quagga 0.96.5
-
-- include files are installed in $(prefix)/include/quagga.  Programs
-  building against these includes should -I$(prefix)/include and e.g.
-  #include <quagga/routemap.h>
-
-- New option --enable-exampledir puts example files in a separate
-  directory from $(sysconfdir), easing NetBSD pkgsrc hierarchy rules
-  compliance.
-
-- New configure options --enable-configfile-mask and
-  --enable-logfile-mask to set umask values for config and log
-  values.  Masks default to 0600, matching previous behavior.
-
-- Import current CVS isisd from SourceForge, then merge it with
-  the Quagga's Framework.
-
-* Changes in Quagga 0.96.4
-
-- Further fixes to ospfd, some relating to the PtP revert. Interface
-lookups should be a lot more robust now. 
-
-- Fix for a remote triggerable crash in vty layer.
-
-- Improvements to ripd, and addition of split horizon support.
-
-- Improved bgpd table support, now dumps at time of day intervals rather
-than time from startup intervals. Much improved support for IPv6 table
-dumps. show commands for views improved.
-
-* Changes in Quagga 0.96.3
-
-- revert the 'generic PtP' patch. Means Quagga will no longer work with
-FreeSWAN, however, on the plus side this gets rid of a lot of niggly bugs
-which the PtP patch introduced.
-
-* Changes in Quagga 0.96.2
-
-- Fix crash in ospfd
-
-* Changes in Quagga 0.96.1
-
-- Iron out problem with the privileges definitions
-
-* Changes in Quagga 0.96
-
-- Privilege support, daemons now run with the minimal privileges needed, see
-  the documentation for details.
-  
-- NSSA ABR support in ospfd.
-
-- OSPF-API support merged in.
-
-- 6WIND patch merged in.
-
-* Changes in zebra-0.93
-
-* Changes in bgpd
-
-** Configuration is changed to new format.
-
-* Changes in ospfd
-
-** Crush bugs which reported on Zebra ML is fixed.
-
-** Opaque LSA and TE LSA support is added by KDD R&D Laboratories,
-   Inc.
-
-* Chages in ospf6d
-
-** Many bugs are fixed.
-
-* Changes in zebra-0.92a
-
-* Changes in bgpd
-
-** Fix "^$" community list bug.
-
-** Below command's Address Family specific configurations are added
-
-  nexthop-self
-  route-reflector-client
-  route-server-client
-  soft-reconfiguration inbound
-
-* Changes in zebra
-
-** Treat kernel type routes as EGP routes.
-
-* Changes in zebra-0.92
-
-** Overall security is improved.  Default umask is 0077.
-
-* Changes in ripd
-
-** If output interface is in simple password authentication mode,
-substruct one from rtemax.
-
-* Changes in bgpd
-
-** IPv4 multicast and IPv6 unicast configuration is changed to so
-called new config.  All of AFI and SAFI specific configuration is
-moved to "address-family" node.  When you have many IPv6 only
-configuration, you will see many "no neighbor X:X::X:X activate" line
-in your configuration to disable IPv4 unicast NLRI exchange.  In that
-case please use "no bgp default ipv4-unicast" command to suppress the
-output.  Until zebra-0.93, old config is still left for compatibility.
-
-Old config
-==========
-router bgp 7675
- bgp router-id 10.0.0.1
- redistribute connected
- network 192.168.0.0/24
- neighbor 10.0.0.2 remote-as 7675
- ipv6 bgp network 3ffe:506::/33
- ipv6 bgp network 3ffe:1800:e800::/40
- ipv6 bgp aggregate-address 3ffe:506::/32
- ipv6 bgp redistribute connected
- ipv6 bgp neighbor 3ffe:506:1000::2 remote-as 1
-
-New config
-==========
-router bgp 7675
- bgp router-id 10.0.0.1
- network 192.168.0.0/24
- redistribute connected
- neighbor 10.0.0.2 remote-as 7675
- neighbor 3ffe:506:1000::2 remote-as 1
- no neighbor 3ffe:506:1000::2 activate
-!
- address-family ipv6
-  network 3ffe:506::/33
-  network 3ffe:1800:e800::/40
-  aggregate-address 3ffe:506::/32
-  redistribute connected
-  neighbor 3ffe:506:1000::2 activate
- exit-address-family
-
-* Changes in ospfd
-
-** Internal interface treatment is changed.  Now ospfd can handle
-multiple IP address for an interface.
-
-** Redistribution of loopback interface's address works fine.
-
-* Changes in zebra-0.91
-
-** --enable-oldrib configure option is removed.
-
-** HAVE_IF_PSEUDO part is removed.  Same feature is now supported by
-default.
-
-* Changes in ripd
-
-** When redistributed route is withdrawn, perform poisoned reverse.
-
-* Changes in zebra
-
-** When interface's address is removed, kernel route pointing out to
-the address is removed.
-
-** IPv6 RIB is now based upon new RIB code.
-
-** zebra can handle same connected route to one interface.
-
-** New command for interface address.  Currently this commands are
-only supported on GNU/Linux with netlink interface.
-
-"ip address A.B.C.D secondary"
-"ip address A.B.C.D label LABEL"
-
-* Changes in bgpd
-
-** BGP flap dampening bugs are fixed.
-
-** BGP non-blocking TCP connection bug is fixed.
-
-** "show ip bgp summary" shows AS path and community entry number.
-
-** New commands have been added.
-  "show ip bgp cidr-only"
-  "show ip bgp ipv4 (unicast|multicast) cidr-only"
-  "show ip bgp A.B.C.D/M longer-prefixes"
-  "show ip bgp ipv4 (unicast|multicast) A.B.C.D/M longer-prefixes"
-  "show ipv6 bgp X:X::X:X/M longer-prefixes"
-  "show ipv6 mbgp X:X::X:X/M longer-prefixes"
-
-** IPv6 IBGP nexthop change is monitored.
-
-** Unknown transitive attribute is passed with partial flag bit on.
-
-* Changes in ospfd
-
-** Fix bug of LSA MaxAge flood.
-
-** Fix bug of NSSA codes.
-
-* Changes in zebra-0.90
-
-** From this beta release, --enable-unixdomain and --enable-newrib
-becomes default.  So both options are removed from configure.in.  To
-revert old behavior please specify below option.
-
---enable-tcp-zebra # TCP/IP socket is used for protocol daemon and zebra.
---enable-oldrib    # Turn on old RIB implementation.
-
-Old RIB implementation will be removed in zebra-0.91.
-
-** From this beta release --enable-multipath is supported.  This
-option is only effective on GNU/Linux kernel with
-CONFIG_IP_ADVANCED_ROUTER and CONFIG_IP_ROUTE_MULTIPATH is set.
-
---enable-multipath=ARG  # ARG must be digit.  When ARG is 0 unlimit multipath number.
-
-** From this release we do not include guile files.
-
-* Changes in lib
-
-** newlist.[ch] is merged with linklist.[ch].
-
-** Now Zebra works on MacOS X public beta.
-
-** Access-list can have remark.  "access-list WORD remark LINE" define
-remark for specified access-list.
-
-** Key of key-chain is sorted by it's idetifier value.
-
-** prefix-list rule is slightly changed.  The rule of "len <= ge-value
-<= le-value" is changed to "len < ge-value <= le-value".
-
-** According to above prefix-list rule change, add automatic
-conversion function of an old rule. ex.) 10.0.0.0/8 ge 8 -> 10.0.0.0/8
-le 32
-
-** SMUX can handle SNMP trap.
-
-** In our event library, event thread is executed before any other
-thread like timer, read and write event.
-
-** Robust method for writing configuration file and recover from
-backing up config file.
-
-** Display "end" at the end of configuration.
-
-** Fix memory leak in vtysh_read().
-
-** Fix memroy leak about access-list and prefix-list name.
-
-* Changes in zebra
-
-** UNIX domain socket server of zebra protocol is added.
-
-** Fix PointoPoint interface network bug.  The destination network
-should be installed into routing table instead of local network.
-
-** Metric value is reflected to kernel routing table.
-
-** "show ip route" display uptime of RIP,OSPF,BGP routes.
-
-** New RIB implementation is added.
-
-Now we have enhanced RIB (routing information base) implementation in
-zebra.  New RIB has many new features and fixed some bugs which exist
-in old RIB code.
-
-*** Static route with distance value
-
-    Static route can be specified with administrative distance.  The
-  distance value 255 means it is not installed into the kernel.
-  Default value of distance for static route is 1.
-  
-    ip route A.B.C.D/M A.B.C.D <1-255>
-    ip route A.B.C.D/M IFNAME <1-255>
-  
-    If the least distance value's route's nexthop are unreachable,
-  select the least distance value route which has reachable nexthop is
-  selected.
-  
-    ip route 0.0.0.0/0 10.0.0.1
-    ip route 0.0.0.0/0 11.0.0.1 2
-  
-    In this case, when 10.0.0.1 is unreachable and 11.0.0.1 is
-  reachable.  The route with nexthop 11.0.0.1 will be installed into
-  forwarding table.
-  
-    zebra> show ip route
-    S>* 0.0.0.0/0 [2/0] via 11.0.0.1
-    S   0.0.0.0/0 [1/0] via 10.0.0.1 inactive
-  
-    If the nexthop is unreachable "inactive" is displayed.  You can
-  specify any string to IFNAME.  There is no need of the interface is
-  there when you configure the route.
-  
-    ip route 1.1.1.1/32 ppp0
-  
-  When ppp0 comes up, the route is installed properly.
-
-*** Multiple nexthop routes for one prefix
-
-    Multiple nexthop routes can be specified for one prefix.  Even the
-  kernel support only one nexthop for one prefix user can configure
-  multiple nexthop.
-  
-    When you configure routes like below, prefix 10.0.0.1 has three
-  nexthop.
-  
-    ip route 10.0.0.1/32 10.0.0.2
-    ip route 10.0.0.1/32 10.0.0.3
-    ip route 10.0.0.1/32 eth0
-  
-    If there is no route to 10.0.0.2 and 10.0.0.3.  And interface eth0
-    is reachable, then the last route is installed into the kernel.
-  
-    zebra> show ip route
-    S>  10.0.0.1/32 [1/0] via 10.0.0.2 inactive
-                          via 10.0.0.3 inactive
-      *                   is directly connected, eth0
-  
-    '*' means this nexthop is installed into the kernel. 
-
-*** Multipath (more than one nexthop for one prefix) can be installed into the kernel.
-
-    When the kernel support multipath, zebra can install multipath
-  routes into the kernel.  Before doing that please make it sure that
-  setting --enable-multipath=ARG to configure script.  ARG must be digit
-  value.  When specify 0 to ARG, there is no limitation of the number
-  of the multipath.  Currently only GNU/Linux with netlink interface is
-  supported.
-  
-    ip route 10.0.0.1/32 10.0.0.2
-    ip route 10.0.0.1/32 10.0.0.3
-    ip route 10.0.0.1/32 eth0
-  
-    zebra> show ip route
-    S>* 10.0.0.1/32 [1/0] via 10.0.0.2
-      *                   via 10.0.0.3
-                          is directly connected, eth0
-
-*** Kernel message delete installed route.
-
-    After zebra install static or dynamic route into the kernel.
-  
-    R>* 0.0.0.0/0 [120/3] via 10.0.0.1
-  
-    If you delete this route outside zebra, old zebra does not reinstall
-  route again.  Now the route is re-processed and properly reinstall the
-  static or dynamic route into the kernel.
-
-** GNU/Linux netlink socket handling is improved to fix race condition
-between kernel message and user command responce.
-
-* Changes in bgpd
-
-** Add show neighbor's routes command.
-
-  "show ip bgp neighbors (A.B.C.D|X:X::X:X) routes"
-  "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) routes"
-  "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) routes"
-  "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) routes"
-
-** BGP passive peer support problem is fixed.
-
-** Redistributed IGP nexthop is passed to BGP nexthop.
-
-** On multiaccess media, if the nexthop is reachable nexthop is passed
-as it is.
-
-** Remove zebra-0.88 compatibility commands.
-
-  "match ip prefix-list WORD"
-  "match ipv6 prefix-list WORD"
-
-  Instead of above please use below commands.
-
-  "match ip address prefix-list WORD"
-  "match ipv6 address prefix-list WORD"
-
-** Fix bug of holdtimer is not reset when bgp cleared.
-
-** "show ip bgp summary" display peer establish/drop count.
-
-** Change "match ip next-hop" argument from IP address to access-list
-name.
-
-** When "bgp enforce-first-as" is enabled, check EBGP peer's update
-has it's AS number in the first AS number in AS sequence.
-
-** New route-map command "set community-delete COMMUNITY-LIST" is
-added.  Community matched the CoMMUNITY-LIST is removed from the
-community.
-
-** BGP-MIB implementation is finished.
-
-** When BGP connection comes from unconfigured IP address, close
-socket immediately.
-
-** Do not compare router ID when the routes comes from EBGP peer.
-When originator ID is same, take shorter cluster-list route.  If
-cluster-list is same take smaller IP address neighbor's route.
-
-** Add "bgp bestpath as-path ignore" command.  When this option is
-set, do not concider AS path length when route selection.
-
-** Add "bgp bestpath compare-routerid".  When this option is set,
-compare router ID when the routes comes from EBGP peer.
-
-** Add "bgp deterministic-med" process.
-
-** BGP flap dampening feature is added.
-
-** When IBGP nexthop is changed, it is reflected to RIB.
-
-** Change "neighbor route-refresh" command to "neighbor capability
-route-refresh".
-
-* Changes in ripd
-
-** Change "match ip next-hop" argument from IP address to access-list
-name.
-
-** "no ip rip (send|receive)" command accept version number argument.
-
-** Memory leak related classfull network generation is fixed.
-
-** When a route is in garbage collection process (invalid with metric
-16) and a router receives the same route with valid metric then route
-was not installed into zebra rib, but only into ripd rib. Moreover ,
-it will never get into zebra rib, because ripd wrongly assumes it's
-already there.
-
-* Change in ospfd
-
-** Fix bug of refreshing default route.
-
-** --enable-nssa turn on undergoing NSSA feature.
-
-** Fix bug of Hello packet's option is not properly set when interface
-comes up.
-
-** Reduce unconditional logging.
-
-** Add nexthop to OSPF path only when it is not there.
-
-** When there is no DR on network (suppose you have only one router
-with interface priority 0). It's router LSA does not contain the link
-information about this network.
-
-** When you change a priority of interface from/to 0
-ISM_NeighborChange event should be scheduled in order to elect new
-DR/BDR on the network.
-
-** When we add some LSA into retransmit list we need to check whether
-the present old LSA in retransmit list is not more recent than the new
-one.
-
-** In states Loading and Full the slave must resend its last Database
-Description packet in response to duplicate Database Description
-packets received from the master.  For this reason the slave must wait
-RouterDeadInterval seconds before freeing the last Database
-Description packet. Reception of a Database Description packet from
-the master after this interval will generate a SeqNumberMismatch
-neighbor event. RFC2328 Section 10.8
-
-** Virtual link can not configured in stub area.
-
-** Clear a ls_upd_queue queue of the interface when interface goes
-down.
-
-** "no router ospf" unregister redistribution requests from zebra.
-
-** New command for virtual-link configuration is added.
-
-  "area A.B.C.D virtual-link A.B.C.D"
-  "area A.B.C.D virtual-link A.B.C.D hello-interval <1-65535> retransmit-interval <3-65535> transmit-delay <1-65535> dead-interval <1-65535>"
-  "area A.B.C.D virtual-link A.B.C.D hello-interval <1-65535> retransmit-interval <3-65535> transmit-delay <1-65535> dead-interval <1-65535> authentication-key AUTH_KEY"
-  "area A.B.C.D virtual-link A.B.C.D authentication-key AUTH_KEY"
-  "area A.B.C.D virtual-link A.B.C.D hello-interval <1-65535> retransmit-interval <3-65535> transmit-delay <1-65535> dead-interval <1-65535> message-digest-key <1-255> md5 KEY"
-  "area A.B.C.D virtual-link A.B.C.D message-digest-key <1-255> md5 KEY"
-
-** Clear cryptographic sequence number when neighbor status is changed
-to NSM down.
-
-** Make Summary LSA's origination and refreshment as same as other
-type of LSA.
-
-** New OSPF pakcet read method. Now maximum packet length may be 65535
-bytes (maximum IP packet length).
-
-** Checking the age of the found LSA and if the LSA is MAXAGE we
-should call refresh instead of originate.
-
-** Install multipath information to zebra.
-
-** Fix socket descriptor leak when system call failed.
-
-* Changes in ospf6d
-
-** Whole functionality has been rewritten as new code. new command
-"show ipv6 ospf6 spf node", "show ipv6 ospf6 spf tree", "show ipv6
-ospf6 spf table" has been added.
-
-** Change to do not send garbage route whose nexthop is not linklocal
-address.
-
-** "redistribute ospf6" was generated in "router ospf6" in config
-file. It is fixed.
-
-** LSDB sync bug is fixed.
-
-** Fix bug of using unavailable route.
-
-* Changes in vtysh
-
-** route-map and access-list configuration is merged into one
-configuration.
-
-** /usr/local/etc/Zebra.conf is integrated configuration file.  "write
-memory" in vtysh will write whole configuration to this file.
-
-** When -b option is specified to vtysh, vtysh read
-/usr/local/etc/Zebra.conf file then pass the confuguration to proper
-protocol daemon.  So make all protocol daemon's configuration file
-empty then invoke all daemon.  After that vtysh -b will setup saved
-configuration.
-
-zebrastart.sh
-=============
-/usr/local/sbin/zebra -d
-/usr/local/sbin/ripd -d
-/usr/local/sbin/ospfd -d
-/usr/local/sbin/bgpd -d
-/usr/local/bin/vtysh -b
-
-* Changes in zebra-0.89
-
-* Changes in lib
-
-** distribute-list can set all interface's access-list and prefix-list
-configuration.
-
-* Changes in ripd
-
-** "show ip protocols" display proper distribute-list settings and
-distance settings.
-
-** When metric infinity route received withdraw the route from kernel
-immediately it used to be wait garbage collection.
-
-** key-chain can be used for simple password authentication.
-
-** RIPv2 MIB getnext interface bug is fixed.
-
-* Changes in vtysh
-
-** --with-libpam enable PAM authentication for vtysh.
-
-** Now vtysh read vtysh.conf.  This file should be
-${SYSCONFDIR}/etc/vtysh.conf for security reason.  Usually it is
-/usr/local/etc/vtysh.conf.
-
-** "username WORD nopassword" command is added to vtysh.
-
-* Chagees in ospfd
-
-** NBMA interface support is added.
-
-** OSPF area is sorted by area ID.
-
-** New implementation of OSPF refreesh.
-
-** OSPF-MIB read function is partly added.
-
-* Changes in bgpd
-
-** When the peering is done by ebgp-multihop, nexthop is looked up
-like IBGP routes.
-
-** "show ip mbgp" commands are changed to "show ip bgp ipv4
-multicast".
-
-** New terminal commands are added.
-  "show ip bgp ipv4 (unicast|multicast) filter-list WORD"
-  "show ip bgp ipv4 (unicast|multicast) community"
-  "show ip bgp ipv4 (unicast|multicast) community-list WORD"
-  "show ip bgp ipv4 (unicast|multicast) community-list WORD exact-match"
-
-** MBGP soft-reconfiguration command is added.
-  "clear ip bgp x.x.x.x ipv4 (unicast|multicast) in"
-  "clear ip bgp x.x.x.x ipv4 (unicast|multicast) out"
-  "clear ip bgp x.x.x.x ipv4 (unicast|multicast) soft"
-  "clear ip bgp <1-65535> ipv4 (unicast|multicast) in"
-  "clear ip bgp <1-65535> ipv4 (unicast|multicast) out"
-  "clear ip bgp <1-65535> ipv4 (unicast|multicast) soft"
-  "clear ip bgp * ipv4 (unicast|multicast) in"
-  "clear ip bgp * ipv4 (unicast|multicast) out"
-  "clear ip bgp * ipv4 (unicast|multicast) soft"
-
-** MED related commands are added.
-  "bgp deterministic-med"
-  "bgp bestpath med confed"
-  "bgp bestpath med missing-as-worst"
-
-** "bgp default local-preference" command is added.
-
-** BGP confederation peer's routes are passed to zebra like IBGP route.
-
-** Community match command is added.
-  "show ip bgp community <val>"
-  "show ip bgp community <val> exact-match"
-
-** EBGP multihop route treatment bug is fixed.  Now nexthop is
-resolved by IGP routes.
-
-** Some commands are added to show routes by filter-list and community
-value.
-  "show ip bgp ipv4 (unicast|multicast) filter-list WORD"
-  "show ip bgp ipv4 (unicast|multicast) community"
-  "show ip bgp ipv4 (unicast|multicast) community-list WORD"
-  "show ip bgp ipv4 (unicast|multicast) community-list WORD exact-match"
-
-* Changes in zebra
-
-** zebra read interface's address information using getifaddrs() when
-it is available.
-
-** Reflect IPv6 interface's address change to protocol daemons.
-
-* Changes in zebra-0.88
-
-* Changes in lib
-
-** "exact-match" option is added to "access-list" and "ipv6
-access-list" command.  If this option is specified, the prefix and
-prefix length is compared as exact match mode.
-
-* Changes in zebra
-
-** New Zebra message ZEBRA_REDISTRIBUTE_DEFAULT_ADD and
-ZEBRA_REDISTRIBUTE_DEFAULT_DELTE are added.
-
-** Default administrative distance value is changed.
-
-            Old         New
-------------------------------------------
-system      10           0
-kernel      20           0
-connected   30           0
-static      40           1
-rip         50         120
-ripng       50         120
-ospf        60         110
-ospf6       49         110
-bgp         70         200(iBGP)  20(eBGP)
-------------------------------------------
-
-** Distance value can be passed from protocol daemon to zebra.
-
-** "show ip route" shows [metric/distance] value pair.
-
-** Zebra Protocol is changed to support multi-path route and distance
-value.
-
-* Changes in ospfd
-
-** "default-information originate [always]" command is added.
-
-** "default-metric <0-16777214>" command is added.
-
-** "show ip ospf database" command is integrated.  LS-ID and AdvRouter can
-   be specifed.  The commands are
-
-   show ip ospf database TYPE LS-ID
-   show ip ospf database TYPE LS-ID ADV-ROUTER
-   show ip ospf database TYPE LS-ID self-originate
-   show ip ospf database TYPE self-originate
-
-** route-map support for `redistribute' command are added.
-   Supported `match' statements are
-
-   match interface
-   match ip address
-   match next-hop
-
-   Supported `set' statements are
-
-   set metric
-   set metric-type
-
-** Pass OSPF metric value to zebra daemon.
-
-* Changes in ripd
-
-** When specified route-map does not exist, it means all deny.
-
-** "default-metric <1-16>" command is added.
-
-** "offset-list ACCESS-LIST-NAME <0-16>" and "offset-list
-ACCESS-LIST-NAME <0-16> IFNAME" commands are added.
-
-** "redistribute ROUTE-TYPE metric <0-16>" command is added.
-
-** "default-information originate" command is added.
-
-** "ip split-horizon" and "no ip split-horizon" is added to interface
-configuration.
-
-** "no router rip" command is added.
-
-** "ip rip authentication mode (md5|text)" is added to interface
-configuration.
-
-** "ip rip authentication key-chain KEY-CHAIN" is added to interface
-configuration.
-
-** Pass RIP metric value to zebra daemon.
-
-** Distance manipulation functions are added.
-
-* Changes in bgpd
-
-** Fix bug of next hop treatment for MPLS-VPN route exchange.
-
-** BGP peer MIB is updated.
-
-** Aggregated route has origin IGP, atomic-aggregate and proper
-aggregator attribute.
-
-** Suppressed route now installed into BGP table.  It is only
-suppressed from announcement.
-
-** BGP router-id is properly set after "no router bgp ASN" and "router
-bgp ASN".
-
-** Add check for nexthop is accessible or not for IBGP routes.
-
-** Add cehck for nexthop is on connected or not for EBGP routes.
-
-** "dump bgp route" command is changed to "dump bgp route-mrt" for
-generating MRT compatible dump output.
-
-** Soft reconfiguration inbound and outbound is supported.
-
-** Route refresh feature is supported.
-
-* Changes in vtysh
-
-** VTY shell is now included into the distribution.
-
-* Changes in zebra-0.87
-
-* Changes in lib
-
-** "show startup-config" command is added.
-
-** "show history" command is added.
-
-** Memory statistics command is changed.  New command
-
-   show memory all
-   show memory lib
-   show memory rip
-   show memory ospf
-   show memory bgp
-
-are added.
-
-** Filters can be removed only specify it's name.  New command
-
-   no access-list NAME
-   no ip community-list NAME
-   no ip as-path access-list NAME
-   no route-map NAME
-
-are added.
-
-** At any node, user can view/save user configuration.
-
-   write terminal
-   write file
-   wirte memory
-
-are added to every node in default.
-
-** LCD completion is added.  For example both "ip" and "ipv6" command
-are exist, "i" then press TAB will be expanded to "ip".
-
-* Changes in bgpd
-
-** "show ip bgp" family shows total number of prefixes.
-
-** "no bgp default ipv4-unicast" command is added.
-
-** Extended Communities support is added.
-
-** "no neighbor PEER send-community extended" command is added.
-
-** MPLS-VPN PE-RR support is added.
-
- New address family vpnv4 unicast is introduced.
-
-  !
-  address-family vpnv4 unicast
-   neighobr PEER activate
-   network A.B.C.D rd RD tag TAG
-  exit-address-family
-  !
-
- To make it route-reflector, please configure it under normal router
-bgp ASN.
-
-  !
-  router bgp 7675
-   no bgp default ipv4-unicast
-   bgp router-id 10.0.0.100
-   bgp cluster-id 10.0.0.100
-   neighbor 10.0.0.1 remote-as 65535
-   neighbor 10.0.0.1 route-reflector-client
-   neighbor 10.0.0.2 remote-as 65535
-   neighbor 10.0.0.2 route-reflector-client
-   neighbor 10.0.0.3 remote-as 65535
-   neighbor 10.0.0.3 route-reflector-client
-  !
-  address-family vpnv4 unicast
-   neighbor 10.0.0.1 activate
-   neighbor 10.0.0.2 activate
-   neighbor 10.0.0.3 activate
-  exit-address-family
-  !
-
-* Changes in ospfd
-
-** Many many bugs are fixed.
-
-* Changes in ripd
-
-** Better interface up/down event handle.
-
-* Changes in zebra
-
-** Better interface up/down event handle.
-
-* Changes in zebra-0.86
-
-* Changes in lib
-
-** Fix bug of exec-timeout command which may cause crush.
-
-** Multiple same policy for "access-list", "ip prefix-list, "as-path
-access-list", "ip community-list" is not duplicated.
-
-** It used to be "ip prefix-list A.B.C.D/M" match routes which mask >=
-M.  Now default behavior is exact match so it only match routes which
-mask == M.
-
-* Changes in bgpd
-
-** "match ip address prefix-list" is added to route-map.
-
-** A route without local preference is evaluated as 100 local preference.
-
-** Select smaller router-id route when other values are same.
-
-** Compare MED only both routes comes from same neighboring AS.
-
-** "bgp always-compare-med" command is added.
-
-** Now MED value is passed to IBGP peer.
-
-** When neighbor's filter is configured with non-existent access-list,
-as-path access-list, ip prefix-list, route-map.  The behavior is
-changed from all permit to all deny.
-
-* Changes in ospfd
-
-** Fix bug of external route tag byte order.
-
-** OSPF Neighbor deletion bug which cause crush is fixed.
-
-** Some route calculation bug are fixed.
-
-** Add sanity check with router        routing table.
-
-** Fix bug of memory leak about linklist.
-
-** Fix bug of 1-WayReceived in NSM.
-
-** Take care of BIGENDIAN architecture.
-
-** Fix bug of NSM state flapping between ExStart and Exchange.
-
-** Fix bug of Network-LSA originated in stub network.
-
-** Fix bug of MS flag unset.
-
-** Add to schedule router_lsa origination when the interface cost
-changes.
-
-** Increment LS age by configured interface transmit_delay.
-
-** distribute-list is reimplemented.
-
-** Fix bug of refresh never occurs.
-
-** Fix bug of summary-LSAs reorigination.  Correctly copy
-OSPF_LSA_APPROVED flag to new LSA. when summary-LSA is reoriginatd.
-
-** Fix bug of re-origination when a neighbor disappears.
-
-** Fix bug of segmentation fault with DD retransmission.
-
-** Fix network-LSA re-origination problem.
-
-** Fix problem of remaining withdrawn routes on zebra.
-
-* Changes in ripd
-
-** Do not leave from multicast group when interface goes down bug is
-fixed.
-
-* Changes in zebra
-
-** Remove client structure when client dies.
-
-** Take care static route when interface goes up/down.
-
-* Changes in zebra-0.85
-
-* Changes in bgpd
-
-** "transparent-nexthop" and "transparenet-as" commands are added.
-
-** Route reflector's originator-id bug is fixed.
-
-* Changes in ospfd
-
-** Fix bug of OSPF LSA memory leak.
-
-** Fix bug of OSPF external route memory leak.
-
-** AS-external-LSA origination bug was fixed.
-
-** LS request treatment is completely rewritten.  Now performance is
-drastically improved.
-
-* Changes in ripd
-
-** RIPv1 update is done by class-full manner.
-
-* Changes in zebra-0.84b
-
-* Changes in lib
-
-** Fix bug of inet_pton return value handling
-
-* Changes in bgpd
-
-** Fix bug of BGP-4+ link-local address nexthop check for IBGP peer.
-
-** Don't allocate whole buffer for displaying "show ip bgp".  Now it
-consume only one screen size memory.
-
-* Changes in ripd
-
-** Fix debug output string.
-
-** Add RIP peer handling.  RIP peer are shown by "show ip protocols".
-
-* Changes in zebra-0.84a
-
-* Changes in bgpd
-
-** Fix serious bug of BGP-4+ peering under IPv6 link-local address.
-   Due to the bug BGP-4+ peering may not be established.
-
-* Changes in zebra-0.84
-
-* Changes in lib
-
-** IPv6 address and prefix parser is added to VTY by Toshiaki Takada
-   <takada@zebra.org>.  DEFUN string is "X:X::X:X" for IPv6 address,
-   "X:X::X:X/M" for IPv6 prefix.  You can use it like this.
-
-   DEFUN (func, cmd, "neighbor (A.B.C.D|X:X::X:X) remote-as <1-65535>")
-
-** VTY configuration is locked during configuration.  This is for
-   avoiding unconditional crush from two terminals modify the
-   configuration at the same time.  "who" command shows which termnal
-   lock the configuration.  VTY which has '*' character at the head of
-   line is locking the configuration.
-
-** Old logging functions are removed.  Functions like
-   log_open,log_close,openlog are deleted.  Instead of that please use
-   zlog_* functions.  zvlog_* used in ospf6d are deleted also.
-
-** "terminal monitor" command is added.  "no terminal monitor" is for
-   disabling.  This command simply display logging information to the
-   VTY.
-
-** dropline.[ch] files are deleted.
-
-* Changes in bgpd
-
-** BGP neighbor configuration are sorted by it's IP address.
-
-** BGP peer configuration and actual peer is separated.  This is
-   preparation for Route Server support.
-
-** "no neighbor PEER" command is added. You can delete neighbor
-   without specifying AS number.
-
-** "no neighbor ebgp-multihop" command is added.
-
-** "no neighbor port PORT" command is added.
-
-** To conform RFC1771, "neighbor PEER send-community" is default
-   behavior.  If you want to disable sending community attribute,
-   please specify "no neighbor PEER send-community" to the peer.
-
-** "neighbor maximum-prefix NUMBER" command is added.
-
-** Multi-protocol extention NLRI is proceeded only when the peer is
-   configured proper Address Family and Subsequent Address Family.  If
-   not, those NLRI are simply ignored.
-
-** Aggregate-address support is improved.  Currently below commands
-   works.
-
-  "aggregate-address"
-  "aggregate-address summary-only"
-  "no aggregate-address"
-  "no aggregate-address summary-only"
-
-  "ipv6 bgp aggregate-address"
-  "ipv6 bgp aggregate-address summary-only"
-  "no ipv6 bgp aggregate-address"
-  "no ipv6 bgp aggregate-address summary-only"
-
-** redistribute route-map bug is fixed.
-
-** MBGP support becomes default.  "configure" option --enable-mbgp is
-   removed.
-
-** New command "neighbor PEER timers connect <1-65535>" is added.
-
-** New command "neighbor PEER override-capability" is added.
-
-** New command "show ip bgp neighbor A.B.C.D advertised-route" is added.
-
-** New command "show ip bgp neighbor A.B.C.D routes" is added.  To use
-   this command, you have to configure neighbor with
-   "neighbor A.B.C.D soft-reconfiguration inbound" beforehand.
-   
-
-* Changes in zebra-0.83
-
-* bgpd
-
-** Serious bug fix about fetching global and link-local address at the
-same time.  Due to this bug, corrupted IPv6 prefix is generated.  If
-you uses bgpd for BGP-4+ please update to this version.  The bug is
-introduced in zebra-0.82.
-
-** When bgpd send Notify message, don't use thread manager.  It is now
-send to neighbor immediately.
-
-* Changes in zebra-0.82
-
-** Solaris 2.6 support is added by Michael Handler
-<handler@sub-rosa.com>.
-
-** MBGP support is added by Robert Olsson <Robert.Olsson@data.slu.se>.
-Please specify --enable-mbgp to configure script.  This option will be
-removed in the future and MBGP support will be default.
-
-* Changes in zebra
-
-** When interface goes down, withdraw connected routes from routing
-table.  When interface goes up, restore the routes to the routing
-table.
-
-** `show interface' show interface's statistics on Linux and BSD with
-routing socket.
-
-** Now zebra can get MTU value on BSDI/OS.
-
-* Changes in bgpd
-
-** Add capability option support based upon
-draft-ietf-idr-bgp4-cap-neg-04.txt.
-
-** Add `show ipv6 bgp prefix-list' command.
-
-** Check self AS appeared in received routes.
-
-** redistribute route-map support is added.
-
-** BGP packet dump feature compatible with MRT.
-
-* Changes in ripd
-
-** Fix bug of `timers basic' command's argument format.
-
-* Changes in ripngd
-
-** Calculate max RTE using interface's MTU value.
-
-* Changes in ospfd
-
-** Some correction to LSU processing.
-
-** Add check for lsa->refresh_list.
-
-* Changes in ospf6d
-
-** Many debug feature is added.
-
-* Changes in zebra-0.81
-
-** SNMP support is disabled in default.--enable-snmp option is added
-to configure script.
-
-* Changes in bgpd
-
-** Fix FSM bug which introduced in zebra-0.80.
-
-* Changes in zebra-0.80
-
-* access-list
-
-  New access-list name space `ipv6 access-list' is added.  At the same
-  time, `access-list' statemant only accepts IPv4 prefix.  Please be
-  careful if you use IPv6 filtering.  You will need to change your
-  configuration.  For IPv6 filtering please use `ipv6 access-list'.
-  
-  As of zebra-0.7x, user can use `access-list' for both IPv4 and IPv6
-  filtering.
-  
-  ! zebra-0.7x
-  access-list DML-net permit 203.181.89.0/24
-  access-list DML-net permit 3ffe:506::0/32
-  access-list DML-net deny any
-  !
-  
-  Above configuration is not valid for zebra-08x.  Please add `ipv6'
-  before 'access-list' when you configure IPv6 filtering.
-  
-  ! zebra-0.8x
-  access-list DML-net permit 203.181.89.0/24
-  access-list DML-net deny any
-  !
-  ipv6 access-list DML-net permit 3ffe:506::0/32
-  ipv6 access-list DML-net deny any
-  !
-
-* prefix-list
-
-  And also new prefix-list name space `ipv6 prefix-list' is added.  It
-  is the same as the change of `access-list'. `ip prefix-list' now only
-  accept IPv4 prefix.  It was source of confusion that `ip prefix-list'
-  can be used both IPv4 and IPv6 filtering.  Now name space is separated
-  to clear the meaning of the filter.
-  
-  If you use `ip prefix-list' for IPv6 filtering, please change the
-  stetement.
-  
-  ! zebra-0.7x
-  ip prefix-list 6bone-filter seq 5 permit 3ffe::/17 le 24 ge 24
-  ip prefix-list 6bone-filter seq 10 permit 3ffe:8000::/17 le 28 ge 28
-  ip prefix-list 6bone-filter seq 12 deny 3ffe::/16
-  ip prefix-list 6bone-filter seq 15 permit 2000::/3 le 16 ge 16
-  ip prefix-list 6bone-filter seq 20 permit 2001::/16 le 35 ge 35
-  ip prefix-list 6bone-filter seq 30 deny any
-  !
-  
-  Now user can explicitly configure it as IPv6 prefix-list.
-  
-  ! zebra-0.8x
-  ipv6 prefix-list 6bone-filter seq 5 permit 3ffe::/17 le 24 ge 24
-  ipv6 prefix-list 6bone-filter seq 10 permit 3ffe:8000::/17 le 28 ge 28
-  ipv6 prefix-list 6bone-filter seq 12 deny 3ffe::/16
-  ipv6 prefix-list 6bone-filter seq 15 permit 2000::/3 le 16 ge 16
-  ipv6 prefix-list 6bone-filter seq 20 permit 2001::/16 le 35 ge 35
-  ipv6 prefix-list 6bone-filter seq 30 deny any
-  !
-
-* RIP configuration
-
-  If you want to filter only default route (0.0.0.0/0) and permit other
-  routes, it was hard to do that.  Now `ip prefix-list' can be used for
-  RIP route filtering.
-  
-  New statement:
-  
-  `distribute-list prefix PLIST_NAME (in|out) IFNAME'
-  
-  is added to ripd.  So you can configure on eth0 interface accept all
-  routes other than default routes.
-  
-  !
-  router rip
-   distribute-list prefix filter-default in eth0
-  !
-  ip prefix-list filter-default deny 0.0.0.0/0 le 0
-  ip prefix-list filter-default permit any
-  !
-
-* RIPng configuration
-
-  Same change is done for ripngd.  You can use `ipv6 prefix-list' for
-  filtering.
-  
-  !
-  router ripng
-   distribute-list prefix filter-default in eth0
-  !
-  ipv6 prefix-list filter-default deny ::/0 le 0
-  ipv6 prefix-list filter-default permit any
-  !
-
-* BGP configuration
-
-  So far, Multiprotocol Extensions for BGP-4 (RFC2283) configuration is
-  done with traditional IPv4 peering statement like blow.
-  
-  !
-  router bgp 7675
-   neighbor 3ffe:506::1 remote-as 2500
-   neighbor 3ffe:506::1 prefix-list 6bone-filter out
-  !
-  
-  For separating configuration IPv4 and IPv6, and for retaining Cisco
-  configuration compatibility, now IPv6 configuration is done by IPv6
-  specific statement.  IPv6 BGP configuration is done by statement which
-  start from `ipv6 bgp'.
-  
-  !
-  router bgp 7675
-  !
-  ipv6 bgp neighbor 3ffe:506::1 remote-as 2500
-  ipv6 bgp neighbor 3ffe:506::1 prefix-list 6bone-filter out
-  !
-  
-  At the same time some IPv6 specific commands are deleted from IPv4
-  configuration.
-  
-  o redistribute ripng
-  o redistribute ospf6
-  o neighbor PEER version BGP_VERSION
-  o neighbor PEER interface IFNAME
-  
-  Those commands are only accepted as like below.
-  
-  o ipv6 bgp redistribute ripng
-  o ipv6 bgp redistribute ospf6
-  o ipv6 bgp neighbor PEER version BGP_VERSION
-  o ipv6 bgp neighbor PEER interface IFNAME
-  
-  And below new commands are added.
-  
-  o ipv6 bgp network IPV6_PREFIX
-  o ipv6 bgp redistribute static
-  o ipv6 bgp redistribute connected
-  o ipv6 bgp neighbor PEER remote-as <1-65535> [passive]
-  o ipv6 bgp neighbor PEER ebgp-multihop [TTL]
-  o ipv6 bgp neighbor PEER description DESCRIPTION
-  o ipv6 bgp neighbor PEER shutdown
-  o ipv6 bgp neighbor PEER route-reflector-client
-  o ipv6 bgp neighbor PEER update-source IFNAME
-  o ipv6 bgp neighbor PEER next-hop-self
-  o ipv6 bgp neighbor PEER timers holdtime <0-65535>
-  o ipv6 bgp neighbor PEER timers keepalive <0-65535>
-  o ipv6 bgp neighbor PEER send-community
-  o ipv6 bgp neighbor PEER weight <0-65535>
-  o ipv6 bgp neighbor PEER default-originate
-  o ipv6 bgp neighbor PEER filter-list FILTER_LIST_NAME (in|out)
-  o ipv6 bgp neighbor PEER prefix-list PREFIX_LIST_NAME (in|out)
-  o ipv6 bgp neighbor PEER distribute-list AS_LIST_NAME (in|out)
-  o ipv6 bgp neighbor PEER route-map ROUTE_MAP_NAME (in|out)
-  
-  And some utility commands are introduced.
-  
-  o clear ipv6 bgp [PEER]
-  o show ipv6 bgp neighbors [PEER]
-  o show ipv6 bgp summary
-  
-  I hope these changes are easy to understand for current Zebra users...
-
-* To restrict connection to VTY interface.
-
-  It used to be both IPv4 and IPv6 filter can be specified with one
-  access-list.  Then the access-list can be appried to VTY interface
-  with `access-class' stetement in `line vty' node.  Below is example in
-  zebra-0.7x.
-  
-  !
-  access-list local-only permit 127.0.0.1/32
-  access-list local-only permit ::1/128
-  access-list local-only deny any
-  !
-  line vty
-   access-class local-only
-  !
-  
-  Now IPv4 and IPv6 filter have each name space.  It is not possible to
-  specify IPv4 and IPv6 filter with one access-list.  For setting IPv6
-  access-list in `line vty', `ipv6 access-class' statement is
-  introduced.  Let me show the configuration in zebra-0.8x.
-  
-  !
-  access-list local-only permit 127.0.0.1/32
-  access-list local-only deny any
-  !
-  ipv6 access-list local-only permit ::1/128
-  ipv6 access-list local-only dny any
-  !
-  line vty
-   access-class local-only
-   ipv6 access-class local-only
-  !
-
-* route-map
-
-  New IPv6 related route-map match commands are added.
-  
-  o match ipv6 address
-  o match ipv6 next-hop
-  
-  Please change your configuration if you use IP match statement for
-  IPv6 route.
-  
-  zebra-0.7x config
-  =================
-  !
-  access-list all permit any
-  !
-  route-map set-nexthop permit 10
-   match ip address all
-   set ipv6 next-hop global 3ffe:506::1
-   set ipv6 next-hop local fe80::cbb5:591a
-  !
-  
-  zebra-0.8x config
-  =================
-  !
-  ipv6 access-list all permit any
-  !
-  route-map set-nexthop permit 10
-   match ipv6 address all
-   set ipv6 next-hop global 3ffe:506::1
-   set ipv6 next-hop local fe80::cbb5:591a
-  !
-
-* zebra connection
-
-  Protocol daemon such as ripd, bgpd, ospfd will reconnect zebra daemon
-  when the connection fail.  Those daemons try to connect zebra every 10
-  seconds first three trial, then the interval changed to 60 seconds.
-  After all, if ten connections are fail, protocol daemon give up the
-  connection to the zebra daemon.
-
-* SNMP support (is not yet finished)
-
-  Zebra uses SMUX protocol (RFC1227) for making communication with SNMP
-  agent.  Currently lib/smux.c can be compiled only with ucd-snmp-4.0.1
-  and http://ucd-snmp.ucdavis.edu/patches/012.patch.  It can not be
-  compiled with ucd-snmp-3.6.2.
-  
-  After applying the patch to ucd-snmp-4.0.1, please configure it with
-  SMUX module.
-  
-  % configure --with-mib-modules=smux
-  
-  After compile & install ucd-snmp-4.0.1, you will need to configure
-  smuxpeer.  I'm now using below configuration.
-  
-  /usr/local/share/snmp/snmpd.conf
-  ================================
-  smuxpeer 1.3.6.1.6.3.1 test
-  
-  Above 1.3.6.1.6.3.1 and test is temporary configuration which is hard
-  coded in lib/smux.c. Yes, I know it is bad, I'll change it ASAP.
-
-* HUP signal treatment
-
-  From zebra-0.80, ripd will reload it's configuration file when ripd
-  receives HUP signal.  Other daemon such as bgpd, ospfd will support
-  HUP signal treatment soon.
-
-* Changes in zebra-0.79
-
-* Changes in zebra
-
-** Broadcast address setting on Linux box bug is fixed.
-
-** Protocol daemon can install connected IPv6 route into the kernel.
-
-** Now zebra can handle blackhole route.
-
-* Changes in ripd
-
-** Add route-map feature for RIP protocol.
-
-** In case of RIP version 2 routing table entry has IPv4 address and
-netmask pair which host part bit is on, ignore the entry.
-
-* Changes in ripngd
-
-** Change CMSG_DATA cast from (u_char *) to (int *).  (u_char *) does
-not work for NetBSD-currnet on SparcStation 10.
-
-* Changes in ospfd
-
-** MaxAge LSA treatment is added.
-
-** ABR/ASBR functionality is added.
-
-** Virtual Link funtionality is added.
-
-** ABR behaviors IBM/Cisco/Shortcut is added.
-
-* Changes in ospf6d
-
-** Enclosed KAME specific part with #ifdef #endif
-
-* Changes in zebra-0.78
-
-* Changes in lib
-
-** SNMP support is started.
-
-** Now Zebra can work on BSD/OS 4.X.
-
-** Now Zebra can compiled on vanilla OpenBSD 2.5 but not yet working correcltly.
-
-* Changes in zebra
-
-** Interface index detection using ioctl() bug is fixed.
-
-** Interface information protocol is changed.  Now interface
-addition/deletion and interface's address addition/deletion is
-separated.
-
-* Changes in bgpd
-
-** BGP hold timer bug is fixed.
-
-** BGP keepavlie timer becomes configurable.
-
-* Changes in ripd
-
-** When making reply to rip's REQUEST message, fill in
-RIP_METRIC_INFINITY with network byte order using htonl ().
-
-** Pass host byte order address to IN_CLASSC and IN_CLASSB macro.
-
-* Changes in ospfd
-
-** LSA flooding works.
-
-** Fix bug of DD processing.
-
-** Fix bug of originating router-LSA bug is fixed.
-
-** LSA structure is changed to support LSA aging.
-
-* Changes in ospf6d
-
-** `ip6' statement in configuration is changed to `ipv6'.
-
-* Changes in zebra-0.77
-
-* Changes in lib
-
-** SIGUSR1 reopen logging file.
-
-** route-map is extended to support multi-protocol routing
-information.
-
-** When compiling under GNU libc 2.1 environment don't use inet6-apps.
-
-* Changes in zebra
-
-** Basic IPv6 router advertisement codes added.  It is not yet usable.
-
-** Fix IPv6 route addition/deletion bug is fixed.
-
-** `show ip route A.B.C.D' works
-
-* Changes in bgpd
-
-** When invalid unfeasible routes length comes, bgpd send notify then
-continue to process the packet.  Now bgpd stop parsing invalid packet
-then return to main loop.
-
-** BGP-4+ withdrawn routes parse bug is fixed.
-
-** When BGP-4+ information passed to non shared network's peer, trim
-link-local next-hop information.
-
-** `no redistribute ROUTE_TYPE' withdraw installed routes from BGP
-routing information.
-
-** `show ipv6 route IPV6ADDR' command added.
-
-** BGP start timer has jitter.
-
-** Holdtimer configuration bug is fixed.  Now configuration does not
-show unconfigured hold time value.
-
-* Changes in ripngd
-
-** Now update timer (default 30 seconds) has +/- 50% jitter value.
-
-** Add timers basic command.
-
-** `network' configuration is dynamically reflected.
-
-** `timers basic <update> <timeout> <garbage>' added.
-
-* Changes in ripd
-
-** Reconstruct almost codes.
-
-** `network' configuration is dynamically reflected.
-
-** RIP timers now conforms to RFC2453.  So user can configure update,
-timeout, garbage timer.
-
-** `timers basic <update> <timeout> <garbage>' works.
-
-* Changes in ospfd
-
-** Bug of originating network LSA is fixed.
-
-** `no router ospf' core dump bug is fixed.
-
-* Changes in ospf6d
-
-** Redistribute route works.
-
-* Changes in zebra-0.76
-
-* Changes in lib
-
-** configure.in Linux IPv6 detection problem is fixed.
-
-** Include SERVICES file to the distribution
-
-** Update zebra.texi to zebra-0.76.
-
-* Changes in zebra-0.75
-
-* Changes in lib
-
-** `termnal length 0' bug is fixed.
-
-* Changes in zebra
-
-** When zebra starts up, sweep all zebra installed routes.  If -k or
---keep_kernel option is specified to zebra dameon.  This function is
-not performed.
-
-* Changes in ripngd
-
-** Aggreagte address command supported.  In router ripngd,
-`aggregate-address IPV6PREFIX' works.
-
-* Changes in bgpd
-
-** Input route-map's bug which cause segmentation violation is fixed.
-
-** route-map method improved.
-
-** BGP-4+ nexthop detection improved.
-
-** BGP-4+ route re-selection bug is fixed.
-
-** BGP-4+ iBGP route's nexthop calculation works.
-
-** After connection Established `show ip bgp neighbor' display BGP TCP
-connection's source and destination address.
-
-** In case of BGP-4+ `show ip bgp neighbor' display BGP-4+ global and
-local nexthop which used for originated route.  This address will be
-used when `next-hop-self'.
-
-* Changes in ospfd
-
-** Fix bug of DR election.
-
-** Set IP precedence field with IPTOS_PREC_INTERNET_CONTROL.
-
-** Schedule NeighborChange event if NSM status change.
-
-** Never include a neighbor in Hello packet, when the neighbor goes
-down.
-
-* Changes in zebra-0.74
-
-* Changes in lib
-
-** Now `terminal length 0' means no line output control.
-
-** `line LINES' command deleted.  Instead of this please use `terminal
-length <0-512>'.
-
-** `terminal length <0-512>' is each vty specific configuration so it
-can not be configured in the configuration file.  If you want to
-configure system wide line control, please use `service
-terminal-length <0-512>'.  This configuration affects to the all vty
-interface.
-
-* Changes in zebra
-
-** Installation of IPv6 route bug is fixed.
-
-* Changes in bgpd
-
-** Very serious bug of bgp_stop () is fixed. When multiple route to
-the same destination exist, bgpd try to announce the information to
-stopped peer.  Then add orphan write thread is added.  This cause
-many strange behavior of bgpd.
-
-** Router-id parsing bug is fixed.
-
-** With BGP-4+ nexthop installation was done with global address but
-it should be link-local address.  This bug is fixed now.
-
-** When incoming route-map prepend AS, old AS path remained.  Now bgpd
-free old AS path.
-
-** `neighbor PEER weight <0-65535>' command added.
-
-* Changes in ripngd
-
-** Almost codes are rewritten to conform to RFC2080.
-
-* Changes in ospfd
-
-** SPF calculation timer is added.  Currently it is set to 30 seconds.
-
-** SPF calculation works now.
-
-** OSPF routing table codes are added.
-
-** OSPF's internal routes installed into the kernel routing table.
-
-** Now `ospfd' works as non-area, non-external route support OSPF
-router.
-
-** Call of log_rotate() is removed.
-
-* Changes in ospf6d
-
-** LSA data structure is changed.
-
-** Call of log_rotate() is removed.
-
-* Changes in zebra-0.73
-
-* Changes in lib
-
-** `config terminal' is changed to `configure terminal'.
-
-** `terminal length <0-512>' command is added.
-
-** Variable length argument was specified by `...'.  Now all strings
-started with character `.' is variable length argument.
-
-* Changes in zebra
-
-** Internal route (such as iBGP, internal OSPF route) handling works
-correctly.
-
-** In interface node, `ipv6 address' and `no ipv6 address' works.
-
-** Interface's address remain after `no ip address' bug is fixed.
-
-** Host route such as IPv4 with /32 mask and IPv6 with /128 mask
-didn't set RTF_GATEWAY even it has gateway.  This bug if fixed now.
-
-* Changes in bgpd
-
-** `match as-path' argument is used to be specify AS PATH value itself
-directly (e.g. ^$).  But it is changed to specify `ip as-apth
-access-list' name.
-
-** iBGP route handle works without getting error from the kernel.
-
-** `set aggregator as AS A.B.C.D' command is added to route-map.
-
-** `set atomic-aggregate' command is added to bgpd's routemap.
-
-** Announcement of atomic aggregate attribute and aggregator attribute
-works.
-
-** `update-source' bug is fixed.
-
-** When a route learned from eBGP is announced to iBGP, local
-preference was set to zero.  But now it set to
-DEFAULT_LOCAL_PREF(100).
-
-* Changes in ripd
-
-** RIPv1 route filter bug is fixed.
-
-** Some memory leak is fixed.
-
-* Changes in ospfd
-
-** Fix bug of DR Election.
-
-** Fix bug of adjacency forming.
-
-* Changes in ospf6d
-
-** Clean up logging message.
-
-** Reflect routing information to zebra daemon.
-
-* Changes in zebra-0.72
-
-* Changes in lib
-
-** When getsockname return IPv4 mapped IPv6 address.  Convert it to
-IPv4 address.
-
-* Changes in bgpd
-
-** Change route-map's next-hop related settings.
-
-set ip nexthop          -> set ip next-hop
-set ipv6 nexthop global -> set ipv6 next-hop global
-set ipv6 nexthop local  -> set ipv6 next-hop local
-
-** Add `next-hop-self' command.
-
-* Changes in ospfd
-
-** Fix bug of multiple `network area' directive crashes.
-
-* Changes in zebra-0.71
-
-* Changes in lib
-
-** `log syslog' command is added.
-
-** Use getaddrinfo function to bind IPv4/IPv6 server socket.
-
-** `no banner motd' will suppress motd output when user connect to VTY.
-
-** Bind `quit' command to major nodes.
-
-* Changes in zebra
-
-** Point-to-point link address handling bug is fixed.
-
-* Changes in bgpd
-
-** AS path validity check is added.  If malformed AS path is received
-NOTIFY Malformed AS path is send to the peer.
-
-** Use getaddrinfo function to bind IPv4/IPv6 server socket.
-
-* Changes in ripd
-
-** Connected network announcement bug is fixed.
-
-** `broadcast' command is deleted.
-
-** `network' command is added.
-
-** `neighbor' command is added.
-
-** `redistribute' command is added.
-
-** `timers basic' command is added.
-
-** `route' command is added.
-
-* Changes in ripngd
-
-** Fix metric calculation bug.
-
-* Changes in ospfd
-
-** Check sum bug is fixed.
-
-* Chanegs in ospf6d
-
-** Routing table code is rewritten.
-
-* Changes in zebra-0.70
-
-* Changes in zebra
-
-** Critical routing information base calculation bug check is fixed.
-
-** zebra ipv4 message is extended to support external/internal route
-flavor.
-
-** Now if internal route doesn't has direct connected nexthop, then
-nexthop is calculated by looking up IGP routing table.
-
-* Changes in bgpd
-
-** `neighbor PEER update-source IFNAME' command added as ALIAS to
-`neighbor PEER interface IFNAME'.
-
-* Changes in ospfd
-
-** DD null pointer bug is fixed.
-
-* Changes in zebra-0.69
-
-* Changes in zebra
-
-** zebra redistirbution supports dynamic notification of the route
-change.  If you add static route while running zebra, it will be
-reflected to other protocol daemon which set `redistribute static'.
-
-** If static route installation is failed due to the error.  The
-static route is not added to the configuration and zebra routing
-table.
-
-** zebra sets forwarding flag to on when it starts up.
-
-** `no ip forwarding' turn off IPv4 forwarding.
-
-** `no ipv6 forwarding' turn off IPv6 forwarding.
-
-** Change `show ipforward' command to `show ip forwarding'.
-
-** Change `show ipv6forward' command to `show ipv6 forwarding'.
-
-** `ip route A.B.C.D/M INTERFACE' works.  So you can set `ip route
-10.0.0.0/8 eth0'.
-
-* Changes in bgpd
-
-** `neighbor PEER send-community' command is added.  If the option is
-set, bgpd will send community attribute to the peer.
-
-** When a BGP route has no-export community attribute and
-send-community is set to the peer, the route is not announced to the
-peer.
-
-* Changes in ripngd
-
-** When ripngd terminates, delete all installed route.
-
-** `redistribute static', `redistribute connected' works.
-
-** Change `debug ripng event' to `debug ripng events'.
-
-** Change `show debug ripng' to `show debugging ripng'.
-
-** Bug of static route deletion is fixed.
-
-* Changes in ospfd
-
-** LS request and LS update can be send and received.
-
-* Changes in zebra-0.68
-
-* Changes in lib
-
-** DEFUN() is extended to support (a|b|c) statement.
-
-** Input buffer overflow bug is fixed.
-
-* Changes in bgpd
-
-** `ip community-list' is added.
-
-** set community and match community is added to route-map statement.
-
-** aggregate-address A.B.C.D/M partly works.  Now it works only
-summary-only mode.
-
-* Changes in zebra
-
-** IPv6 network address delete bug is fixed.
-
-* Changes in ospfd
-
-** DR election bug fixed.
-
-** Now Database Description can be send or received.
-
-** Neighbor State Machine goes to Full state.
-
-* Changes in ospf6d
-
-** router zebra related bug is fixed.
-
-* Changes in zebra-0.67
-
-* Changes in lib
-
-** `service password-encryption' is added for encrypted password.
-
-* Changes in bgpd
-
-** `set as-path prepend ASPATH' is added to route-map command.
-
-** `set weight WEIGHT' is added to route-map command.
-
-** `no set ipv6 nexthop global' and `no set ipv6 nexthop local'
-command is added to route-map.
-
-** `neighbor IP_ADDR version BGP_VERSION' command's BGP_VERSION
-argument changed.
-
-Old               New
-=====================
-bgp4              4
-bgp4+             4+
-bgp4+-draft-00    4-
-=====================
-
-If you want to peer with old draft version of BGP-4+, please configure
-like below:
-
-router bgp ASN
- neighbor PEER version 4-
-
-** Some AS path isn't correctly compared during route selection.  Now
-it is fixed.
-
-* Changes in ospfd
-
-** `router zebra' is default behavior.
-
-* Changes in ospf6d
-
-** `router zebra' is default behavior.
-
-* Changes in zebra-0.66
-
-* Changes in zebra
-
-** When other daemon such as gated install routes into the kernel then
-zebra blocks.  This is only occur with netlink socket.  Now socket is
-set as NONBLOCKING and problem is fixed.  Reported and fixed by
-Patrick Koppen <koppen@rhrk.uni-kl.de>
-
-* Changes in bgpd
-
-** Now `router zebra' is not needed to insert BGP routes into the
-kernel.  It is default behavior.  If you don't want to install the BGP
-routes to the kernel, please configure like below:
-
-!
-router zebra
- no redistribute bgp
-!
-
-** redistribute connected works.
-
-** redistribute static now filter local loopback routes and link local
-network.
-
-* Changes in ripd
-
-** Some network check is added.  Patch is done by Carlos Alberto
-Barcenilla <barce@frlp.utn.edu.ar>
-
-* Changes in ripngd
-
-** Sometimes ripngd install wrong nexthop into the kernel.  This bug
-is fixed now.
-
-** Now `router zebra' is not needed to insert RIPng routes into the
-kernel.  It is default behavior. If you don't want to install the BGP
-routes to the kernel, please configure like below:
-
-!
-router zebra
- no redistribute ripng
-!
-
-* Changes in zebra-0.65
-
-* Changes in lib
-
-** `C-c' changes current node to ENABLE_NODE.  Previously it doesn't.
-
-** In ENABLE_NODE, `exit' command close vty connection.
-
-** `service advanced-vty' enable advanced vty function.  If this
-service is specified one can directly connect to ENABLE_NODE when
-enable password is not set.
-
-** `lines LINES' command is added by Stephen R. van den Berg
-<srb@cuci.nl>.
-
-* Changes in zebra
-
-** Basic Linux policy based routing table support is added by Stephen
-R. van den Berg <srb@cuci.nl>.
-
-* Changes in bgpd
-
-** route-map command is improved:
-  `match ip next-hop': New command.
-  `match metric': New command.
-  `set metric': Doc fixed.
-  `set local-preference': DEFUN added.
-
-* Changes in ripd
-
-** Check of announced network is added.  Now multicast address is
-filtered.  Reported by Carlos Alberto Barcenilla
-<barce@frlp.utn.edu.ar>
-
-** Check of network 127 is added.  Reported by Carlos Alberto
-Barcenilla <barce@frlp.utn.edu.ar>
-
-* Changes in ripngd
-
-** Aging route bug is fixed.
-
-** `router zebra' semantics changed.  ripngd automatically connect to
-zebra.
-
-* Changes in ospfd
-
-** `no router ospf' works.
-
-* Changes in ospf6d
-
-** Bug fix about network vertex.
-
-* Changes in zebra-0.64.1.
-
-This is bug fix release.
-
-* Changes in lib
-
-** Add check of sin6_scope_id in struct sockaddr_in6.  For compilation
-on implementation which doesn't have sin6_scope_id.  Reported by Wim
-Biemolt <Wim.Biemolt@ipv6.surfnet.nl>.
-
-* Changes in zebra
-
-** Fix bug of display BGP routes as "O" instead of "B".  Reported by
-"William F. Maton" <wmaton@enterprise.ic.gc.ca> and Dave Hartzell
-<hartzell@greatplains.net>.
-
-* Changes in bgpd
-
-** `no network IPV6_NETWORK' statement and `no neighbor IP_ADDR timers
-holdtime [TIMER]' statement doesn't work. Reported by Georg Hitsch
-<georg@atnet.at>.  Now both statement work.
-
-* Changes in ospfd
-
-** Last interface is not updated by ospf_if_update().  Reported by
-Dave Hartzell <hartzell@greatplains.net>.
-
-* Changes in ospf6d
-
-** Byte order of ifid is changed.  Due to this change, this code will
-not work with previous version, sorry.
-
-** Fix `show ip route' route type mismatch.
-
-** Fix bug of no network IPV6_NETWORK.
-
-** Important bug fix about intra-area-prefix-lsa.
-
-* Changes in zebra-0.64.
-
-* Changes in lib
-
-** prefix-list based filtering routine is added.  Currently used in
-bgpd but it will be in other daemons.
-
-* Changes in bgpd
-
-** `no router bgp' works.  But network statement is not cleared.  This
-should be fixed in next beta.
-
-** Route reflector related statement is added.
-
-  router bgp ASN
-    bgp cluster-id a.b.c.d
-    neighbor a.b.c.d route-reflector-client
-
-  is added.
-
-** Prefix list based filtering is added.
-
-  router bgp ASN
-    neighbor a.b.c.d prefix-list PREFIX_LIST_NAME
-
-** Prefix list based routing display works.
-
-  show ip bgp prefix-list PREFIX_LIST_NAME
-
-* Changes in ripd
-
-** Fix route metric check bug.  Reported from Mr. Carlos Alberto
-Barcenilla.
-
-* Changes in ospf6d
-
-** There are many changes.  If you have interested in ospf6d please
-visit ospf6d/README file.
-
-* Changes in zebra-0.63 first beta package.
-
-* Changes in lib
-
-** `copy running-config stgartup-config' command is added.
-
-** prefix length check bug is fixed.  Thanks Marlos Barcenilla
-<barce@frip.utn.edu.ar>.
-
-* Changes in ospfd
-
-** DR and BDR election works.
-
-** OSPF Hello simple authentication works.
-
-* Changes in ospf6d
-
-** Now ospf6d can be compiled on both Linux and *BSD system.
-
-* Changes in zebra-19990420 snapshot
-
-** `make dist' at top directory works now.
-
-* Changes in lib
-
-** VTY has now access-class to restrict remote connection.
-Implemented by Alex Bligh <amb@gxn.net>.
-
-!
-line vty
-  access-class ACCESS-LIST-NAME
-!
-
-** `show version' command added.  Implemented by Carlos Alberto
-Barcenilla <barce@frlp.utn.edu.ar>
-
-* Changes in zebra
-
-** `ip address' command on *BSD bug is fixed.
-
-** `no ip address' works now for IPv4 address.
-
-** Now `write terminal' display `ip address' configuration.
-
-* Changes in bgpd
-
-** Redistribute static works now.  Please run both zebra and bgpd.
-bgpd.conf should be like this:
-
-!
-router zebra
-!
-router bgp ASN
-  redisitribute static
-!
-
-* Changes in guile
-
-** configure --enable-guile turns on zebra-guile build.
-
-** (router-bgp ASN) allocates real bgp structre.
-
-* Changes in zebra-19990416 snapshot
-
-** Set version to 0.60 for preparation of beta release.
-
-** New directory guile is added for linking with guile interpreter.
-
-* Changes in zebra
-
-** On GNU/Linux Kernel 2.2.x (with netlink support), zebra detects
-asynchronous routing updates.  *BSD support is not yet finished.
-
-* Changes in bgpd
-
-** `show ip bgp regexp ASPATH_REGEX' uses CISCO like regular expression 
-instead of RPSL like regular expression.  I'm planing to provide RPSL
-like regular expression with `show ip bgp rpsl' or something.
-
-* Changes in lib
-
-** Press '?' at variable mandatory argument, vty prints nothing.  Now
-vty outputs description about the argument.  Fixed by Alex Bligh
-<amb@gxn.net>
-
-** buffer.c has some ugly bugs.  Due to the bug, vty interface hangs
-when large output date exists.  This bug is fixed. Reported by Alex
-Bligh <amb@gxn.net>.
-
-* Changes in ospfd
-
-** DR and BDR information is shown by `show ip ospf interface' command.
-
-* Changes in zebra-19990408 snapshot
-
-* Changes in bgpd
-
-** Old BGP-4+ specification (described in old draft) treatment bug is
-fixed.  It seems that mrtd uses this format as default.  So if you
-have problem peering with mrtd and want to use old draft format please
-use version statement like this.
-
-neighbor PEER_ADDRESS remote-as ASN
-neighbor PEER_ADDRESS version bgp4+-draft-00
-
-** When AS path is epmty (routes generated by bgpd), SEGV is occur
-when announce the routes to eBGP peer.  Reported by
-kad@gibson.skif.net.
-
-** ip as-path access-list command is added.
-
-** neighbor PEER_ADDRESS filter-list AS_LIST [in|out] command is added.
-
-** neighbor PEER_ADDRESS timers holdtimer TIMER command is added.
-
-* Changes in all daemons
-
-** With KAME stack, terminal interface is now bind AF_INET socket
-instead of AF_INET6 one.
-
-* Changes in zebra-19990403 snapshot
-
-* Changes in bgpd
-
-** When bgpd has 'router zebra', bgpd automatically select it's router
-ID as most highest interface's IP Address.
-
-** When AS path is empty (in case of iBGP), it doesn't include any AS
-segment.  This change is for announcement to gated under iBGP.
-
-* Changes in ospfd
-
-** OSPF hello packet send/receive works.
-
-* Changes in ospf6d
-
-** Yasuhiro Ohara's ospf6d codes is imported.  It is under development
-and can't be compiled on any platform.
-
-* Changes in zebra-19990327 snapshot
-
-* Changes in bgpd
-
-** When BGP-4+ connection is done by IPv6 link-local address.  One
-have to specify interface index for the connection.  So I've added
-interface statement to the neighbor commmand.  Please specify
-interface name for getting interface index like below.  This statement
-only works on GNU/Linux.  I'll support BSD ASAP.
-
-router bgp 7675
- neighbor fe80::200:f8ff:fe01:5fd3 remote-as 2500
- neighbor fe80::200:f8ff:fe01:5fd3 interface sit3
-
-** For disable BGP peering `shutdown' command is added.
-
-router bgp 7675
- neighbor 10.0.0.1 shutdown
-
-** `description' command is added to neighbor statement.
-
-router bgp 7675
- neighbor 10.0.0.1 description peering with Norway.
-
-** `show ip bgp regexp AS-REGEXP' works again.
-
-show ip bgp regexp AS7675
-
-will show routes which include AS7675.
-
-** When a route which is made from `network' statement is send to
-neighbor.  Set it's nexthop to self.  So 10.0.0.0/8 is announced to
-the peer A with source address 192.168.1.1.  The routes nexthop is set
-to 192.168.1.1.
-
-* Changes in zebra
-
-** In zebra/rtread_sysctl.c, function rtm_read() may overrun allocated
-buffer when the address family is not supported and the length is big
-(i.e link address).  Reported Achim Patzner <ap@bnc.net>.
-
-* Changes in ospfd
-
-** Now ospfd receive OSPF packet.
-
-* Changes in zebra-19990319 snapshot
-
-* Changes in configuration and libraries
-
-** User can disable IPv6 feature and/or pthread feature by configure
-   option.
-
-  To disable IPv6:    configure --disable-ipv6
-  To disable pthread: configure --disable-pthread
-
-** User can disable specified daemon by configure option.
-
-  Don't make zebra:  configure --disable-zebra
-  Don't make bgpd:   configure --disable-bgpd
-  Don't make ripd:   configure --disable-ripd
-  Don't make ripngd: configure --disable-ripngd
-  Don't make ospfd:  configure --disable-ospfd
-  Don't make ospf6d: configure --disable-ospf6d
-
-** Sample configuration files are installed as 600 file flag.
-   Suggested by Jeroen Ruigrok/Asmodai <asmodai@wxs.nl>.
-
-** syslog logging feature is added by Peter Galbavy
-   <Peter.Galbavy@knowledge.com>
-
-** Inclusion of standard header files is reworked by Peter Galbavy
-   <Peter.Galbavy@knowledge.com>
-
-** Change description from GNU/Linux 2.1.X to GNU/Linux 2.2.X
-
-** If daemon function exists in standard C library use it.
-
-** To generate configure script we upgrade autoconf to 2.13.  To
-generate Makefile.in we upgrade automake to 1.4.
-
-** doc/texinfo.tex is added to distribution.
-
-** Update ports/pkg/DESCR description.
-
-** Update doc/zebra.texi.
-
-** logfile FILENAME statement deleted.  Instead of that please use log
-file FILENAME.
-
-* Changes in zebra
-
-* Changes in bgpd
-
-** Communication between zebra and bgpd works now.  So if there is
-   `router zebra' line in bgpd.conf, selected route is installed
-   into kernel routing table.
-
-** Delete all routes which inserted by bgpd when bgpd dies.  If you
-want to retain routes even bgpd dies please specify [-r|--retain]
-option to bgpd.
-
-** BGP announcement code is reworked.  Now bgpd announce selected
-   routes to other peer.
-
-** All output bgp packet is buffered.  It's written to the socket when
-   it gets ready.
-
-** Output route-map works now.  You can specify output route-map by:
-
-   neighbor IP_ADDR route-map ROUTE_MAP_NAME out
-
-** New route-map command added.
-
-   set ip nexthop IP_ADDR
-   set ipv6 nexthop global IP_ADDR
-
-** Fix bug about unlock of the route_node structure.
-
-** BGP-4+ support is added.  bgpd can listen and speak BGP-4+ packet
-specified in RFC2283. You can view IPv6 bgp table by: `show ipv6 bgp'.
-
-** Meny packet overflow check is added.
-
-* Changes in ripd
-
-* Changes in ripngd
-
-* Changes in ospfd
-
-** ospfd work is started by Toshiaki Takada <takada@zebra.org>.  Now
-several files are included in ospfd directory.
-
-** ospf6d codes are merged from Yasuhiro Ohara <yasu@sfc.wide.ad.jp>'s
-ospfd work.  Now codes are located in ospf6d directory.
-
-
-Local variables:
-mode: outline
-paragraph-separate: "[         ]*$"
-end:
diff --git a/README b/README
deleted file mode 100644 (file)
index 7600ec5..0000000
--- a/README
+++ /dev/null
@@ -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
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..48142f2
--- /dev/null
+++ b/README.md
@@ -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
+```
index ff5cca42a0a89c688054db4253a3e1454d9d3a37..31778901a62efb8567c6ee8edbaa60c15ebb1246 100644 (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"
index ba2b58131c96ccac9036c519f7846aa9b53bbe55..d4c962af3b4390d38ce78ab57e1f742defe09003 100644 (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>
index c1592fb18a11c6167f05631e1f34063e170dff64..512b60e29a11491818dabfaf249ccf8b345cccb5 100644 (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>
index ad9a6bad92afad787eeb8a4e103cb676e4b18817..d1f6a4414291b2da7475c943f9ff96bc8bac7e1d 100644 (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>
index 1f219774424cc57a7e2ff33d6462b05524720804..8949075f67d0beaced0dddd29f878780f726305d 100644 (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>
index d6dd848952cb404f13c43cf2502fe49b643c9c96..75bca0620639d32f9f17cd01ea7b017818f8f0b0 100644 (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>
index 6f91f739307989a836dfbb9bb9ceb6c5a5d82032..e1f2cb0a00d78b2ecdfeb6b0736419bfc99baf1b 100644 (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 = \
index 4a3ecace0ccad0748ac8dca4463b93fa273586fc..880cda2fce7ceb540fa067642192081cb9e303f6 100644 (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>
index e554d1b33f68dcf17f10612280d4798d27fabcc0..2b020911fbe3d58ee9342efe8d36d69e0aabe33d 100644 (file)
@@ -1,3 +1,2 @@
 # ignore binary files
-*.a
 bfdd
index b3253a14d75150a26a4ed1ace5f50218c390277f..cf7c027db5d8f8022c1825a5473589cca5dae11a 100644 (file)
@@ -78,7 +78,7 @@ struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)
        } else {
                memset(&shop, 0, sizeof(shop));
                shop.peer = bpc->bpc_peer;
-               if (!bpc->bpc_has_vxlan && bpc->bpc_has_localif)
+               if (bpc->bpc_has_localif)
                        strlcpy(shop.port_name, bpc->bpc_localif,
                                sizeof(shop.port_name));
 
@@ -311,33 +311,6 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp, char *port_name,
        return l_bfd;
 }
 
-#if 0  /* TODO VxLAN Support */
-static void
-_update_vxlan_sess_parms(struct bfd_session *bfd, bfd_sess_parms *sess_parms)
-{
-       struct bfd_session_vxlan_info *vxlan_info = &bfd->vxlan_info;
-       bfd_parms_list *parms = &sess_parms->parms;
-
-       vxlan_info->vnid = parms->vnid;
-       vxlan_info->check_tnl_key = parms->check_tnl_key;
-       vxlan_info->forwarding_if_rx = parms->forwarding_if_rx;
-       vxlan_info->cpath_down = parms->cpath_down;
-       vxlan_info->decay_min_rx = parms->decay_min_rx;
-
-       inet_aton(parms->local_dst_ip, &vxlan_info->local_dst_ip);
-       inet_aton(parms->remote_dst_ip, &vxlan_info->peer_dst_ip);
-
-       memcpy(vxlan_info->local_dst_mac, parms->local_dst_mac, ETH_ALEN);
-       memcpy(vxlan_info->peer_dst_mac, parms->remote_dst_mac, ETH_ALEN);
-
-       /* The interface may change for Vxlan BFD sessions, so update
-        * the local mac and ifindex
-        */
-       bfd->ifindex = sess_parms->ifindex;
-       memcpy(bfd->local_mac, sess_parms->local_mac, sizeof(bfd->local_mac));
-}
-#endif /* VxLAN support */
-
 int bfd_xmt_cb(struct thread *t)
 {
        struct bfd_session *bs = THREAD_ARG(t);
@@ -364,7 +337,7 @@ int bfd_recvtimer_cb(struct thread *t)
        switch (bs->ses_state) {
        case PTM_BFD_INIT:
        case PTM_BFD_UP:
-               ptm_bfd_ses_dn(bs, BFD_DIAGDETECTTIME);
+               ptm_bfd_ses_dn(bs, BD_CONTROL_EXPIRED);
                bfd_recvtimer_update(bs);
                break;
 
@@ -387,7 +360,7 @@ int bfd_echo_recvtimer_cb(struct thread *t)
        switch (bs->ses_state) {
        case PTM_BFD_INIT:
        case PTM_BFD_UP:
-               ptm_bfd_ses_dn(bs, BFD_DIAGDETECTTIME);
+               ptm_bfd_ses_dn(bs, BD_ECHO_FAILED);
                break;
        }
 
@@ -535,8 +508,6 @@ static int bfd_session_update(struct bfd_session *bs, struct bfd_peer_cfg *bpc)
 
        _bfd_session_update(bs, bpc);
 
-       /* TODO add VxLAN support. */
-
        control_notify_config(BCM_NOTIFY_CONFIG_UPDATE, bs);
 
        return 0;
@@ -606,9 +577,6 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
                ptm_bfd_fetch_local_mac(bpc->bpc_localif, bfd->local_mac);
        }
 
-       if (bpc->bpc_has_vxlan)
-               BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_VXLAN);
-
        if (bpc->bpc_ipv4 == false) {
                BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6);
 
@@ -644,30 +612,13 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
                bfd_mhop_insert(bfd);
        } else {
                bfd->shop.peer = bpc->bpc_peer;
-               if (!bpc->bpc_has_vxlan && bpc->bpc_has_localif)
+               if (bpc->bpc_has_localif)
                        strlcpy(bfd->shop.port_name, bpc->bpc_localif,
                                sizeof(bfd->shop.port_name));
 
                bfd_shop_insert(bfd);
        }
 
-       if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_VXLAN)) {
-               static uint8_t bfd_def_vxlan_dmac[] = {0x00, 0x23, 0x20,
-                                                      0x00, 0x00, 0x01};
-               memcpy(bfd->peer_mac, bfd_def_vxlan_dmac,
-                      sizeof(bfd_def_vxlan_dmac));
-       }
-#if 0 /* TODO */
-       else if (event->rmac) {
-               if (sscanf(event->rmac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
-                   &bfd->peer_mac[0], &bfd->peer_mac[1], &bfd->peer_mac[2],
-                   &bfd->peer_mac[3], &bfd->peer_mac[4], &bfd->peer_mac[5])
-                   != 6)
-                       DLOG("%s: Assigning remote mac = %s", __func__,
-                            event->rmac);
-       }
-#endif
-
        /*
         * XXX: session update triggers echo start, so we must have our
         * discriminator ID set first.
index d665448abf79f1e0791db3d7bb6fd8eea525c00a..3a58a8d53cfeab25e889167cb18a1267c19bc882 100644 (file)
@@ -105,9 +105,6 @@ struct bfd_echo_pkt {
 #define BFD_CBIT 0x08
 #define BFD_ABIT 0x04
 #define BFD_DEMANDBIT 0x02
-#define BFD_DIAGNEIGHDOWN 3
-#define BFD_DIAGDETECTTIME 1
-#define BFD_DIAGADMINDOWN 7
 #define BFD_SETDEMANDBIT(flags, val)                                           \
        {                                                                      \
                if ((val))                                                     \
@@ -133,18 +130,27 @@ struct bfd_echo_pkt {
 #define BFD_GETSTATE(flags) ((flags >> 6) & 0x3)
 #define BFD_ECHO_VERSION 1
 #define BFD_ECHO_PKT_LEN sizeof(struct bfd_echo_pkt)
-#define BFD_CTRL_PKT_LEN sizeof(struct bfd_pkt)
-#define IP_HDR_LEN 20
-#define UDP_HDR_LEN 8
-#define ETH_HDR_LEN 14
-#define VXLAN_HDR_LEN 8
-#define HEADERS_MIN_LEN (ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN)
-#define BFD_ECHO_PKT_TOT_LEN                                                   \
-       ((int)(ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN + BFD_ECHO_PKT_LEN))
-#define BFD_VXLAN_PKT_TOT_LEN                                                  \
-       ((int)(VXLAN_HDR_LEN + ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN          \
-              + BFD_CTRL_PKT_LEN))
-#define BFD_RX_BUF_LEN 160
+
+enum bfd_diagnosticis {
+       BD_OK = 0,
+       /* Control Detection Time Expired. */
+       BD_CONTROL_EXPIRED = 1,
+       /* Echo Function Failed. */
+       BD_ECHO_FAILED = 2,
+       /* Neighbor Signaled Session Down. */
+       BD_NEIGHBOR_DOWN = 3,
+       /* Forwarding Plane Reset. */
+       BD_FORWARDING_RESET = 4,
+       /* Path Down. */
+       BD_PATH_DOWN = 5,
+       /* Concatenated Path Down. */
+       BD_CONCATPATH_DOWN = 6,
+       /* Administratively Down. */
+       BD_ADMIN_DOWN = 7,
+       /* Reverse Concatenated Path Down. */
+       BD_REVCONCATPATH_DOWN = 8,
+       /* 9..31: reserved. */
+};
 
 /* BFD session flags */
 enum bfd_session_flags {
@@ -154,9 +160,6 @@ enum bfd_session_flags {
                                             * actively
                                             */
        BFD_SESS_FLAG_MH = 1 << 2,        /* BFD Multi-hop session */
-       BFD_SESS_FLAG_VXLAN = 1 << 3,       /* BFD Multi-hop session which is
-                                            * used to monitor vxlan tunnel
-                                            */
        BFD_SESS_FLAG_IPV6 = 1 << 4,    /* BFD IPv6 session */
        BFD_SESS_FLAG_SEND_EVT_ACTIVE = 1 << 5, /* send event timer active */
        BFD_SESS_FLAG_SEND_EVT_IGNORE = 1 << 6, /* ignore send event when timer
@@ -191,18 +194,6 @@ struct bfd_session_stats {
        uint64_t znotification;
 };
 
-struct bfd_session_vxlan_info {
-       uint32_t vnid;
-       uint32_t decay_min_rx;
-       uint8_t forwarding_if_rx;
-       uint8_t cpath_down;
-       uint8_t check_tnl_key;
-       uint8_t local_dst_mac[ETHERNET_ADDRESS_LENGTH];
-       uint8_t peer_dst_mac[ETHERNET_ADDRESS_LENGTH];
-       struct in_addr local_dst_ip;
-       struct in_addr peer_dst_ip;
-};
-
 /* bfd_session shortcut label forwarding. */
 struct peer_label;
 
@@ -249,16 +240,11 @@ struct bfd_session {
        int ifindex;
        uint8_t local_mac[ETHERNET_ADDRESS_LENGTH];
        uint8_t peer_mac[ETHERNET_ADDRESS_LENGTH];
-       uint16_t ip_id;
 
        /* BFD session flags */
        enum bfd_session_flags flags;
 
-       uint8_t echo_pkt[BFD_ECHO_PKT_TOT_LEN]; /* Save the Echo Packet
-                                                * which will be transmitted
-                                                */
        struct bfd_session_stats stats;
-       struct bfd_session_vxlan_info vxlan_info;
 
        struct timeval uptime;   /* last up time */
        struct timeval downtime; /* last down time */
@@ -407,7 +393,7 @@ struct bfd_global {
        int bg_shop6;
        int bg_mhop6;
        int bg_echo;
-       int bg_vxlan;
+       int bg_echov6;
        struct thread *bg_ev[6];
 
        int bg_csock;
@@ -473,10 +459,10 @@ void log_fatal(const char *fmt, ...);
  *
  * Contains the code related with receiving/seding, packing/unpacking BFD data.
  */
-int bp_set_ttlv6(int sd);
-int bp_set_ttl(int sd);
-int bp_set_tosv6(int sd);
-int bp_set_tos(int sd);
+int bp_set_ttlv6(int sd, uint8_t value);
+int bp_set_ttl(int sd, uint8_t value);
+int bp_set_tosv6(int sd, uint8_t value);
+int bp_set_tos(int sd, uint8_t value);
 int bp_bind_dev(int sd, const char *dev);
 
 int bp_udp_shop(void);
@@ -485,14 +471,14 @@ int bp_udp6_shop(void);
 int bp_udp6_mhop(void);
 int bp_peer_socket(struct bfd_peer_cfg *bpc);
 int bp_peer_socketv6(struct bfd_peer_cfg *bpc);
+int bp_echo_socket(void);
+int bp_echov6_socket(void);
 
 void ptm_bfd_snd(struct bfd_session *bfd, int fbit);
 void ptm_bfd_echo_snd(struct bfd_session *bfd);
 
 int bfd_recv_cb(struct thread *t);
 
-uint16_t checksum(uint16_t *buf, int len);
-
 
 /*
  * event.c
@@ -602,30 +588,13 @@ int ptm_bfd_notify(struct bfd_session *bs);
 /*
  * OS compatibility functions.
  */
-struct udp_psuedo_header {
-       uint32_t saddr;
-       uint32_t daddr;
-       uint8_t reserved;
-       uint8_t protocol;
-       uint16_t len;
-};
-
-#define UDP_PSUEDO_HDR_LEN sizeof(struct udp_psuedo_header)
-
 #if defined(BFD_LINUX) || defined(BFD_BSD)
 int ptm_bfd_fetch_ifindex(const char *ifname);
 void ptm_bfd_fetch_local_mac(const char *ifname, uint8_t *mac);
 void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen);
-int ptm_bfd_echo_sock_init(void);
-int ptm_bfd_vxlan_sock_init(void);
 #endif /* BFD_LINUX || BFD_BSD */
 
-#ifdef BFD_LINUX
-uint16_t udp4_checksum(struct iphdr *iph, uint8_t *buf, int len);
-#endif /* BFD_LINUX */
-
 #ifdef BFD_BSD
-uint16_t udp4_checksum(struct ip *ip, uint8_t *buf, int len);
 ssize_t bsd_echo_sock_read(int sd, uint8_t *buf, ssize_t *buflen,
                           struct sockaddr_storage *ss, socklen_t *sslen,
                           uint8_t *ttl, uint32_t *id);
index 543181a12a1af719934ed537e132ec685910621e..8acb9438c564662af5ccc903ce3becb3229ebe5b 100644 (file)
 
 #include "bfd.h"
 
-/*
- * Definitions
- */
-
-/* iov for BFD control frames */
-#define CMSG_HDR_LEN sizeof(struct cmsghdr)
-#define CMSG_TTL_LEN (CMSG_HDR_LEN + sizeof(uint32_t))
-#define CMSG_IN_PKT_INFO_LEN (CMSG_HDR_LEN + sizeof(struct in_pktinfo) + 4)
-#define CMSG_IN6_PKT_INFO_LEN                                                  \
-       (CMSG_HDR_LEN + sizeof(struct in6_addr) + sizeof(int) + 4)
-
-struct bfd_raw_echo_pkt {
-#ifdef BFD_LINUX
-       struct iphdr ip;
-#endif /* BFD_LINUX */
-#ifdef BFD_BSD
-       struct ip ip;
-#endif /* BFD_BSD */
-       struct udphdr udp;
-       struct bfd_echo_pkt data;
-};
-
-#if 0 /* TODO: VxLAN support. */
-struct bfd_raw_ctrl_pkt {
-       struct iphdr ip;
-       struct udphdr udp;
-       struct bfd_pkt data;
-};
-#endif
-
-struct vxlan_hdr {
-       uint32_t flags;
-       uint32_t vnid;
-};
-
-#define IP_ECHO_PKT_LEN (IP_HDR_LEN + UDP_HDR_LEN + BFD_ECHO_PKT_LEN)
-#define UDP_ECHO_PKT_LEN (UDP_HDR_LEN + BFD_ECHO_PKT_LEN)
-#define IP_CTRL_PKT_LEN (IP_HDR_LEN + UDP_HDR_LEN + BFD_PKT_LEN)
-#define UDP_CTRL_PKT_LEN (UDP_HDR_LEN + BFD_PKT_LEN)
-
-static uint8_t msgbuf[BFD_PKT_LEN];
-
-static int ttlval = BFD_TTL_VAL;
-static int tosval = BFD_TOS_VAL;
-static int rcvttl = BFD_RCV_TTL_VAL;
 
 /*
  * Prototypes
  */
-static uint16_t ptm_bfd_gen_IP_ID(struct bfd_session *bfd);
-static void ptm_bfd_echo_pkt_create(struct bfd_session *bfd);
-static int ptm_bfd_echo_loopback(uint8_t *pkt, int pkt_len, struct sockaddr *ss,
-                                socklen_t sslen);
-static void ptm_bfd_vxlan_pkt_snd(struct bfd_session *bfd, int fbit);
 static int ptm_bfd_process_echo_pkt(int s);
-static bool
-ptm_bfd_validate_vxlan_pkt(struct bfd_session *bfd,
-                          struct bfd_session_vxlan_info *vxlan_info);
+int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
+                 size_t datalen);
 
 static void bfd_sd_reschedule(int sd);
-static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
-                            char *vrfname, size_t vrfnamelen,
-                            struct sockaddr_any *local,
-                            struct sockaddr_any *peer);
-static ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
-                            char *vrfname, size_t vrfnamelen,
-                            struct sockaddr_any *local,
-                            struct sockaddr_any *peer);
+ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
+                     char *port, size_t portlen, char *vrfname,
+                     size_t vrfnamelen, struct sockaddr_any *local,
+                     struct sockaddr_any *peer);
+ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
+                     char *port, size_t portlen, char *vrfname,
+                     size_t vrfnamelen, struct sockaddr_any *local,
+                     struct sockaddr_any *peer);
+int bp_udp_send(int sd, uint8_t ttl, uint8_t *data, size_t datalen,
+               struct sockaddr *to, socklen_t tolen);
+int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr);
 
 /* socket related prototypes */
 static void bp_set_ipopts(int sd);
@@ -116,68 +68,17 @@ static void bp_bind_ipv6(int sd, uint16_t port);
 /*
  * Functions
  */
-uint16_t checksum(uint16_t *buf, int len)
-{
-       int nbytes = len;
-       int sum = 0;
-       uint16_t csum = 0;
-       int size = sizeof(uint16_t);
-
-       while (nbytes > 1) {
-               sum += *buf++;
-               nbytes -= size;
-       }
-
-       if (nbytes == 1) {
-               *(uint8_t *)(&csum) = *(uint8_t *)buf;
-               sum += csum;
-       }
-
-       sum = (sum >> 16) + (sum & 0xFFFF);
-       sum += (sum >> 16);
-       csum = ~sum;
-       return csum;
-}
-
-static uint16_t ptm_bfd_gen_IP_ID(struct bfd_session *bfd)
-{
-       return (++bfd->ip_id);
-}
-
-static int _ptm_bfd_send(struct bfd_session *bs, bool use_layer2,
-                        uint16_t *port, const void *data, size_t datalen)
+int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
+                 size_t datalen)
 {
        struct sockaddr *sa;
        struct sockaddr_in sin;
        struct sockaddr_in6 sin6;
-#ifdef BFD_LINUX
-       struct sockaddr_ll dll;
-#endif /* BFD_LINUX */
        socklen_t slen;
        ssize_t rv;
        int sd = -1;
 
-       if (use_layer2) {
-#ifdef BFD_LINUX
-               memset(&dll, 0, sizeof(dll));
-               dll.sll_family = AF_PACKET;
-               dll.sll_protocol = htons(ETH_P_IP);
-               memcpy(dll.sll_addr, bs->peer_mac, ETHERNET_ADDRESS_LENGTH);
-               dll.sll_halen = htons(ETHERNET_ADDRESS_LENGTH);
-               dll.sll_ifindex = bs->ifindex;
-
-               sd = bglobal.bg_echo;
-               sa = (struct sockaddr *)&dll;
-               slen = sizeof(dll);
-#else
-               /*
-                * TODO: implement layer 2 send for *BSDs. This is
-                * needed for VxLAN.
-                */
-               log_warning("packet-send: not implemented");
-               return -1;
-#endif
-       } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6)) {
+       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6)) {
                memset(&sin6, 0, sizeof(sin6));
                sin6.sin6_family = AF_INET6;
                sin6.sin6_addr = bs->shop.peer.sa_sin6.sin6_addr;
@@ -219,332 +120,63 @@ static int _ptm_bfd_send(struct bfd_session *bs, bool use_layer2,
        return 0;
 }
 
-static void ptm_bfd_echo_pkt_create(struct bfd_session *bfd)
-{
-       struct bfd_raw_echo_pkt ep;
-       uint8_t *pkt = bfd->echo_pkt;
-
-       memset(&ep, 0, sizeof(ep));
-       memset(bfd->echo_pkt, 0, sizeof(bfd->echo_pkt));
-
-       /* Construct ethernet header information */
-       memcpy(pkt, bfd->peer_mac, ETHERNET_ADDRESS_LENGTH);
-       pkt = pkt + ETHERNET_ADDRESS_LENGTH;
-       memcpy(pkt, bfd->local_mac, ETHERNET_ADDRESS_LENGTH);
-       pkt = pkt + ETHERNET_ADDRESS_LENGTH;
-#ifdef BFD_LINUX
-       pkt[0] = ETH_P_IP / 256;
-       pkt[1] = ETH_P_IP % 256;
-#endif /* BFD_LINUX */
-#ifdef BFD_BSD
-       pkt[0] = ETHERTYPE_IP / 256;
-       pkt[1] = ETHERTYPE_IP % 256;
-#endif /* BFD_BSD */
-       pkt += 2;
-
-       /* Construct IP header information */
-#ifdef BFD_LINUX
-       ep.ip.version = 4;
-       ep.ip.ihl = 5;
-       ep.ip.tos = 0;
-       ep.ip.tot_len = htons(IP_ECHO_PKT_LEN);
-       ep.ip.id = htons(ptm_bfd_gen_IP_ID(bfd));
-       ep.ip.frag_off = 0;
-       ep.ip.ttl = BFD_TTL_VAL;
-       ep.ip.protocol = IPPROTO_UDP;
-       ep.ip.saddr = bfd->local_ip.sa_sin.sin_addr.s_addr;
-       ep.ip.daddr = bfd->shop.peer.sa_sin.sin_addr.s_addr;
-       ep.ip.check = checksum((uint16_t *)&ep.ip, IP_HDR_LEN);
-#endif /* BFD_LINUX */
-#ifdef BFD_BSD
-       ep.ip.ip_v = 4;
-       ep.ip.ip_hl = 5;
-       ep.ip.ip_tos = 0;
-       ep.ip.ip_len = htons(IP_ECHO_PKT_LEN);
-       ep.ip.ip_id = htons(ptm_bfd_gen_IP_ID(bfd));
-       ep.ip.ip_off = 0;
-       ep.ip.ip_ttl = BFD_TTL_VAL;
-       ep.ip.ip_p = IPPROTO_UDP;
-       ep.ip.ip_src = bfd->local_ip.sa_sin.sin_addr;
-       ep.ip.ip_dst = bfd->shop.peer.sa_sin.sin_addr;
-       ep.ip.ip_sum = checksum((uint16_t *)&ep.ip, IP_HDR_LEN);
-#endif /* BFD_BSD */
-
-       /* Construct UDP header information */
-#ifdef BFD_LINUX
-       ep.udp.source = htons(BFD_DEF_ECHO_PORT);
-       ep.udp.dest = htons(BFD_DEF_ECHO_PORT);
-       ep.udp.len = htons(UDP_ECHO_PKT_LEN);
-#endif /* BFD_LINUX */
-#ifdef BFD_BSD
-       ep.udp.uh_sport = htons(BFD_DEF_ECHO_PORT);
-       ep.udp.uh_dport = htons(BFD_DEF_ECHO_PORT);
-       ep.udp.uh_ulen = htons(UDP_ECHO_PKT_LEN);
-#endif /* BFD_BSD */
-
-       /* Construct Echo packet information */
-       ep.data.ver = BFD_ECHO_VERSION;
-       ep.data.len = BFD_ECHO_PKT_LEN;
-       ep.data.my_discr = htonl(bfd->discrs.my_discr);
-#ifdef BFD_LINUX
-       ep.udp.check =
-#endif /* BFD_LINUX */
-#ifdef BFD_BSD
-       ep.udp.uh_sum =
-#endif /* BFD_BSD */
-               udp4_checksum(&ep.ip, (uint8_t *)&ep.udp,
-                             UDP_ECHO_PKT_LEN);
-
-       memcpy(pkt, &ep, sizeof(ep));
-}
-
 void ptm_bfd_echo_snd(struct bfd_session *bfd)
 {
-       struct bfd_raw_echo_pkt *ep;
-       bool use_layer2 = false;
-       const void *pkt;
-       size_t pktlen;
-       uint16_t port = htons(BFD_DEF_ECHO_PORT);
+       struct sockaddr_any *sa;
+       socklen_t salen;
+       int sd;
+       struct bfd_echo_pkt bep;
+       struct sockaddr_in sin;
+       struct sockaddr_in6 sin6;
 
-       if (!BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE)) {
-               ptm_bfd_echo_pkt_create(bfd);
+       if (!BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
                BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE);
-       } else {
-               /* just update the checksum and ip Id */
-               ep = (struct bfd_raw_echo_pkt *)(bfd->echo_pkt + ETH_HDR_LEN);
-#ifdef BFD_LINUX
-               ep->ip.id = htons(ptm_bfd_gen_IP_ID(bfd));
-               ep->ip.check = 0;
-               ep->ip.check = checksum((uint16_t *)&ep->ip, IP_HDR_LEN);
-#endif /* BFD_LINUX */
-#ifdef BFD_BSD
-               ep->ip.ip_id = htons(ptm_bfd_gen_IP_ID(bfd));
-               ep->ip.ip_sum = 0;
-               ep->ip.ip_sum = checksum((uint16_t *)&ep->ip, IP_HDR_LEN);
-#endif /* BFD_BSD */
-       }
 
-       if (use_layer2) {
-               pkt = bfd->echo_pkt;
-               pktlen = BFD_ECHO_PKT_TOT_LEN;
+       memset(&bep, 0, sizeof(bep));
+       bep.ver = BFD_ECHO_VERSION;
+       bep.len = BFD_ECHO_PKT_LEN;
+       bep.my_discr = htonl(bfd->discrs.my_discr);
+
+       sa = BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_MH) ? &bfd->mhop.peer
+                                                         : &bfd->shop.peer;
+       if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6)) {
+               sd = bglobal.bg_echov6;
+               sin6 = sa->sa_sin6;
+               sin6.sin6_port = htons(BFD_DEF_ECHO_PORT);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+               sin6.sin6_len = sizeof(sin6);
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+               sa = (struct sockaddr_any *)&sin6;
+               salen = sizeof(sin6);
        } else {
-               pkt = &bfd->echo_pkt[ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN];
-               pktlen = BFD_ECHO_PKT_TOT_LEN
-                        - (ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN);
-       }
+               sd = bglobal.bg_echo;
+               sin = sa->sa_sin;
+               sin.sin_port = htons(BFD_DEF_ECHO_PORT);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+               sin.sin_len = sizeof(sin);
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
 
-       if (_ptm_bfd_send(bfd, use_layer2, &port, pkt, pktlen) != 0) {
-               log_debug("echo-packet: send failure: %s", strerror(errno));
-               return;
+               sa = (struct sockaddr_any *)&sin;
+               salen = sizeof(sin);
        }
+       if (bp_udp_send(sd, BFD_TTL_VAL, (uint8_t *)&bep, sizeof(bep),
+                       (struct sockaddr *)sa, salen)
+           == -1)
+               return;
 
        bfd->stats.tx_echo_pkt++;
 }
 
-static int ptm_bfd_echo_loopback(uint8_t *pkt, int pkt_len, struct sockaddr *ss,
-                                socklen_t sslen)
-{
-#ifdef BFD_LINUX
-       struct bfd_raw_echo_pkt *ep =
-               (struct bfd_raw_echo_pkt *)(pkt + ETH_HDR_LEN);
-       uint8_t temp_mac[ETHERNET_ADDRESS_LENGTH];
-       uint32_t temp_ip;
-       struct ethhdr *eth = (struct ethhdr *)pkt;
-
-       /* swap the mac addresses */
-       memcpy(temp_mac, eth->h_source, ETHERNET_ADDRESS_LENGTH);
-       memcpy(eth->h_source, eth->h_dest, ETHERNET_ADDRESS_LENGTH);
-       memcpy(eth->h_dest, temp_mac, ETHERNET_ADDRESS_LENGTH);
-
-       /* swap ip addresses */
-       temp_ip = ep->ip.saddr;
-       ep->ip.saddr = ep->ip.daddr;
-       ep->ip.daddr = temp_ip;
-
-       ep->ip.ttl = ep->ip.ttl - 1;
-       ep->ip.check = 0;
-       ep->ip.check = checksum((uint16_t *)ep, IP_HDR_LEN);
-#endif /* BFD_LINUX */
-#ifdef BFD_BSD_FILTER
-       struct bfd_raw_echo_pkt_t *ep =
-               (struct bfd_raw_echo_pkt *)(pkt + ETH_HDR_LEN);
-       uint8_t temp_mac[ETHERNET_ADDRESS_LENGTH];
-       struct in_addr temp_ip;
-       struct ether_header *ether = (struct ether_header *)pkt;
-
-       /*
-        * TODO: this is not yet implemented and requires BPF code for
-        * OmniOS, NetBSD and FreeBSD9.
-        */
-
-       /* swap the mac addresses */
-       memcpy(temp_mac, ether->ether_shost, ETHERNET_ADDRESS_LENGTH);
-       memcpy(ether->ether_shost, ether->ether_dhost, ETHERNET_ADDRESS_LENGTH);
-       memcpy(ether->ether_dhost, temp_mac, ETHERNET_ADDRESS_LENGTH);
-
-       /* swap ip addresses */
-       temp_ip = ep->ip.ip_src;
-       ep->ip.ip_src = ep->ip.ip_dst;
-       ep->ip.ip_dst = temp_ip;
-
-       ep->ip.ip_ttl = ep->ip.ip_ttl - 1;
-       ep->ip.ip_sum = 0;
-       ep->ip.ip_sum = checksum((uint16_t *)ep, IP_HDR_LEN);
-#endif /* BFD_BSD_FILTER */
-
-       if (sendto(bglobal.bg_echo, pkt, pkt_len, 0, ss, sslen) < 0) {
-               log_debug("echo-loopback: send failure: %s", strerror(errno));
-               return -1;
-       }
-
-       return 0;
-}
-
-static void ptm_bfd_vxlan_pkt_snd(struct bfd_session *bfd
-                                 __attribute__((__unused__)),
-                                 int fbit __attribute__((__unused__)))
-{
-#if 0 /* TODO: VxLAN support. */
-       struct bfd_raw_ctrl_pkt cp;
-       uint8_t vxlan_pkt[BFD_VXLAN_PKT_TOT_LEN];
-       uint8_t *pkt = vxlan_pkt;
-       struct sockaddr_in sin;
-       struct vxlan_hdr *vhdr;
-
-       memset(vxlan_pkt, 0, sizeof(vxlan_pkt));
-       memset(&cp, 0, sizeof(cp));
-
-       /* Construct VxLAN header information */
-       vhdr = (struct vxlan_hdr *)pkt;
-       vhdr->flags = htonl(0x08000000);
-       vhdr->vnid = htonl(bfd->vxlan_info.vnid << 8);
-       pkt += VXLAN_HDR_LEN;
-
-       /* Construct ethernet header information */
-       memcpy(pkt, bfd->vxlan_info.peer_dst_mac, ETHERNET_ADDRESS_LENGTH);
-       pkt = pkt + ETHERNET_ADDRESS_LENGTH;
-       memcpy(pkt, bfd->vxlan_info.local_dst_mac, ETHERNET_ADDRESS_LENGTH);
-       pkt = pkt + ETHERNET_ADDRESS_LENGTH;
-       pkt[0] = ETH_P_IP / 256;
-       pkt[1] = ETH_P_IP % 256;
-       pkt += 2;
-
-       /* Construct IP header information */
-       cp.ip.version = 4;
-       cp.ip.ihl = 5;
-       cp.ip.tos = 0;
-       cp.ip.tot_len = htons(IP_CTRL_PKT_LEN);
-       cp.ip.id = ptm_bfd_gen_IP_ID(bfd);
-       cp.ip.frag_off = 0;
-       cp.ip.ttl = BFD_TTL_VAL;
-       cp.ip.protocol = IPPROTO_UDP;
-       cp.ip.daddr = bfd->vxlan_info.peer_dst_ip.s_addr;
-       cp.ip.saddr = bfd->vxlan_info.local_dst_ip.s_addr;
-       cp.ip.check = checksum((uint16_t *)&cp.ip, IP_HDR_LEN);
-
-       /* Construct UDP header information */
-       cp.udp.source = htons(BFD_DEFDESTPORT);
-       cp.udp.dest = htons(BFD_DEFDESTPORT);
-       cp.udp.len = htons(UDP_CTRL_PKT_LEN);
-
-       /* Construct BFD control packet information */
-       cp.data.diag = bfd->local_diag;
-       BFD_SETVER(cp.data.diag, BFD_VERSION);
-       BFD_SETSTATE(cp.data.flags, bfd->ses_state);
-       BFD_SETDEMANDBIT(cp.data.flags, BFD_DEF_DEMAND);
-       BFD_SETPBIT(cp.data.flags, bfd->polling);
-       BFD_SETFBIT(cp.data.flags, fbit);
-       cp.data.detect_mult = bfd->detect_mult;
-       cp.data.len = BFD_PKT_LEN;
-       cp.data.discrs.my_discr = htonl(bfd->discrs.my_discr);
-       cp.data.discrs.remote_discr = htonl(bfd->discrs.remote_discr);
-       cp.data.timers.desired_min_tx = htonl(bfd->timers.desired_min_tx);
-       cp.data.timers.required_min_rx = htonl(bfd->timers.required_min_rx);
-       cp.data.timers.required_min_echo = htonl(bfd->timers.required_min_echo);
-
-       cp.udp.check =
-               udp4_checksum(&cp.ip, (uint8_t *)&cp.udp, UDP_CTRL_PKT_LEN);
-
-       memcpy(pkt, &cp, sizeof(cp));
-       sin.sin_family = AF_INET;
-       sin.sin_addr = bfd->shop.peer.sa_sin.sin_addr;
-       sin.sin_port = htons(4789);
-
-       if (sendto(bfd->sock, vxlan_pkt, BFD_VXLAN_PKT_TOT_LEN, 0,
-                  (struct sockaddr *)&sin, sizeof(struct sockaddr_in))
-           < 0) {
-               ERRLOG("Error sending vxlan bfd pkt: %s", strerror(errno));
-       } else {
-               bfd->stats.tx_ctrl_pkt++;
-       }
-#endif
-}
-
 static int ptm_bfd_process_echo_pkt(int s)
 {
-       uint32_t my_discr = 0;
-       struct sockaddr_storage ss;
-       socklen_t sslen = sizeof(ss);
-       uint8_t rx_pkt[BFD_RX_BUF_LEN];
-       ssize_t pkt_len = sizeof(rx_pkt);
        struct bfd_session *bfd;
-#ifdef BFD_LINUX
-       struct bfd_raw_echo_pkt *ep;
-
-       /*
-        * valgrind: memset() ss so valgrind doesn't complain about
-        * uninitialized memory.
-        */
-       memset(&ss, 0, sizeof(ss));
-       pkt_len = recvfrom(s, rx_pkt, sizeof(rx_pkt), MSG_DONTWAIT,
-                          (struct sockaddr *)&ss, &sslen);
-       if (pkt_len <= 0) {
-               if (errno != EAGAIN)
-                       log_error("echo-packet: read failure: %s",
-                                 strerror(errno));
-
-               return -1;
-       }
-
-       /* Check if we have at least the basic headers to send back. */
-       if (pkt_len < BFD_ECHO_PKT_TOT_LEN) {
-               log_debug("echo-packet: too short (got %ld, expected %d)",
-                         pkt_len, BFD_ECHO_PKT_TOT_LEN);
-               return -1;
-       }
-
-       ep = (struct bfd_raw_echo_pkt *)(rx_pkt + ETH_HDR_LEN);
-       /* if TTL = 255, assume that the received echo packet has
-        * to be looped back
-        */
-       if (ep->ip.ttl == BFD_TTL_VAL)
-               return ptm_bfd_echo_loopback(rx_pkt, pkt_len,
-                                            (struct sockaddr *)&ss,
-                                            sizeof(struct sockaddr_ll));
-
-       my_discr = ntohl(ep->data.my_discr);
-       if (ep->data.my_discr == 0) {
-               log_debug("echo-packet: 'my discriminator' is zero");
-               return -1;
-       }
-#endif /* BFD_LINUX */
-#ifdef BFD_BSD
-       int rv;
-       uint8_t ttl;
-
-       /*
-        * bsd_echo_sock_read() already treats invalid TTL values and
-        * zeroed discriminators.
-        */
-       rv = bsd_echo_sock_read(s, rx_pkt, &pkt_len, &ss, &sslen, &ttl,
-                               &my_discr);
-       if (rv == -1)
-               return -1;
+       uint32_t my_discr = 0;
+       uint8_t ttl = 0;
 
-       if (ttl == BFD_TTL_VAL)
-               return ptm_bfd_echo_loopback(rx_pkt, pkt_len,
-                                            (struct sockaddr *)&ss, sslen);
-#endif /* BFD_BSD */
+       /* Receive and parse echo packet. */
+       if (bp_bfd_echo_in(s, &ttl, &my_discr) == -1)
+               return 0;
 
        /* Your discriminator not zero - use it to find session */
        bfd = bfd_id_lookup(my_discr);
@@ -554,8 +186,8 @@ static int ptm_bfd_process_echo_pkt(int s)
        }
 
        if (!BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE)) {
-               log_debug("echo-packet: echo disabled [%s]", my_discr,
-                         bs_to_string(bfd));
+               log_debug("echo-packet: echo disabled [%s] (id:%u)",
+                         bs_to_string(bfd), my_discr);
                return -1;
        }
 
@@ -574,14 +206,6 @@ void ptm_bfd_snd(struct bfd_session *bfd, int fbit)
 {
        struct bfd_pkt cp;
 
-       /* if the BFD session is for VxLAN tunnel, then construct and
-        * send bfd raw packet
-        */
-       if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_VXLAN)) {
-               ptm_bfd_vxlan_pkt_snd(bfd, fbit);
-               return;
-       }
-
        /* Set fields according to section 6.5.7 */
        cp.diag = bfd->local_diag;
        BFD_SETVER(cp.diag, BFD_VERSION);
@@ -605,98 +229,16 @@ void ptm_bfd_snd(struct bfd_session *bfd, int fbit)
        }
        cp.timers.required_min_echo = htonl(bfd->timers.required_min_echo);
 
-       if (_ptm_bfd_send(bfd, false, NULL, &cp, BFD_PKT_LEN) != 0)
+       if (_ptm_bfd_send(bfd, NULL, &cp, BFD_PKT_LEN) != 0)
                return;
 
        bfd->stats.tx_ctrl_pkt++;
 }
 
-#if 0  /* TODO VxLAN Support */
-static struct bfd_pkt *
-ptm_bfd_process_vxlan_pkt(int s, ptm_sockevent_e se, void *udata, int *ifindex,
-                         struct sockaddr_in *sin,
-                         struct bfd_session_vxlan_info_t *vxlan_info,
-                         uint8_t *rx_pkt, int *mlen)
-{
-       struct sockaddr_ll sll;
-       uint32_t from_len = sizeof(struct sockaddr_ll);
-       struct bfd_raw_ctrl_pkt *cp;
-       uint8_t *pkt = rx_pkt;
-       struct iphdr *iph;
-       struct ethhdr *inner_ethh;
-
-       *mlen = recvfrom(s, rx_pkt, BFD_RX_BUF_LEN, MSG_DONTWAIT,
-                        (struct sockaddr *)&sll, &from_len);
-
-       if (*mlen < 0) {
-               if (errno != EAGAIN)
-                       ERRLOG("Error receiving from BFD Vxlan socket %d: %m",
-                              s);
-               return NULL;
-       }
-
-       iph = (struct iphdr *)(pkt + ETH_HDR_LEN);
-       pkt = pkt + ETH_HDR_LEN + IP_HDR_LEN + UDP_HDR_LEN;
-       vxlan_info->vnid = ntohl(*((int *)(pkt + 4)));
-       vxlan_info->vnid = vxlan_info->vnid >> 8;
-
-       pkt = pkt + VXLAN_HDR_LEN;
-       inner_ethh = (struct ethhdr *)pkt;
-
-       cp = (struct bfd_raw_ctrl_pkt *)(pkt + ETH_HDR_LEN);
-
-       /* Discard the non BFD packets */
-       if (ntohs(cp->udp.dest) != BFD_DEFDESTPORT)
-               return NULL;
-
-       *ifindex = sll.sll_ifindex;
-       sin->sin_addr.s_addr = iph->saddr;
-       sin->sin_port = ntohs(cp->udp.dest);
-
-       vxlan_info->local_dst_ip.s_addr = cp->ip.daddr;
-       memcpy(vxlan_info->local_dst_mac, inner_ethh->h_dest,
-              ETHERNET_ADDRESS_LENGTH);
-
-       return &cp->data;
-}
-#endif /* VxLAN */
-
-static bool
-ptm_bfd_validate_vxlan_pkt(struct bfd_session *bfd,
-                          struct bfd_session_vxlan_info *vxlan_info)
-{
-       if (bfd->vxlan_info.check_tnl_key && (vxlan_info->vnid != 0)) {
-               log_error("vxlan-packet: vnid not zero: %d", vxlan_info->vnid);
-               return false;
-       }
-
-       if (bfd->vxlan_info.local_dst_ip.s_addr
-           != vxlan_info->local_dst_ip.s_addr) {
-               log_error("vxlan-packet: wrong inner destination",
-                         inet_ntoa(vxlan_info->local_dst_ip));
-               return false;
-       }
-
-       if (memcmp(bfd->vxlan_info.local_dst_mac, vxlan_info->local_dst_mac,
-                  ETHERNET_ADDRESS_LENGTH)) {
-               log_error(
-                       "vxlan-packet: wrong inner mac: %02x:%02x:%02x:%02x:%02x:%02x",
-                       vxlan_info->local_dst_mac[0],
-                       vxlan_info->local_dst_mac[1],
-                       vxlan_info->local_dst_mac[2],
-                       vxlan_info->local_dst_mac[3],
-                       vxlan_info->local_dst_mac[4],
-                       vxlan_info->local_dst_mac[5]);
-               return false;
-       }
-
-       return true;
-}
-
-static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
-                            char *vrfname, size_t vrfnamelen,
-                            struct sockaddr_any *local,
-                            struct sockaddr_any *peer)
+ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
+                     char *port, size_t portlen, char *vrfname,
+                     size_t vrfnamelen, struct sockaddr_any *local,
+                     struct sockaddr_any *peer)
 {
        struct cmsghdr *cm;
        int ifindex;
@@ -706,9 +248,11 @@ static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
        struct iovec iov[1];
        uint8_t cmsgbuf[255];
 
+       port[0] = '\0';
+
        /* Prepare the recvmsg params. */
        iov[0].iov_base = msgbuf;
-       iov[0].iov_len = sizeof(msgbuf);
+       iov[0].iov_len = msgbuflen;
 
        memset(&msghdr, 0, sizeof(msghdr));
        msghdr.msg_name = &msgaddr;
@@ -739,16 +283,14 @@ static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
                switch (cm->cmsg_type) {
 #ifdef BFD_LINUX
                case IP_TTL: {
-                       uint32_t ttl;
-
-                       memcpy(&ttl, CMSG_DATA(cm), sizeof(ttl));
-                       if ((is_mhop == false) && (ttl != BFD_TTL_VAL)) {
-                               log_debug(
-                                       "ipv4-recv: invalid TTL from %s (expected %d, got %d flags %d)",
-                                       satostr(peer), ttl, BFD_TTL_VAL,
-                                       msghdr.msg_flags);
+                       uint32_t ttlval;
+
+                       memcpy(&ttlval, CMSG_DATA(cm), sizeof(ttlval));
+                       if (ttlval > 255) {
+                               log_debug("ipv4-recv: invalid TTL: %u", ttlval);
                                return -1;
                        }
+                       *ttl = ttlval;
                        break;
                }
 
@@ -768,16 +310,7 @@ static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
 #endif /* BFD_LINUX */
 #ifdef BFD_BSD
                case IP_RECVTTL: {
-                       uint8_t ttl;
-
-                       memcpy(&ttl, CMSG_DATA(cm), sizeof(ttl));
-                       if ((is_mhop == false) && (ttl != BFD_TTL_VAL)) {
-                               log_debug(
-                                       "ipv4-recv: invalid TTL from %s (expected %d, got %d flags %d)",
-                                       satostr(peer), ttl, BFD_TTL_VAL,
-                                       msghdr.msg_flags);
-                               return -1;
-                       }
+                       memcpy(ttl, CMSG_DATA(cm), sizeof(*ttl));
                        break;
                }
 
@@ -812,14 +345,16 @@ static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
        return mlen;
 }
 
-ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
-                     char *vrfname, size_t vrfnamelen,
-                     struct sockaddr_any *local, struct sockaddr_any *peer)
+ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
+                     char *port, size_t portlen, char *vrfname,
+                     size_t vrfnamelen, struct sockaddr_any *local,
+                     struct sockaddr_any *peer)
 {
        struct cmsghdr *cm;
        struct in6_pktinfo *pi6 = NULL;
        int ifindex = 0;
        ssize_t mlen;
+       uint32_t ttlval;
        struct sockaddr_in6 msgaddr6;
        struct msghdr msghdr6;
        struct iovec iov[1];
@@ -827,7 +362,7 @@ ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
 
        /* Prepare the recvmsg params. */
        iov[0].iov_base = msgbuf;
-       iov[0].iov_len = sizeof(msgbuf);
+       iov[0].iov_len = msgbuflen;
 
        memset(&msghdr6, 0, sizeof(msghdr6));
        msghdr6.msg_name = &msgaddr6;
@@ -840,7 +375,7 @@ ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
        mlen = recvmsg(sd, &msghdr6, MSG_DONTWAIT);
        if (mlen == -1) {
                if (errno != EAGAIN)
-                       log_error("ipv4-recv: recv failed: %s",
+                       log_error("ipv6-recv: recv failed: %s",
                                  strerror(errno));
 
                return -1;
@@ -856,14 +391,13 @@ ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
                        continue;
 
                if (cm->cmsg_type == IPV6_HOPLIMIT) {
-                       memcpy(&ttlval, CMSG_DATA(cm), 4);
-                       if ((is_mhop == false) && (ttlval != BFD_TTL_VAL)) {
-                               log_debug(
-                                       "ipv6-recv: invalid TTL from %s (expected %d, got %d flags %d)",
-                                       satostr(peer), ttlval, BFD_TTL_VAL,
-                                       msghdr6.msg_flags);
+                       memcpy(&ttlval, CMSG_DATA(cm), sizeof(ttlval));
+                       if (ttlval > 255) {
+                               log_debug("ipv6-recv: invalid TTL: %u", ttlval);
                                return -1;
                        }
+
+                       *ttl = ttlval;
                } else if (cm->cmsg_type == IPV6_PKTINFO) {
                        pi6 = (struct in6_pktinfo *)CMSG_DATA(cm);
                        if (pi6) {
@@ -888,28 +422,28 @@ ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
 static void bfd_sd_reschedule(int sd)
 {
        if (sd == bglobal.bg_shop) {
-               bglobal.bg_ev[0] = NULL;
+               THREAD_OFF(bglobal.bg_ev[0]);
                thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop,
                                &bglobal.bg_ev[0]);
        } else if (sd == bglobal.bg_mhop) {
-               bglobal.bg_ev[1] = NULL;
+               THREAD_OFF(bglobal.bg_ev[1]);
                thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop,
                                &bglobal.bg_ev[1]);
        } else if (sd == bglobal.bg_shop6) {
-               bglobal.bg_ev[2] = NULL;
+               THREAD_OFF(bglobal.bg_ev[2]);
                thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop6,
                                &bglobal.bg_ev[2]);
        } else if (sd == bglobal.bg_mhop6) {
-               bglobal.bg_ev[3] = NULL;
+               THREAD_OFF(bglobal.bg_ev[3]);
                thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop6,
                                &bglobal.bg_ev[3]);
        } else if (sd == bglobal.bg_echo) {
-               bglobal.bg_ev[4] = NULL;
+               THREAD_OFF(bglobal.bg_ev[4]);
                thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echo,
                                &bglobal.bg_ev[4]);
-       } else if (sd == bglobal.bg_vxlan) {
-               bglobal.bg_ev[5] = NULL;
-               thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_vxlan,
+       } else if (sd == bglobal.bg_echov6) {
+               THREAD_OFF(bglobal.bg_ev[5]);
+               thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echov6,
                                &bglobal.bg_ev[5]);
        }
 }
@@ -955,18 +489,19 @@ int bfd_recv_cb(struct thread *t)
        int sd = THREAD_FD(t);
        struct bfd_session *bfd;
        struct bfd_pkt *cp;
-       bool is_mhop, is_vxlan;
+       bool is_mhop;
        ssize_t mlen = 0;
        uint32_t oldEchoXmt_TO, oldXmtTime;
+       uint8_t ttl;
        struct sockaddr_any local, peer;
        char port[MAXNAMELEN + 1], vrfname[MAXNAMELEN + 1];
-       struct bfd_session_vxlan_info vxlan_info;
+       uint8_t msgbuf[1516];
 
        /* Schedule next read. */
        bfd_sd_reschedule(sd);
 
        /* Handle echo packets. */
-       if (sd == bglobal.bg_echo) {
+       if (sd == bglobal.bg_echo || sd == bglobal.bg_echov6) {
                ptm_bfd_process_echo_pkt(sd);
                return 0;
        }
@@ -978,28 +513,18 @@ int bfd_recv_cb(struct thread *t)
        memset(&peer, 0, sizeof(peer));
 
        /* Handle control packets. */
-       is_mhop = is_vxlan = false;
+       is_mhop = false;
        if (sd == bglobal.bg_shop || sd == bglobal.bg_mhop) {
                is_mhop = sd == bglobal.bg_mhop;
-               mlen = bfd_recv_ipv4(sd, is_mhop, port, sizeof(port), vrfname,
-                                    sizeof(vrfname), &local, &peer);
+               mlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), &ttl, port,
+                                    sizeof(port), vrfname, sizeof(vrfname),
+                                    &local, &peer);
        } else if (sd == bglobal.bg_shop6 || sd == bglobal.bg_mhop6) {
                is_mhop = sd == bglobal.bg_mhop6;
-               mlen = bfd_recv_ipv6(sd, is_mhop, port, sizeof(port), vrfname,
-                                    sizeof(vrfname), &local, &peer);
+               mlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), &ttl, port,
+                                    sizeof(port), vrfname, sizeof(vrfname),
+                                    &local, &peer);
        }
-#if 0 /* TODO vxlan handling */
-       cp = ptm_bfd_process_vxlan_pkt(s, se, udata, &local_ifindex,
-                                      &sin, &vxlan_info, rx_pkt, &mlen);
-       if (!cp)
-               return -1;
-
-       is_vxlan = true;
-       /* keep in network-byte order */
-       peer.ip4_addr.s_addr = sin.sin_addr.s_addr;
-       peer.family = AF_INET;
-       strcpy(peer_addr, inet_ntoa(sin.sin_addr));
-#endif
 
        /* Implement RFC 5880 6.8.6 */
        if (mlen < BFD_PKT_LEN) {
@@ -1008,6 +533,13 @@ int bfd_recv_cb(struct thread *t)
                return 0;
        }
 
+       /* Validate packet TTL. */
+       if ((is_mhop == false) && (ttl != BFD_TTL_VAL)) {
+               cp_debug(is_mhop, &peer, &local, port, vrfname,
+                        "invalid TTL: %d expected %d", ttl, BFD_TTL_VAL);
+               return 0;
+       }
+
        /*
         * Parse the control header for inconsistencies:
         * - Invalid version;
@@ -1047,10 +579,6 @@ int bfd_recv_cb(struct thread *t)
                return 0;
        }
 
-       /* Handle VxLAN cases. */
-       if (is_vxlan && !ptm_bfd_validate_vxlan_pkt(bfd, &vxlan_info))
-               return 0;
-
        bfd->stats.rx_ctrl_pkt++;
 
        /*
@@ -1058,10 +586,10 @@ int bfd_recv_cb(struct thread *t)
         * Single hop: set local address that received the packet.
         */
        if (is_mhop) {
-               if ((BFD_TTL_VAL - bfd->mh_ttl) > ttlval) {
+               if ((BFD_TTL_VAL - bfd->mh_ttl) > BFD_TTL_VAL) {
                        cp_debug(is_mhop, &peer, &local, port, vrfname,
                                 "exceeded max hop count (expected %d, got %d)",
-                                bfd->mh_ttl, ttlval);
+                                bfd->mh_ttl, BFD_TTL_VAL);
                        return 0;
                }
        } else if (bfd->local_ip.sa_sin.sin_family == AF_UNSPEC) {
@@ -1111,7 +639,7 @@ int bfd_recv_cb(struct thread *t)
        /* State switch from section 6.8.6 */
        if (BFD_GETSTATE(cp->flags) == PTM_BFD_ADM_DOWN) {
                if (bfd->ses_state != PTM_BFD_DOWN)
-                       ptm_bfd_ses_dn(bfd, BFD_DIAGNEIGHDOWN);
+                       ptm_bfd_ses_dn(bfd, BD_NEIGHBOR_DOWN);
        } else {
                switch (bfd->ses_state) {
                case (PTM_BFD_DOWN):
@@ -1127,7 +655,7 @@ int bfd_recv_cb(struct thread *t)
                        break;
                case (PTM_BFD_UP):
                        if (BFD_GETSTATE(cp->flags) == PTM_BFD_DOWN)
-                               ptm_bfd_ses_dn(bfd, BFD_DIAGNEIGHDOWN);
+                               ptm_bfd_ses_dn(bfd, BD_NEIGHBOR_DOWN);
                        break;
                }
        }
@@ -1209,6 +737,121 @@ int bfd_recv_cb(struct thread *t)
        return 0;
 }
 
+/*
+ * bp_bfd_echo_in: proccesses an BFD echo packet. On TTL == BFD_TTL_VAL
+ * the packet is looped back or returns the my discriminator ID along
+ * with the TTL.
+ *
+ * Returns -1 on error or loopback or 0 on success.
+ */
+int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr)
+{
+       struct bfd_echo_pkt *bep;
+       ssize_t rlen;
+       struct sockaddr_any local, peer;
+       char port[MAXNAMELEN + 1], vrfname[MAXNAMELEN + 1];
+       uint8_t msgbuf[1516];
+
+       if (sd == bglobal.bg_echo)
+               rlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), ttl, port,
+                                    sizeof(port), vrfname, sizeof(vrfname),
+                                    &local, &peer);
+       else
+               rlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), ttl, port,
+                                    sizeof(port), vrfname, sizeof(vrfname),
+                                    &local, &peer);
+
+       /* Short packet, better not risk reading it. */
+       if (rlen < (ssize_t)sizeof(*bep)) {
+               cp_debug(false, &peer, &local, port, vrfname,
+                        "small echo packet");
+               return -1;
+       }
+
+       /* Test for loopback. */
+       if (*ttl == BFD_TTL_VAL) {
+               bp_udp_send(sd, *ttl - 1, msgbuf, rlen,
+                           (struct sockaddr *)&peer,
+                           (sd == bglobal.bg_echo) ? sizeof(peer.sa_sin)
+                                                   : sizeof(peer.sa_sin6));
+               return -1;
+       }
+
+       /* Read my discriminator from BFD Echo packet. */
+       bep = (struct bfd_echo_pkt *)msgbuf;
+       *my_discr = ntohl(bep->my_discr);
+       if (*my_discr == 0) {
+               cp_debug(false, &peer, &local, port, vrfname,
+                        "invalid echo packet discriminator (zero)");
+               return -1;
+       }
+
+       return 0;
+}
+
+int bp_udp_send(int sd, uint8_t ttl, uint8_t *data, size_t datalen,
+               struct sockaddr *to, socklen_t tolen)
+{
+       struct cmsghdr *cmsg;
+       ssize_t wlen;
+       int ttlval = ttl;
+       bool is_ipv6 = to->sa_family == AF_INET6;
+       struct msghdr msg;
+       struct iovec iov[1];
+       uint8_t msgctl[255];
+
+       /* Prepare message data. */
+       iov[0].iov_base = data;
+       iov[0].iov_len = datalen;
+
+       memset(&msg, 0, sizeof(msg));
+       memset(msgctl, 0, sizeof(msgctl));
+       msg.msg_name = to;
+       msg.msg_namelen = tolen;
+       msg.msg_iov = iov;
+       msg.msg_iovlen = 1;
+
+       /* Prepare the packet TTL information. */
+       if (ttl > 0) {
+               /* Use ancillary data. */
+               msg.msg_control = msgctl;
+               msg.msg_controllen = CMSG_LEN(sizeof(ttlval));
+
+               /* Configure the ancillary data. */
+               cmsg = CMSG_FIRSTHDR(&msg);
+               cmsg->cmsg_len = CMSG_LEN(sizeof(ttlval));
+               if (is_ipv6) {
+                       cmsg->cmsg_level = IPPROTO_IPV6;
+                       cmsg->cmsg_type = IPV6_HOPLIMIT;
+               } else {
+#if BFD_LINUX
+                       cmsg->cmsg_level = IPPROTO_IP;
+                       cmsg->cmsg_type = IP_TTL;
+#else
+                       /* FreeBSD does not support TTL in ancillary data. */
+                       msg.msg_control = NULL;
+                       msg.msg_controllen = 0;
+
+                       bp_set_ttl(sd, ttl);
+#endif /* BFD_BSD */
+               }
+               memcpy(CMSG_DATA(cmsg), &ttlval, sizeof(ttlval));
+       }
+
+       /* Send echo back. */
+       wlen = sendmsg(sd, &msg, 0);
+       if (wlen <= 0) {
+               log_debug("udp-send: loopback failure: (%d) %s", errno, strerror(errno));
+               return -1;
+       } else if (wlen < (ssize_t)datalen) {
+               log_debug("udp-send: partial send: %ld expected %ld", wlen,
+                         datalen);
+               return -1;
+       }
+
+       return 0;
+}
+
 
 /*
  * Sockets creation.
@@ -1218,10 +861,12 @@ int bfd_recv_cb(struct thread *t)
 /*
  * IPv4 sockets
  */
-int bp_set_ttl(int sd)
+int bp_set_ttl(int sd, uint8_t value)
 {
-       if (setsockopt(sd, IPPROTO_IP, IP_TTL, &ttlval, sizeof(ttlval)) == -1) {
-               log_warning("%s: setsockopt(IP_TTL): %s", __func__,
+       int ttl = value;
+
+       if (setsockopt(sd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) == -1) {
+               log_warning("set-ttl: setsockopt(IP_TTL, %d): %s", value,
                            strerror(errno));
                return -1;
        }
@@ -1229,10 +874,12 @@ int bp_set_ttl(int sd)
        return 0;
 }
 
-int bp_set_tos(int sd)
+int bp_set_tos(int sd, uint8_t value)
 {
-       if (setsockopt(sd, IPPROTO_IP, IP_TOS, &tosval, sizeof(tosval)) == -1) {
-               log_warning("%s: setsockopt(IP_TOS): %s", __func__,
+       int tos = value;
+
+       if (setsockopt(sd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1) {
+               log_warning("set-tos: setsockopt(IP_TOS, %d): %s", value,
                            strerror(errno));
                return -1;
        }
@@ -1242,20 +889,23 @@ int bp_set_tos(int sd)
 
 static void bp_set_ipopts(int sd)
 {
-       if (bp_set_ttl(sd) != 0)
-               log_fatal("%s: TTL configuration failed", __func__);
+       int rcvttl = BFD_RCV_TTL_VAL;
+
+       if (bp_set_ttl(sd, BFD_TTL_VAL) != 0)
+               log_fatal("set-ipopts: TTL configuration failed");
 
        if (setsockopt(sd, IPPROTO_IP, IP_RECVTTL, &rcvttl, sizeof(rcvttl))
            == -1)
-               log_fatal("%s: setsockopt(IP_RECVTTL): %s", __func__,
+               log_fatal("set-ipopts: setsockopt(IP_RECVTTL, %d): %s", rcvttl,
                          strerror(errno));
 
 #ifdef BFD_LINUX
        int pktinfo = BFD_PKT_INFO_VAL;
+
        /* Figure out address and interface to do the peer matching. */
        if (setsockopt(sd, IPPROTO_IP, IP_PKTINFO, &pktinfo, sizeof(pktinfo))
            == -1)
-               log_fatal("%s: setsockopt(IP_PKTINFO): %s", __func__,
+               log_fatal("set-ipopts: setsockopt(IP_PKTINFO, %d): %s", pktinfo,
                          strerror(errno));
 #endif /* BFD_LINUX */
 #ifdef BFD_BSD
@@ -1263,12 +913,12 @@ static void bp_set_ipopts(int sd)
 
        /* Find out our address for peer matching. */
        if (setsockopt(sd, IPPROTO_IP, IP_RECVDSTADDR, &yes, sizeof(yes)) == -1)
-               log_fatal("%s: setsockopt(IP_RECVDSTADDR): %s", __func__,
+               log_fatal("set-ipopts: setsockopt(IP_RECVDSTADDR, %d): %s", yes,
                          strerror(errno));
 
        /* Find out interface where the packet came in. */
        if (setsockopt_ifindex(AF_INET, sd, yes) == -1)
-               log_fatal("%s: setsockopt_ipv4_ifindex: %s", __func__,
+               log_fatal("set-ipopts: setsockopt_ipv4_ifindex(%d): %s", yes,
                          strerror(errno));
 #endif /* BFD_BSD */
 }
@@ -1282,7 +932,7 @@ static void bp_bind_ip(int sd, uint16_t port)
        sin.sin_addr.s_addr = htonl(INADDR_ANY);
        sin.sin_port = htons(port);
        if (bind(sd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
-               log_fatal("%s: bind: %s", __func__, strerror(errno));
+               log_fatal("bind-ip: bind: %s", strerror(errno));
 }
 
 int bp_udp_shop(void)
@@ -1291,7 +941,7 @@ int bp_udp_shop(void)
 
        sd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
        if (sd == -1)
-               log_fatal("%s: socket: %s", __func__, strerror(errno));
+               log_fatal("udp-shop: socket: %s", strerror(errno));
 
        bp_set_ipopts(sd);
        bp_bind_ip(sd, BFD_DEFDESTPORT);
@@ -1305,7 +955,7 @@ int bp_udp_mhop(void)
 
        sd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
        if (sd == -1)
-               log_fatal("%s: socket: %s", __func__, strerror(errno));
+               log_fatal("udp-mhop: socket: %s", strerror(errno));
 
        bp_set_ipopts(sd);
        bp_bind_ip(sd, BFD_DEF_MHOP_DEST_PORT);
@@ -1326,22 +976,19 @@ int bp_peer_socket(struct bfd_peer_cfg *bpc)
                return -1;
        }
 
-       if (!bpc->bpc_has_vxlan) {
-               /* Set TTL to 255 for all transmitted packets */
-               if (bp_set_ttl(sd) != 0) {
-                       close(sd);
-                       return -1;
-               }
+       /* Set TTL to 255 for all transmitted packets */
+       if (bp_set_ttl(sd, BFD_TTL_VAL) != 0) {
+               close(sd);
+               return -1;
        }
 
        /* Set TOS to CS6 for all transmitted packets */
-       if (bp_set_tos(sd) != 0) {
+       if (bp_set_tos(sd, BFD_TOS_VAL) != 0) {
                close(sd);
                return -1;
        }
 
-       /* dont bind-to-device incase of vxlan */
-       if (!bpc->bpc_has_vxlan && bpc->bpc_has_localif) {
+       if (bpc->bpc_has_localif) {
                if (bp_bind_dev(sd, bpc->bpc_localif) != 0) {
                        close(sd);
                        return -1;
@@ -1360,7 +1007,7 @@ int bp_peer_socket(struct bfd_peer_cfg *bpc)
 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
        sin.sin_len = sizeof(sin);
 #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
-       if (bpc->bpc_mhop || bpc->bpc_has_vxlan)
+       if (bpc->bpc_mhop)
                sin.sin_addr = bpc->bpc_local.sa_sin.sin_addr;
        else
                sin.sin_addr.s_addr = INADDR_ANY;
@@ -1400,16 +1047,14 @@ int bp_peer_socketv6(struct bfd_peer_cfg *bpc)
                return -1;
        }
 
-       if (!bpc->bpc_has_vxlan) {
-               /* Set TTL to 255 for all transmitted packets */
-               if (bp_set_ttlv6(sd) != 0) {
-                       close(sd);
-                       return -1;
-               }
+       /* Set TTL to 255 for all transmitted packets */
+       if (bp_set_ttlv6(sd, BFD_TTL_VAL) != 0) {
+               close(sd);
+               return -1;
        }
 
        /* Set TOS to CS6 for all transmitted packets */
-       if (bp_set_tosv6(sd) != 0) {
+       if (bp_set_tosv6(sd, BFD_TOS_VAL) != 0) {
                close(sd);
                return -1;
        }
@@ -1454,24 +1099,27 @@ int bp_peer_socketv6(struct bfd_peer_cfg *bpc)
        return sd;
 }
 
-int bp_set_ttlv6(int sd)
+int bp_set_ttlv6(int sd, uint8_t value)
 {
-       if (setsockopt(sd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttlval,
-                      sizeof(ttlval))
+       int ttl = value;
+
+       if (setsockopt(sd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl))
            == -1) {
-               log_warning("%s: setsockopt(IPV6_UNICAST_HOPS): %s", __func__,
-                           strerror(errno));
+               log_warning("set-ttlv6: setsockopt(IPV6_UNICAST_HOPS, %d): %s",
+                           value, strerror(errno));
                return -1;
        }
 
        return 0;
 }
 
-int bp_set_tosv6(int sd)
+int bp_set_tosv6(int sd, uint8_t value)
 {
-       if (setsockopt(sd, IPPROTO_IPV6, IPV6_TCLASS, &tosval, sizeof(tosval))
+       int tos = value;
+
+       if (setsockopt(sd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos))
            == -1) {
-               log_warning("%s: setsockopt(IPV6_TCLASS): %s", __func__,
+               log_warning("set-tosv6: setsockopt(IPV6_TCLASS, %d): %s", value,
                            strerror(errno));
                return -1;
        }
@@ -1481,28 +1129,26 @@ int bp_set_tosv6(int sd)
 
 static void bp_set_ipv6opts(int sd)
 {
-       static int ipv6_pktinfo = BFD_IPV6_PKT_INFO_VAL;
-       static int ipv6_only = BFD_IPV6_ONLY_VAL;
+       int ipv6_pktinfo = BFD_IPV6_PKT_INFO_VAL;
+       int ipv6_only = BFD_IPV6_ONLY_VAL;
 
-       if (setsockopt(sd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttlval,
-                      sizeof(ttlval))
-           == -1)
-               log_fatal("%s: setsockopt(IPV6_UNICAST_HOPS): %s", __func__,
-                         strerror(errno));
+       if (bp_set_ttlv6(sd, BFD_TTL_VAL) == -1)
+               log_fatal("set-ipv6opts: setsockopt(IPV6_UNICAST_HOPS, %d): %s",
+                         BFD_TTL_VAL, strerror(errno));
 
-       if (setsockopt_ipv6_hoplimit(sd, rcvttl) == -1)
-               log_fatal("%s: setsockopt(IPV6_HOPLIMIT): %s", __func__,
-                         strerror(errno));
+       if (setsockopt_ipv6_hoplimit(sd, BFD_RCV_TTL_VAL) == -1)
+               log_fatal("set-ipv6opts: setsockopt(IPV6_HOPLIMIT, %d): %s",
+                         BFD_RCV_TTL_VAL, strerror(errno));
 
        if (setsockopt_ipv6_pktinfo(sd, ipv6_pktinfo) == -1)
-               log_fatal("%s: setsockopt(IPV6_PKTINFO): %s", __func__,
-                         strerror(errno));
+               log_fatal("set-ipv6opts: setsockopt(IPV6_PKTINFO, %d): %s",
+                         ipv6_pktinfo, strerror(errno));
 
        if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6_only,
                       sizeof(ipv6_only))
            == -1)
-               log_fatal("%s: setsockopt(IPV6_V6ONLY): %s", __func__,
-                         strerror(errno));
+               log_fatal("set-ipv6opts: setsockopt(IPV6_V6ONLY, %d): %s",
+                         ipv6_only, strerror(errno));
 }
 
 static void bp_bind_ipv6(int sd, uint16_t port)
@@ -1517,7 +1163,7 @@ static void bp_bind_ipv6(int sd, uint16_t port)
        sin6.sin6_len = sizeof(sin6);
 #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
        if (bind(sd, (struct sockaddr *)&sin6, sizeof(sin6)) == -1)
-               log_fatal("%s: bind: %s", __func__, strerror(errno));
+               log_fatal("bind-ipv6: bind: %s", strerror(errno));
 }
 
 int bp_udp6_shop(void)
@@ -1526,7 +1172,7 @@ int bp_udp6_shop(void)
 
        sd = socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC);
        if (sd == -1)
-               log_fatal("%s: socket: %s", __func__, strerror(errno));
+               log_fatal("udp6-shop: socket: %s", strerror(errno));
 
        bp_set_ipv6opts(sd);
        bp_bind_ipv6(sd, BFD_DEFDESTPORT);
@@ -1540,10 +1186,38 @@ int bp_udp6_mhop(void)
 
        sd = socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC);
        if (sd == -1)
-               log_fatal("%s: socket: %s", __func__, strerror(errno));
+               log_fatal("udp6-mhop: socket: %s", strerror(errno));
 
        bp_set_ipv6opts(sd);
        bp_bind_ipv6(sd, BFD_DEF_MHOP_DEST_PORT);
 
        return sd;
 }
+
+int bp_echo_socket(void)
+{
+       int s;
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s == -1)
+               log_fatal("echo-socket: socket: %s", strerror(errno));
+
+       bp_set_ipopts(s);
+       bp_bind_ip(s, BFD_DEF_ECHO_PORT);
+
+       return s;
+}
+
+int bp_echov6_socket(void)
+{
+       int s;
+
+       s = socket(AF_INET6, SOCK_DGRAM, 0);
+       if (s == -1)
+               log_fatal("echov6-socket: socket: %s", strerror(errno));
+
+       bp_set_ipv6opts(s);
+       bp_bind_ipv6(s, BFD_DEF_ECHO_PORT);
+
+       return s;
+}
index 940efd161447bbcb46fb46c83d1795478934e88f..0da1ca8df6c7e14cbe70262f8a7e112eefcd165a 100644 (file)
@@ -66,9 +66,6 @@ struct bfd_peer_cfg {
        bool bpc_has_label;
        char bpc_label[MAXNAMELEN];
 
-       bool bpc_has_vxlan;
-       unsigned int bpc_vxlan;
-
        bool bpc_has_localif;
        char bpc_localif[MAXNAMELEN + 1];
 
index 144619088d3a3ca733cb01bbaa7b087825611499..250f8d21c0d30aaf5ed77b3d0871fa627d746b3b 100644 (file)
@@ -90,7 +90,6 @@ static void sigterm_handler(void)
        socket_close(&bglobal.bg_mhop);
        socket_close(&bglobal.bg_shop6);
        socket_close(&bglobal.bg_mhop6);
-       socket_close(&bglobal.bg_vxlan);
 
        /* Terminate and free() FRR related memory. */
        frr_fini();
@@ -131,17 +130,22 @@ static struct option longopts[] = {
 struct bfd_global bglobal;
 
 struct bfd_diag_str_list diag_list[] = {
-       {.str = "NeighDown", .type = BFD_DIAGNEIGHDOWN},
-       {.str = "DetectTime", .type = BFD_DIAGDETECTTIME},
-       {.str = "AdminDown", .type = BFD_DIAGADMINDOWN},
+       {.str = "control-expired", .type = BD_CONTROL_EXPIRED},
+       {.str = "echo-failed", .type = BD_ECHO_FAILED},
+       {.str = "neighbor-down", .type = BD_NEIGHBOR_DOWN},
+       {.str = "forwarding-reset", .type = BD_FORWARDING_RESET},
+       {.str = "path-down", .type = BD_PATH_DOWN},
+       {.str = "concatenated-path-down", .type = BD_CONCATPATH_DOWN},
+       {.str = "administratively-down", .type = BD_ADMIN_DOWN},
+       {.str = "reverse-concat-path-down", .type = BD_REVCONCATPATH_DOWN},
        {.str = NULL},
 };
 
 struct bfd_state_str_list state_list[] = {
-       {.str = "AdminDown", .type = PTM_BFD_ADM_DOWN},
-       {.str = "Down", .type = PTM_BFD_DOWN},
-       {.str = "Init", .type = PTM_BFD_INIT},
-       {.str = "Up", .type = PTM_BFD_UP},
+       {.str = "admin-down", .type = PTM_BFD_ADM_DOWN},
+       {.str = "down", .type = PTM_BFD_DOWN},
+       {.str = "init", .type = PTM_BFD_INIT},
+       {.str = "up", .type = PTM_BFD_UP},
        {.str = NULL},
 };
 
@@ -154,8 +158,8 @@ static void bg_init(void)
        bglobal.bg_mhop = bp_udp_mhop();
        bglobal.bg_shop6 = bp_udp6_shop();
        bglobal.bg_mhop6 = bp_udp6_mhop();
-       bglobal.bg_echo = ptm_bfd_echo_sock_init();
-       bglobal.bg_vxlan = ptm_bfd_vxlan_sock_init();
+       bglobal.bg_echo = bp_echo_socket();
+       bglobal.bg_echov6 = bp_echov6_socket();
 }
 
 int main(int argc, char *argv[])
@@ -216,10 +220,8 @@ int main(int argc, char *argv[])
                        &bglobal.bg_ev[3]);
        thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echo,
                        &bglobal.bg_ev[4]);
-#if 0 /* TODO VxLAN support. */
-       thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_vxlan,
+       thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echov6,
                        &bglobal.bg_ev[5]);
-#endif
        thread_add_read(master, control_accept, NULL, bglobal.bg_csock,
                        &bglobal.bg_csockev);
 
index ae6081f01ad360f18c50dff55e06eddaf2f38b35..1c6d03195c8a5754f99fe9f5a4f63e38357bb220 100644 (file)
@@ -827,7 +827,7 @@ DEFPY(bfd_show_peers_counters, bfd_show_peers_counters_cmd,
  * Configuration rules:
  *
  * Single hop:
- * peer + (optional vxlan or interface name)
+ * peer + (interface name)
  *
  * Multi hop:
  * peer + local + (optional vrf)
@@ -896,23 +896,6 @@ static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
 
        bpc->bpc_mhop = mhop;
 
-#if 0
-       /* Handle VxLAN configuration. */
-       if (vxlan >= 0) {
-               if (vxlan > ((1 << 24) - 1)) {
-                       snprintf(ebuf, ebuflen, "invalid VxLAN %d", vxlan);
-                       return -1;
-               }
-               if (bpc->bpc_mhop) {
-                       snprintf(ebuf, ebuflen,
-                                "multihop doesn't accept VxLAN");
-                       return -1;
-               }
-
-               bpc->bpc_vxlan = vxlan;
-       }
-#endif /* VxLAN */
-
        /* Handle interface specification configuration. */
        if (ifname) {
                if (bpc->bpc_mhop) {
index 34a3a1a801e22268954488f14553221ae44d6ac7..e0fb340e30e3087bd6fdb935b2bd42380f6d0f93 100644 (file)
 
 #include "bfd.h"
 
-/*
- * Prototypes
- */
-static const char *sockaddr_to_string(const void *sv, char *buf, size_t buflen);
-
 /*
  * Definitions.
  */
-static const char *sockaddr_to_string(const void *sv, char *buf, size_t buflen)
-{
-       const struct sockaddr *sa = sv;
-       const struct sockaddr_in *sin = sv;
-       const struct sockaddr_in6 *sin6 = sv;
-       int unknown = 1;
-
-       switch (sa->sa_family) {
-       case AF_INET:
-               if (inet_ntop(AF_INET, &sin->sin_addr, buf, buflen) != NULL)
-                       unknown = 0;
-               break;
-
-       case AF_INET6:
-               if (inet_ntop(AF_INET6, &sin6->sin6_addr, buf, buflen) != NULL)
-                       unknown = 0;
-               break;
-       }
-       if (unknown == 0)
-               return buf;
-
-       snprintf(buf, buflen, "unknown (af=%d)", sa->sa_family);
-       return buf;
-}
-
 int ptm_bfd_fetch_ifindex(const char *ifname)
 {
        return if_nametoindex(ifname);
@@ -129,133 +99,6 @@ void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen)
                            __LINE__);
 }
 
-int ptm_bfd_echo_sock_init(void)
-{
-       int s, ttl, yes = 1;
-       struct sockaddr_in sin;
-
-       s = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
-       if (s == -1) {
-               log_error("echo-socket: creation failed: %s", strerror(errno));
-               return -1;
-       }
-
-       memset(&sin, 0, sizeof(sin));
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-       /* OmniOS doesn't have this field, but uses this code. */
-       sin.sin_len = sizeof(sin);
-#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
-       sin.sin_family = AF_INET;
-       sin.sin_port = htons(3785);
-       if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
-               log_error("echo-socket: bind failure: %s", strerror(errno));
-               close(s);
-               return -1;
-       }
-
-       if (setsockopt(s, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) == -1) {
-               log_error("echo-socket: setsockopt(IP_RECVTTL): %s",
-                         strerror(errno));
-               close(s);
-               return -1;
-       }
-
-       ttl = BFD_TTL_VAL;
-       if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) == -1) {
-               log_error("echo-socket: setsockopt(IP_TTL): %s",
-                         strerror(errno));
-               close(s);
-               return -1;
-       }
-
-       return s;
-}
-
-ssize_t bsd_echo_sock_read(int sd, uint8_t *buf, ssize_t *buflen,
-                          struct sockaddr_storage *ss, socklen_t *sslen,
-                          uint8_t *ttl, uint32_t *id)
-{
-       struct cmsghdr *cmsg;
-       struct bfd_echo_pkt *bep;
-       ssize_t readlen;
-       struct iovec iov;
-       struct msghdr msg;
-       uint8_t msgctl[255];
-       char errbuf[255];
-
-       /* Prepare socket read. */
-       memset(ss, 0, sizeof(*ss));
-       memset(&msg, 0, sizeof(msg));
-       iov.iov_base = buf;
-       iov.iov_len = *buflen;
-       msg.msg_iov = &iov;
-       msg.msg_iovlen = 1;
-       msg.msg_control = msgctl;
-       msg.msg_controllen = sizeof(msgctl);
-       msg.msg_name = ss;
-       msg.msg_namelen = *sslen;
-
-       /* Read the socket and treat errors. */
-       readlen = recvmsg(sd, &msg, 0);
-       if (readlen == 0) {
-               log_error("%s: recvmsg: socket closed", __func__);
-               return -1;
-       }
-       if (readlen == -1) {
-               if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
-                       return -1;
-
-               log_error("%s: recvmsg: (%d) %s", __func__, errno,
-                         strerror(errno));
-               return -1;
-       }
-       /* Short packet, better not risk reading it. */
-       if (readlen < (ssize_t)sizeof(*bep)) {
-               log_warning("%s: short packet (%ld of %d) from %s", __func__,
-                           readlen, sizeof(*bep),
-                           sockaddr_to_string(ss, errbuf, sizeof(errbuf)));
-               return -1;
-       }
-       *buflen = readlen;
-
-       /* Read TTL information. */
-       *ttl = 0;
-       for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
-            cmsg = CMSG_NXTHDR(&msg, cmsg)) {
-               if (cmsg->cmsg_level != IPPROTO_IP)
-                       continue;
-               if (cmsg->cmsg_type != IP_RECVTTL)
-                       continue;
-
-               *ttl = *(uint8_t *)CMSG_DATA(cmsg);
-               break;
-       }
-       if (*ttl == 0) {
-               log_debug("%s: failed to read TTL", __func__);
-               return -1;
-       }
-
-       /* Read my discriminator from BFD Echo packet. */
-       bep = (struct bfd_echo_pkt *)buf;
-       *id = bep->my_discr;
-       if (*id == 0) {
-               log_debug("%s: invalid packet discriminator from: %s", __func__,
-                         sockaddr_to_string(ss, errbuf, sizeof(errbuf)));
-               return -1;
-       }
-
-       /* Set the returned sockaddr new length. */
-       *sslen = msg.msg_namelen;
-
-       return 0;
-}
-
-int ptm_bfd_vxlan_sock_init(void)
-{
-       /* TODO: not supported yet. */
-       return -1;
-}
-
 int bp_bind_dev(int sd, const char *dev)
 {
        /*
@@ -266,25 +109,4 @@ int bp_bind_dev(int sd, const char *dev)
        return 0;
 }
 
-uint16_t udp4_checksum(struct ip *ip, uint8_t *buf, int len)
-{
-       char *ptr;
-       struct udp_psuedo_header pudp_hdr;
-       uint16_t csum;
-
-       pudp_hdr.saddr = ip->ip_src.s_addr;
-       pudp_hdr.daddr = ip->ip_dst.s_addr;
-       pudp_hdr.reserved = 0;
-       pudp_hdr.protocol = ip->ip_p;
-       pudp_hdr.len = htons(len);
-
-       ptr = XMALLOC(MTYPE_BFDD_TMP, UDP_PSUEDO_HDR_LEN + len);
-       memcpy(ptr, &pudp_hdr, UDP_PSUEDO_HDR_LEN);
-       memcpy(ptr + UDP_PSUEDO_HDR_LEN, buf, len);
-
-       csum = checksum((uint16_t *)ptr, UDP_PSUEDO_HDR_LEN + len);
-       XFREE(MTYPE_BFDD_TMP, ptr);
-       return csum;
-}
-
 #endif /* BFD_BSD */
index 0e0d8b7d706ff0238c6b89db70c9a94e4663beba..06089780c6ba8c163d2e8db142f7076c5607cc02 100644 (file)
@@ -218,10 +218,6 @@ static int parse_peer_config(struct json_object *jo, struct bfd_peer_cfg *bpc)
                        } else {
                                log_debug("\tlocal-interface: %s", sval);
                        }
-               } else if (strcmp(key, "vxlan") == 0) {
-                       bpc->bpc_vxlan = json_object_get_int64(jo_val);
-                       bpc->bpc_has_vxlan = true;
-                       log_debug("\tvxlan: %ld", bpc->bpc_vxlan);
                } else if (strcmp(key, "vrf-name") == 0) {
                        bpc->bpc_has_vrfname = true;
                        sval = json_object_get_string(jo_val);
index ba12f5b4e80066dc8086cb1ee019518824d3cb2d..63f64077ebd40da8ff35fc5f695e2c5f412a96e9 100644 (file)
@@ -49,8 +49,7 @@ void bfd_recvtimer_update(struct bfd_session *bs)
 #endif /* BFD_EVENT_DEBUG */
 
        /* Remove previous schedule if any. */
-       if (bs->recvtimer_ev)
-               bfd_recvtimer_delete(bs);
+       bfd_recvtimer_delete(bs);
 
        thread_add_timer_tv(master, bfd_recvtimer_cb, bs, &tv,
                            &bs->recvtimer_ev);
@@ -70,8 +69,7 @@ void bfd_echo_recvtimer_update(struct bfd_session *bs)
 #endif /* BFD_EVENT_DEBUG */
 
        /* Remove previous schedule if any. */
-       if (bs->echo_recvtimer_ev)
-               bfd_echo_recvtimer_delete(bs);
+       bfd_echo_recvtimer_delete(bs);
 
        thread_add_timer_tv(master, bfd_echo_recvtimer_cb, bs, &tv,
                            &bs->echo_recvtimer_ev);
@@ -91,8 +89,7 @@ void bfd_xmttimer_update(struct bfd_session *bs, uint64_t jitter)
 #endif /* BFD_EVENT_DEBUG */
 
        /* Remove previous schedule if any. */
-       if (bs->xmttimer_ev)
-               bfd_xmttimer_delete(bs);
+       bfd_xmttimer_delete(bs);
 
        thread_add_timer_tv(master, bfd_xmt_cb, bs, &tv, &bs->xmttimer_ev);
 }
@@ -111,8 +108,7 @@ void bfd_echo_xmttimer_update(struct bfd_session *bs, uint64_t jitter)
 #endif /* BFD_EVENT_DEBUG */
 
        /* Remove previous schedule if any. */
-       if (bs->echo_xmttimer_ev)
-               bfd_echo_xmttimer_delete(bs);
+       bfd_echo_xmttimer_delete(bs);
 
        thread_add_timer_tv(master, bfd_echo_xmt_cb, bs, &tv,
                            &bs->echo_xmttimer_ev);
@@ -120,36 +116,20 @@ void bfd_echo_xmttimer_update(struct bfd_session *bs, uint64_t jitter)
 
 void bfd_recvtimer_delete(struct bfd_session *bs)
 {
-       if (bs->recvtimer_ev == NULL)
-               return;
-
-       thread_cancel(bs->recvtimer_ev);
-       bs->recvtimer_ev = NULL;
+       THREAD_OFF(bs->recvtimer_ev);
 }
 
 void bfd_echo_recvtimer_delete(struct bfd_session *bs)
 {
-       if (bs->echo_recvtimer_ev == NULL)
-               return;
-
-       thread_cancel(bs->echo_recvtimer_ev);
-       bs->echo_recvtimer_ev = NULL;
+       THREAD_OFF(bs->echo_recvtimer_ev);
 }
 
 void bfd_xmttimer_delete(struct bfd_session *bs)
 {
-       if (bs->xmttimer_ev == NULL)
-               return;
-
-       thread_cancel(bs->xmttimer_ev);
-       bs->xmttimer_ev = NULL;
+       THREAD_OFF(bs->xmttimer_ev);
 }
 
 void bfd_echo_xmttimer_delete(struct bfd_session *bs)
 {
-       if (bs->echo_xmttimer_ev == NULL)
-               return;
-
-       thread_cancel(bs->echo_xmttimer_ev);
-       bs->echo_xmttimer_ev = NULL;
+       THREAD_OFF(bs->echo_xmttimer_ev);
 }
index 5f24ef4d19cc573e122806f2c860e055760322a9..e260851ddba6a229573406c7540c3e20b3a99ec0 100644 (file)
 
 #ifdef BFD_LINUX
 
-/* XXX: fix compilation error on Ubuntu 16.04 or older. */
-#ifndef _UAPI_IPV6_H
-#define _UAPI_IPV6_H
-#endif /* _UAPI_IPV6_H */
-
-#include <linux/filter.h>
-#include <linux/if_packet.h>
-
-#include <netinet/if_ether.h>
-
-#include <net/if.h>
-#include <sys/ioctl.h>
-
 #include "bfd.h"
 
-/* Berkeley Packet filter code to filter out BFD Echo packets.
- * tcpdump -dd "(udp dst port 3785)"
- */
-static struct sock_filter bfd_echo_filter[] = {
-       {0x28, 0, 0, 0x0000000c}, {0x15, 0, 4, 0x000086dd},
-       {0x30, 0, 0, 0x00000014}, {0x15, 0, 11, 0x00000011},
-       {0x28, 0, 0, 0x00000038}, {0x15, 8, 9, 0x00000ec9},
-       {0x15, 0, 8, 0x00000800}, {0x30, 0, 0, 0x00000017},
-       {0x15, 0, 6, 0x00000011}, {0x28, 0, 0, 0x00000014},
-       {0x45, 4, 0, 0x00001fff}, {0xb1, 0, 0, 0x0000000e},
-       {0x48, 0, 0, 0x00000010}, {0x15, 0, 1, 0x00000ec9},
-       {0x6, 0, 0, 0x0000ffff},  {0x6, 0, 0, 0x00000000},
-};
-
-/* Berkeley Packet filter code to filter out BFD vxlan packets.
- * tcpdump -dd "(udp dst port 4789)"
- */
-static struct sock_filter bfd_vxlan_filter[] = {
-       {0x28, 0, 0, 0x0000000c}, {0x15, 0, 4, 0x000086dd},
-       {0x30, 0, 0, 0x00000014}, {0x15, 0, 11, 0x00000011},
-       {0x28, 0, 0, 0x00000038}, {0x15, 8, 9, 0x000012b5},
-       {0x15, 0, 8, 0x00000800}, {0x30, 0, 0, 0x00000017},
-       {0x15, 0, 6, 0x00000011}, {0x28, 0, 0, 0x00000014},
-       {0x45, 4, 0, 0x00001fff}, {0xb1, 0, 0, 0x0000000e},
-       {0x48, 0, 0, 0x00000010}, {0x15, 0, 1, 0x000012b5},
-       {0x6, 0, 0, 0x0000ffff},  {0x6, 0, 0, 0x00000000},
-};
-
 
 /*
  * Definitions.
@@ -128,55 +87,6 @@ void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen)
                          ifr.ifr_name, ifname);
 }
 
-int ptm_bfd_echo_sock_init(void)
-{
-       int s;
-       struct sock_fprog bpf = {.len = sizeof(bfd_echo_filter)
-                                       / sizeof(bfd_echo_filter[0]),
-                                .filter = bfd_echo_filter};
-
-       s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
-       if (s == -1) {
-               log_error("echo-socket: creation failure: %s", strerror(errno));
-               return -1;
-       }
-
-       if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))
-           == -1) {
-               log_error("echo-socket: setsockopt(SO_ATTACH_FILTER): %s",
-                         strerror(errno));
-               close(s);
-               return -1;
-       }
-
-       return s;
-}
-
-int ptm_bfd_vxlan_sock_init(void)
-{
-       int s;
-       struct sock_fprog bpf = {.len = sizeof(bfd_vxlan_filter)
-                                       / sizeof(bfd_vxlan_filter[0]),
-                                .filter = bfd_vxlan_filter};
-
-       s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
-       if (s == -1) {
-               log_error("vxlan-socket: creation failure: %s",
-                         strerror(errno));
-               return -1;
-       }
-
-       if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))
-           == -1) {
-               log_error("vxlan-socket: setsockopt(SO_ATTACH_FILTER): %s",
-                         strerror(errno));
-               close(s);
-               return -1;
-       }
-
-       return s;
-}
-
 int bp_bind_dev(int sd __attribute__((__unused__)),
                const char *dev __attribute__((__unused__)))
 {
@@ -197,25 +107,4 @@ int bp_bind_dev(int sd __attribute__((__unused__)),
        return 0;
 }
 
-uint16_t udp4_checksum(struct iphdr *iph, uint8_t *buf, int len)
-{
-       char *ptr;
-       struct udp_psuedo_header pudp_hdr;
-       uint16_t csum;
-
-       pudp_hdr.saddr = iph->saddr;
-       pudp_hdr.daddr = iph->daddr;
-       pudp_hdr.reserved = 0;
-       pudp_hdr.protocol = iph->protocol;
-       pudp_hdr.len = htons(len);
-
-       ptr = XMALLOC(MTYPE_BFDD_TMP, UDP_PSUEDO_HDR_LEN + len);
-       memcpy(ptr, &pudp_hdr, UDP_PSUEDO_HDR_LEN);
-       memcpy(ptr + UDP_PSUEDO_HDR_LEN, buf, len);
-
-       csum = checksum((uint16_t *)ptr, UDP_PSUEDO_HDR_LEN + len);
-       XFREE(MTYPE_BFDD_TMP, ptr);
-       return csum;
-}
-
 #endif /* BFD_LINUX */
index 4287891621f06306c589b96ebeb9be04708508bb..a5fae3383cd7248ba0994f318e2e877dd90f283f 100644 (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:
index 86923f5cec50dfef6d884e8e8e148a7d980d8931..334e974b048a9eb1676666b4e63c8eaa65e3d97c 100644 (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 = \
index 105be2299503e9b435b7ada521e2c4f733c9ce1d..2e77195b90088e07a8ddb644dd05d0a5a069ab3a 100644 (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
diff --git a/bgpd/Makefile b/bgpd/Makefile
new file mode 100644 (file)
index 0000000..b8664a8
--- /dev/null
@@ -0,0 +1,10 @@
+all: ALWAYS
+       @$(MAKE) -s -C .. bgpd/bgpd
+%: ALWAYS
+       @$(MAKE) -s -C .. bgpd/$@
+
+Makefile:
+       #nothing
+ALWAYS:
+.PHONY: ALWAYS makefiles
+.SUFFIXES:
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
deleted file mode 100644 (file)
index b6b125f..0000000
+++ /dev/null
@@ -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
-
index e29508bf3680d9e946bb77db9b40cc593a947386..c604135bfd1beccbae4a4310fb139709902d01c9 100644 (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"
 
index 32506623c79f97bc12b1df83e3124951875ffddb..2107d1f9f9a18ff6e6adfd9a19ca81152655850a 100644 (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)
index 82b268c31d8b487b5d01d2abb5205f379d9fedce..2e0bb1ae6223ee7bbd7e51f47e6174f60919ae07 100644 (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"
index a427608f67d7b51edfd228d9f786087aafe09748..51504bb0ad5005f907f3ae6060727f0141a1ecd6 100644 (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"
index 691e1e4ec87281ee2d110b48a6a6259855395d65..c5fda15d33fc03c43e38b4346afcc33d99b0dd38 100644 (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"
index 3217d34e77b37c42e3f22d2598a416de08226b5a..ce5acf002c20fa79932aac298a1946059cc45150 100644 (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"
index 4c506da6865f881944fe62bc27d6728f14381e84..4601718f1209e063b3bc9dff299fa228d79bea65 100644 (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"
index 59387240fabffe1d7145a58b403fed8bae2bbc79..f18c6bfe12999cee193f95707460f09d8f700ecd 100644 (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"
index 3ac217ff8942c8639b85d0c3575c776b0c35e936..008da30118a5ab34060436a5ef7b4ef963f1c986 100644 (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"
index b2767da8b262c2d7c0e6c0bae12ab4c0973d83dd..cd751319eb5da387fd1e94f0a1404172ce368b6f 100644 (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"
diff --git a/bgpd/rfp-example/librfp/Makefile b/bgpd/rfp-example/librfp/Makefile
new file mode 100644 (file)
index 0000000..8deb93d
--- /dev/null
@@ -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:
diff --git a/bgpd/rfp-example/librfp/Makefile.am b/bgpd/rfp-example/librfp/Makefile.am
deleted file mode 100644 (file)
index fc66a40..0000000
+++ /dev/null
@@ -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)
index 75e57a029e042f47ee481fa7a86b2312e7e6e1a4..af3092232cf851ee10de6d38b54680b875546f71 100644 (file)
  * 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"
diff --git a/bgpd/rfp-example/librfp/subdir.am b/bgpd/rfp-example/librfp/subdir.am
new file mode 100644 (file)
index 0000000..254ab71
--- /dev/null
@@ -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
diff --git a/bgpd/rfp-example/rfptest/Makefile b/bgpd/rfp-example/rfptest/Makefile
new file mode 100644 (file)
index 0000000..659a9ce
--- /dev/null
@@ -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:
diff --git a/bgpd/rfp-example/rfptest/Makefile.am b/bgpd/rfp-example/rfptest/Makefile.am
deleted file mode 100644 (file)
index f5db852..0000000
+++ /dev/null
@@ -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 = 
index 53e1c33cfbb0f0406761b4d38b8850c713983014..48df6c0cc7689250b7ece7ffb786764ed7937617 100644 (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>
diff --git a/bgpd/rfp-example/rfptest/subdir.am b/bgpd/rfp-example/rfptest/subdir.am
new file mode 100644 (file)
index 0000000..fa7c660
--- /dev/null
@@ -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
diff --git a/bgpd/subdir.am b/bgpd/subdir.am
new file mode 100644 (file)
index 0000000..4291388
--- /dev/null
@@ -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
diff --git a/common.am b/common.am
deleted file mode 100644 (file)
index 9c0c547..0000000
--- a/common.am
+++ /dev/null
@@ -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
index 09a6f364fb30981c971a6e33c8c32b6fc0dd7ef7..08f1c117ec83092b099cf0508ab71a5be72d0252 100755 (executable)
@@ -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-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])])
-
-      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
+  # Check for protoc & protoc-c
+
+  # protoc is not required, it's only for a "be nice" helper target
+  AC_CHECK_PROGS([PROTOC], [protoc], [/bin/false])
+
+  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
index d2218d00f9bd895f12436351e3d2166b5c78bd74..605353289c178e0dd3df54571f91728430eaf42d 100644 (file)
@@ -1,5 +1,3 @@
-AUTHORS
-NEWS
-README
+README.md
 doc/user/*.rst
 doc/figures/*.png
index d99a6a5b2dbdf5c1e18341d85242a58c3bf8ced6..fa2b50832168f17cdefc9227d41c94a407248cc6 100644 (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
index d4c2c3bfd0a5dbd50eada7f48fb9b5422f56c3c9..5f10f3715d13499867b25ce660c747bae25c3f23 100644 (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
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 31cd4dcc49ed8a67c62d87af2ee0dcaf935f5b5a..b157f540ab512824d4918b0c4696bf5101b0ff78 100644 (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
index 208c580b63dea4192e94c4c2a83b6d718f9f8986..669cc4ae2f60390a9981a1da9982335f361af5d7 100644 (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
index 20391c47bcfe52e663be3d1b3d19d5e1caa520d6..c0716a5c9319cf0f7ae3deb89fb28e9e45b66e88 100644 (file)
@@ -450,8 +450,6 @@ is no ordering requirement)
 
 .. code-block:: make
 
-   include ../common.am
-
    # ...
 
    # if linked into a LTLIBRARY (.la/.so):
index 5fff6fca6651cd6014b6ca42da0b745ce1357269..74d3eb7bbdccb605e79cf65151c4e08cbc11a5f2 100644 (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.
 
index e540d236ea147d42331c0b0cdbda6cda4d8f75b0..f57bc1d27868eecc379211746d44bad55e19ef32 100644 (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 -------------------------------------------
diff --git a/doc/manpages/fabricd.rst b/doc/manpages/fabricd.rst
new file mode 100644 (file)
index 0000000..c14c076
--- /dev/null
@@ -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
+
index c62835c7701f3588a63902459e0d92b0f775e5ce..053555c4e4274205a4d41aa02e6f21e83d522989 100644 (file)
@@ -10,6 +10,7 @@
    bgpd
    eigrpd
    isisd
+   fabricd
    ldpd
    nhrpd
    ospf6d
index 24f47fc7a548e04ce09a5abc566552972838c273..4a9aa4de4d58acfa2e8e9f9bf859021cac9e7513 100644 (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
diff --git a/doc/mpls/.gitignore b/doc/mpls/.gitignore
deleted file mode 100644 (file)
index b0a4a46..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-.arch-ids
-.arch-inventory
-*~
-*.loT
-
diff --git a/doc/user/fabricd.rst b/doc/user/fabricd.rst
new file mode 100644 (file)
index 0000000..cf0f937
--- /dev/null
@@ -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
index 5818551343aecdf6fc4551605b92b300ce2dba07..8190415bf4c335739400baa68493b683a7ec3ae2 100644 (file)
@@ -42,6 +42,7 @@ Protocols
    bfd
    bgp
    babeld
+   fabricd
    ldpd
    eigrpd
    isisd
index 3da5a6cd3037b584755398bc22c433b7edd18633..da431916aec69a513ec14ef731899a44b3a0971f 100644 (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.
index 54f82f683255836bfccf4bd4e167658aafdb606b..ee681858d1a4bc6f8590039fcf8c9178f6c9282f 100644 (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
index 68ce14982be90d194418c3600063a5014c2a050a..8a76a61e787a29704603d3b7554e4fb9837a8511 100644 (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
index e27da63b536f951221e0ff7dd777c2b550140efe..8831c0159b1395ee6112aa8144f0059c7f40dc59 100644 (file)
@@ -33,13 +33,14 @@ All sharp commands are under the enable node and preceeded by the ``sharp``
 keyword. At present, no sharp commands will be preserved in the config.
 
 .. index:: sharp install
-.. clicmd:: sharp install routes A.B.C.D nexthop E.F.G.H (1-1000000)
+.. clicmd:: sharp install routes A.B.C.D nexthop <E.F.G.H|X:X::X:X> (1-1000000)
 
    Install up to 1,000,000 (one million) /32 routes starting at ``A.B.C.D``
-   with specified nexthop ``E.F.G.H``. The nexthop is a ``NEXTHOP_TYPE_IPV4``
-   and must be reachable to be installed into the kernel. The routes are
-   installed into zebra as ``ZEBRA_ROUTE_SHARP`` and can be used as part of a
-   normal route redistribution. Route installation time is noted in the debug
+   with specified nexthop ``E.F.G.H`` or ``X:X::X:X``. The nexthop is
+   a ``NEXTHOP_TYPE_IPV4`` or ``NEXTHOP_TYPE_IPV6`` and must be reachable
+   to be installed into the kernel. The routes are installed into zebra as
+   ``ZEBRA_ROUTE_SHARP`` and can be used as part of a normal route
+   redistribution. Route installation time is noted in the debug
    log. When zebra successfully installs a route into the kernel and SHARP
    receives success notifications for all routes this is logged as well.
 
index 6e51eed9d12bbfb3a0dab70776c4a818d9322d37..53d36052ac8d2e5dada1b87367ac3e7b78237ca5 100644 (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 \
index 5b72399e727f7159c2c86428af808e846bf0a37d..0303c6f0d437709ecc0f3201ab8bda6e9ac5137d 100644 (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
-
index eeefc519688ccce2c37f7298254b46bfa46b91be..d291cab4c0c7566237693ff29d127cb0e2c6b9c4 100644 (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"
index 190c18777e23139b7447d84feb0d4e505a8f4245..311fbce4ab68170caf0c7d9ade6190990fc90ab8 100644 (file)
@@ -1085,7 +1085,7 @@ DEFUN (eigrp_redistribute_source_metric,
 DEFUN (no_eigrp_redistribute_source_metric,
        no_eigrp_redistribute_source_metric_cmd,
        "no redistribute " FRR_REDIST_STR_EIGRPD
-       " metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)",
+       " [metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)]",
        "Disable\n"
        REDIST_STR
        FRR_REDIST_HELP_STR_EIGRPD
index 2635d555d9a202e4039b025b77a311c8f16bc4de..bc48173bba11d9b593bf5bd16221eacd59db1443 100644 (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 = \
diff --git a/fpm/.gitignore b/fpm/.gitignore
deleted file mode 100644 (file)
index 17e9044..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-!Makefile
-Makefile.in
-*.o
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.a
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
index 795535596b6fd0a6ec5f4c06a6808059bc73f724..05cec5a5282484ab4b4790c231aadccdd6e1f4cf 100644 (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
diff --git a/init/.gitignore b/init/.gitignore
deleted file mode 100644 (file)
index 30b4bc9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-Makefile
-Makefile.in
-.nfs*
-*~
-*.loT
-
index a882bbf675443d4213f538474e8cceb722719a30..b6184ca0f54b515c8f6837d5fedc3c0acd285c0f 100644 (file)
@@ -1,15 +1,3 @@
-!Makefile
-Makefile.in
-*.o
 isisd
-.deps
+fabricd
 isisd.conf
-.nfs*
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
-*.a
diff --git a/isisd/fabricd.c b/isisd/fabricd.c
new file mode 100644 (file)
index 0000000..7951efe
--- /dev/null
@@ -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;
+}
diff --git a/isisd/fabricd.conf.sample b/isisd/fabricd.conf.sample
new file mode 100644 (file)
index 0000000..be9e33b
--- /dev/null
@@ -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
+!
diff --git a/isisd/fabricd.h b/isisd/fabricd.h
new file mode 100644 (file)
index 0000000..76c182f
--- /dev/null
@@ -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
index 4b3d78421e8cf3a451b6c22feef551d3bd274376..a41d6ff8152267214bb99680de920d8654d6a8c8 100644 (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);
index 7e8a4a4edaba81502d7ba6ec840a3c2baa431882..28750278b017eee7c198153e7cc2c70bd9017d62 100644 (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);
index cd4b76139f7455f6603abbbb1cb6ce910beb9209..817a44bafe66fad4e2598c7f30d6d8b360a0559c 100644 (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;
 }
index 8dbd7ac492b9017cb952b5d15fcf4b4546bc7eb9..ea68767fe0fb35c1bfb5b40ff61631df5918a258 100644 (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 */
index 66c97ae8974413610db366e68b64c5abdc2cbd45..e8777e9b53a1d6eaab1e706e77058e2771f401f9 100644 (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);
-                                               }
-                                       }
+                               if (fabricd_init_c) {
+                                       fabricd_sync_incomplete |=
+                                               ISIS_CHECK_FLAG(lsp->SSNflags,
+                                                               fabricd_init_c);
                                }
-                               list_delete_all_node(lsp_list);
                        }
                }
        }
 
-       list_delete_and_null(&lsp_list);
+       if (fabricd_init_c
+           && !fabricd_sync_incomplete
+           && !isis_tx_queue_len(fabricd_init_c->tx_queue)) {
+               fabricd_initial_sync_finish(area);
+       }
 
        return ISIS_OK;
 }
@@ -1928,7 +1931,7 @@ void lsp_purge_pseudo(uint8_t *id, struct isis_circuit *circuit, int level)
        if (!lsp)
                return;
 
-       lsp_purge(lsp, level);
+       lsp_purge(lsp, level, NULL);
 }
 
 /*
@@ -1952,27 +1955,44 @@ void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr,
        memcpy(&lsp->hdr, hdr, sizeof(lsp->hdr));
        lsp->hdr.rem_lifetime = 0;
 
+       lsp_purge_add_poi(lsp, NULL);
+
        lsp_pack_pdu(lsp);
 
        lsp_insert(lsp, area->lspdb[lsp->level - 1]);
-       lsp_set_all_srmflags(lsp);
+       lsp_flood(lsp, NULL);
 
        return;
 }
 
-void lsp_set_all_srmflags(struct isis_lsp *lsp)
+void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set)
 {
        struct listnode *node;
        struct isis_circuit *circuit;
 
        assert(lsp);
 
-       ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags);
+       if (!lsp->area)
+               return;
 
-       if (lsp->area) {
-               struct list *circuit_list = lsp->area->circuit_list;
-               for (ALL_LIST_ELEMENTS_RO(circuit_list, node, circuit)) {
-                       ISIS_SET_FLAG(lsp->SRMflags, circuit);
+       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);
+       }
+}
index d531cb1576c1e7bf710875d4749c728f7afe219f..4e6379447cf5136de7f28ed31a6d95a34812f33d 100644 (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 */
diff --git a/isisd/isis_lsp_hash.c b/isisd/isis_lsp_hash.c
deleted file mode 100644 (file)
index c521f42..0000000
+++ /dev/null
@@ -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);
-}
diff --git a/isisd/isis_lsp_hash.h b/isisd/isis_lsp_hash.h
deleted file mode 100644 (file)
index b50aa09..0000000
+++ /dev/null
@@ -1,34 +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
- */
-#ifndef ISIS_LSP_HASH_H
-#define ISIS_LSP_HASH_H
-
-struct isis_lsp_hash;
-
-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
index 3b4168adb97fca0597c1420186fb02bbe292c456..4d6a6da5d602b2b883d4b0ba75055a22bf3d70da 100644 (file)
 #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();
index 2155bf584ec13d78aebd0d0d9401a365c3059093..2dfccf9830bdccbeb8a795c68dbe935f7e323a6d 100644 (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++;
                }
        }
index 5c4e3a35bcb44baf60bd4374df7ff909f4ea97af..88575f531943770c7155aba12fa36757fd96a075 100644 (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;
 }
index c69bfedeae78603ebcd3c3852d5f5ead79b063ca..3d2420eb036abf340f7459c8e93b2215fd5ad509 100644 (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);
index cd3ca44379c35aaeff9fbd98b1d8d2377277a073..ab7584ed3e04c5dc9a71ee50de70476593bf8c3c 100644 (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);
 }
index 341921146bb522858fe6bb004b3bbd439eb0090d..6a7528623c08df603c5315f327f26d737373af95 100644 (file)
 #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"
 #include "isis_csm.h"
 #include "isis_mt.h"
 #include "isis_tlvs.h"
+#include "fabricd.h"
+#include "isis_spf_private.h"
 
 DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info");
 
-enum vertextype {
-       VTYPE_PSEUDO_IS = 1,
-       VTYPE_PSEUDO_TE_IS,
-       VTYPE_NONPSEUDO_IS,
-       VTYPE_NONPSEUDO_TE_IS,
-       VTYPE_ES,
-       VTYPE_IPREACH_INTERNAL,
-       VTYPE_IPREACH_EXTERNAL,
-       VTYPE_IPREACH_TE,
-       VTYPE_IP6REACH_INTERNAL,
-       VTYPE_IP6REACH_EXTERNAL
-};
-
-#define VTYPE_IS(t) ((t) >= VTYPE_PSEUDO_IS && (t) <= VTYPE_NONPSEUDO_TE_IS)
-#define VTYPE_ES(t) ((t) == VTYPE_ES)
-#define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL)
-
-struct prefix_pair {
-       struct prefix dest;
-       struct prefix_ipv6 src;
-};
-
-/*
- * Triple <N, d(N), {Adj(N)}>
- */
-union isis_N {
-       uint8_t id[ISIS_SYS_ID_LEN + 1];
-       struct prefix_pair ip;
-};
-struct isis_vertex {
-       enum vertextype type;
-       union isis_N N;
-       uint32_t d_N;     /* d(N) Distance from this IS      */
-       uint16_t depth; /* The depth in the imaginary tree */
-       struct list *Adj_N;    /* {Adj(N)} next hop or neighbor list */
-       struct list *parents;  /* list of parents for ECMP */
-       uint64_t insert_counter;
-};
-
-/* Vertex Queue and associated functions */
-
-struct isis_vertex_queue {
-       union {
-               struct skiplist *slist;
-               struct list *list;
-       } l;
-       struct hash *hash;
-       uint64_t insert_counter;
-};
-
-static unsigned isis_vertex_queue_hash_key(void *vp)
-{
-       struct isis_vertex *vertex = vp;
-
-       if (VTYPE_IP(vertex->type)) {
-               uint32_t key;
-
-               key = prefix_hash_key(&vertex->N.ip.dest);
-               key = jhash_1word(prefix_hash_key(&vertex->N.ip.src), key);
-               return key;
-       }
-
-       return jhash(vertex->N.id, ISIS_SYS_ID_LEN + 1, 0x55aa5a5a);
-}
-
-static int isis_vertex_queue_hash_cmp(const void *a, const void *b)
-{
-       const struct isis_vertex *va = a, *vb = b;
-
-       if (va->type != vb->type)
-               return 0;
-
-       if (VTYPE_IP(va->type)) {
-               if (prefix_cmp(&va->N.ip.dest, &vb->N.ip.dest))
-                       return 0;
-
-               return prefix_cmp((struct prefix *)&va->N.ip.src,
-                                 (struct prefix *)&vb->N.ip.src) == 0;
-       }
-
-       return memcmp(va->N.id, vb->N.id, ISIS_SYS_ID_LEN + 1) == 0;
-}
-
-/*
- * Compares vertizes for sorting in the TENT list. Returns true
- * if candidate should be considered before current, false otherwise.
- */
-static int isis_vertex_queue_tent_cmp(void *a, void *b)
-{
-       struct isis_vertex *va = a;
-       struct isis_vertex *vb = b;
-
-       if (va->d_N < vb->d_N)
-               return -1;
-
-       if (va->d_N > vb->d_N)
-               return 1;
-
-       if (va->type < vb->type)
-               return -1;
-
-       if (va->type > vb->type)
-               return 1;
-
-       if (va->insert_counter < vb->insert_counter)
-               return -1;
-
-       if (va->insert_counter > vb->insert_counter)
-               return 1;
-
-       return 0;
-}
-
-static struct skiplist *isis_vertex_queue_skiplist(void)
-{
-       return skiplist_new(0, isis_vertex_queue_tent_cmp, NULL);
-}
-
-static void isis_vertex_queue_init(struct isis_vertex_queue *queue,
-                                  const char *name, bool ordered)
-{
-       if (ordered) {
-               queue->insert_counter = 1;
-               queue->l.slist = isis_vertex_queue_skiplist();
-       } else {
-               queue->insert_counter = 0;
-               queue->l.list = list_new();
-       }
-       queue->hash = hash_create(isis_vertex_queue_hash_key,
-                                 isis_vertex_queue_hash_cmp, name);
-}
-
-static void isis_vertex_del(struct isis_vertex *vertex);
-
-static void isis_vertex_queue_clear(struct isis_vertex_queue *queue)
-{
-       hash_clean(queue->hash, NULL);
-
-       if (queue->insert_counter) {
-               struct isis_vertex *vertex;
-               while (0 == skiplist_first(queue->l.slist, NULL,
-                                          (void **)&vertex)) {
-                       isis_vertex_del(vertex);
-                       skiplist_delete_first(queue->l.slist);
-               }
-               queue->insert_counter = 1;
-       } else {
-               queue->l.list->del = (void (*)(void *))isis_vertex_del;
-               list_delete_all_node(queue->l.list);
-               queue->l.list->del = NULL;
-       }
-}
-
-static void isis_vertex_queue_free(struct isis_vertex_queue *queue)
-{
-       isis_vertex_queue_clear(queue);
-
-       hash_free(queue->hash);
-       queue->hash = NULL;
-
-       if (queue->insert_counter) {
-               skiplist_free(queue->l.slist);
-               queue->l.slist = NULL;
-       } else
-               list_delete_and_null(&queue->l.list);
-}
-
-static unsigned int isis_vertex_queue_count(struct isis_vertex_queue *queue)
-{
-       return hashcount(queue->hash);
-}
-
-static void isis_vertex_queue_append(struct isis_vertex_queue *queue,
-                                    struct isis_vertex *vertex)
-{
-       assert(!queue->insert_counter);
-
-       listnode_add(queue->l.list, vertex);
-
-       struct isis_vertex *inserted;
-
-       inserted = hash_get(queue->hash, vertex, hash_alloc_intern);
-       assert(inserted == vertex);
-}
-
-static void isis_vertex_queue_insert(struct isis_vertex_queue *queue,
-                                    struct isis_vertex *vertex)
-{
-       assert(queue->insert_counter);
-       vertex->insert_counter = queue->insert_counter++;
-       assert(queue->insert_counter != (uint64_t)-1);
-
-       skiplist_insert(queue->l.slist, vertex, vertex);
-
-       struct isis_vertex *inserted;
-       inserted = hash_get(queue->hash, vertex, hash_alloc_intern);
-       assert(inserted == vertex);
-}
-
-static struct isis_vertex *
-isis_vertex_queue_pop(struct isis_vertex_queue *queue)
-{
-       assert(queue->insert_counter);
-
-       struct isis_vertex *rv;
-
-       if (skiplist_first(queue->l.slist, NULL, (void **)&rv))
-               return NULL;
-
-       skiplist_delete_first(queue->l.slist);
-       hash_release(queue->hash, rv);
-
-       return rv;
-}
-
-static void isis_vertex_queue_delete(struct isis_vertex_queue *queue,
-                                    struct isis_vertex *vertex)
-{
-       assert(queue->insert_counter);
-
-       skiplist_delete(queue->l.slist, vertex, vertex);
-       hash_release(queue->hash, vertex);
-}
-
-#define ALL_QUEUE_ELEMENTS_RO(queue, node, data)                               \
-       ALL_LIST_ELEMENTS_RO((queue)->l.list, node, data)
-
-
-/* End of vertex queue definitions */
-
-struct isis_spftree {
-       struct isis_vertex_queue paths; /* the SPT */
-       struct isis_vertex_queue tents; /* TENT */
-       struct route_table *route_table;
-       struct isis_area *area;    /* back pointer to area */
-       unsigned int runcount;     /* number of runs since uptime */
-       time_t last_run_timestamp; /* last run timestamp as wall time for display */
-       time_t last_run_monotime;  /* last run as monotime for scheduling */
-       time_t last_run_duration;  /* last run duration in msec */
-
-       uint16_t mtid;
-       int family;
-       int level;
-       enum spf_tree_id tree_id;
-};
-
-
 /*
  *  supports the given af ?
  */
@@ -411,8 +162,7 @@ static const char *vtype2string(enum vertextype vtype)
        return NULL; /* Not reached */
 }
 
-#define VID2STR_BUFFER SRCDEST2STR_BUFFER
-static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
+const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
 {
        if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) {
                return print_sys_hostname(vertex->N.id);
@@ -428,44 +178,26 @@ static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
        return "UNKNOWN";
 }
 
-static void isis_vertex_id_init(struct isis_vertex *vertex, union isis_N *n,
-                               enum vertextype vtype)
-{
-       vertex->type = vtype;
-
-       if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) {
-               memcpy(vertex->N.id, n->id, ISIS_SYS_ID_LEN + 1);
-       } else if (VTYPE_IP(vtype)) {
-               memcpy(&vertex->N.ip, &n->ip, sizeof(n->ip));
-       } else {
-               flog_err(LIB_ERR_DEVELOPMENT, "Unknown Vertex Type");
-       }
-}
-
-static struct isis_vertex *isis_vertex_new(union isis_N *n,
+static struct isis_vertex *isis_vertex_new(struct isis_spftree *spftree,
+                                          void *id,
                                           enum vertextype vtype)
 {
        struct isis_vertex *vertex;
 
        vertex = XCALLOC(MTYPE_ISIS_VERTEX, sizeof(struct isis_vertex));
 
-       isis_vertex_id_init(vertex, n, vtype);
+       isis_vertex_id_init(vertex, id, vtype);
 
        vertex->Adj_N = list_new();
        vertex->parents = list_new();
 
-       return vertex;
-}
-
-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);
+       if (spftree->hopcount_metric) {
+               vertex->firsthops = hash_create(isis_vertex_queue_hash_key,
+                                               isis_vertex_queue_hash_cmp,
+                                               NULL);
+       }
 
-       return;
+       return vertex;
 }
 
 static void isis_vertex_adj_del(struct isis_vertex *vertex,
@@ -563,6 +295,9 @@ void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj)
                                             adj);
                }
        }
+
+       if (fabricd_spftree(area) != NULL)
+               isis_spftree_adj_del(fabricd_spftree(area), adj);
 }
 
 /*
@@ -595,17 +330,13 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
 #ifdef EXTREME_DEBUG
        char buff[VID2STR_BUFFER];
 #endif /* EXTREME_DEBUG */
-       union isis_N n;
-
-       memcpy(n.id, sysid, ISIS_SYS_ID_LEN);
-       LSP_PSEUDO_ID(n.id) = 0;
 
        lsp = isis_root_system_lsp(spftree->area, spftree->level, sysid);
        if (lsp == NULL)
                zlog_warn("ISIS-Spf: could not find own l%d LSP!",
                          spftree->level);
 
-       vertex = isis_vertex_new(&n,
+       vertex = isis_vertex_new(spftree, sysid,
                                 spftree->area->oldmetric
                                         ? VTYPE_NONPSEUDO_IS
                                         : VTYPE_NONPSEUDO_TE_IS);
@@ -621,14 +352,24 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
        return vertex;
 }
 
-static struct isis_vertex *isis_find_vertex(struct isis_vertex_queue *queue,
-                                           union isis_N *n,
-                                           enum vertextype vtype)
+static void vertex_add_parent_firsthop(struct hash_backet *backet, void *arg)
 {
-       struct isis_vertex querier;
+       struct isis_vertex *vertex = arg;
+       struct isis_vertex *hop = backet->data;
 
-       isis_vertex_id_init(&querier, n, vtype);
-       return hash_lookup(queue->hash, &querier);
+       hash_get(vertex->firsthops, hop, hash_alloc_intern);
+}
+
+static void vertex_update_firsthops(struct isis_vertex *vertex,
+                                   struct isis_vertex *parent)
+{
+       if (vertex->d_N <= 2)
+               hash_get(vertex->firsthops, vertex, hash_alloc_intern);
+
+       if (vertex->d_N < 2 || !parent)
+               return;
+
+       hash_iterate(parent->firsthops, vertex_add_parent_firsthop, vertex);
 }
 
 /*
@@ -649,7 +390,7 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
 
        assert(isis_find_vertex(&spftree->paths, id, vtype) == NULL);
        assert(isis_find_vertex(&spftree->tents, id, vtype) == NULL);
-       vertex = isis_vertex_new(id, vtype);
+       vertex = isis_vertex_new(spftree, id, vtype);
        vertex->d_N = cost;
        vertex->depth = depth;
 
@@ -657,6 +398,9 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
                listnode_add(vertex->parents, parent);
        }
 
+       if (spftree->hopcount_metric)
+               vertex_update_firsthops(vertex, parent);
+
        if (parent && parent->Adj_N && listcount(parent->Adj_N) > 0) {
                for (ALL_LIST_ELEMENTS_RO(parent->Adj_N, node, parent_adj))
                        listnode_add(vertex->Adj_N, parent_adj);
@@ -722,6 +466,10 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
 
        assert(spftree && parent);
 
+       if (spftree->hopcount_metric
+           && !VTYPE_IS(vtype))
+               return;
+
        struct prefix_pair p;
        if (vtype >= VTYPE_IPREACH_INTERNAL) {
                memcpy(&p, id, sizeof(p));
@@ -774,6 +522,8 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
                                if (listnode_lookup(vertex->Adj_N, parent_adj)
                                    == NULL)
                                        listnode_add(vertex->Adj_N, parent_adj);
+                       if (spftree->hopcount_metric)
+                               vertex_update_firsthops(vertex, parent);
                        /*      2) */
                        if (listcount(vertex->Adj_N) > ISIS_MAX_PATH_SPLITS)
                                remove_excess_adjs(vertex->Adj_N);
@@ -853,6 +603,9 @@ lspfragloop:
                        for (r = (struct isis_oldstyle_reach *)
                                         lsp->tlvs->oldstyle_reach.head;
                             r; r = r->next) {
+                               if (fabricd)
+                                       continue;
+
                                /* C.2.6 a) */
                                /* Two way connectivity */
                                if (!memcmp(r->id, root_sysid, ISIS_SYS_ID_LEN))
@@ -889,7 +642,7 @@ lspfragloop:
                        if (!pseudo_lsp
                            && !memcmp(er->id, null_sysid, ISIS_SYS_ID_LEN))
                                continue;
-                       dist = cost + er->metric;
+                       dist = cost + (spftree->hopcount_metric ? 1 : er->metric);
                        process_N(spftree,
                                  LSP_PSEUDO_ID(er->id) ? VTYPE_PSEUDO_TE_IS
                                                        : VTYPE_NONPSEUDO_TE_IS,
@@ -897,7 +650,7 @@ lspfragloop:
                }
        }
 
-       if (!pseudo_lsp && spftree->family == AF_INET
+       if (!fabricd && !pseudo_lsp && spftree->family == AF_INET
            && spftree->mtid == ISIS_MT_IPV4_UNICAST) {
                struct isis_item_list *reachs[] = {
                        &lsp->tlvs->oldstyle_ip_reach,
@@ -1037,7 +790,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                /*
                 * Add IP(v6) addresses of this circuit
                 */
-               if (spftree->family == AF_INET) {
+               if (spftree->family == AF_INET && !spftree->hopcount_metric) {
                        memset(&ip_info, 0, sizeof(ip_info));
                        ip_info.dest.family = AF_INET;
                        for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, ipnode,
@@ -1050,7 +803,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                                                   &ip_info, NULL, 0, parent);
                        }
                }
-               if (spftree->family == AF_INET6) {
+               if (spftree->family == AF_INET6 && !spftree->hopcount_metric) {
                        memset(&ip_info, 0, sizeof(ip_info));
                        ip_info.dest.family = AF_INET6;
                        for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link,
@@ -1094,6 +847,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                                        LSP_PSEUDO_ID(lsp_id) = 0;
                                        isis_spf_add_local(
                                                spftree, VTYPE_ES, lsp_id, adj,
+                                               spftree->hopcount_metric ? 1 :
                                                circuit->te_metric
                                                        [spftree->level - 1],
                                                parent);
@@ -1111,6 +865,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                                                        ? VTYPE_NONPSEUDO_IS
                                                        : VTYPE_NONPSEUDO_TE_IS,
                                                lsp_id, adj,
+                                               spftree->hopcount_metric ? 1 :
                                                circuit->te_metric
                                                        [spftree->level - 1],
                                                parent);
@@ -1180,10 +935,10 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                                        circuit->circuit_id);
                                continue;
                        }
-                       isis_spf_process_lsp(
-                               spftree, lsp,
-                               circuit->te_metric[spftree->level - 1], 0,
-                               root_sysid, parent);
+                       isis_spf_process_lsp(spftree, lsp,
+                                            spftree->hopcount_metric ?
+                                            1 : circuit->te_metric[spftree->level - 1],
+                                            0, root_sysid, parent);
                } else if (circuit->circ_type == CIRCUIT_T_P2P) {
                        adj = circuit->u.p2p.neighbor;
                        if (!adj || adj->adj_state != ISIS_ADJ_UP)
@@ -1196,6 +951,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                                LSP_PSEUDO_ID(lsp_id) = 0;
                                isis_spf_add_local(
                                        spftree, VTYPE_ES, lsp_id, adj,
+                                       spftree->hopcount_metric ? 1 :
                                        circuit->te_metric[spftree->level - 1],
                                        parent);
                                break;
@@ -1215,6 +971,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
                                                        ? VTYPE_NONPSEUDO_IS
                                                        : VTYPE_NONPSEUDO_TE_IS,
                                                lsp_id, adj,
+                                               spftree->hopcount_metric ? 1 :
                                                circuit->te_metric
                                                        [spftree->level - 1],
                                                parent);
@@ -1275,7 +1032,8 @@ static void add_to_paths(struct isis_spftree *spftree,
 }
 
 static void init_spt(struct isis_spftree *spftree, int mtid, int level,
-                    int family, enum spf_tree_id tree_id)
+                    int family, enum spf_tree_id tree_id,
+                    bool hopcount_metric)
 {
        isis_vertex_queue_clear(&spftree->tents);
        isis_vertex_queue_clear(&spftree->paths);
@@ -1284,7 +1042,63 @@ static void init_spt(struct isis_spftree *spftree, int mtid, int level,
        spftree->level = level;
        spftree->family = family;
        spftree->tree_id = tree_id;
-       return;
+       spftree->hopcount_metric = hopcount_metric;
+}
+
+static void isis_spf_loop(struct isis_spftree *spftree,
+                         uint8_t *root_sysid)
+{
+       struct isis_vertex *vertex;
+       struct isis_lsp *lsp;
+
+       while (isis_vertex_queue_count(&spftree->tents)) {
+               vertex = isis_vertex_queue_pop(&spftree->tents);
+
+#ifdef EXTREME_DEBUG
+               zlog_debug(
+                       "ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS",
+                       print_sys_hostname(vertex->N.id),
+                       vtype2string(vertex->type), vertex->depth, vertex->d_N);
+#endif /* EXTREME_DEBUG */
+
+               add_to_paths(spftree, vertex);
+               if (!VTYPE_IS(vertex->type))
+                       continue;
+
+               lsp = lsp_for_vertex(spftree, vertex);
+               if (!lsp) {
+                       zlog_warn("ISIS-Spf: No LSP found for %s",
+                                 rawlspid_print(vertex->N.id)); /* FIXME */
+                       continue;
+               }
+
+               isis_spf_process_lsp(spftree, lsp, vertex->d_N, vertex->depth,
+                                    root_sysid, vertex);
+       }
+}
+
+struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area,
+                                          uint8_t *sysid,
+                                          struct isis_spftree *spftree)
+{
+       if (!spftree)
+               spftree = isis_spftree_new(area);
+
+       init_spt(spftree, ISIS_MT_IPV4_UNICAST, ISIS_LEVEL2,
+                AF_INET, SPFTREE_IPV4, true);
+       if (!memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN)) {
+               /* If we are running locally, initialize with information from adjacencies */
+               struct isis_vertex *root = isis_spf_add_root(spftree, sysid);
+               isis_spf_preload_tent(spftree, sysid, root);
+       } else {
+               isis_vertex_queue_insert(&spftree->tents, isis_vertex_new(
+                                        spftree, sysid,
+                                        VTYPE_NONPSEUDO_TE_IS));
+       }
+
+       isis_spf_loop(spftree, sysid);
+
+       return spftree;
 }
 
 static int isis_run_spf(struct isis_area *area, int level,
@@ -1292,11 +1106,8 @@ static int isis_run_spf(struct isis_area *area, int level,
                        uint8_t *sysid, struct timeval *nowtv)
 {
        int retval = ISIS_OK;
-       struct isis_vertex *vertex;
        struct isis_vertex *root_vertex;
        struct isis_spftree *spftree = area->spftree[tree_id][level - 1];
-       uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
-       struct isis_lsp *lsp;
        struct timeval time_now;
        unsigned long long start_time, end_time;
        uint16_t mtid = 0;
@@ -1330,7 +1141,7 @@ static int isis_run_spf(struct isis_area *area, int level,
        /*
         * C.2.5 Step 0
         */
-       init_spt(spftree, mtid, level, family, tree_id);
+       init_spt(spftree, mtid, level, family, tree_id, false);
        /*              a) */
        root_vertex = isis_spf_add_root(spftree, sysid);
        /*              b) */
@@ -1350,32 +1161,7 @@ static int isis_run_spf(struct isis_area *area, int level,
                          print_sys_hostname(sysid));
        }
 
-       while (isis_vertex_queue_count(&spftree->tents)) {
-               vertex = isis_vertex_queue_pop(&spftree->tents);
-
-#ifdef EXTREME_DEBUG
-               zlog_debug(
-                       "ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS",
-                       print_sys_hostname(vertex->N.id),
-                       vtype2string(vertex->type), vertex->depth, vertex->d_N);
-#endif /* EXTREME_DEBUG */
-
-               add_to_paths(spftree, vertex);
-               if (VTYPE_IS(vertex->type)) {
-                       memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
-                       LSP_FRAGMENT(lsp_id) = 0;
-                       lsp = lsp_search(lsp_id, area->lspdb[level - 1]);
-                       if (lsp && lsp->hdr.rem_lifetime != 0) {
-                               isis_spf_process_lsp(spftree, lsp, vertex->d_N,
-                                                    vertex->depth, sysid,
-                                                    vertex);
-                       } else {
-                               zlog_warn("ISIS-Spf: No LSP found for %s",
-                                         rawlspid_print(lsp_id));
-                       }
-               }
-       }
-
+       isis_spf_loop(spftree, sysid);
 out:
        spftree->runcount++;
        spftree->last_run_timestamp = time(NULL);
@@ -1446,6 +1232,8 @@ static int isis_run_spf_cb(struct thread *thread)
        for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
                UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
 
+       fabricd_run_spf(area);
+
        return retval;
 }
 
@@ -1617,12 +1405,18 @@ static void isis_print_spftree(struct vty *vty, int level,
 
 DEFUN (show_isis_topology,
        show_isis_topology_cmd,
-       "show isis topology [<level-1|level-2>]",
-       SHOW_STR
-       "IS-IS information\n"
+       "show " PROTO_NAME " topology"
+#ifndef FABRICD
+       " [<level-1|level-2>]"
+#endif
+       , SHOW_STR
+       PROTO_HELP
        "IS-IS paths to Intermediate Systems\n"
+#ifndef FABRICD
        "Paths to all level-1 routers in the area\n"
-       "Paths to all level-2 routers in the domain\n")
+       "Paths to all level-2 routers in the domain\n"
+#endif
+       )
 {
        int levels;
        struct listnode *node;
@@ -1660,6 +1454,13 @@ DEFUN (show_isis_topology,
                        }
                }
 
+               if (fabricd_spftree(area)) {
+                       vty_out(vty,
+                               "IS-IS paths to level-2 routers with hop-by-hop metric\n");
+                       isis_print_paths(vty, &fabricd_spftree(area)->paths, isis->sysid);
+                       vty_out(vty, "\n");
+               }
+
                vty_out(vty, "\n");
        }
 
index 9a73ca8783dd3b6d766eb2b73b21fe45692773b0..f4db98cfed532af958e56671be8aba600e97ca07 100644 (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 */
diff --git a/isisd/isis_spf_private.h b/isisd/isis_spf_private.h
new file mode 100644 (file)
index 0000000..af552e0
--- /dev/null
@@ -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
index 44ba64ce26f80f76d3a3064b9241560fa4f41681..08b905c65032fd89ca22169329ac76cc45151d62 100644 (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;
 }
index a433fcdb41a86f3da769b084d55d8c1dfb12ce56..b22460a0b5402abb914d1a45ea26aec402a114e4 100644 (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));
+       }
+}
index bd1fa3e6768d3cea582f6b3821393a0bc2b9765a..4144809fa3aeaaf4a55317dfe522679906ae3705 100644 (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
diff --git a/isisd/isis_tx_queue.c b/isisd/isis_tx_queue.c
new file mode 100644 (file)
index 0000000..3242762
--- /dev/null
@@ -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);
+}
diff --git a/isisd/isis_tx_queue.h b/isisd/isis_tx_queue.h
new file mode 100644 (file)
index 0000000..ddecdf1
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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
+ */
+#ifndef ISIS_TX_QUEUE_H
+#define ISIS_TX_QUEUE_H
+
+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);
+
+#endif
diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c
deleted file mode 100644 (file)
index ce2952c..0000000
+++ /dev/null
@@ -1,2165 +0,0 @@
-/*
- * IS-IS Rout(e)ing protocol - isis_circuit.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
- */
-
-#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"
-
-static 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 isis WORD",
-       "Interface Internet Protocol config commands\n"
-       "IP router interface commands\n"
-       "IS-IS Routing for IP\n"
-       "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 isis WORD",
-       "Interface Internet Protocol config commands\n"
-       "IP router interface commands\n"
-       "IS-IS Routing for IP\n"
-       "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 isis WORD",
-       NO_STR
-       "Interface Internet Protocol config commands\n"
-       "IP router interface commands\n"
-       "IP router interface commands\n"
-       "IS-IS Routing for IP\n"
-       "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",
-                       argv[idx_afi]->arg);
-               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,
-       "isis passive",
-       "IS-IS commands\n"
-       "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 isis passive",
-       NO_STR
-       "IS-IS commands\n"
-       "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_circuit_type,
-       isis_circuit_type_cmd,
-       "isis circuit-type <level-1|level-1-2|level-2-only>",
-       "IS-IS commands\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 commands\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 commands\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 commands\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_passwd,
-       isis_passwd_cmd,
-       "isis password <md5|clear> WORD",
-       "IS-IS commands\n"
-       "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 isis password [<md5|clear> WORD]",
-       NO_STR
-       "IS-IS commands\n"
-       "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_priority,
-       isis_priority_cmd,
-       "isis priority (0-127)",
-       "IS-IS commands\n"
-       "Set priority for Designated Router election\n"
-       "Priority value\n")
-{
-       int idx_number = 2;
-       int prio;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       prio = atoi(argv[idx_number]->arg);
-       if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
-               vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       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 commands\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_l1,
-       isis_priority_l1_cmd,
-       "isis priority (0-127) level-1",
-       "IS-IS commands\n"
-       "Set priority for Designated Router election\n"
-       "Priority value\n"
-       "Specify priority for level-1 routing\n")
-{
-       int idx_number = 2;
-       int prio;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       prio = atoi(argv[idx_number]->arg);
-       if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
-               vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->priority[0] = prio;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_priority_l1,
-       no_isis_priority_l1_cmd,
-       "no isis priority [(0-127)] level-1",
-       NO_STR
-       "IS-IS commands\n"
-       "Set priority for Designated Router election\n"
-       "Priority value\n"
-       "Specify priority for level-1 routing\n")
-{
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       circuit->priority[0] = DEFAULT_PRIORITY;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (isis_priority_l2,
-       isis_priority_l2_cmd,
-       "isis priority (0-127) level-2",
-       "IS-IS commands\n"
-       "Set priority for Designated Router election\n"
-       "Priority value\n"
-       "Specify priority for level-2 routing\n")
-{
-       int idx_number = 2;
-       int prio;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       prio = atoi(argv[idx_number]->arg);
-       if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
-               vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->priority[1] = prio;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_priority_l2,
-       no_isis_priority_l2_cmd,
-       "no isis priority [(0-127)] level-2",
-       NO_STR
-       "IS-IS commands\n"
-       "Set priority for Designated Router election\n"
-       "Priority value\n"
-       "Specify priority for level-2 routing\n")
-{
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       circuit->priority[1] = DEFAULT_PRIORITY;
-
-       return CMD_SUCCESS;
-}
-
-
-/* Metric command */
-DEFUN (isis_metric,
-       isis_metric_cmd,
-       "isis metric (0-16777215)",
-       "IS-IS commands\n"
-       "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 isis metric [(0-16777215)]",
-       NO_STR
-       "IS-IS commands\n"
-       "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_metric_l1,
-       isis_metric_l1_cmd,
-       "isis metric (0-16777215) level-1",
-       "IS-IS commands\n"
-       "Set default metric for circuit\n"
-       "Default metric value\n"
-       "Specify metric for level-1 routing\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);
-       CMD_FERR_RETURN(isis_circuit_metric_set(circuit, IS_LEVEL_1, met),
-                       "Failed to set L1 metric: $ERR");
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_isis_metric_l1,
-       no_isis_metric_l1_cmd,
-       "no isis metric [(0-16777215)] level-1",
-       NO_STR
-       "IS-IS commands\n"
-       "Set default metric for circuit\n"
-       "Default metric value\n"
-       "Specify metric for level-1 routing\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");
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (isis_metric_l2,
-       isis_metric_l2_cmd,
-       "isis metric (0-16777215) level-2",
-       "IS-IS commands\n"
-       "Set default metric for circuit\n"
-       "Default metric value\n"
-       "Specify metric for level-2 routing\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);
-       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_l2,
-       no_isis_metric_l2_cmd,
-       "no isis metric [(0-16777215)] level-2",
-       NO_STR
-       "IS-IS commands\n"
-       "Set default metric for circuit\n"
-       "Default metric value\n"
-       "Specify metric for level-2 routing\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_2,
-                                               DEFAULT_CIRCUIT_METRIC),
-                       "Failed to set L2 metric: $ERR");
-       return CMD_SUCCESS;
-}
-
-/* end of metrics */
-
-DEFUN (isis_hello_interval,
-       isis_hello_interval_cmd,
-       "isis hello-interval (1-600)",
-       "IS-IS commands\n"
-       "Set Hello interval\n"
-       "Holdtime 1 seconds, interval depends on multiplier\n")
-{
-       int idx_number = 2;
-       int interval;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       interval = atoi(argv[idx_number]->arg);
-       if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) {
-               vty_out(vty, "Invalid hello-interval %d - should be <1-600>\n",
-                       interval);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->hello_interval[0] = (uint16_t)interval;
-       circuit->hello_interval[1] = (uint16_t)interval;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_isis_hello_interval,
-       no_isis_hello_interval_cmd,
-       "no isis hello-interval [(1-600)]",
-       NO_STR
-       "IS-IS commands\n"
-       "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_interval_l1,
-       isis_hello_interval_l1_cmd,
-       "isis hello-interval (1-600) level-1",
-       "IS-IS commands\n"
-       "Set Hello interval\n"
-       "Holdtime 1 second, interval depends on multiplier\n"
-       "Specify hello-interval for level-1 IIHs\n")
-{
-       int idx_number = 2;
-       long interval;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       interval = atoi(argv[idx_number]->arg);
-       if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) {
-               vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n",
-                       interval);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->hello_interval[0] = (uint16_t)interval;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_isis_hello_interval_l1,
-       no_isis_hello_interval_l1_cmd,
-       "no isis hello-interval [(1-600)] level-1",
-       NO_STR
-       "IS-IS commands\n"
-       "Set Hello interval\n"
-       "Holdtime 1 second, interval depends on multiplier\n"
-       "Specify hello-interval for level-1 IIHs\n")
-{
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (isis_hello_interval_l2,
-       isis_hello_interval_l2_cmd,
-       "isis hello-interval (1-600) level-2",
-       "IS-IS commands\n"
-       "Set Hello interval\n"
-       "Holdtime 1 second, interval depends on multiplier\n"
-       "Specify hello-interval for level-2 IIHs\n")
-{
-       int idx_number = 2;
-       long interval;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       interval = atoi(argv[idx_number]->arg);
-       if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) {
-               vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n",
-                       interval);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->hello_interval[1] = (uint16_t)interval;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_isis_hello_interval_l2,
-       no_isis_hello_interval_l2_cmd,
-       "no isis hello-interval [(1-600)] level-2",
-       NO_STR
-       "IS-IS commands\n"
-       "Set Hello interval\n"
-       "Holdtime 1 second, interval depends on multiplier\n"
-       "Specify hello-interval for level-2 IIHs\n")
-{
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (isis_hello_multiplier,
-       isis_hello_multiplier_cmd,
-       "isis hello-multiplier (2-100)",
-       "IS-IS commands\n"
-       "Set multiplier for Hello holding time\n"
-       "Hello multiplier value\n")
-{
-       int idx_number = 2;
-       int mult;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       mult = atoi(argv[idx_number]->arg);
-       if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) {
-               vty_out(vty,
-                       "Invalid hello-multiplier %d - should be <2-100>\n",
-                       mult);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->hello_multiplier[0] = (uint16_t)mult;
-       circuit->hello_multiplier[1] = (uint16_t)mult;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_isis_hello_multiplier,
-       no_isis_hello_multiplier_cmd,
-       "no isis hello-multiplier [(2-100)]",
-       NO_STR
-       "IS-IS commands\n"
-       "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 (isis_hello_multiplier_l1,
-       isis_hello_multiplier_l1_cmd,
-       "isis hello-multiplier (2-100) level-1",
-       "IS-IS commands\n"
-       "Set multiplier for Hello holding time\n"
-       "Hello multiplier value\n"
-       "Specify hello multiplier for level-1 IIHs\n")
-{
-       int idx_number = 2;
-       int mult;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       mult = atoi(argv[idx_number]->arg);
-       if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) {
-               vty_out(vty,
-                       "Invalid hello-multiplier %d - should be <2-100>\n",
-                       mult);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->hello_multiplier[0] = (uint16_t)mult;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_isis_hello_multiplier_l1,
-       no_isis_hello_multiplier_l1_cmd,
-       "no isis hello-multiplier [(2-100)] level-1",
-       NO_STR
-       "IS-IS commands\n"
-       "Set multiplier for Hello holding time\n"
-       "Hello multiplier value\n"
-       "Specify hello multiplier for level-1 IIHs\n")
-{
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (isis_hello_multiplier_l2,
-       isis_hello_multiplier_l2_cmd,
-       "isis hello-multiplier (2-100) level-2",
-       "IS-IS commands\n"
-       "Set multiplier for Hello holding time\n"
-       "Hello multiplier value\n"
-       "Specify hello multiplier for level-2 IIHs\n")
-{
-       int idx_number = 2;
-       int mult;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       mult = atoi(argv[idx_number]->arg);
-       if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) {
-               vty_out(vty,
-                       "Invalid hello-multiplier %d - should be <2-100>\n",
-                       mult);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->hello_multiplier[1] = (uint16_t)mult;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_isis_hello_multiplier_l2,
-       no_isis_hello_multiplier_l2_cmd,
-       "no isis hello-multiplier [(2-100)] level-2",
-       NO_STR
-       "IS-IS commands\n"
-       "Set multiplier for Hello holding time\n"
-       "Hello multiplier value\n"
-       "Specify hello multiplier for level-2 IIHs\n")
-{
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (isis_hello_padding,
-       isis_hello_padding_cmd,
-       "isis hello padding",
-       "IS-IS commands\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 commands\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 (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 (csnp_interval,
-       csnp_interval_cmd,
-       "isis csnp-interval (1-600)",
-       "IS-IS commands\n"
-       "Set CSNP interval in seconds\n"
-       "CSNP interval value\n")
-{
-       int idx_number = 2;
-       unsigned long interval;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       interval = atol(argv[idx_number]->arg);
-       if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) {
-               vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
-                       interval);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->csnp_interval[0] = (uint16_t)interval;
-       circuit->csnp_interval[1] = (uint16_t)interval;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_csnp_interval,
-       no_csnp_interval_cmd,
-       "no isis csnp-interval [(1-600)]",
-       NO_STR
-       "IS-IS commands\n"
-       "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 (csnp_interval_l1,
-       csnp_interval_l1_cmd,
-       "isis csnp-interval (1-600) level-1",
-       "IS-IS commands\n"
-       "Set CSNP interval in seconds\n"
-       "CSNP interval value\n"
-       "Specify interval for level-1 CSNPs\n")
-{
-       int idx_number = 2;
-       unsigned long interval;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       interval = atol(argv[idx_number]->arg);
-       if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) {
-               vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
-                       interval);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->csnp_interval[0] = (uint16_t)interval;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_csnp_interval_l1,
-       no_csnp_interval_l1_cmd,
-       "no isis csnp-interval [(1-600)] level-1",
-       NO_STR
-       "IS-IS commands\n"
-       "Set CSNP interval in seconds\n"
-       "CSNP interval value\n"
-       "Specify interval for level-1 CSNPs\n")
-{
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (csnp_interval_l2,
-       csnp_interval_l2_cmd,
-       "isis csnp-interval (1-600) level-2",
-       "IS-IS commands\n"
-       "Set CSNP interval in seconds\n"
-       "CSNP interval value\n"
-       "Specify interval for level-2 CSNPs\n")
-{
-       int idx_number = 2;
-       unsigned long interval;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       interval = atol(argv[idx_number]->arg);
-       if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) {
-               vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
-                       interval);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->csnp_interval[1] = (uint16_t)interval;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_csnp_interval_l2,
-       no_csnp_interval_l2_cmd,
-       "no isis csnp-interval [(1-600)] level-2",
-       NO_STR
-       "IS-IS commands\n"
-       "Set CSNP interval in seconds\n"
-       "CSNP interval value\n"
-       "Specify interval for level-2 CSNPs\n")
-{
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (psnp_interval,
-       psnp_interval_cmd,
-       "isis psnp-interval (1-120)",
-       "IS-IS commands\n"
-       "Set PSNP interval in seconds\n"
-       "PSNP interval value\n")
-{
-       int idx_number = 2;
-       unsigned long interval;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       interval = atol(argv[idx_number]->arg);
-       if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) {
-               vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
-                       interval);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->psnp_interval[0] = (uint16_t)interval;
-       circuit->psnp_interval[1] = (uint16_t)interval;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_psnp_interval,
-       no_psnp_interval_cmd,
-       "no isis psnp-interval [(1-120)]",
-       NO_STR
-       "IS-IS commands\n"
-       "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 (psnp_interval_l1,
-       psnp_interval_l1_cmd,
-       "isis psnp-interval (1-120) level-1",
-       "IS-IS commands\n"
-       "Set PSNP interval in seconds\n"
-       "PSNP interval value\n"
-       "Specify interval for level-1 PSNPs\n")
-{
-       int idx_number = 2;
-       unsigned long interval;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       interval = atol(argv[idx_number]->arg);
-       if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) {
-               vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
-                       interval);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->psnp_interval[0] = (uint16_t)interval;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_psnp_interval_l1,
-       no_psnp_interval_l1_cmd,
-       "no isis psnp-interval [(1-120)] level-1",
-       NO_STR
-       "IS-IS commands\n"
-       "Set PSNP interval in seconds\n"
-       "PSNP interval value\n"
-       "Specify interval for level-1 PSNPs\n")
-{
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (psnp_interval_l2,
-       psnp_interval_l2_cmd,
-       "isis psnp-interval (1-120) level-2",
-       "IS-IS commands\n"
-       "Set PSNP interval in seconds\n"
-       "PSNP interval value\n"
-       "Specify interval for level-2 PSNPs\n")
-{
-       int idx_number = 2;
-       unsigned long interval;
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       interval = atol(argv[idx_number]->arg);
-       if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) {
-               vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
-                       interval);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       circuit->psnp_interval[1] = (uint16_t)interval;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (no_psnp_interval_l2,
-       no_psnp_interval_l2_cmd,
-       "no isis psnp-interval [(1-120)] level-2",
-       NO_STR
-       "IS-IS commands\n"
-       "Set PSNP interval in seconds\n"
-       "PSNP interval value\n"
-       "Specify interval for level-2 PSNPs\n")
-{
-       struct isis_circuit *circuit = isis_circuit_lookup(vty);
-       if (!circuit)
-               return CMD_ERR_NO_MATCH;
-
-       circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (circuit_topology,
-       circuit_topology_cmd,
-       "isis topology " ISIS_MT_NAMES,
-       "IS-IS commands\n"
-       "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 isis topology " ISIS_MT_NAMES,
-       NO_STR
-       "IS-IS commands\n"
-       "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);
-}
-
-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_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;
-}
-
-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;
-}
-
-static int area_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 area_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 area_lsp_mtu_set(vty, DEFAULT_LSP_MTU);
-}
-
-
-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;
-}
-
-static int set_lsp_gen_interval(struct vty *vty, struct isis_area *area,
-                               uint16_t interval, int level)
-{
-       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 [<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")
-{
-       int idx = 0;
-       VTY_DECLVAR_CONTEXT(isis_area, area);
-       uint16_t interval;
-       int level;
-
-       level = 0;
-       level |= argv_find(argv, argc, "level-1", &idx) ? IS_LEVEL_1 : 0;
-       level |= argv_find(argv, argc, "level-2", &idx) ? IS_LEVEL_2 : 0;
-       if (!level)
-               level = IS_LEVEL_1 | IS_LEVEL_2;
-
-       argv_find(argv, argc, "(1-120)", &idx);
-
-       interval = atoi(argv[idx]->arg);
-       return set_lsp_gen_interval(vty, area, interval, level);
-}
-
-DEFUN (no_lsp_gen_interval,
-       no_lsp_gen_interval_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")
-{
-       int idx = 0;
-       VTY_DECLVAR_CONTEXT(isis_area, area);
-       uint16_t interval;
-       int level;
-
-       level = 0;
-       level |= argv_find(argv, argc, "level-1", &idx) ? IS_LEVEL_1 : 0;
-       level |= argv_find(argv, argc, "level-2", &idx) ? IS_LEVEL_2 : 0;
-       if (!level)
-               level = IS_LEVEL_1 | IS_LEVEL_2;
-
-       interval = DEFAULT_MIN_LSP_GEN_INTERVAL;
-       return set_lsp_gen_interval(vty, area, interval, level);
-}
-
-DEFUN (spf_interval,
-       spf_interval_cmd,
-       "spf-interval (1-120)",
-       "Minimum interval between SPF calculations\n"
-       "Minimum interval between consecutive SPFs in seconds\n")
-{
-       int idx_number = 1;
-       VTY_DECLVAR_CONTEXT(isis_area, area);
-       uint16_t interval;
-
-       interval = atoi(argv[idx_number]->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 [[<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);
-
-       area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
-       area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (spf_interval_l1,
-       spf_interval_l1_cmd,
-       "spf-interval level-1 (1-120)",
-       "Minimum interval between SPF calculations\n"
-       "Set interval for level 1 only\n"
-       "Minimum interval between consecutive SPFs in seconds\n")
-{
-       int idx_number = 2;
-       VTY_DECLVAR_CONTEXT(isis_area, area);
-       uint16_t interval;
-
-       interval = atoi(argv[idx_number]->arg);
-       area->min_spf_interval[0] = interval;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (no_spf_interval_l1,
-       no_spf_interval_l1_cmd,
-       "no spf-interval level-1",
-       NO_STR
-       "Minimum interval between SPF calculations\n"
-       "Set interval for level 1 only\n")
-{
-       VTY_DECLVAR_CONTEXT(isis_area, area);
-
-       area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
-
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (spf_interval_l2,
-       spf_interval_l2_cmd,
-       "spf-interval level-2 (1-120)",
-       "Minimum interval between SPF calculations\n"
-       "Set interval for level 2 only\n"
-       "Minimum interval between consecutive SPFs in seconds\n")
-{
-       int idx_number = 2;
-       VTY_DECLVAR_CONTEXT(isis_area, area);
-       uint16_t interval;
-
-       interval = atoi(argv[idx_number]->arg);
-       area->min_spf_interval[1] = interval;
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (no_spf_interval_l2,
-       no_spf_interval_l2_cmd,
-       "no spf-interval level-2",
-       NO_STR
-       "Minimum interval between SPF calculations\n"
-       "Set interval for level 2 only\n")
-{
-       VTY_DECLVAR_CONTEXT(isis_area, area);
-
-       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;
-}
-
-static int area_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 [<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")
-{
-       int idx = 0;
-       unsigned int level = IS_LEVEL_1_AND_2;
-
-       if (argv_find(argv, argc, "level-1", &idx))
-               level = IS_LEVEL_1;
-       else if (argv_find(argv, argc, "level-2", &idx))
-               level = IS_LEVEL_2;
-
-       argv_find(argv, argc, "(350-65535)", &idx);
-       int lifetime = atoi(argv[idx]->arg);
-
-       return area_max_lsp_lifetime_set(vty, level, lifetime);
-}
-
-
-DEFUN (no_max_lsp_lifetime,
-       no_max_lsp_lifetime_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")
-{
-       int idx = 0;
-       unsigned int level = IS_LEVEL_1_AND_2;
-
-       if (argv_find(argv, argc, "level-1", &idx))
-               level = IS_LEVEL_1;
-       else if (argv_find(argv, argc, "level-2", &idx))
-               level = IS_LEVEL_2;
-
-       return area_max_lsp_lifetime_set(vty, level, DEFAULT_LSP_LIFETIME);
-}
-
-static int area_lsp_refresh_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_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 [<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")
-{
-       int idx = 0;
-       unsigned int level = IS_LEVEL_1_AND_2;
-       unsigned int interval = 0;
-
-       if (argv_find(argv, argc, "level-1", &idx))
-               level = IS_LEVEL_1;
-       else if (argv_find(argv, argc, "level-2", &idx))
-               level = IS_LEVEL_2;
-
-       interval = atoi(argv[argc - 1]->arg);
-       return area_lsp_refresh_interval_set(vty, level, interval);
-}
-
-DEFUN (no_lsp_refresh_interval,
-       no_lsp_refresh_interval_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")
-{
-       int idx = 0;
-       unsigned int level = IS_LEVEL_1_AND_2;
-
-       if (argv_find(argv, argc, "level-1", &idx))
-               level = IS_LEVEL_1;
-       else if (argv_find(argv, argc, "level-2", &idx))
-               level = IS_LEVEL_2;
-
-       return area_lsp_refresh_interval_set(vty, level,
-                                            DEFAULT_MAX_LSP_GEN_INTERVAL);
-}
-
-static int area_passwd_set(struct vty *vty, int level,
-                          int (*type_set)(struct isis_area *area, int level,
-                                          const char *passwd,
-                                          uint8_t snp_auth),
-                          const char *passwd, uint8_t snp_auth)
-{
-       VTY_DECLVAR_CONTEXT(isis_area, area);
-
-       if (passwd && strlen(passwd) > 254) {
-               vty_out(vty, "Too long area password (>254)\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       type_set(area, level, passwd, snp_auth);
-       return CMD_SUCCESS;
-}
-
-
-DEFUN (area_passwd_md5,
-       area_passwd_md5_cmd,
-       "area-password md5 WORD [authenticate snp <send-only|validate>]",
-       "Configure the authentication password for an area\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")
-{
-       int idx_password = 0;
-       int idx_word = 2;
-       int idx_type = 5;
-       uint8_t snp_auth = 0;
-       int level = strmatch(argv[idx_password]->text, "domain-password")
-                           ? IS_LEVEL_2
-                           : IS_LEVEL_1;
-
-       if (argc > 3) {
-               snp_auth = SNP_AUTH_SEND;
-               if (strmatch(argv[idx_type]->text, "validate"))
-                       snp_auth |= SNP_AUTH_RECV;
-       }
-
-       return area_passwd_set(vty, level, isis_area_passwd_hmac_md5_set,
-                              argv[idx_word]->arg, snp_auth);
-}
-
-DEFUN (domain_passwd_md5,
-       domain_passwd_md5_cmd,
-       "domain-password md5 WORD [authenticate snp <send-only|validate>]",
-       "Set the authentication password for a routing domain\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 area_passwd_md5(self, vty, argc, argv);
-}
-
-DEFUN (area_passwd_clear,
-       area_passwd_clear_cmd,
-       "area-password clear WORD [authenticate snp <send-only|validate>]",
-       "Configure the authentication password for an area\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")
-{
-       int idx_password = 0;
-       int idx_word = 2;
-       int idx_type = 5;
-       uint8_t snp_auth = 0;
-       int level = strmatch(argv[idx_password]->text, "domain-password")
-                           ? IS_LEVEL_2
-                           : IS_LEVEL_1;
-
-       if (argc > 3) {
-               snp_auth = SNP_AUTH_SEND;
-               if (strmatch(argv[idx_type]->text, "validate"))
-                       snp_auth |= SNP_AUTH_RECV;
-       }
-
-       return area_passwd_set(vty, level, isis_area_passwd_cleartext_set,
-                              argv[idx_word]->arg, snp_auth);
-}
-
-DEFUN (domain_passwd_clear,
-       domain_passwd_clear_cmd,
-       "domain-password clear WORD [authenticate snp <send-only|validate>]",
-       "Set the authentication password for a routing domain\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 area_passwd_clear(self, vty, argc, argv);
-}
-
-DEFUN (no_area_passwd,
-       no_area_passwd_cmd,
-       "no <area-password|domain-password>",
-       NO_STR
-       "Configure the authentication password for an area\n"
-       "Set the authentication password for a routing domain\n")
-{
-       int idx_password = 1;
-       int level = strmatch(argv[idx_password]->text, "domain-password")
-                           ? IS_LEVEL_2
-                           : IS_LEVEL_1;
-       VTY_DECLVAR_CONTEXT(isis_area, area);
-
-       return isis_area_passwd_unset(area, level);
-}
-
-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_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_passwd_cmd);
-       install_element(INTERFACE_NODE, &no_isis_passwd_cmd);
-
-       install_element(INTERFACE_NODE, &isis_priority_cmd);
-       install_element(INTERFACE_NODE, &no_isis_priority_cmd);
-       install_element(INTERFACE_NODE, &isis_priority_l1_cmd);
-       install_element(INTERFACE_NODE, &no_isis_priority_l1_cmd);
-       install_element(INTERFACE_NODE, &isis_priority_l2_cmd);
-       install_element(INTERFACE_NODE, &no_isis_priority_l2_cmd);
-
-       install_element(INTERFACE_NODE, &isis_metric_cmd);
-       install_element(INTERFACE_NODE, &no_isis_metric_cmd);
-       install_element(INTERFACE_NODE, &isis_metric_l1_cmd);
-       install_element(INTERFACE_NODE, &no_isis_metric_l1_cmd);
-       install_element(INTERFACE_NODE, &isis_metric_l2_cmd);
-       install_element(INTERFACE_NODE, &no_isis_metric_l2_cmd);
-
-       install_element(INTERFACE_NODE, &isis_hello_interval_cmd);
-       install_element(INTERFACE_NODE, &no_isis_hello_interval_cmd);
-       install_element(INTERFACE_NODE, &isis_hello_interval_l1_cmd);
-       install_element(INTERFACE_NODE, &no_isis_hello_interval_l1_cmd);
-       install_element(INTERFACE_NODE, &isis_hello_interval_l2_cmd);
-       install_element(INTERFACE_NODE, &no_isis_hello_interval_l2_cmd);
-
-       install_element(INTERFACE_NODE, &isis_hello_multiplier_cmd);
-       install_element(INTERFACE_NODE, &no_isis_hello_multiplier_cmd);
-       install_element(INTERFACE_NODE, &isis_hello_multiplier_l1_cmd);
-       install_element(INTERFACE_NODE, &no_isis_hello_multiplier_l1_cmd);
-       install_element(INTERFACE_NODE, &isis_hello_multiplier_l2_cmd);
-       install_element(INTERFACE_NODE, &no_isis_hello_multiplier_l2_cmd);
-
-       install_element(INTERFACE_NODE, &isis_hello_padding_cmd);
-       install_element(INTERFACE_NODE, &no_isis_hello_padding_cmd);
-
-       install_element(INTERFACE_NODE, &isis_threeway_adj_cmd);
-
-       install_element(INTERFACE_NODE, &csnp_interval_cmd);
-       install_element(INTERFACE_NODE, &no_csnp_interval_cmd);
-       install_element(INTERFACE_NODE, &csnp_interval_l1_cmd);
-       install_element(INTERFACE_NODE, &no_csnp_interval_l1_cmd);
-       install_element(INTERFACE_NODE, &csnp_interval_l2_cmd);
-       install_element(INTERFACE_NODE, &no_csnp_interval_l2_cmd);
-
-       install_element(INTERFACE_NODE, &psnp_interval_cmd);
-       install_element(INTERFACE_NODE, &no_psnp_interval_cmd);
-       install_element(INTERFACE_NODE, &psnp_interval_l1_cmd);
-       install_element(INTERFACE_NODE, &no_psnp_interval_l1_cmd);
-       install_element(INTERFACE_NODE, &psnp_interval_l2_cmd);
-       install_element(INTERFACE_NODE, &no_psnp_interval_l2_cmd);
-
-       install_element(INTERFACE_NODE, &circuit_topology_cmd);
-       install_element(INTERFACE_NODE, &no_circuit_topology_cmd);
-
-       install_element(ISIS_NODE, &metric_style_cmd);
-       install_element(ISIS_NODE, &no_metric_style_cmd);
-
-       install_element(ISIS_NODE, &set_overload_bit_cmd);
-       install_element(ISIS_NODE, &no_set_overload_bit_cmd);
-
-       install_element(ISIS_NODE, &set_attached_bit_cmd);
-       install_element(ISIS_NODE, &no_set_attached_bit_cmd);
-
-       install_element(ISIS_NODE, &dynamic_hostname_cmd);
-       install_element(ISIS_NODE, &no_dynamic_hostname_cmd);
-
-       install_element(ISIS_NODE, &area_lsp_mtu_cmd);
-       install_element(ISIS_NODE, &no_area_lsp_mtu_cmd);
-
-       install_element(ISIS_NODE, &is_type_cmd);
-       install_element(ISIS_NODE, &no_is_type_cmd);
-
-       install_element(ISIS_NODE, &lsp_gen_interval_cmd);
-       install_element(ISIS_NODE, &no_lsp_gen_interval_cmd);
-
-       install_element(ISIS_NODE, &spf_interval_cmd);
-       install_element(ISIS_NODE, &no_spf_interval_cmd);
-       install_element(ISIS_NODE, &spf_interval_l1_cmd);
-       install_element(ISIS_NODE, &no_spf_interval_l1_cmd);
-       install_element(ISIS_NODE, &spf_interval_l2_cmd);
-       install_element(ISIS_NODE, &no_spf_interval_l2_cmd);
-
-       install_element(ISIS_NODE, &max_lsp_lifetime_cmd);
-       install_element(ISIS_NODE, &no_max_lsp_lifetime_cmd);
-
-       install_element(ISIS_NODE, &lsp_refresh_interval_cmd);
-       install_element(ISIS_NODE, &no_lsp_refresh_interval_cmd);
-
-       install_element(ISIS_NODE, &area_passwd_md5_cmd);
-       install_element(ISIS_NODE, &area_passwd_clear_cmd);
-       install_element(ISIS_NODE, &domain_passwd_md5_cmd);
-       install_element(ISIS_NODE, &domain_passwd_clear_cmd);
-       install_element(ISIS_NODE, &no_area_passwd_cmd);
-
-       install_element(ISIS_NODE, &spf_delay_ietf_cmd);
-       install_element(ISIS_NODE, &no_spf_delay_ietf_cmd);
-}
diff --git a/isisd/isis_vty_common.c b/isisd/isis_vty_common.c
new file mode 100644 (file)
index 0000000..2b98a88
--- /dev/null
@@ -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();
+}
diff --git a/isisd/isis_vty_common.h b/isisd/isis_vty_common.h
new file mode 100644 (file)
index 0000000..b726b4e
--- /dev/null
@@ -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
diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c
new file mode 100644 (file)
index 0000000..95ebe0d
--- /dev/null
@@ -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);
+}
diff --git a/isisd/isis_vty_isisd.c b/isisd/isis_vty_isisd.c
new file mode 100644 (file)
index 0000000..95aaeae
--- /dev/null
@@ -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);
+}
index 9bc0f2ef350f674a896e0a87d802713c2802d615..33d8a0f77172036155ea8a5cb845195137fd9821 100644 (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;
index a19f287453f463ad817301038bcb5a4a1659be07..e3ff3b8d93e377111a666099048a991ef9212319 100644 (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();
 }
index ce602e4402b3488fd7f9223333629dbd6b6304c9..864021428aa885dfbf07d3eae33e98dec79f4ed7 100644 (file)
 #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 {                                                                   \
index 7b8be46167cf25144d09be6cd80cf8462fe1cd6e..7571255e59251cc0b22c135da34fd2967b9bd3c0 100644 (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)
index a2f4b51698ba10405f6d56e3bb5e5919b8bf9e37..ec8a5c40863d9b26c6e84f914bb28a1f03f04a94 100644 (file)
@@ -1,17 +1,2 @@
-!Makefile
-Makefile.in
-*.o
 ldpd
 ldpd.conf
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.a
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
index 03b62b482b26076fd10c0162d217dec626c2a6f7..81043988863b1c5ab9a6caad4be78b427ff5e8e5 100644 (file)
@@ -1620,10 +1620,8 @@ lde_address_list_free(struct lde_nbr *ln)
 {
        struct lde_addr         *lde_addr;
 
-       while ((lde_addr = TAILQ_FIRST(&ln->addr_list)) != NULL) {
-               TAILQ_REMOVE(&ln->addr_list, lde_addr, entry);
+       while ((lde_addr = TAILQ_POP_FIRST(&ln->addr_list, entry)) != NULL)
                free(lde_addr);
-       }
 }
 
 static void zclient_sync_init(unsigned short instance)
index 906737217c0e0513a7279b6658f9f9dde1e2ca22..a719d0cbb7067e5b5af614655b24bc6e21288be0 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #ifdef __OpenBSD__
 #include <sys/types.h>
 #include <sys/socket.h>
index 2d87be0cda80e7d92279cc76df48f1c3d23e98ec..24e738d6227a0805c5861f40d98e3f65bf3ab7b0 100644 (file)
@@ -6,6 +6,8 @@ if LDPD
 noinst_LIBRARIES += ldpd/libldp.a
 sbin_PROGRAMS += ldpd/ldpd
 dist_examples_DATA += ldpd/ldpd.conf.sample
+vtysh_scan += $(top_srcdir)/ldpd/ldp_vty_cmds.c
+man8 += $(MANBUILD)/ldpd.8
 endif
 
 ldpd_libldp_a_SOURCES = \
index 072146dbd54877508bf76f6fa568a0ec95f7ea4a..6176b30f8d2fd8f7f328c920de96758d3bb5e164 100644 (file)
@@ -1,26 +1,13 @@
-!Makefile
-Makefile.in
-*.o
-*.lo
-*.la
-version.c
-version.h
-gitversion.h
-gitversion.h.tmp
-.deps
-.nfs*
-.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
-route_types.h
-memtypes.h
-command_lex.c
-command_lex.h
-command_parse.c
-command_parse.h
-refix
-grammar_sandbox
-clippy
-defun_lex.c
+/version.c
+/version.h
+/gitversion.h
+/gitversion.h.tmp
+/route_types.h
+/memtypes.h
+/command_lex.c
+/command_lex.h
+/command_parse.c
+/command_parse.h
+/grammar_sandbox
+/clippy
+/defun_lex.c
index 1df644210723a3e7ec47ad382bf79940d08c5d82..26afc762fba20dabc846bd921e41aca305155e62 100644 (file)
@@ -146,6 +146,7 @@ const char *node_names[] = {
                                     */
        "bfd",                   /* BFD_NODE */
        "bfd peer",              /* BFD_PEER_NODE */
+       "openfabric",               // OPENFABRIC_NODE
 };
 /* clang-format on */
 
@@ -1197,6 +1198,7 @@ static int handle_pipe_action(struct vty *vty, const char *cmd_in,
 
        /* retrieve action */
        token = strsep(&working, " ");
+       assert(token);
 
        /* match result to known actions */
        if (strmatch(token, "include")) {
@@ -1435,6 +1437,7 @@ void cmd_exit(struct vty *vty)
        case LDP_NODE:
        case LDP_L2VPN_NODE:
        case ISIS_NODE:
+       case OPENFABRIC_NODE:
        case KEYCHAIN_NODE:
        case RMAP_NODE:
        case PBRMAP_NODE:
@@ -1550,6 +1553,7 @@ DEFUN (config_end,
        case LDP_L2VPN_NODE:
        case LDP_PSEUDOWIRE_NODE:
        case ISIS_NODE:
+       case OPENFABRIC_NODE:
        case KEYCHAIN_NODE:
        case KEYCHAIN_KEY_NODE:
        case VTY_NODE:
index 75b69507ec7bf153e281b3ca818dacf4ba4cf073..8e51641b88cfab90b2ced915b9f2f052f1caa91c 100644 (file)
@@ -141,6 +141,7 @@ enum node_type {
        BGP_FLOWSPECV6_NODE,    /* BGP IPv6 FLOWSPEC Address-Family */
        BFD_NODE,                /* BFD protocol mode. */
        BFD_PEER_NODE,           /* BFD peer configuration mode. */
+       OPENFABRIC_NODE,        /* OpenFabric router configuration node */
        NODE_TYPE_MAX, /* maximum */
 };
 
@@ -364,7 +365,6 @@ struct cmd_node {
 #define PREFIX_LIST_STR "Build a prefix list\n"
 #define OSPF6_DUMP_TYPE_LIST                                                   \
        "<neighbor|interface|area|lsa|zebra|config|dbex|spf|route|lsdb|redistribute|hook|asbr|prefix|abr>"
-#define ISIS_STR "IS-IS information\n"
 #define AREA_TAG_STR "[area tag]\n"
 #define COMMUNITY_AANN_STR "Community number where AA and NN are (0-65535)\n"
 #define COMMUNITY_VAL_STR  "Community number in AA:NN format (where AA and NN are (0-65535)) or local-AS|no-advertise|no-export|internet or additive\n"
index 0d6e6ee7e5fc60b0ac55918d38acc258face2219..3b18b58a2e9e3dfefdb0fdedc2549c4ff8c901a4 100644 (file)
  * 02111-1307, USA.
  */
 
+%top{
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+}
 %{
 /* ignore flex generated code in static analyzer */
 #ifndef __clang_analyzer__
index ce84783aa6f7570da98027cabbc489a8cf1cd4b6..582106ebd429356cf98b6ff224c0f4e89dc6501a 100644 (file)
--- a/lib/csv.c
+++ b/lib/csv.c
  * 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
  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -563,6 +568,8 @@ void csv_decode(csv_t *csv, char *inbuf)
        csv_record_t *rec;
 
        buf = (inbuf) ? inbuf : csv->buf;
+       assert(buf);
+
        pos = strpbrk(buf, "\n");
        while (pos != NULL) {
                rec = calloc(1, sizeof(csv_record_t));
index d901c26a2ed336ad37eefd66984e359b0e0dd246..6c0805a4fa9b4542319eaf82476b35d6bae53698 100644 (file)
@@ -1,4 +1,3 @@
-%{
 /*
  * clippy (CLI preparator in python) C pseudo-lexer
  * Copyright (C) 2016-2017  David Lamparter for NetDEF, Inc.
  * code documentation in it.
  */
 
+%top{
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+}
+%{
 /* ignore harmless bugs in old versions of flex */
 #pragma GCC diagnostic ignored "-Wsign-compare"
 #pragma GCC diagnostic ignored "-Wunused-value"
index 35d0fe4ff420de5e6c7e64684d938e3bcf64a91f..afef196cec4ce3cfac14fdc7af747b28eabc91c0 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
@@ -148,7 +152,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json)
                        snprintf(pbuf, sizeof(pbuf), "\nError %"PRIu32" - %s",
                                 ref->code, ref->title);
                        memset(ubuf, '=', strlen(pbuf));
-                       ubuf[strlen(pbuf) - 1] = '\0';
+                       ubuf[strlen(pbuf)] = '\0';
 
                        vty_out(vty, "%s\n%s\n", pbuf, ubuf);
                        vty_out(vty, "Description:\n%s\n\n", ref->description);
index c0aae5e52e098e6da07bc72bdc459bc453440daa..d48b23f38a9a1804831cfa81f1541d03260adc9f 100644 (file)
@@ -19,6 +19,9 @@
 
 #include <zebra.h>
 #include <pthread.h>
+#ifdef HAVE_PTHREAD_NP_H
+#include <pthread_np.h>
+#endif
 #include <sched.h>
 
 #include "frr_pthread.h"
@@ -163,10 +166,14 @@ int frr_pthread_set_name(struct frr_pthread *fpt, const char *name,
                pthread_mutex_lock(&fpt->mtx);
                snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", os_name);
                pthread_mutex_unlock(&fpt->mtx);
-#ifdef GNU_LINUX
+#ifdef HAVE_PTHREAD_SETNAME_NP
+# ifdef GNU_LINUX
                ret = pthread_setname_np(fpt->thread, fpt->os_name);
-#elif defined(OPEN_BSD)
-               ret = pthread_set_name_np(fpt->thread, fpt->os_name);
+# else /* NetBSD */
+               ret = pthread_setname_np(fpt->thread, fpt->os_name, NULL);
+# endif
+#elif defined(HAVE_PTHREAD_SET_NAME_NP)
+               pthread_set_name_np(fpt->thread, fpt->os_name);
 #endif
        }
 
index cc4fc74337b940abd82f42ad8d4b78bd8ee6326d..732e2925fef67246b6e2b9a6184b2b223ea59ea5 100644 (file)
@@ -234,4 +234,8 @@ void frr_pthread_yield(void);
  */
 uint32_t frr_pthread_get_id(void);
 
+#ifndef HAVE_PTHREAD_CONDATTR_SETCLOCK
+#define pthread_condattr_setclock(A, B)
+#endif
+
 #endif /* _FRR_PTHREAD_H */
index 715e67b868c24bbe9adeb945f6aec9986850d3bb..85d968182b042f87a46f7eb33e9802339ca818d3 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <string.h>
 #include <ctype.h>
 #include <sys/types.h>
index 51e7a3987e00297dcebc1cf9515989df792d4fb6..ef03e85217b4c10d703c2c1e67e7ff6cab5a87e5 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "command.h"
 #include "memory_vty.h"
 #include "graph.h"
index 264c7c48f00ec6a30d91670bf777c0710efce8a4..c9c942f9bf897a02599dea196ce1dcea5463556a 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "command.h"
 #include "memory_vty.h"
 
index 935064f4d2aee42cae984101c987684e2665221c..4fe305f282681009ec462869e75968e6af31fd47 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "memory.h"
 #include "hook.h"
 
index 2bf0c6e6b5ae4a93f65bbaacda9a9864eff9eaa0..a03c9da6f91e5aa6329e662206909d10e758e6aa 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -619,7 +619,7 @@ DEFUN (no_interface_desc,
  *     if not:
  *     - no idea, just get the name in its entirety.
  */
-static struct interface *if_sunwzebra_get(char *name, vrf_id_t vrf_id)
+static struct interface *if_sunwzebra_get(const char *name, vrf_id_t vrf_id)
 {
        struct interface *ifp;
        char *cp;
index b83f1f76f2a617dae2d4f9eaf21e383fde2b2c5a..c2f4052b8f5ea66be9be7b5f3cfdcba19cc570a7 100644 (file)
@@ -21,9 +21,9 @@
 #include "queue.h"
 #include "imsg.h"
 
-int ibuf_realloc(struct ibuf *, size_t);
-void ibuf_enqueue(struct msgbuf *, struct ibuf *);
-void ibuf_dequeue(struct msgbuf *, struct ibuf *);
+static int ibuf_realloc(struct ibuf *, size_t);
+static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
+static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
 
 struct ibuf *ibuf_open(size_t len)
 {
@@ -57,7 +57,7 @@ struct ibuf *ibuf_dynamic(size_t len, size_t max)
        return (buf);
 }
 
-int ibuf_realloc(struct ibuf *buf, size_t len)
+static int ibuf_realloc(struct ibuf *buf, size_t len)
 {
        uint8_t *b;
 
@@ -183,6 +183,8 @@ void msgbuf_drain(struct msgbuf *msgbuf, size_t n)
                next = TAILQ_NEXT(buf, entry);
                if (buf->rpos + n >= buf->wpos) {
                        n -= buf->wpos - buf->rpos;
+
+                       TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
                        ibuf_dequeue(msgbuf, buf);
                } else {
                        buf->rpos += n;
@@ -195,7 +197,7 @@ void msgbuf_clear(struct msgbuf *msgbuf)
 {
        struct ibuf *buf;
 
-       while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
+       while ((buf = TAILQ_POP_FIRST(&msgbuf->bufs, entry)) != NULL)
                ibuf_dequeue(msgbuf, buf);
 }
 
@@ -266,16 +268,15 @@ again:
        return (1);
 }
 
-void ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
+static void ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
 {
        TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
        msgbuf->queued++;
 }
 
-void ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
+static void ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
 {
-       TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
-
+       /* TAILQ_REMOVE done by caller */
        if (buf->fd != -1)
                close(buf->fd);
 
index 54241407205d203f0ae3964e784afbf27bc03e7d..935d13772752a2a668fc4d9699793c4addd7845a 100644 (file)
@@ -299,11 +299,10 @@ int imsg_get_fd(struct imsgbuf *ibuf)
        int fd;
        struct imsg_fd *ifd;
 
-       if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
+       if ((ifd = TAILQ_POP_FIRST(&ibuf->fds, entry)) == NULL)
                return (-1);
 
        fd = ifd->fd;
-       TAILQ_REMOVE(&ibuf->fds, ifd, entry);
        free(ifd);
 
        return (fd);
index 332a5b1d453aac833f4811dd1734a177b9f1a98c..2ddc571e688999eab79fa1412066e7379ffa5676 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "lib_errors.h"
 
 /* clang-format off */
index 010b98478699ad082f67979c6702788a280cab58..521783e4b09887d5434d33b98e36a2314dd0f9e2 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -1074,6 +1074,8 @@ int proto_redistnum(int afi, const char *s)
                        return ZEBRA_ROUTE_BABEL;
                else if (strmatch(s, "sharp"))
                        return ZEBRA_ROUTE_SHARP;
+               else if (strmatch(s, "openfabric"))
+                       return ZEBRA_ROUTE_OPENFABRIC;
        }
        if (afi == AFI_IP6) {
                if (strmatch(s, "kernel"))
@@ -1102,6 +1104,8 @@ int proto_redistnum(int afi, const char *s)
                        return ZEBRA_ROUTE_BABEL;
                else if (strmatch(s, "sharp"))
                        return ZEBRA_ROUTE_SHARP;
+               else if (strmatch(s, "openfabric"))
+                       return ZEBRA_ROUTE_OPENFABRIC;
        }
        return -1;
 }
index 695bbfe11572e85b046319c6d5e083f5250e91c9..fee23a75ac67e1d11463c102b2e68a87444ba1b5 100644 (file)
@@ -20,6 +20,9 @@
 #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
index 73a18529a2a80fe270d548f7fc9017c6d425812d..5fd9c3b900437c13a5feb6c2f792d7aa96a08c33 100644 (file)
@@ -28,7 +28,9 @@
 #include <malloc/malloc.h>
 #endif
 #include <dlfcn.h>
+#ifdef HAVE_LINK_H
 #include <link.h>
+#endif
 
 #include "log.h"
 #include "memory.h"
index 35bfce3a890d73e9cd9acd080bef56c7a2f39ee4..e8d13339b633cf8470628e625f3b68a0ea00eb06 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 
 #include <lib/openbsd-tree.h>
index 69fd61e2a06998ea914551f4b02b3aeb71e43c24..7f868beda419048aef5a788c7e05af2c59b9919d 100644 (file)
  * 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
  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
index 04fbeee7004c98ab159eb714a9968dfd8eda94f1..11e28b4c912554caf2c9cae8adebb407a46ce0fb 100644 (file)
 #include "freebsd-queue.h"
 #endif /* defined(__OpenBSD__) && !defined(STAILQ_HEAD) */
 
+#ifndef TAILQ_POP_FIRST
+#define TAILQ_POP_FIRST(head, field)                                           \
+       ({  typeof((head)->tqh_first) _elm = TAILQ_FIRST(head);                \
+           if (_elm) {                                                        \
+               if ((TAILQ_NEXT((_elm), field)) != NULL)                       \
+                       TAILQ_NEXT((_elm), field)->field.tqe_prev =            \
+                               &TAILQ_FIRST(head);                            \
+               else                                                           \
+                       (head)->tqh_last = &TAILQ_FIRST(head);                 \
+               TAILQ_FIRST(head) = TAILQ_NEXT((_elm), field);                 \
+       }; _elm; })
+#endif
+
 #endif /* _FRR_QUEUE_H */
index 72f59a1b78608d84e436baa6e6835e2bf20b1a7e..c5eff44ca7f07271310c26bd08ee4c29df183b07 100644 (file)
@@ -82,6 +82,7 @@ ZEBRA_ROUTE_BABEL,      babel,     babeld, 'A', 1, 1, 1,     "Babel"
 ZEBRA_ROUTE_SHARP,      sharp,     sharpd, 'D', 1, 1, 1,     "SHARP"
 ZEBRA_ROUTE_PBR,        pbr,       pbrd,   'F', 1, 1, 0,     "PBR"
 ZEBRA_ROUTE_BFD,        bfd,       bfdd,   '-', 0, 0, 0,     "BFD"
+ZEBRA_ROUTE_OPENFABRIC, openfabric, fabricd,  'f', 1, 1, 1, "OpenFabric"
 ZEBRA_ROUTE_ALL,        wildcard,  none,   '-', 0, 0, 0,     "-"
 
 
@@ -109,3 +110,4 @@ ZEBRA_ROUTE_BABEL,  "Babel routing protocol (Babel)"
 ZEBRA_ROUTE_SHARP, "Super Happy Advanced Routing Protocol (sharpd)"
 ZEBRA_ROUTE_PBR, "Policy Based Routing (PBR)"
 ZEBRA_ROUTE_BFD, "Bidirectional Fowarding Detection (BFD)"
+ZEBRA_ROUTE_OPENFABRIC, "OpenFabric Routing Protocol"
index a36bf47139c307ceacc85629427a747dec394939..585cf859e5742b1a952a0ba935e6c9f1c6b19d56 100644 (file)
@@ -202,6 +202,7 @@ int skiplist_insert(register struct skiplist *l, register void *key,
        }
 
        k = randomLevel();
+       assert(k >= 0);
        if (k > l->level) {
                k = ++l->level;
                update[k] = l->header;
index 55e7f6435826118df2c8735f12a3832ea7912191..589a2292568281580c8690dd2e7e453a20a272e9 100644 (file)
@@ -270,7 +270,7 @@ void stream_forward_endp(struct stream *s, size_t size)
 }
 
 /* Copy from stream to destination. */
-inline bool stream_get2(void *dst, struct stream *s, size_t size)
+bool stream_get2(void *dst, struct stream *s, size_t size)
 {
        STREAM_VERIFY_SANE(s);
 
@@ -299,7 +299,7 @@ void stream_get(void *dst, struct stream *s, size_t size)
 }
 
 /* Get next character from the stream. */
-inline bool stream_getc2(struct stream *s, uint8_t *byte)
+bool stream_getc2(struct stream *s, uint8_t *byte)
 {
        STREAM_VERIFY_SANE(s);
 
@@ -344,7 +344,7 @@ uint8_t stream_getc_from(struct stream *s, size_t from)
        return c;
 }
 
-inline bool stream_getw2(struct stream *s, uint16_t *word)
+bool stream_getw2(struct stream *s, uint16_t *word)
 {
        STREAM_VERIFY_SANE(s);
 
@@ -465,7 +465,7 @@ void stream_get_from(void *dst, struct stream *s, size_t from, size_t size)
        memcpy(dst, s->data + from, size);
 }
 
-inline bool stream_getl2(struct stream *s, uint32_t *l)
+bool stream_getl2(struct stream *s, uint32_t *l)
 {
        STREAM_VERIFY_SANE(s);
 
index be211f82a8e527a8ec8e1dda6cc47e14559460ee..39773d9ac89ef7cfe022cc444266eea243b9eee5 100644 (file)
 /* adapted for Quagga from glibc patch submission originally from
  * Florian Weimer <fweimer@redhat.com>, 2016-05-18 */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdint.h>
 #include <string.h>
 
-#include "config.h"
-
 #ifndef HAVE_STRLCAT
 #undef strlcat
 
index b0c33ca7f42baeac4acd8dce8b9163fc5974b639..71ee9f1a5452740f3f585df1d81048b04d8a72b1 100644 (file)
 /* adapted for Quagga from glibc patch submission originally from
  * Florian Weimer <fweimer@redhat.com>, 2016-05-18 */
 
-#include <string.h>
-
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
+
+#include <string.h>
 
 #ifndef HAVE_STRLCPY
 #undef strlcpy
index ef6c8f8e55ee8a1e6583bcee8095697134bb878b..499bb94920d6c7039b0c29f66985866a4edcf057 100644 (file)
@@ -84,6 +84,22 @@ lib_libfrr_la_SOURCES = \
        lib/logicalrouter.c \
        # end
 
+vtysh_scan += \
+       $(top_srcdir)/lib/distribute.c \
+       $(top_srcdir)/lib/filter.c \
+       $(top_srcdir)/lib/if.c \
+       $(top_srcdir)/lib/if_rmap.c \
+       $(top_srcdir)/lib/keychain.c \
+       $(top_srcdir)/lib/logicalrouter.c \
+       $(top_srcdir)/lib/nexthop_group.c \
+       $(top_srcdir)/lib/plist.c \
+       $(top_srcdir)/lib/routemap.c \
+       $(top_srcdir)/lib/vrf.c \
+       $(top_srcdir)/lib/vty.c \
+       # end
+# can be loaded as DSO - always include for vtysh
+vtysh_scan += $(top_srcdir)/lib/agentx.c
+
 lib/plist_clippy.c: $(CLIPPY_DEPS)
 lib/plist.lo: lib/plist_clippy.c
 lib/nexthop_group_clippy.c: $(CLIPPY_DEPS)
@@ -152,6 +168,7 @@ pkginclude_HEADERS += \
        lib/sha256.h \
        lib/sigevent.h \
        lib/skiplist.h \
+       lib/smux.h \
        lib/sockopt.h \
        lib/sockunion.h \
        lib/spf_backoff.h \
@@ -237,9 +254,10 @@ lib_grammar_sandbox_SOURCES = \
 lib_grammar_sandbox_LDADD = \
        lib/libfrr.la
 
-lib_clippy_CPPFLAGS = $(AM_CPPFLAGS) -D_GNU_SOURCE -DBUILDING_CLIPPY @SAN_CLIPPY_FLAGS@
-lib_clippy_CFLAGS = $(PYTHON_CFLAGS) @SAN_CLIPPY_FLAGS@
+lib_clippy_CPPFLAGS = $(AM_CPPFLAGS) -D_GNU_SOURCE -DBUILDING_CLIPPY
+lib_clippy_CFLAGS = $(PYTHON_CFLAGS)
 lib_clippy_LDADD = $(PYTHON_LIBS)
+lib_clippy_LDFLAGS = -export-dynamic
 lib_clippy_SOURCES = \
        lib/clippy.c \
        lib/command_graph.c \
@@ -252,6 +270,26 @@ lib_clippy_SOURCES = \
        lib/vector.c \
        # end
 
+# (global) clippy rules for all directories
+
+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) $<
 
 #
 # generated sources & extra foo
index 748c14f675c35d5159d025fe128360e048ecfc22..480137a7a956f4853567d442313b5efcaa022b4b 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -811,6 +811,7 @@ static void vty_end_config(struct vty *vty)
        case LDP_L2VPN_NODE:
        case LDP_PSEUDOWIRE_NODE:
        case ISIS_NODE:
+       case OPENFABRIC_NODE:
        case KEYCHAIN_NODE:
        case KEYCHAIN_KEY_NODE:
        case VTY_NODE:
@@ -1210,6 +1211,7 @@ static void vty_stop_input(struct vty *vty)
        case LDP_L2VPN_NODE:
        case LDP_PSEUDOWIRE_NODE:
        case ISIS_NODE:
+       case OPENFABRIC_NODE:
        case KEYCHAIN_NODE:
        case KEYCHAIN_KEY_NODE:
        case VTY_NODE:
index b12f6616bae9d4c96f1b4ad290b676cfcbf79e8a..d80aa06935500d11e032fea227ea8dcb2006bcb0 100644 (file)
@@ -28,7 +28,6 @@
 #include "compiler.h"
 
 #ifdef SUNOS_5
-#define _XPG4_2
 typedef unsigned int uint32_t;
 typedef unsigned short uint16_t;
 typedef unsigned char uint8_t;
@@ -414,6 +413,7 @@ extern const char *zserv_command_string(unsigned int command);
 #define ZEBRA_FLAG_FIB_OVERRIDE       0x200
 #define ZEBRA_FLAG_EVPN_ROUTE         0x400
 #define ZEBRA_FLAG_RR_USE_DISTANCE    0x800
+#define ZEBRA_FLAG_ONLINK             0x1000
 /* ZEBRA_FLAG_BLACKHOLE was 0x04 */
 /* ZEBRA_FLAG_REJECT was 0x80 */
 
index 798188b0b93d284c066bf7845fd74f23040fde0d..357e65588dce38a2ed99904d332d81c69ad8f752 100644 (file)
@@ -1,8 +1,8 @@
-Makefile
-Makefile.in
-.arch-inventory
-.arch-ids
-*~
-*.loT
+*.m4
+
+!ax_compare_version.m4
+!ax_prog_perl_modules.m4
 !ax_pthread.m4
 !ax_sys_weak_alias.m4
+!ax_sys_weak_alias.m4
+!pkg.m4
index c5b26b52e6cdb5891332f7e87addae9306ba7107..a8dcd17c418797a506574e0867a95e8ff0efac29 100644 (file)
--- a/m4/pkg.m4
+++ b/m4/pkg.m4
@@ -109,7 +109,7 @@ AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
 AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
 
 pkg_failed=no
-AC_MSG_CHECKING([for $1])
+AC_MSG_CHECKING([for $1 ($2)])
 
 _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
 _PKG_CONFIG([$1][_LIBS], [libs], [$2])
index 3f47381278fd22c0ae9acb294ad226e47d1ca878..3d4d56d58937167938c270128e28ab6c83749cd1 100644 (file)
@@ -1,2 +1 @@
-!Makefile
 nhrpd
index 46a327b59f21265aa2bac727c951cb18a89a4ebf..85e941e7bacd1d63fed3300fe7e708df39c4f420 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
index af78b3d9ee6a74f560ed13dcce6aa4279c4ac1d7..4c6827cb3d63536e4976426e02c373d95b397006 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <fcntl.h>
 #include <net/if.h>
 #include <netinet/if_ether.h>
index 75ecaa70c124cf84756fc6094fe9ef3278161cd0..3fdfa9c31307d14af5121c7d182295d30141357c 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <sys/socket.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
index 7ca9731765d2d1c6691d0d869e2a1eb67f24ef85..9301c2d515eba9084658e6f8167414d956361ca0 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/un.h>
index 3a42712748cd3b768820f0f0ca7d60df4c39cc96..ccca100db57940b038501c5a08b44cccd3958e20 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <net/if_arp.h>
 #include "zebra.h"
 #include "linklist.h"
index 737e70103e553e125c512ddc31a36b79e926c913..f99e566399b571f4a59faa195b31bbfdaf1f1006 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <unistd.h>
 
 #include "zebra.h"
index e62ee1ef72206a17924c031a0d4281d85ce92c51..a983aa71bca91997184b3fe268e0768fee8b8868 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <netinet/if_ether.h>
 #include "nhrpd.h"
 #include "zbuf.h"
index 44271d68ac7930697598e388b784d4a0aa51bc6d..e051830f8524681ea0ab0daa848dac472dd403ad 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <netinet/if_ether.h>
 
 #include "zebra.h"
index 044529a5cab4c53a74a62172cd5f46d363aa5f51..e7b187f3b607eeac0f747fcdca6a29c118923d85 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "nhrpd.h"
 #include "table.h"
 #include "memory.h"
index 9ed2517069372b784a6afb1ab432abd8fb5d4a7b..84053b4b5d68ee8c31551297c5a322f50292376f 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "nhrpd.h"
 #include "table.h"
 #include "memory.h"
index dfa5dc3df0537fb8bbc9f4a52c73a76a596cfbfa..f017d974dfd5adf1358b69b088f68fb2aab38f20 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <ares.h>
 #include <ares_version.h>
 
index d66e96822417658ee574b05cede67ba54a3ff1f2..758c22e2be87d62a406082d1688416df8fb4ab07 100644 (file)
@@ -4,6 +4,8 @@
 
 if NHRPD
 sbin_PROGRAMS += nhrpd/nhrpd
+vtysh_scan += $(top_srcdir)/nhrpd/nhrp_vty.c
+man8 += $(MANBUILD)/nhrpd.8
 endif
 
 nhrpd_nhrpd_LDADD = lib/libfrr.la @LIBCAP@ @CARES_LIBS@
index 7cd703414ac9aee81c0c77e2d9b4fdc44a2d5f89..c1a99685f39d6e34c61c57cd59c08b68b3aca277 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/un.h>
index 6e7cad8aec2c5940fbfc538d8c5b910187db04f6..c662295083e79063f814c14bfeecdde45fd03880 100644 (file)
@@ -7,7 +7,10 @@
  * (at your option) any later version.
  */
 
-#define _GNU_SOURCE
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
index 01b2f433af8b6128a56be47a116d103c22b23af8..6030987a1bdf25bb802d7068440628228a9482dd 100644 (file)
@@ -7,6 +7,10 @@
  * (at your option) any later version.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <fcntl.h>
 #include <errno.h>
 #include <string.h>
index 744af2d5ce70a847a0b2e9303dd73f9f9e04f4d6..e398b1ca58644440c2d1e60af60fbb8e50ee51e9 100644 (file)
@@ -1,18 +1,2 @@
-!Makefile
-Makefile.in
-*.o
-*.patch
 ospf6d
 ospf6d.conf
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
-*.a
index 5af88defeba69dc6a65251900ff33c61567a5db1..dc7a3f6d45766c8f8b848b45273fbdcab741a6da 100644 (file)
@@ -732,7 +732,8 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
                                                        ? 1
                                                        : 2,
                                                buf, listcount(route->paths),
-                                               listcount(route->nh_list));
+                                               route->nh_list ?
+                                               listcount(route->nh_list) : 0);
                                }
 
                                if (listcount(route->paths)) {
index 8b720b6d844ae0e98cea494cd3a89b0736d70fbf..40b3522c3d7c94f033cdda8495544912623e79b1 100644 (file)
@@ -130,7 +130,7 @@ uint8_t ospf6_lstype_debug(uint16_t type)
 {
        const struct ospf6_lsa_handler *handler;
        handler = ospf6_get_lsa_handler(type);
-       return handler->debug;
+       return handler->lh_debug;
 }
 
 /* RFC2328: Section 13.2 */
@@ -844,13 +844,13 @@ DEFUN (debug_ospf6_lsa_type,
 
        if (argc == 5) {
                if (strmatch(argv[idx_type]->text, "originate"))
-                       SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
+                       SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE);
                else if (strmatch(argv[idx_type]->text, "examine"))
-                       SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
+                       SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
                else if (strmatch(argv[idx_type]->text, "flooding"))
-                       SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD);
+                       SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
        } else
-               SET_FLAG(handler->debug, OSPF6_LSA_DEBUG);
+               SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
 
        return CMD_SUCCESS;
 }
@@ -896,13 +896,14 @@ DEFUN (no_debug_ospf6_lsa_type,
 
        if (argc == 6) {
                if (strmatch(argv[idx_type]->text, "originate"))
-                       UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
+                       UNSET_FLAG(handler->lh_debug,
+                                  OSPF6_LSA_DEBUG_ORIGINATE);
                if (strmatch(argv[idx_type]->text, "examine"))
-                       UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
+                       UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
                if (strmatch(argv[idx_type]->text, "flooding"))
-                       UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD);
+                       UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
        } else
-               UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG);
+               UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
 
        return CMD_SUCCESS;
 }
@@ -924,16 +925,16 @@ int config_write_ospf6_debug_lsa(struct vty *vty)
                handler = vector_slot(ospf6_lsa_handler_vector, i);
                if (handler == NULL)
                        continue;
-               if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG))
+               if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG))
                        vty_out(vty, "debug ospf6 lsa %s\n",
                                ospf6_lsa_handler_name(handler));
-               if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE))
+               if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE))
                        vty_out(vty, "debug ospf6 lsa %s originate\n",
                                ospf6_lsa_handler_name(handler));
-               if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN))
+               if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN))
                        vty_out(vty, "debug ospf6 lsa %s examine\n",
                                ospf6_lsa_handler_name(handler));
-               if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD))
+               if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD))
                        vty_out(vty, "debug ospf6 lsa %s flooding\n",
                                ospf6_lsa_handler_name(handler));
        }
index e88d10ad7e594b129821334929b94b5ea4f72981..d871a8842ecb3969fe8b0eea28433db9e6fdebdb 100644 (file)
@@ -137,21 +137,14 @@ struct ospf6_lsa {
 #define OSPF6_LSA_SEQWRAPPED 0x20
 
 struct ospf6_lsa_handler {
-       const struct {
-               uint16_t type; /* host byte order */
-               const char *name;
-               const char *short_name;
-               int (*show)(struct vty *, struct ospf6_lsa *);
-               char *(*get_prefix_str)(struct ospf6_lsa *, char *buf,
-                                       int buflen, int pos);
-       } s;
-#define lh_type       s.type
-#define lh_name       s.name
-#define lh_short_name s.short_name
-#define lh_show       s.show
-#define lh_get_prefix_str s.get_prefix_str
-       uint8_t debug;
-#define lh_debug debug
+       uint16_t lh_type; /* host byte order */
+       const char *lh_name;
+       const char *lh_short_name;
+       int (*lh_show)(struct vty *, struct ospf6_lsa *);
+       char *(*lh_get_prefix_str)(struct ospf6_lsa *, char *buf,
+                                  int buflen, int pos);
+
+       uint8_t lh_debug;
 };
 
 #define OSPF6_LSA_IS_KNOWN(t)                                                  \
index 0cc7294d67995cae0bb0037da7edda552c15fbf0..4c24f47131893ff1ea8b463088900a7ccb08fa58 100644 (file)
@@ -921,7 +921,7 @@ DEFUN (no_debug_ospf6,
                handler = vector_slot(ospf6_lsa_handler_vector, i);
 
                if (handler != NULL) {
-                       UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG);
+                       UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
                }
        }
 
index a099eead49bab5bf718a24ec3901b28f5f6a9bdc..021e825ae33dc82a27de356081d523d06f2b3cee 100644 (file)
@@ -732,7 +732,7 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
                route->next = next;
 
                if (node->info == next) {
-                       assert(next->rnode == node);
+                       assert(next && next->rnode == node);
                        node->info = route;
                        UNSET_FLAG(next->flag, OSPF6_ROUTE_BEST);
                        SET_FLAG(route->flag, OSPF6_ROUTE_BEST);
index fde47c74fef9e8a148ee522de1d24f734af5cb00..ca1a65ff0b293e7833dcb91bdafc6bdea71a2e49 100644 (file)
@@ -425,19 +425,6 @@ DEFUN(no_ospf6_router_id,
        return CMD_SUCCESS;
 }
 
-#if CONFDATE > 20180828
-CPP_NOTICE("ospf6: `router-id A.B.C.D` deprecated 2017/08/28")
-#endif
-ALIAS_HIDDEN(ospf6_router_id, ospf6_router_id_hdn_cmd, "router-id A.B.C.D",
-            "Configure OSPF6 Router-ID\n" V4NOTATION_STR)
-
-#if CONFDATE > 20180828
-CPP_NOTICE("ospf6: `no router-id A.B.C.D` deprecated 2017/08/28")
-#endif
-ALIAS_HIDDEN(no_ospf6_router_id, no_ospf6_router_id_hdn_cmd,
-            "no router-id [A.B.C.D]",
-            NO_STR "Configure OSPF6 Router-ID\n" V4NOTATION_STR)
-
 DEFUN (ospf6_log_adjacency_changes,
        ospf6_log_adjacency_changes_cmd,
        "log-adjacency-changes",
@@ -1144,8 +1131,6 @@ void ospf6_top_init(void)
        install_default(OSPF6_NODE);
        install_element(OSPF6_NODE, &ospf6_router_id_cmd);
        install_element(OSPF6_NODE, &no_ospf6_router_id_cmd);
-       install_element(OSPF6_NODE, &ospf6_router_id_hdn_cmd);
-       install_element(OSPF6_NODE, &no_ospf6_router_id_hdn_cmd);
        install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
        install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
        install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
index 8a6c4a5ccfd3437e9a1910068307ea1d2c0fee64..d9c29f2651b9e028996f72367ea2c1ff23386ef3 100644 (file)
@@ -6,9 +6,27 @@ if OSPF6D
 noinst_LIBRARIES += ospf6d/libospf6.a
 sbin_PROGRAMS += ospf6d/ospf6d
 dist_examples_DATA += ospf6d/ospf6d.conf.sample
+vtysh_scan += \
+       $(top_srcdir)/ospf6d/ospf6_abr.c \
+       $(top_srcdir)/ospf6d/ospf6_asbr.c \
+       $(top_srcdir)/ospf6d/ospf6_area.c \
+       $(top_srcdir)/ospf6d/ospf6_bfd.c \
+       $(top_srcdir)/ospf6d/ospf6_flood.c \
+       $(top_srcdir)/ospf6d/ospf6_interface.c \
+       $(top_srcdir)/ospf6d/ospf6_intra.c \
+       $(top_srcdir)/ospf6d/ospf6_lsa.c \
+       $(top_srcdir)/ospf6d/ospf6_message.c \
+       $(top_srcdir)/ospf6d/ospf6_neighbor.c \
+       $(top_srcdir)/ospf6d/ospf6_route.c \
+       $(top_srcdir)/ospf6d/ospf6_spf.c \
+       $(top_srcdir)/ospf6d/ospf6_top.c \
+       $(top_srcdir)/ospf6d/ospf6_zebra.c \
+       $(top_srcdir)/ospf6d/ospf6d.c \
+       # end
 if SNMP
 module_LTLIBRARIES += ospf6d/ospf6d_snmp.la
 endif
+man8 += $(MANBUILD)/ospf6d.8
 endif
 
 ospf6d_libospf6_a_SOURCES = \
index 1740b04fbcbcb940b11d52f195b2c471989249bb..9be70451f001d86fa42e383ae12510f61d2efbec 100644 (file)
@@ -1,16 +1 @@
-!Makefile
-Makefile.in
-*.o
 ospfclient
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
-refix
index 834d4aaba77e64e00102d52bbf7d12b4f0f6a97a..df7d85a1f5d810ed637f425fa9d9bee6f0494f32 100644 (file)
@@ -5,6 +5,7 @@
 if OSPFCLIENT
 lib_LTLIBRARIES += ospfclient/libfrrospfapiclient.la
 sbin_PROGRAMS += ospfclient/ospfclient
+man8 += $(MANBUILD)/ospfclient.8
 endif
 
 ospfclient_libfrrospfapiclient_la_LDFLAGS = -version-info 0:0:0
index 752c875a622136a8e523968d0e02b27e4c44b0bf..fc65db33ee539c245d548a15d8d92f82675cbd26 100644 (file)
@@ -1,17 +1,2 @@
-!Makefile
-Makefile.in
-*.o
 ospfd
 ospfd.conf
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
-*.a
index 19d2e6a95251f4fb1de862a5c56bda0105842370..755634a2f166c5d2d9935351a016a71a7b1b3cc1 100644 (file)
@@ -995,7 +995,6 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name,
                        if (len <= 0)
                                type_next = 1;
                        else {
-                               len = 1;
                                type_next = 0;
                                *type = *offset;
                        }
index 62eca156f55d4ffbd694208c85bded837e9174f1..220de3234d2097fb9b0943d1e86a01394725d317 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
index cd659a9bc92592448beb1de28040a1b992df6d9b..83074b5ac018f8c8f2d6a0c152b3cde4e0671bdd 100644 (file)
@@ -6,9 +6,20 @@ if OSPFD
 noinst_LIBRARIES += ospfd/libfrrospf.a
 sbin_PROGRAMS += ospfd/ospfd
 dist_examples_DATA += ospfd/ospfd.conf.sample
+vtysh_scan += \
+       $(top_srcdir)/ospfd/ospf_bfd.c \
+       $(top_srcdir)/ospfd/ospf_dump.c \
+       $(top_srcdir)/ospfd/ospf_opaque.c \
+       $(top_srcdir)/ospfd/ospf_ri.c \
+       $(top_srcdir)/ospfd/ospf_routemap.c \
+       $(top_srcdir)/ospfd/ospf_te.c \
+       $(top_srcdir)/ospfd/ospf_sr.c \
+       $(top_srcdir)/ospfd/ospf_vty.c \
+       # end
 if SNMP
 module_LTLIBRARIES += ospfd/ospfd_snmp.la
 endif
+man8 += $(MANBUILD)/ospfd.8
 endif
 
 ospfd_libfrrospf_a_SOURCES = \
index ff95d885276f568677fb67c1c4c38b14213d6502..86622ea1741650b27941db46ae0338cd8d19f111 100644 (file)
@@ -1,15 +1 @@
-!Makefile
-Makefile.in
-libpbr.a
 pbrd
-tags
-TAGS
-.deps
-*.o
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
index 42ab393218ff8c6f47260b00bf7b18961b00e4f1..79475590345dd8ac9d7e8476fb47e7e5eadca393 100644 (file)
@@ -6,6 +6,11 @@ if PBRD
 noinst_LIBRARIES += pbrd/libpbr.a
 sbin_PROGRAMS += pbrd/pbrd
 dist_examples_DATA += pbrd/pbrd.conf.sample
+vtysh_scan += \
+       $(top_srcdir)/pbrd/pbr_vty.c \
+       $(top_srcdir)/pbrd/pbr_debug.c \
+       # end
+man8 += $(MANBUILD)/pbrd.8
 endif
 
 pbrd_libpbr_a_SOURCES = \
index 1f56cfaecdabd2dac7344f859ef8710ce6b03079..b1780df7584697357283efef27fb41449690cccc 100644 (file)
@@ -1,17 +1,3 @@
-!Makefile
-Makefile.in
-libpim.a
 pimd
 mtracebis
 test_igmpv3_join
-tags
-TAGS
-.deps
-*.o
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
index c0d95aeed9e3799542ee7097f3d982b899a8e98e..65c495eff04502a6f0ca35e74be2d362f4d0aa30 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #ifdef __linux__
 
 #include "pim_igmp_mtrace.h"
index b4bf6bada34b256c4ef2eab050cdce6c1a05fbd9..30ee8f24abd7fb26a165818a84a6999ff5ed21ab 100644 (file)
  *
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #ifdef __linux__
 
 #include <stdio.h>
index 8c1cd8d96303b03995347409b10db6ddd3960986..8d974403ac631e8e100a5fba4c989f992bd6854a 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #ifdef __linux__
 
 #include <asm/types.h>
index 95d0278a34317a789275e5357ee9dab41b33e310..1fb624a6a0bde85f6542697ed8312eef70020c1f 100644 (file)
@@ -615,7 +615,7 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr,
        static uint32_t qry_id, qry_src;
        char mtrace_buf[MTRACE_HDR_SIZE + MTRACE_MAX_HOPS * MTRACE_RSP_SIZE];
        struct interface *ifp;
-       struct interface *out_ifp;
+       struct interface *out_ifp = NULL;
        struct pim_interface *pim_ifp;
        struct pim_instance *pim;
        struct igmp_mtrace *mtracep;
index 428816e1f095d6d7a02b400e7d0d0a5ce0c26c60..40851a45299a356f05b7706b099c870c23158874 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "pim_igmp_stats.h"
 
 void igmp_stats_init(struct igmp_stats *stats)
index 55d56ece976255f88fee56472fdcda0b3c2c8e88..fef8e36577fe9f5116cafe43222d2d3b871a785f 100644 (file)
@@ -8,6 +8,9 @@ sbin_PROGRAMS += pimd/pimd
 bin_PROGRAMS += pimd/mtracebis
 noinst_PROGRAMS += pimd/test_igmpv3_join
 dist_examples_DATA += pimd/pimd.conf.sample
+vtysh_scan += $(top_srcdir)/pimd/pim_cmd.c
+man8 += $(MANBUILD)/pimd.8
+man8 += $(MANBUILD)/mtracebis.8
 endif
 
 pimd_libpim_a_SOURCES = \
index 63e9a66d8f76434ac50c56ae9c3424fd5f133b78..c97f963b3da62e7caf32879f88e2759488a93afd 100644 (file)
@@ -1,8 +1 @@
-Makefile
-Makefile.in
 *.sh
-.arch-inventory
-.arch-ids
-*~
-*.loT
-
diff --git a/ports/.gitignore b/ports/.gitignore
deleted file mode 100644 (file)
index dd5bf7c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-.arch-inventory
-.arch-ids
-
-*~
-*.loT
-
diff --git a/ports/files/.gitignore b/ports/files/.gitignore
deleted file mode 100644 (file)
index dd5bf7c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-.arch-inventory
-.arch-ids
-
-*~
-*.loT
-
diff --git a/ports/pkg/.gitignore b/ports/pkg/.gitignore
deleted file mode 100644 (file)
index dd5bf7c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-.arch-inventory
-.arch-ids
-
-*~
-*.loT
-
index 4134f4c94e7239bdd7e887936f4bc6927f5eaff9..a140ce3d5454404312181bb02dee46f542b311b7 100644 (file)
@@ -96,7 +96,7 @@ class IP4Handler(IPBase):
     code = Template('_fail = !inet_aton(argv[_i]->arg, &$varname);')
 class IP6Handler(IPBase):
     argtype = 'struct in6_addr'
-    decl = Template('struct in6_addr $varname = IN6ADDR_ANY_INIT;')
+    decl = Template('struct in6_addr $varname = {};')
     code = Template('_fail = !inet_pton(AF_INET6, argv[_i]->arg, &$varname);')
 class IPGenHandler(IPBase):
     argtype = 'const union sockunion *'
diff --git a/qpb/.gitignore b/qpb/.gitignore
deleted file mode 100644 (file)
index 17e9044..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-!Makefile
-Makefile.in
-*.o
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.a
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
index 7e5ba5b0ce40fb9e56edfe8f521674d25d05b053..aca611ba1952cef41179e371eccbfff443045bda 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "linear_allocator.h"
 
 #include "qpb_allocator.h"
index 3c006fd221b5fddc1eef351a6dd9263af492fe3b..75a733f8fcfeba54682d169d492814cac42cf40c 100644 (file)
@@ -2,24 +2,45 @@ if HAVE_PROTOBUF
 lib_LTLIBRARIES += qpb/libfrr_pb.la
 endif
 
-qpb_libfrr_pb_la_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib \
-       $(Q_PROTOBUF_C_CLIENT_INCLUDES)
+qpb_libfrr_pb_la_CPPFLAGS = $(AM_CPPFLAGS) $(PROTOBUF_C_CFLAGS)
+qpb_libfrr_pb_la_LIBADD = $(PROTOBUF_C_LIBS)
 qpb_libfrr_pb_la_LDFLAGS = -version-info 0:0:0
 
 qpb_libfrr_pb_la_SOURCES = \
+       qpb/qpb.c \
+       qpb/qpb_allocator.c \
+       # end
+nodist_qpb_libfrr_pb_la_SOURCES = \
+       qpb/qpb.pb-c.c \
+       # end
+
+noinst_HEADERS += \
        qpb/linear_allocator.h \
        qpb/qpb.h \
-       qpb/qpb.c \
        qpb/qpb_allocator.h \
        # end
 
-if HAVE_PROTOBUF
-qpb_libfrr_pb_la_SOURCES += qpb/qpb_allocator.c
-nodist_qpb_libfrr_pb_la_SOURCES = qpb/qpb.pb-c.c
 CLEANFILES += \
        qpb/qpb.pb-c.c \
        qpb/qpb.pb-c.h \
        # end
-endif
 
 EXTRA_DIST += qpb/qpb.proto
+
+if HAVE_PROTOBUF
+
+# Rules
+.proto.pb.h:
+       $(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)$(PROTOC_C) -I$(top_srcdir) --c_out=$(top_srcdir) $(top_srcdir)/$^
+.pb-c.c.pb-c.h:
+       @/bin/true
+
+endif  # HAVE_PROTOBUF
index a38f1c06e32ab01ec2f0ecce0dcef1dce1f6808f..15804cea0fa7e831c48361adf4bcb17c2ee80263 100644 (file)
@@ -1,10 +1,2 @@
 zebra.spec
 frr.spec
-Makefile
-Makefile.in
-.nfs*
-.arch-inventory
-.arch-ids
-*~
-*.loT
-
index c461e543d238b4cd23d78ae8bbe1b7b58e63b88e..a3f095786d817f11cdc93450982dd0ffadcca0e3 100644 (file)
@@ -3,16 +3,15 @@ Building your own FRRouting RPM
 (Tested on CentOS 6, CentOS 7 and Fedora 24.)
 
 1. On CentOS 6 (which doesn't provide a bison/automake/autoconf of a recent enough version):
-    - Check out ../doc/Building_FRR_on_CentOS6.md for details on installing
+    - Check out ../doc/developer/building-frr-for-centos6.rst for details on installing
     a bison/automake/autoconf to support frr building.
 
     Newer automake/autoconf/bison is only needed to build the rpm and is
     **not** needed to install the binary rpm package
 
-2. Install the build packages as documented in doc/Building_on_xxxxx.md 
-   and the following additional packages:
+2. Install the build packages as documented in doc/developer/building-frr-for-xxxxx.rst and the following additional packages:
 
-        yum install rpm-build net-snmp-devel pam-devel
+        yum install rpm-build net-snmp-devel pam-devel libcap-devel
 
     Additionally, on systems with systemd (CentOS 7, Fedora)
 
@@ -28,8 +27,9 @@ Building your own FRRouting RPM
 
         cd frr
         ./bootstrap.sh
-        ./configure --with-pkg-extra-version=-MyRPMVersion
-        make SPHINXBUILD=sphinx-build2.7 dist
+        ./configure --with-pkg-extra-version=-MyRPMVersion \
+            SPHINXBUILD=sphinx-build2.7
+        make dist
             
     Note: configure parameters are not important for the RPM building - except the `with-pkg-extra-version` if you want to give the RPM a specific name to
     mark your own unoffical build
index de708cf4fd7e313f6866c97543641cec8527bdd3..c301a1c23a5de4d8f9fa85eb5ae1f6704fb26595 100644 (file)
@@ -53,6 +53,7 @@ sharpd=no
 pbrd=no
 staticd=no
 bfdd=no
+fabricd=no
 
 #
 # Command line options for the daemons
@@ -73,6 +74,7 @@ sharpd_options=("-A 127.0.0.1")
 pbrd_options=("-A 127.0.0.1")
 staticd_options=("-A 127.0.0.1")
 bfdd_options=("-A 127.0.0.1")
+fabricd_options=("-A 127.0.0.1")
 
 #
 # If the vtysh_enable is yes, then the unified config is read
index 2e33aee1730c84c70afef20d9e4f83315c6ecfe0..47a92eed32cc67fb651ad610d81968abbb2ce82f 100755 (executable)
@@ -33,7 +33,7 @@ V_PATH=/var/run/frr
 # Local Daemon selection may be done by using /etc/frr/daemons.
 # See /usr/share/doc/frr/README.Debian.gz for further information.
 # Keep zebra first and do not list watchfrr!
-DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd pimd pbrd ldpd nhrpd eigrpd babeld staticd sharpd bfdd"
+DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd pimd pbrd ldpd nhrpd eigrpd babeld staticd sharpd bfdd fabricd"
 MAX_INSTANCES=5
 RELOAD_SCRIPT=/usr/lib/frr/frr-reload.py
 
index 654d355fd7ea94cbeb6e79a9620c96d0b2a34afe..df7c5da54e5896262ecfcb2601ca4bb23d5b9887 100644 (file)
     /bin/kill -USR1 `cat /var/run/frr/bfdd.pid 2> /dev/null` 2> /dev/null || true
     endscript
 }
+
+/var/log/frr/fabricd.log {
+    notifempty
+    missingok
+    postrotate
+        /bin/kill -USR1 `cat /var/run/frr/fabricd.pid 2> /dev/null` 2> /dev/null || true
+    endscript
+}
index 25b48506a6ed7b22d5660b2f19642e08c5fe1441..bff0b405151344571be6a87080cb0bf9e4b6113d 100644 (file)
@@ -86,7 +86,7 @@
 %{!?frr_gid:            %global  frr_gid            92 }
 %{!?vty_gid:            %global  vty_gid            85 }
 
-%define daemon_list zebra ripd ospfd bgpd isisd ripngd ospf6d pbrd staticd bfdd
+%define daemon_list zebra ripd ospfd bgpd isisd ripngd ospf6d pbrd staticd bfdd fabricd
 
 %if %{with_ldpd}
     %define daemon_ldpd ldpd
@@ -343,22 +343,23 @@ developing OSPF-API and frr applications.
     --disable-rpki \
 %endif
 %if %{with_bfdd}
-    --enable-bfdd
+    --enable-bfdd \
 %else
-    --disable-bfdd
+    --disable-bfdd \
 %endif
+    SPHINXBUILD=%{sphinx}
 
-make %{?_smp_mflags} MAKEINFO="makeinfo --no-split" SPHINXBUILD=%{sphinx}
+make %{?_smp_mflags} MAKEINFO="makeinfo --no-split"
 
 pushd doc
-make SPHINXBUILD=%{sphinx} info
+make info
 popd
 
 
 %install
 mkdir -p %{buildroot}%{_sysconfdir}/{frr,sysconfig,logrotate.d,pam.d,default} \
          %{buildroot}%{_localstatedir}/log/frr %{buildroot}%{_infodir}
-make DESTDIR=%{buildroot} INSTALL="install -p" CP="cp -p" SPHINXBUILD=%{sphinx} install
+make DESTDIR=%{buildroot} INSTALL="install -p" CP="cp -p" install
 
 # Remove this file, as it is uninstalled and causes errors when building on RH9
 rm -rf %{buildroot}/usr/share/info/dir
@@ -459,6 +460,7 @@ zebra_spec_add_service isisd    2608/tcp "ISISd vty"
 %if %{with_bfdd}
     zebra_spec_add_service bfdd     2617/tcp "BFDd vty"
 %endif
+zebra_spec_add_service fabricd 2618/tcp "Fabricd vty"
 
 %if "%{initsystem}" == "systemd"
     for daemon in %all_daemons ; do
@@ -559,9 +561,9 @@ fi
 
 
 %files
-%doc */*.sample* AUTHORS COPYING
+%doc */*.sample* COPYING
 %doc doc/mpls
-%doc ChangeLog NEWS README
+%doc README.md
 %if 0%{?frr_user:1}
     %dir %attr(751,%{frr_user},%{frr_user}) %{configdir}
     %dir %attr(750,%{frr_user},%{frr_user}) %{_localstatedir}/log/frr
@@ -594,6 +596,7 @@ fi
     %{_sbindir}/pbrd
 %endif
 %{_sbindir}/isisd
+%{_sbindir}/fabricd
 %if %{with_ldpd}
     %{_sbindir}/ldpd
 %endif
index 177250ca6108989feb9094b2374f9a956e85ba15..f149501d61b42b4b7bc6cb4edd303c419ea14df6 100644 (file)
@@ -1,17 +1,2 @@
-!Makefile
-Makefile.in
-*.o
 ripd
 ripd.conf
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
-*.a
index 612db1a7abc5646f8d44800c91c53f587d02eee5..0d06e7e653c0f7d00db57b434000902cfcbde20f 100644 (file)
@@ -6,9 +6,18 @@ if RIPD
 noinst_LIBRARIES += ripd/librip.a
 sbin_PROGRAMS += ripd/ripd
 dist_examples_DATA += ripd/ripd.conf.sample
+vtysh_scan += \
+       $(top_srcdir)/ripd/rip_debug.c \
+       $(top_srcdir)/ripd/rip_interface.c \
+       $(top_srcdir)/ripd/rip_offset.c \
+       $(top_srcdir)/ripd/rip_zebra.c \
+       $(top_srcdir)/ripd/ripd.c \
+       # end
+
 if SNMP
 module_LTLIBRARIES += ripd/ripd_snmp.la
 endif
+man8 += $(MANBUILD)/ripd.8
 endif
 
 ripd_librip_a_SOURCES = \
index 213384d139312c317649d738960bfb0a02e7c51e..e6a8ee6be2d47dacb5e014945076a4371142a1d6 100644 (file)
@@ -1,17 +1,2 @@
-!Makefile
-Makefile.in
-*.o
 ripngd
 ripngd.conf
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
-*.a
index 1f7ff09d6edc52005e4e3b362b593d4eeb6e211c..8f834a1d297d5200fd4b711a90b7264d6fbf5bc2 100644 (file)
@@ -5,6 +5,14 @@
 if RIPNGD
 noinst_LIBRARIES += ripngd/libripng.a
 sbin_PROGRAMS += ripngd/ripngd
+vtysh_scan += \
+       $(top_srcdir)/ripngd/ripng_debug.c \
+       $(top_srcdir)/ripngd/ripng_interface.c \
+       $(top_srcdir)/ripngd/ripng_offset.c \
+       $(top_srcdir)/ripngd/ripng_zebra.c \
+       $(top_srcdir)/ripngd/ripngd.c \
+       # end
+man8 += $(MANBUILD)/ripngd.8
 endif
 
 ripngd_libripng_a_SOURCES = \
index cc33cfc188ae9f31827264419d4d39f7caed902d..91b9f2e902f83bab903573cbd30f0339a1bfb7a9 100644 (file)
@@ -1,17 +1,2 @@
-Makefile
-Makefile.in
-*.o
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.a
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
 sharpd
 sharpd.conf
index 956da9d4edd44baa4b13a4bcae40432346d0f987..797e336c2d2de814d91a6a5e3437d34e9146a9a0 100644 (file)
@@ -81,13 +81,14 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
 
 DEFPY (install_routes,
        install_routes_cmd,
-       "sharp install routes A.B.C.D$start nexthop A.B.C.D$nexthop (1-1000000)$routes [instance (0-255)$instance]",
+       "sharp install routes A.B.C.D$start nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6> (1-1000000)$routes [instance (0-255)$instance]",
        "Sharp routing Protocol\n"
        "install some routes\n"
        "Routes to install\n"
        "Address to start /32 generation at\n"
-       "Nexthop to use\n"
-       "Nexthop address\n"
+       "Nexthop to use(Can be an IPv4 or IPv6 address)\n"
+       "V4 Nexthop address to use\n"
+       "V6 Nexthop address to use\n"
        "How many to create\n"
        "Instance to use\n"
        "Instance\n")
@@ -107,8 +108,13 @@ DEFPY (install_routes,
        p.prefixlen = 32;
        p.u.prefix4 = start;
 
-       nhop.gate.ipv4 = nexthop;
-       nhop.type = NEXTHOP_TYPE_IPV4;
+       if (nexthop4.s_addr != INADDR_ANY) {
+               nhop.gate.ipv4 = nexthop4;
+               nhop.type = NEXTHOP_TYPE_IPV4;
+       } else {
+               memcpy(&nhop.gate.ipv6, &nexthop6, IPV6_MAX_BYTELEN);
+               nhop.type = NEXTHOP_TYPE_IPV6;
+       }
 
        zlog_debug("Inserting %ld routes", routes);
 
@@ -185,6 +191,18 @@ DEFPY (remove_routes,
        return CMD_SUCCESS;
 }
 
+DEFUN_NOSH (show_debugging_sharpd,
+           show_debugging_sharpd_cmd,
+           "show debugging [sharp]",
+           SHOW_STR
+           DEBUG_STR
+           "Sharp Information\n")
+{
+       vty_out(vty, "Sharp debugging status\n");
+
+       return CMD_SUCCESS;
+}
+
 void sharp_vty_init(void)
 {
        install_element(ENABLE_NODE, &install_routes_cmd);
@@ -192,5 +210,8 @@ void sharp_vty_init(void)
        install_element(ENABLE_NODE, &vrf_label_cmd);
        install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
        install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
+
+       install_element(VIEW_NODE, &show_debugging_sharpd_cmd);
+
        return;
 }
index fcb555170b8870d94c6422da6b370456d5a59db5..286f320874ca3a80727eec1770f0ad8593203348 100644 (file)
@@ -193,7 +193,7 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop *nh)
 
        api_nh = &api.nexthops[0];
        api_nh->vrf_id = VRF_DEFAULT;
-       api_nh->gate.ipv4 = nh->gate.ipv4;
+       api_nh->gate = nh->gate;
        api_nh->type = nh->type;
        api_nh->ifindex = nh->ifindex;
        api.nexthop_num = 1;
index 490a2ba787ebc3c1c936c4bc4a2364f735d99a0b..2a34aecfb3eff05f495b85f1222d594cb5cba3dc 100644 (file)
@@ -6,6 +6,8 @@ if SHARPD
 noinst_LIBRARIES += sharpd/libsharp.a
 sbin_PROGRAMS += sharpd/sharpd
 dist_examples_DATA += sharpd/sharpd.conf.sample
+vtysh_scan += $(top_srcdir)/sharpd/sharp_vty.c
+man8 += $(MANBUILD)/sharpd.8
 endif
 
 sharpd_libsharp_a_SOURCES = \
index ac7860290b9e3dd2ade4fa1155075c96da6c4916..a4796fd730c03f239528114f8942d9315ff481f9 100644 (file)
@@ -3,4 +3,3 @@ parts
 prime
 stage
 frr*.snap
-!*/Makefile
index a249b6199618d22e4cdbe3a7b5025b451d7f8b82..3f1a0385a4261c3b3e3112a234654d352b6ce8ab 100644 (file)
@@ -17,6 +17,3 @@ depend.smf
 frr.init
 *.pkg
 *.pkg.gz
-*~
-*.loT
-*.a
index 771d8d1de37a5c0cbe445ca122b54c90c97eca0e..f697969a7227d34faae573098b5a67d706124d84 100644 (file)
@@ -88,8 +88,8 @@ static struct list *static_list;
 
 static int static_list_compare_helper(const char *s1, const char *s2)
 {
-       /* Are Both NULL */
-       if (s1 == s2)
+       /* extra (!s1 && !s2) to keep SA happy */
+       if (s1 == s2 || (!s1 && !s2))
                return 0;
 
        if (!s1 && s2)
@@ -1390,6 +1390,18 @@ DEFPY(ipv6_route_vrf,
                table_str);
 }
 
+DEFUN_NOSH (show_debugging_staticd,
+           show_debugging_staticd_cmd,
+           "show debugging [static]",
+           SHOW_STR
+           DEBUG_STR
+           "Static Information\n")
+{
+       vty_out(vty, "Static debugging status\n");
+
+       return CMD_SUCCESS;
+}
+
 void static_vty_init(void)
 {
        install_element(CONFIG_NODE, &ip_mroute_dist_cmd);
@@ -1408,6 +1420,8 @@ void static_vty_init(void)
        install_element(CONFIG_NODE, &ipv6_route_cmd);
        install_element(VRF_NODE, &ipv6_route_vrf_cmd);
 
+       install_element(VIEW_NODE, &show_debugging_staticd_cmd);
+
        static_list = list_new();
        static_list->cmp = (int (*)(void *, void *))static_list_compare;
        static_list->del = (void (*)(void *))static_list_delete;
index 3b06a92e22a85f9cc6a9c010cdfd6fde264c0b9f..33cc0e20505ea1d37b149595a3bcd034b294f27b 100644 (file)
@@ -6,6 +6,8 @@ if STATICD
 noinst_LIBRARIES += staticd/libstatic.a
 sbin_PROGRAMS += staticd/staticd
 dist_examples_DATA += staticd/staticd.conf.sample
+vtysh_scan += $(top_srcdir)/staticd/static_vty.c
+man8 += $(MANBUILD)/staticd.8
 endif
 
 staticd_libstatic_a_SOURCES = \
index c8368b39b613985f3c0ed8d99b28e32fdedd72d1..37cd245de08c0c7453057e2931b2d83ab91fe258 100644 (file)
@@ -1,24 +1,6 @@
-Makefile
-Makefile.in
-*.o
-tags
-TAGS
-.cache
-.deps
-.nfs*
-*~
-*.loT
-*.lo
-*.la
-*.libs
-*.bak
 *.log
 *.sum
 *.xml
-*.pyc
-.arch-inventory
-.arch-ids
-__pycache__
 .pytest_cache
 /bgpd/test_aspath
 /bgpd/test_bgp_table
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644 (file)
index 0000000..dd4594f
--- /dev/null
@@ -0,0 +1,10 @@
+all: ALWAYS
+       @$(MAKE) -s -C .. check
+%: ALWAYS
+       @$(MAKE) -s -C .. tests/$@
+
+Makefile:
+       #nothing
+ALWAYS:
+.PHONY: ALWAYS makefiles
+.SUFFIXES:
diff --git a/tests/Makefile.am b/tests/Makefile.am
deleted file mode 100644 (file)
index a7dec67..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-include ../common.am
-
-PYTHON ?= python
-
-AUTOMAKE_OPTIONS = subdir-objects
-AM_CPPFLAGS += \
-       -I.. \
-       -I$(top_srcdir) \
-       -I$(top_srcdir)/lib \
-       -I$(top_builddir)/lib \
-       -I$(top_srcdir)/tests/helpers/c \
-       -I$(top_builddir)/tests/helpers/c \
-       -O
-DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\"
-
-if BGPD
-TESTS_BGPD = \
-       bgpd/test_aspath \
-       bgpd/test_capability \
-       bgpd/test_packet \
-       bgpd/test_peer_attr \
-       bgpd/test_ecommunity \
-       bgpd/test_mp_attr \
-       bgpd/test_mpath \
-       bgpd/test_bgp_table
-else
-TESTS_BGPD =
-endif
-
-if ISISD
-if SOLARIS
-TESTS_ISISD =
-else
-TESTS_ISISD = \
-       isisd/test_fuzz_isis_tlv \
-       isisd/test_isis_vertex_queue \
-       # end
-endif
-else
-TESTS_ISISD =
-endif
-
-if OSPF6D
-TESTS_OSPF6D = \
-       ospf6d/test_lsdb \
-       # end
-else
-TESTS_OSPF6D =
-endif
-
-if ENABLE_BGP_VNC
-BGP_VNC_RFP_LIB=@top_builddir@/$(LIBRFP)/librfp.a
-else
-BGP_VNC_RFP_LIB =
-endif
-
-lib/cli/test_cli.o: lib/cli/test_cli_clippy.c
-ospf6d/test_lsdb.o: ospf6d/test_lsdb_clippy.c
-
-check_PROGRAMS = \
-       lib/test_buffer \
-       lib/test_checksum \
-       lib/test_heavy_thread \
-       lib/test_heavy_wq \
-       lib/test_heavy \
-       lib/test_memory \
-       lib/test_nexthop_iter \
-       lib/test_privs \
-       lib/test_ringbuf \
-       lib/test_srcdest_table \
-       lib/test_segv \
-       lib/test_sig \
-       lib/test_stream \
-       lib/test_table \
-       lib/test_timer_correctness \
-       lib/test_timer_performance \
-       lib/test_ttable \
-       lib/test_zlog \
-       lib/test_graph \
-       lib/cli/test_cli \
-       lib/cli/test_commands \
-       $(TESTS_BGPD) \
-       $(TESTS_ISISD) \
-       $(TESTS_OSPF6D) \
-       # end
-
-if ZEROMQ
-check_PROGRAMS += \
-       lib/test_zmq \
-       # end
-endif
-
-../vtysh/vtysh_cmd.c:
-       $(MAKE) -C ../vtysh vtysh_cmd.c
-
-lib/cli/test_commands_defun.c: ../vtysh/vtysh_cmd.c
-       sed \
-               -e 's/"vtysh\.h"/"tests.h"/' \
-               -e 's/vtysh_init_cmd/test_init_cmd/' \
-               -e 's/VTYSH_[A-Z][A-Z_0-9]*/0/g' \
-               < ../vtysh/vtysh_cmd.c \
-               > "$@"
-
-isisd/test_fuzz_isis_tlv_tests.h: $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
-       gzip -d < $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz > "$@"
-
-noinst_HEADERS = \
-       ./helpers/c/prng.h \
-       ./helpers/c/tests.h \
-       ./lib/cli/common_cli.h
-
-lib_test_buffer_SOURCES = lib/test_buffer.c
-lib_test_checksum_SOURCES = lib/test_checksum.c
-lib_test_heavy_thread_SOURCES = lib/test_heavy_thread.c helpers/c/main.c
-lib_test_heavy_wq_SOURCES = lib/test_heavy_wq.c helpers/c/main.c
-lib_test_heavy_SOURCES = lib/test_heavy.c helpers/c/main.c
-lib_test_memory_SOURCES = lib/test_memory.c
-lib_test_nexthop_iter_SOURCES = lib/test_nexthop_iter.c helpers/c/prng.c
-lib_test_privs_SOURCES = lib/test_privs.c
-lib_test_ringbuf_SOURCES = lib/test_ringbuf.c
-lib_test_srcdest_table_SOURCES = lib/test_srcdest_table.c \
-                                 helpers/c/prng.c
-lib_test_segv_SOURCES = lib/test_segv.c
-lib_test_sig_SOURCES = lib/test_sig.c
-lib_test_stream_SOURCES = lib/test_stream.c
-lib_test_table_SOURCES = lib/test_table.c
-lib_test_timer_correctness_SOURCES = lib/test_timer_correctness.c \
-                                     helpers/c/prng.c
-lib_test_timer_performance_SOURCES = lib/test_timer_performance.c \
-                                     helpers/c/prng.c
-lib_test_ttable_SOURCES = lib/test_ttable.c
-lib_test_zlog_SOURCES = lib/test_zlog.c
-lib_test_graph_SOURCES = lib/test_graph.c
-lib_test_zmq_SOURCES = lib/test_zmq.c
-lib_test_zmq_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS)
-lib_cli_test_cli_SOURCES = lib/cli/test_cli.c lib/cli/common_cli.c
-lib_cli_test_commands_SOURCES = lib/cli/test_commands_defun.c \
-                                lib/cli/test_commands.c \
-                                helpers/c/prng.c
-bgpd_test_aspath_SOURCES = bgpd/test_aspath.c
-bgpd_test_capability_SOURCES = bgpd/test_capability.c
-bgpd_test_packet_SOURCES = bgpd/test_packet.c
-bgpd_test_peer_attr_SOURCES = bgpd/test_peer_attr.c
-bgpd_test_ecommunity_SOURCES = bgpd/test_ecommunity.c
-bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c
-bgpd_test_mpath_SOURCES = bgpd/test_mpath.c
-bgpd_test_bgp_table_SOURCES = bgpd/test_bgp_table.c
-isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv.c
-nodist_isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv_tests.h
-BUILT_SOURCES=isisd/test_fuzz_isis_tlv_tests.h
-CLEANFILES=isisd/test_fuzz_isis_tlv_tests.h
-isisd_test_fuzz_isis_tlv_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/tests/isisd
-isisd_test_isis_vertex_queue_SOURCES = isisd/test_isis_vertex_queue.c
-
-ospf6d_test_lsdb_SOURCES = ospf6d/test_lsdb.c lib/cli/common_cli.c
-
-ALL_TESTS_LDADD = ../lib/libfrr.la @LIBCAP@
-BGP_TEST_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) $(ALL_TESTS_LDADD) -lm
-ISISD_TEST_LDADD = ../isisd/libisis.a $(ALL_TESTS_LDADD)
-OSPF6_TEST_LDADD = ../ospf6d/libospf6.a $(ALL_TESTS_LDADD)
-
-lib_test_buffer_LDADD = $(ALL_TESTS_LDADD)
-lib_test_checksum_LDADD = $(ALL_TESTS_LDADD)
-lib_test_heavy_thread_LDADD = $(ALL_TESTS_LDADD) -lm
-lib_test_heavy_wq_LDADD = $(ALL_TESTS_LDADD) -lm
-lib_test_heavy_LDADD = $(ALL_TESTS_LDADD) -lm
-lib_test_memory_LDADD = $(ALL_TESTS_LDADD)
-lib_test_nexthop_iter_LDADD = $(ALL_TESTS_LDADD)
-lib_test_privs_LDADD = $(ALL_TESTS_LDADD)
-lib_test_ringbuf_LDADD = $(ALL_TESTS_LDADD)
-lib_test_srcdest_table_LDADD = $(ALL_TESTS_LDADD)
-lib_test_segv_LDADD = $(ALL_TESTS_LDADD)
-lib_test_sig_LDADD = $(ALL_TESTS_LDADD)
-lib_test_stream_LDADD = $(ALL_TESTS_LDADD)
-lib_test_table_LDADD = $(ALL_TESTS_LDADD) -lm
-lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD)
-lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD)
-lib_test_ttable_LDADD = $(ALL_TESTS_LDADD)
-lib_test_zlog_LDADD = $(ALL_TESTS_LDADD)
-lib_test_graph_LDADD = $(ALL_TESTS_LDADD)
-lib_test_zmq_LDADD = ../lib/libfrrzmq.la $(ALL_TESTS_LDADD) $(ZEROMQ_LIBS)
-lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD)
-lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD)
-bgpd_test_aspath_LDADD = $(BGP_TEST_LDADD)
-bgpd_test_capability_LDADD = $(BGP_TEST_LDADD)
-bgpd_test_packet_LDADD = $(BGP_TEST_LDADD)
-bgpd_test_peer_attr_LDADD = $(BGP_TEST_LDADD)
-bgpd_test_ecommunity_LDADD = $(BGP_TEST_LDADD)
-bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD)
-bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD)
-bgpd_test_bgp_table_LDADD = $(BGP_TEST_LDADD)
-isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD)
-isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD)
-ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD)
-
-EXTRA_DIST = \
-    runtests.py \
-    bgpd/test_aspath.py \
-    bgpd/test_capability.py \
-    bgpd/test_ecommunity.py \
-    bgpd/test_mp_attr.py \
-    bgpd/test_mpath.py \
-       bgpd/test_peer_attr.py \
-    helpers/python/frrsix.py \
-    helpers/python/frrtest.py \
-    isisd/test_fuzz_isis_tlv.py \
-    isisd/test_fuzz_isis_tlv_tests.h.gz \
-    isisd/test_isis_vertex_queue.py \
-    lib/cli/test_commands.in \
-    lib/cli/test_commands.py \
-    lib/cli/test_commands.refout \
-    lib/cli/test_cli.in \
-    lib/cli/test_cli.py \
-    lib/cli/test_cli.refout \
-    lib/test_nexthop_iter.py \
-    lib/test_ringbuf.py \
-    lib/test_srcdest_table.py \
-    lib/test_stream.py \
-    lib/test_stream.refout \
-    lib/test_table.py \
-    lib/test_timer_correctness.py \
-    lib/test_ttable.py \
-    lib/test_ttable.refout \
-    lib/test_zlog.py \
-    lib/test_graph.py \
-    lib/test_graph.refout \
-    ospf6d/test_lsdb.py \
-    ospf6d/test_lsdb.in \
-    ospf6d/test_lsdb.refout \
-    # end
-
-.PHONY: tests.xml
-tests.xml: $(check_PROGRAMS)
-       $(PYTHON) $(srcdir)/runtests.py --junitxml=$@ -v $(srcdir)
-check: tests.xml
index da9e447fc0a78929d6672f5cce701ddf2172bd16..60bee5c88c710a458cb02b8f81184e9a2beaf0e7 100644 (file)
@@ -176,8 +176,14 @@ class TestRefOut(object):
         basedir = os.path.dirname(inspect.getsourcefile(type(self)))
         program = os.path.join(basedir, self.program)
 
-        refin = program + '.in'
-        refout = program + '.refout'
+        if getattr(self, 'built_refin', False):
+            refin = binpath(program) + '.in'
+        else:
+            refin = program + '.in'
+        if getattr(self, 'built_refout', False):
+            refout = binpath(program) + '.refout'
+        else:
+            refout = program + '.refout'
 
         intext = ''
         if os.path.exists(refin):
index 67a1593500b96ef92e41aef9cfcdf5948909dc47..b75c1002d43034613d71ad7437f33b30d59696f8 100644 (file)
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "test_fuzz_isis_tlv_tests.h"
 
 #include <zebra.h>
@@ -114,7 +118,11 @@ static int test(FILE *input, FILE *output)
        const char *s_tlvs = isis_format_tlvs(tlvs);
        fprintf(output, "Unpacked TLVs:\n%s", s_tlvs);
 
+       struct isis_item *orig_auth = tlvs->isis_auth.head;
+       tlvs->isis_auth.head = NULL;
+       s_tlvs = isis_format_tlvs(tlvs);
        struct isis_tlvs *tlv_copy = isis_copy_tlvs(tlvs);
+       tlvs->isis_auth.head = orig_auth;
        isis_free_tlvs(tlvs);
 
        struct stream *s2 = stream_new(TEST_STREAM_SIZE);
index 4abbe81499be693f39a91cf6581bde569ebd3da8..4a89bda84eac865059ab1755ffddc96497bc9691 100644 (file)
Binary files a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz and b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz differ
index 3e31b833511d2ded04ba55ce053d4ab5cfa6b3ad..869dd732eb9dcf6b3ba98156e427d1ade530685f 100644 (file)
@@ -16,42 +16,46 @@ static size_t vertex_count;
 
 static void setup_test_vertices(void)
 {
-       union isis_N nid, nip = {
-               .ip.dest.family = AF_UNSPEC
+       struct isis_spftree t = {
        };
+       struct prefix_pair p = {
+       };
+       uint8_t node_id[7];
 
        vertices = XMALLOC(MTYPE_TMP, sizeof(*vertices) * 16);
 
-       nip.ip.dest.family = AF_INET;
-       nip.ip.dest.prefixlen = 24;
-       inet_pton(AF_INET, "192.168.1.0", &nip.ip.dest.u.prefix4);
-       vertices[vertex_count] = isis_vertex_new(&nip, VTYPE_IPREACH_TE);
+       p.dest.family = AF_INET;
+       p.dest.prefixlen = 24;
+       inet_pton(AF_INET, "192.168.1.0", &p.dest.u.prefix4);
+       vertices[vertex_count] = isis_vertex_new(&t, &p, VTYPE_IPREACH_TE);
        vertices[vertex_count]->d_N = 20;
        vertex_count++;
 
-       nip.ip.dest.family = AF_INET;
-       nip.ip.dest.prefixlen = 24;
-       inet_pton(AF_INET, "192.168.2.0", &nip.ip.dest.u.prefix4);
-       vertices[vertex_count] = isis_vertex_new(&nip, VTYPE_IPREACH_TE);
+       p.dest.family = AF_INET;
+       p.dest.prefixlen = 24;
+       inet_pton(AF_INET, "192.168.2.0", &p.dest.u.prefix4);
+       vertices[vertex_count] = isis_vertex_new(&t, &p, VTYPE_IPREACH_TE);
        vertices[vertex_count]->d_N = 20;
        vertex_count++;
 
-       memset(nid.id, 0, sizeof(nid.id));
-       nid.id[6] = 1;
-       vertices[vertex_count] = isis_vertex_new(&nid, VTYPE_PSEUDO_TE_IS);
+       memset(node_id, 0, sizeof(node_id));
+       node_id[6] = 1;
+       vertices[vertex_count] = isis_vertex_new(&t, node_id,
+                                                VTYPE_PSEUDO_TE_IS);
        vertices[vertex_count]->d_N = 15;
        vertex_count++;
 
-       memset(nid.id, 0, sizeof(nid.id));
-       nid.id[5] = 2;
-       vertices[vertex_count] = isis_vertex_new(&nid, VTYPE_NONPSEUDO_TE_IS);
+       memset(node_id, 0, sizeof(node_id));
+       node_id[5] = 2;
+       vertices[vertex_count] = isis_vertex_new(&t, node_id,
+                                                VTYPE_NONPSEUDO_TE_IS);
        vertices[vertex_count]->d_N = 15;
        vertex_count++;
 
-       nip.ip.dest.family = AF_INET;
-       nip.ip.dest.prefixlen = 24;
-       inet_pton(AF_INET, "192.168.3.0", &nip.ip.dest.u.prefix4);
-       vertices[vertex_count] = isis_vertex_new(&nip, VTYPE_IPREACH_TE);
+       p.dest.family = AF_INET;
+       p.dest.prefixlen = 24;
+       inet_pton(AF_INET, "192.168.3.0", &p.dest.u.prefix4);
+       vertices[vertex_count] = isis_vertex_new(&t, &p, VTYPE_IPREACH_TE);
        vertices[vertex_count]->d_N = 20;
        vertex_count++;
 };
index 4cc15ba23fd8db5e466948071abdfe79c3108771..8f062d8b5efdf916f3ae90160641bfc692f165d3 100644 (file)
@@ -41,7 +41,7 @@ DUMMY_DEFUN(cmd13, "alt a X:X::X:X");
 DUMMY_DEFUN(cmd14,
            "pat g {  foo A.B.C.D$foo|foo|bar   X:X::X:X$bar| baz } [final]");
 
-#include "lib/cli/test_cli_clippy.c"
+#include "tests/lib/cli/test_cli_clippy.c"
 
 DEFPY(magic_test, magic_test_cmd,
        "magic (0-100) {ipv4net A.B.C.D/M|X:X::X:X$ipv6}",
index e3c31c2d91fb4d78b8b97d165c63081b3b7fcf56..7371db283ac3a3d3a2bd7aae01d287044e54f349 100644 (file)
@@ -2,3 +2,4 @@ import frrtest
 
 class TestCli(frrtest.TestRefOut):
     program = './test_cli'
+    built_refout = True
index ec0835c7191258667c93f5e8d7be7a66214f86c7..24821febe6be0ef4065efcc16f7cf87b3d430154 100644 (file)
@@ -29,7 +29,7 @@
 #include "ospf6d/ospf6_lsdb.h"
 
 #include "tests/lib/cli/common_cli.h"
-#include "ospf6d/test_lsdb_clippy.c"
+#include "tests/ospf6d/test_lsdb_clippy.c"
 
 static struct ospf6_lsdb *lsdb;
 
diff --git a/tests/subdir.am b/tests/subdir.am
new file mode 100644 (file)
index 0000000..739a0e8
--- /dev/null
@@ -0,0 +1,295 @@
+#
+# tests
+#
+
+PYTHON ?= python
+
+if BGPD
+TESTS_BGPD = \
+       tests/bgpd/test_aspath \
+       tests/bgpd/test_capability \
+       tests/bgpd/test_packet \
+       tests/bgpd/test_peer_attr \
+       tests/bgpd/test_ecommunity \
+       tests/bgpd/test_mp_attr \
+       tests/bgpd/test_mpath \
+       tests/bgpd/test_bgp_table
+else
+TESTS_BGPD =
+endif
+
+if ISISD
+if SOLARIS
+TESTS_ISISD =
+else
+TESTS_ISISD = \
+       tests/isisd/test_fuzz_isis_tlv \
+       tests/isisd/test_isis_vertex_queue \
+       # end
+endif
+else
+TESTS_ISISD =
+endif
+
+if OSPF6D
+TESTS_OSPF6D = \
+       tests/ospf6d/test_lsdb \
+       # end
+else
+TESTS_OSPF6D =
+endif
+
+tests/lib/cli/tests_lib_cli_test_cli-test_cli.$(OBJEXT): tests/lib/cli/test_cli_clippy.c
+tests/lib/cli/test_cli-test_cli.$(OBJEXT): tests/lib/cli/test_cli_clippy.c
+tests/ospf6d/tests_ospf6d_test_lsdb-test_lsdb.$(OBJEXT): tests/ospf6d/test_lsdb_clippy.c
+tests/ospf6d/test_lsdb-test_lsdb.$(OBJEXT): tests/ospf6d/test_lsdb_clippy.c
+
+check_PROGRAMS = \
+       tests/lib/test_buffer \
+       tests/lib/test_checksum \
+       tests/lib/test_heavy_thread \
+       tests/lib/test_heavy_wq \
+       tests/lib/test_heavy \
+       tests/lib/test_memory \
+       tests/lib/test_nexthop_iter \
+       tests/lib/test_privs \
+       tests/lib/test_ringbuf \
+       tests/lib/test_srcdest_table \
+       tests/lib/test_segv \
+       tests/lib/test_sig \
+       tests/lib/test_stream \
+       tests/lib/test_table \
+       tests/lib/test_timer_correctness \
+       tests/lib/test_timer_performance \
+       tests/lib/test_ttable \
+       tests/lib/test_zlog \
+       tests/lib/test_graph \
+       tests/lib/cli/test_cli \
+       tests/lib/cli/test_commands \
+       $(TESTS_BGPD) \
+       $(TESTS_ISISD) \
+       $(TESTS_OSPF6D) \
+       # end
+
+if ZEROMQ
+check_PROGRAMS += \
+       tests/lib/test_zmq \
+       # end
+endif
+
+tests/lib/cli/test_commands_defun.c: vtysh/vtysh_cmd.c
+       sed \
+               -e 's%"vtysh/vtysh\.h"%"tests/helpers/c/tests.h"%' \
+               -e 's/vtysh_init_cmd/test_init_cmd/' \
+               -e 's/VTYSH_[A-Z][A-Z_0-9]*/0/g' \
+               < vtysh/vtysh_cmd.c \
+               > "$@"
+
+tests/isisd/test_fuzz_isis_tlv_tests.h: $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
+       gzip -d < $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz > "$@"
+CLEANFILES += tests/isisd/test_fuzz_isis_tlv_tests.h
+
+tests/isisd/tests_isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.$(OBJEXT): \
+       tests/isisd/test_fuzz_isis_tlv_tests.h
+tests/isisd/test_fuzz_isis_tlv-test_fuzz_isis_tlv.$(OBJEXT): \
+       tests/isisd/test_fuzz_isis_tlv_tests.h
+
+noinst_HEADERS += \
+       tests/helpers/c/prng.h \
+       tests/helpers/c/tests.h \
+       tests/lib/cli/common_cli.h \
+       # end
+
+#
+# *sigh* - there is no way to get CPPFLAGS or CFLAGS for a group of files :(
+#
+
+TESTS_CPPFLAGS = $(AM_CPPFLAGS) \
+       -I$(top_srcdir)/tests/helpers/c \
+       -I$(top_builddir)/tests/helpers/c \
+       # end
+TESTS_CFLAGS = $(SAN_FLAGS)
+# note no -Werror
+
+ALL_TESTS_LDADD = lib/libfrr.la @LIBCAP@
+BGP_TEST_LDADD = bgpd/libbgp.a $(RFPLDADD) $(ALL_TESTS_LDADD) -lm
+ISISD_TEST_LDADD = isisd/libisis.a $(ALL_TESTS_LDADD)
+OSPF6_TEST_LDADD = ospf6d/libospf6.a $(ALL_TESTS_LDADD)
+
+tests_bgpd_test_aspath_CFLAGS = $(TESTS_CFLAGS)
+tests_bgpd_test_aspath_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_bgpd_test_aspath_LDADD = $(BGP_TEST_LDADD)
+tests_bgpd_test_aspath_SOURCES = tests/bgpd/test_aspath.c
+tests_bgpd_test_bgp_table_CFLAGS = $(TESTS_CFLAGS)
+tests_bgpd_test_bgp_table_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_bgpd_test_bgp_table_LDADD = $(BGP_TEST_LDADD)
+tests_bgpd_test_bgp_table_SOURCES = tests/bgpd/test_bgp_table.c
+tests_bgpd_test_capability_CFLAGS = $(TESTS_CFLAGS)
+tests_bgpd_test_capability_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_bgpd_test_capability_LDADD = $(BGP_TEST_LDADD)
+tests_bgpd_test_capability_SOURCES = tests/bgpd/test_capability.c
+tests_bgpd_test_ecommunity_CFLAGS = $(TESTS_CFLAGS)
+tests_bgpd_test_ecommunity_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_bgpd_test_ecommunity_LDADD = $(BGP_TEST_LDADD)
+tests_bgpd_test_ecommunity_SOURCES = tests/bgpd/test_ecommunity.c
+tests_bgpd_test_mp_attr_CFLAGS = $(TESTS_CFLAGS)
+tests_bgpd_test_mp_attr_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD)
+tests_bgpd_test_mp_attr_SOURCES = tests/bgpd/test_mp_attr.c
+tests_bgpd_test_mpath_CFLAGS = $(TESTS_CFLAGS)
+tests_bgpd_test_mpath_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD)
+tests_bgpd_test_mpath_SOURCES = tests/bgpd/test_mpath.c
+tests_bgpd_test_packet_CFLAGS = $(TESTS_CFLAGS)
+tests_bgpd_test_packet_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_bgpd_test_packet_LDADD = $(BGP_TEST_LDADD)
+tests_bgpd_test_packet_SOURCES = tests/bgpd/test_packet.c
+tests_bgpd_test_peer_attr_CFLAGS = $(TESTS_CFLAGS)
+tests_bgpd_test_peer_attr_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_bgpd_test_peer_attr_LDADD = $(BGP_TEST_LDADD)
+tests_bgpd_test_peer_attr_SOURCES = tests/bgpd/test_peer_attr.c
+
+tests_isisd_test_fuzz_isis_tlv_CFLAGS = $(TESTS_CFLAGS) -I$(top_builddir)/tests/isisd
+tests_isisd_test_fuzz_isis_tlv_CPPFLAGS = $(TESTS_CPPFLAGS) -I$(top_builddir)/tests/isisd
+tests_isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD)
+tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv.c
+nodist_tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv_tests.h
+tests_isisd_test_isis_vertex_queue_CFLAGS = $(TESTS_CFLAGS)
+tests_isisd_test_isis_vertex_queue_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD)
+tests_isisd_test_isis_vertex_queue_SOURCES = tests/isisd/test_isis_vertex_queue.c
+
+tests_lib_cli_test_cli_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_cli_test_cli_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_cli_test_cli_SOURCES = tests/lib/cli/test_cli.c tests/lib/cli/common_cli.c
+tests_lib_cli_test_commands_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_cli_test_commands_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_cli_test_commands_SOURCES = tests/lib/cli/test_commands_defun.c tests/lib/cli/test_commands.c tests/helpers/c/prng.c
+tests_lib_test_buffer_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_buffer_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_buffer_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_buffer_SOURCES = tests/lib/test_buffer.c
+tests_lib_test_checksum_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_checksum_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_checksum_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_checksum_SOURCES = tests/lib/test_checksum.c
+tests_lib_test_graph_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_graph_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_graph_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_graph_SOURCES = tests/lib/test_graph.c
+tests_lib_test_heavy_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_heavy_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_heavy_LDADD = $(ALL_TESTS_LDADD) -lm
+tests_lib_test_heavy_SOURCES = tests/lib/test_heavy.c tests/helpers/c/main.c
+tests_lib_test_heavy_thread_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_heavy_thread_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_heavy_thread_LDADD = $(ALL_TESTS_LDADD) -lm
+tests_lib_test_heavy_thread_SOURCES = tests/lib/test_heavy_thread.c tests/helpers/c/main.c
+tests_lib_test_heavy_wq_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_heavy_wq_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_heavy_wq_LDADD = $(ALL_TESTS_LDADD) -lm
+tests_lib_test_heavy_wq_SOURCES = tests/lib/test_heavy_wq.c tests/helpers/c/main.c
+tests_lib_test_memory_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_memory_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_memory_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_memory_SOURCES = tests/lib/test_memory.c
+tests_lib_test_nexthop_iter_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_nexthop_iter_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_nexthop_iter_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_nexthop_iter_SOURCES = tests/lib/test_nexthop_iter.c tests/helpers/c/prng.c
+tests_lib_test_privs_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_privs_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_privs_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_privs_SOURCES = tests/lib/test_privs.c
+tests_lib_test_ringbuf_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_ringbuf_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_ringbuf_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_ringbuf_SOURCES = tests/lib/test_ringbuf.c
+tests_lib_test_segv_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_segv_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_segv_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_segv_SOURCES = tests/lib/test_segv.c
+tests_lib_test_sig_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_sig_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_sig_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_sig_SOURCES = tests/lib/test_sig.c
+tests_lib_test_srcdest_table_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_srcdest_table_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_srcdest_table_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_srcdest_table_SOURCES = tests/lib/test_srcdest_table.c tests/helpers/c/prng.c
+tests_lib_test_stream_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_stream_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_stream_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_stream_SOURCES = tests/lib/test_stream.c
+tests_lib_test_table_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_table_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_table_LDADD = $(ALL_TESTS_LDADD) -lm
+tests_lib_test_table_SOURCES = tests/lib/test_table.c
+tests_lib_test_timer_correctness_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_timer_correctness_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_timer_correctness_SOURCES = tests/lib/test_timer_correctness.c tests/helpers/c/prng.c
+tests_lib_test_timer_performance_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_timer_performance_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_timer_performance_SOURCES = tests/lib/test_timer_performance.c tests/helpers/c/prng.c
+tests_lib_test_ttable_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_ttable_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_ttable_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_ttable_SOURCES = tests/lib/test_ttable.c
+tests_lib_test_zlog_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_zlog_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_zlog_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_zlog_SOURCES = tests/lib/test_zlog.c
+tests_lib_test_zmq_CFLAGS = $(TESTS_CFLAGS) $(ZEROMQ_CFLAGS)
+tests_lib_test_zmq_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_zmq_LDADD = lib/libfrrzmq.la $(ALL_TESTS_LDADD) $(ZEROMQ_LIBS)
+tests_lib_test_zmq_SOURCES = tests/lib/test_zmq.c
+
+tests_ospf6d_test_lsdb_CFLAGS = $(TESTS_CFLAGS)
+tests_ospf6d_test_lsdb_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD)
+tests_ospf6d_test_lsdb_SOURCES = tests/ospf6d/test_lsdb.c tests/lib/cli/common_cli.c
+
+EXTRA_DIST += \
+       tests/runtests.py \
+       tests/bgpd/test_aspath.py \
+       tests/bgpd/test_capability.py \
+       tests/bgpd/test_ecommunity.py \
+       tests/bgpd/test_mp_attr.py \
+       tests/bgpd/test_mpath.py \
+       tests/bgpd/test_peer_attr.py \
+       tests/helpers/python/frrsix.py \
+       tests/helpers/python/frrtest.py \
+       tests/isisd/test_fuzz_isis_tlv.py \
+       tests/isisd/test_fuzz_isis_tlv_tests.h.gz \
+       tests/isisd/test_isis_vertex_queue.py \
+       tests/lib/cli/test_commands.in \
+       tests/lib/cli/test_commands.py \
+       tests/lib/cli/test_commands.refout \
+       tests/lib/cli/test_cli.in \
+       tests/lib/cli/test_cli.py \
+       tests/lib/cli/test_cli.refout \
+       tests/lib/test_nexthop_iter.py \
+       tests/lib/test_ringbuf.py \
+       tests/lib/test_srcdest_table.py \
+       tests/lib/test_stream.py \
+       tests/lib/test_stream.refout \
+       tests/lib/test_table.py \
+       tests/lib/test_timer_correctness.py \
+       tests/lib/test_ttable.py \
+       tests/lib/test_ttable.refout \
+       tests/lib/test_zlog.py \
+       tests/lib/test_graph.py \
+       tests/lib/test_graph.refout \
+       tests/ospf6d/test_lsdb.py \
+       tests/ospf6d/test_lsdb.in \
+       tests/ospf6d/test_lsdb.refout \
+       # end
+
+.PHONY: tests/tests.xml
+tests/tests.xml: $(check_PROGRAMS)
+       ( cd tests; $(PYTHON) ../$(srcdir)/tests/runtests.py --junitxml=tests.xml -v ../$(srcdir)/tests; )
+check: tests/tests.xml
index c751c0b12d03bf04d4260c77352279dc084c0338..652d7618a8665809411983ad4bbe438200550833 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "lib/stream.h"
 #include "lib/zclient.h"
 
index 7bf3be9dbf6f85a59246d3ec3aeffa308d42049d..d400dfe8fa573f5d2837f1e635c1b3cd16de4b5d 100644 (file)
@@ -1,10 +1,2 @@
-!Makefile
-.arch-inventory
-.arch-ids
-
-*~
-*.loT
-.libs
-*.o
 /permutations
 /ssd
index 4c6968ac2765bede04b79465ea70c8d277bfd559..bbb358fc6c5b4176415daf5eac0fdfbe84c3226c 100644 (file)
@@ -11,3 +11,4 @@
 194  sharp
 195  pbr
 196  static
+197  openfabric
index 0b170d33fd62f386728a177aea0946741113abb7..9c8a8e90433f0bed598553ea5b20dc5d97046d61 100755 (executable)
--- a/tools/frr
+++ b/tools/frr
@@ -587,6 +587,7 @@ case "$1" in
           ip route flush proto 194
           ip route flush proto 195
          ip route flush proto 196
+         ip route flush proto 197
        else
          [ -n "$dmn" ] && eval "${dmn/-/_}=0"
          start_watchfrr
index 80441753e7a2b907e0da0f3cf522c0be87be05d3..c5109dc3e8823b626d82f3d676bfc38d3a0ae14d 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "command.h"
 #include "graph.h"
 #include "vector.h"
index de58e0a20e2b75756bc168828a9563872ad033da..cc0315c1307de1c0166af7821c752bd56388f8eb 100644 (file)
  *   the whole automake/config.h dance.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #ifdef HAVE_LXC
 #define _GNU_SOURCE
 #include <sched.h>
 #endif /* HAVE_LXC */
 
 #include <stddef.h>
+#undef VERSION
 #define VERSION "1.9.18"
 
 #define MIN_POLL_INTERVAL 20000 /*us*/
@@ -602,7 +607,7 @@ static int pid_is_exec(pid_t pid, const struct stat *esb)
        struct stat sb;
        char buf[32];
 
-       sprintf(buf, "/proc/%d/exe", pid);
+       sprintf(buf, "/proc/%ld/exe", (long)pid);
        if (stat(buf, &sb) != 0)
                return 0;
        return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
@@ -614,7 +619,7 @@ static int pid_is_user(pid_t pid, uid_t uid)
        struct stat sb;
        char buf[32];
 
-       sprintf(buf, "/proc/%d", pid);
+       sprintf(buf, "/proc/%ld", (long)pid);
        if (stat(buf, &sb) != 0)
                return 0;
        return (sb.st_uid == uid);
@@ -627,7 +632,7 @@ static int pid_is_cmd(pid_t pid, const char *name)
        FILE *f;
        int c;
 
-       sprintf(buf, "/proc/%d/stat", pid);
+       sprintf(buf, "/proc/%ld/stat", (long)pid);
        f = fopen(buf, "r");
        if (!f)
                return 0;
@@ -659,12 +664,12 @@ static void check(pid_t pid)
 static void do_pidfile(const char *name)
 {
        FILE *f;
-       pid_t pid;
+       long pid;
 
        f = fopen(name, "r");
        if (f) {
-               if (fscanf(f, "%d", &pid) == 1)
-                       check(pid);
+               if (fscanf(f, "%ld", &pid) == 1)
+                       check((pid_t)pid);
                fclose(f);
        } else if (errno != ENOENT)
                fatal("open pidfile %s: %s", name, strerror(errno));
@@ -677,7 +682,7 @@ static void do_procinit(void)
        DIR *procdir;
        struct dirent *entry;
        int foundany;
-       pid_t pid;
+       long pid;
 
        procdir = opendir("/proc");
        if (!procdir)
@@ -685,10 +690,10 @@ static void do_procinit(void)
 
        foundany = 0;
        while ((entry = readdir(procdir)) != NULL) {
-               if (sscanf(entry->d_name, "%d", &pid) != 1)
+               if (sscanf(entry->d_name, "%ld", &pid) != 1)
                        continue;
                foundany++;
-               check(pid);
+               check((pid_t)pid);
        }
        closedir(procdir);
        if (!foundany)
@@ -723,21 +728,21 @@ static void do_stop(int signal_nr, int quietmode, int *n_killed,
 
        for (p = found; p; p = p->next) {
                if (testmode)
-                       printf("Would send signal %d to %d.\n", signal_nr,
-                              p->pid);
+                       printf("Would send signal %d to %ld.\n", signal_nr,
+                              (long)p->pid);
                else if (kill(p->pid, signal_nr) == 0) {
                        push(&killed, p->pid);
                        (*n_killed)++;
                } else {
-                       printf("%s: warning: failed to kill %d: %s\n", progname,
-                              p->pid, strerror(errno));
+                       printf("%s: warning: failed to kill %ld: %s\n",
+                              progname, (long)p->pid, strerror(errno));
                        (*n_notkilled)++;
                }
        }
        if (quietmode < 0 && killed) {
                printf("Stopped %s (pid", what_stop);
                for (p = killed; p; p = p->next)
-                       printf(" %d", p->pid);
+                       printf(" %ld", (long)p->pid);
                putchar(')');
                if (retry_nr > 0)
                        printf(", retry #%d", retry_nr);
@@ -1050,7 +1055,7 @@ int main(int argc, char **argv)
                if (pidf == NULL)
                        fatal("Unable to open pidfile `%s' for writing: %s",
                              pidfile, strerror(errno));
-               fprintf(pidf, "%d\n", pidt);
+               fprintf(pidf, "%ld\n", (long)pidt);
                fclose(pidf);
        }
        set_namespaces();
index 5856eac25352641ae5e513b7fe35c10b4654e47f..c1a39b8a12a41a08e65eae250cc9f6be9392da2b 100644 (file)
@@ -1,16 +1,3 @@
-Makefile
-Makefile.in
-*.o
 vtysh
-tags
-TAGS
-.deps
 vtysh_cmd.c
-.nfs*
 extract.pl
-.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
-
diff --git a/vtysh/Makefile b/vtysh/Makefile
new file mode 100644 (file)
index 0000000..07e093b
--- /dev/null
@@ -0,0 +1,10 @@
+all: ALWAYS
+       @$(MAKE) -s -C .. vtysh/vtysh
+%: ALWAYS
+       @$(MAKE) -s -C .. vtysh/$@
+
+Makefile:
+       #nothing
+ALWAYS:
+.PHONY: ALWAYS makefiles
+.SUFFIXES:
diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am
deleted file mode 100644 (file)
index 936640c..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-## Process this file with Automake to create Makefile.in
-
-include ../common.am
-
-if ENABLE_BGP_VNC
-BGP_VNC_RFP_SRCDIR   = @top_srcdir@/@LIBRFP@
-BGP_VNC_RFP_INCDIR   = -I$(BGP_VNC_RFP_SRCDIR)
-BGP_VNC_RFP_SRC      = $(BGP_VNC_RFP_SRCDIR)/*.c
-BGP_VNC_RFAPI_SRCDIR = @top_srcdir@/bgpd/rfapi
-BGP_VNC_RFAPI_INCDIR = -I$(BGP_VNC_RFAPI_SRCDIR) -I$(top_srcdir)/bgpd
-BGP_VNC_RFAPI_SRC    = $(BGP_VNC_RFAPI_SRCDIR)/*.c
-else
-BGP_VNC_RFP_INCDIR   =
-BGP_VNC_RFP_SRCDIR   =
-BGP_VNC_RFP_SRC      =
-BGP_VNC_RFAPI_INCDIR =
-BGP_VNC_RFAPI_SRCDIR =
-BGP_VNC_RFAPI_SRC    =
-endif
-AM_CPPFLAGS += -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib \
-       $(BGP_VNC_RFAPI_INCDIR) $(BGP_VNC_RFP_INCDIR)
-DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
-
-LIBS = @LIBS@ @CURSES@ @LIBPAM@
-
-bin_PROGRAMS = vtysh
-
-vtysh_SOURCES = vtysh_main.c vtysh.c vtysh_user.c vtysh_config.c
-nodist_vtysh_SOURCES = vtysh_cmd.c
-CLEANFILES = vtysh_cmd.c
-noinst_HEADERS = vtysh.h vtysh_user.h
-vtysh_LDADD = ../lib/libfrr.la @LIBCAP@ @LIBREADLINE@
-
-examplesdir = $(exampledir)
-dist_examples_DATA = vtysh.conf.sample
-
-EXTRA_DIST = extract.pl
-
-vtysh_scan =
-
-if PIMD
-vtysh_scan += $(top_srcdir)/pimd/pim_cmd.c
-endif
-
-if BGPD
-vtysh_scan += $(top_srcdir)/bgpd/bgp_bfd.c
-vtysh_scan += $(top_srcdir)/bgpd/bgp_debug.c
-vtysh_scan += $(top_srcdir)/bgpd/bgp_dump.c
-vtysh_scan += $(top_srcdir)/bgpd/bgp_evpn_vty.c
-vtysh_scan += $(top_srcdir)/bgpd/bgp_filter.c
-vtysh_scan += $(top_srcdir)/bgpd/bgp_mplsvpn.c
-vtysh_scan += $(top_srcdir)/bgpd/bgp_nexthop.c
-vtysh_scan += $(top_srcdir)/bgpd/bgp_route.c
-vtysh_scan += $(top_srcdir)/bgpd/bgp_routemap.c
-vtysh_scan += $(top_srcdir)/bgpd/bgp_vty.c
-vtysh_scan += $(top_srcdir)/bgpd/bgp_flowspec_vty.c
-endif
-
-if RPKI
-vtysh_scan += $(top_srcdir)/bgpd/bgp_rpki.c
-endif
-
-if ISISD
-vtysh_scan += $(top_srcdir)/isisd/isis_redist.c
-vtysh_scan += $(top_srcdir)/isisd/isis_spf.c
-vtysh_scan += $(top_srcdir)/isisd/isis_te.c
-vtysh_scan += $(top_srcdir)/isisd/isis_vty.c
-vtysh_scan += $(top_srcdir)/isisd/isisd.c
-endif
-
-if OSPFD
-vtysh_scan += $(top_srcdir)/ospfd/ospf_bfd.c
-vtysh_scan += $(top_srcdir)/ospfd/ospf_dump.c
-vtysh_scan += $(top_srcdir)/ospfd/ospf_opaque.c
-vtysh_scan += $(top_srcdir)/ospfd/ospf_ri.c
-vtysh_scan += $(top_srcdir)/ospfd/ospf_routemap.c
-vtysh_scan += $(top_srcdir)/ospfd/ospf_te.c
-vtysh_scan += $(top_srcdir)/ospfd/ospf_sr.c
-vtysh_scan += $(top_srcdir)/ospfd/ospf_vty.c
-endif
-
-if OSPF6D
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_abr.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_asbr.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_area.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_bfd.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_flood.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_interface.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_intra.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_lsa.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_message.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_neighbor.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_route.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_spf.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_top.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6_zebra.c
-vtysh_scan += $(top_srcdir)/ospf6d/ospf6d.c
-endif
-
-if RIPD
-vtysh_scan += $(top_srcdir)/ripd/rip_debug.c
-vtysh_scan += $(top_srcdir)/ripd/rip_interface.c
-vtysh_scan += $(top_srcdir)/ripd/rip_offset.c
-vtysh_scan += $(top_srcdir)/ripd/rip_zebra.c
-vtysh_scan += $(top_srcdir)/ripd/ripd.c
-endif
-
-if RIPNGD
-vtysh_scan += $(top_srcdir)/ripngd/ripng_debug.c
-vtysh_scan += $(top_srcdir)/ripngd/ripng_interface.c
-vtysh_scan += $(top_srcdir)/ripngd/ripng_offset.c
-vtysh_scan += $(top_srcdir)/ripngd/ripng_zebra.c
-vtysh_scan += $(top_srcdir)/ripngd/ripngd.c
-endif
-
-if LDPD
-vtysh_scan += $(top_srcdir)/ldpd/ldp_vty_cmds.c
-endif
-
-if NHRPD
-vtysh_scan += $(top_srcdir)/nhrpd/nhrp_vty.c
-endif
-
-if EIGRPD
-vtysh_scan += $(top_srcdir)/eigrpd/eigrp_dump.c
-#vtysh_scan += $(top_srcdir)/eigrpd/eigrp_routemap.c
-vtysh_scan += $(top_srcdir)/eigrpd/eigrp_vty.c
-endif
-
-if BABELD
-vtysh_scan += $(top_srcdir)/babeld/babel_interface.c
-vtysh_scan += $(top_srcdir)/babeld/babel_zebra.c
-vtysh_scan += $(top_srcdir)/babeld/babeld.c
-endif
-
-if SHARPD
-vtysh_scan += $(top_srcdir)/sharpd/sharp_vty.c
-endif
-
-if SNMP
-vtysh_scan += $(top_srcdir)/lib/agentx.c
-endif
-
-if PBRD
-vtysh_scan += $(top_srcdir)/pbrd/pbr_vty.c
-vtysh_scan += $(top_srcdir)/pbrd/pbr_debug.c
-endif
-
-if STATICD
-vtysh_scan += $(top_srcdir)/staticd/static_vty.c
-endif
-
-if BFDD
-vtysh_scan += $(top_srcdir)/bfdd/bfdd_vty.c
-endif
-
-vtysh_cmd_FILES = $(vtysh_scan) \
-                 $(top_srcdir)/lib/keychain.c $(top_srcdir)/lib/routemap.c \
-                 $(top_srcdir)/lib/filter.c $(top_srcdir)/lib/plist.c \
-                 $(top_srcdir)/lib/distribute.c $(top_srcdir)/lib/if_rmap.c \
-                 $(top_srcdir)/lib/vrf.c $(top_srcdir)/lib/if.c \
-                 $(top_srcdir)/lib/vty.c $(top_srcdir)/zebra/debug.c \
-                 $(top_srcdir)/lib/logicalrouter.c \
-                 $(top_srcdir)/lib/nexthop_group.c \
-                 $(top_srcdir)/zebra/interface.c \
-                 $(top_srcdir)/zebra/irdp_interface.c \
-                 $(top_srcdir)/zebra/rtadv.c $(top_srcdir)/zebra/zebra_vty.c \
-                 $(top_srcdir)/zebra/zserv.c $(top_srcdir)/zebra/router-id.c \
-                 $(top_srcdir)/zebra/zebra_routemap.c \
-                 $(top_srcdir)/zebra/zebra_fpm.c \
-                 $(top_srcdir)/zebra/zebra_ptm.c \
-                 $(top_srcdir)/zebra/zebra_mpls_vty.c \
-                 $(top_srcdir)/zebra/zebra_pw.c \
-                 $(top_srcdir)/watchfrr/watchfrr_vty.c \
-                 $(BGP_VNC_RFAPI_SRC) $(BGP_VNC_RFP_SRC)
-
-vtysh_cmd.c: $(vtysh_cmd_FILES) extract.pl
-       ./extract.pl $(vtysh_cmd_FILES) > vtysh_cmd.c
index 92b5686a945a1a26f2ca6a0207b5142784647aed..0f68e58d62ea5cb9640b4d07714fcaec4d083536 100755 (executable)
@@ -29,16 +29,18 @@ print <<EOF;
 #include "command.h"
 #include "linklist.h"
 
-#include "vtysh.h"
+#include "vtysh/vtysh.h"
 
 EOF
 
 my $cli_stomp = 0;
 
-foreach (@ARGV) {
-    $file = $_;
+sub scan_file {
+    my ( $file, $fabricd) = @_;
+
+    $cppadd = $fabricd ? "-DFABRICD=1" : "";
 
-    open (FH, "@CPP@ -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -I@top_builddir@ -I@srcdir@/ -I@srcdir@/.. -I@top_srcdir@/lib -I@top_builddir@/lib -I@top_srcdir@/bgpd -I@top_srcdir@/@LIBRFP@ -I@top_srcdir@/bgpd/rfapi @CPPFLAGS@ $file |");
+    open (FH, "@CPP@ -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -Ivtysh/@top_builddir@ -Ivtysh/@top_srcdir@ -Ivtysh/@top_srcdir@/lib -Ivtysh/@top_builddir@/lib -Ivtysh/@top_srcdir@/bgpd -Ivtysh/@top_srcdir@/bgpd/rfapi @CPPFLAGS@ $cppadd $file |");
     local $/; undef $/;
     $line = <FH>;
     close (FH);
@@ -77,6 +79,10 @@ foreach (@ARGV) {
         $cmd =~ s/^\s+//g;
         $cmd =~ s/\s+$//g;
 
+        if ($fabricd) {
+            $cmd = "fabricd_" . $cmd;
+        }
+
         # $protocol is VTYSH_PROTO format for redirection of user input
         if ($file =~ /lib\/keychain\.c$/) {
             $protocol = "VTYSH_RIPD";
@@ -107,9 +113,9 @@ foreach (@ARGV) {
        }
         elsif ($file =~ /lib\/plist\.c$/) {
             if ($defun_array[1] =~ m/ipv6/) {
-                $protocol = "VTYSH_RIPNGD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_BABELD|VTYSH_ISISD";
+                $protocol = "VTYSH_RIPNGD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_BABELD|VTYSH_ISISD|VTYSH_FABRICD";
             } else {
-                $protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_ISISD";
+                $protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_ISISD|VTYSH_FABRICD";
             }
         }
         elsif ($file =~ /lib\/distribute\.c$/) {
@@ -132,6 +138,9 @@ foreach (@ARGV) {
         elsif ($file =~ /librfp\/.*\.c$/ || $file =~ /rfapi\/.*\.c$/) {
            $protocol = "VTYSH_BGPD";
         }
+        elsif ($fabricd) {
+           $protocol = "VTYSH_FABRICD";
+        }
         else {
            ($protocol) = ($file =~ /^.*\/([a-z0-9]+)\/[a-zA-Z0-9_\-]+\.c$/);
            $protocol = "VTYSH_" . uc $protocol;
@@ -170,6 +179,10 @@ foreach (@ARGV) {
         $ecmd =~ s/^\s+//g;
         $ecmd =~ s/\s+$//g;
 
+        if ($fabricd) {
+            $ecmd = "fabricd_" . $ecmd;
+        }
+
         # Register $ecmd
         if (defined ($cmd2str{$ecmd})) {
             my ($key);
@@ -187,6 +200,24 @@ foreach (@ARGV) {
     }
 }
 
+foreach (@ARGV) {
+    if (/\/isisd\//) {
+        # We scan all the IS-IS files twice, once for isisd,
+        # once for fabricd. Exceptions are made for the files
+        # that are not shared between the two.
+        if (/isis_vty_isisd.c/) {
+            scan_file($_, 0);
+        } elsif (/isis_vty_fabricd.c/) {
+            scan_file($_, 1);
+        } else {
+            scan_file($_, 0);
+            scan_file($_, 1);
+        }
+    } else {
+        scan_file($_, 0);
+    }
+}
+
 # When we have cli commands that map to the same function name, we
 # can introduce subtle bugs due to code not being called when
 # we think it is.
diff --git a/vtysh/subdir.am b/vtysh/subdir.am
new file mode 100644 (file)
index 0000000..932429a
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# vtysh
+#
+
+if VTYSH
+bin_PROGRAMS += vtysh/vtysh
+dist_examples_DATA += vtysh/vtysh.conf.sample
+man1 += $(MANBUILD)/vtysh.1
+endif
+
+vtysh_vtysh_SOURCES = \
+       vtysh/vtysh_main.c \
+       vtysh/vtysh.c \
+       vtysh/vtysh_user.c \
+       vtysh/vtysh_config.c \
+       # end
+nodist_vtysh_vtysh_SOURCES = \
+       vtysh/vtysh_cmd.c \
+       # end
+CLEANFILES += vtysh/vtysh_cmd.c
+
+noinst_HEADERS += \
+       vtysh/vtysh.h \
+       vtysh/vtysh_user.h \
+       # end
+
+vtysh_vtysh_LDADD = lib/libfrr.la @LIBCAP@ @LIBREADLINE@ @LIBS@ @CURSES@ @LIBPAM@
+
+EXTRA_DIST += vtysh/extract.pl
+
+AM_V_EXTRACT = $(am__v_EXTRACT_$(V))
+am__v_EXTRACT_ = $(am__v_EXTRACT_$(AM_DEFAULT_VERBOSITY))
+am__v_EXTRACT_0 = @echo "  EXTRACT " $@;
+am__v_EXTRACT_1 =
+
+vtysh/vtysh_cmd.c: $(vtysh_scan) vtysh/extract.pl
+       $(AM_V_EXTRACT) vtysh/extract.pl $(vtysh_scan) > vtysh/vtysh_cmd.c
index c249115fd372d8468cb2e5f887c98f6ddc70912b..6a92b9081377f32f5ad3bff15e39fb91abb722af 100644 (file)
@@ -132,6 +132,7 @@ struct vtysh_client vtysh_client[] = {
        {.fd = -1, .name = "eigrpd", .flag = VTYSH_EIGRPD, .next = NULL},
        {.fd = -1, .name = "babeld", .flag = VTYSH_BABELD, .next = NULL},
        {.fd = -1, .name = "sharpd", .flag = VTYSH_SHARPD, .next = NULL},
+       {.fd = -1, .name = "fabricd", .flag = VTYSH_FABRICD, .next = NULL},
        {.fd = -1, .name = "watchfrr", .flag = VTYSH_WATCHFRR, .next = NULL},
        {.fd = -1, .name = "pbrd", .flag = VTYSH_PBRD, .next = NULL},
        {.fd = -1, .name = "staticd", .flag = VTYSH_STATICD, .next = NULL},
@@ -1112,7 +1113,7 @@ static char *command_generator(const char *text, int state)
        return NULL;
 }
 
-static char **new_completion(char *text, int start, int end)
+static char **new_completion(const char *text, int start, int end)
 {
        char **matches;
 
@@ -1141,6 +1142,10 @@ static struct cmd_node isis_node = {
        ISIS_NODE, "%s(config-router)# ",
 };
 
+static struct cmd_node openfabric_node = {
+       OPENFABRIC_NODE, "%s(config-router)# ",
+};
+
 static struct cmd_node interface_node = {
        INTERFACE_NODE, "%s(config-if)# ",
 };
@@ -1252,9 +1257,7 @@ struct cmd_node link_params_node = {
        LINK_PARAMS_NODE, "%s(config-link-params)# ",
 };
 
-#if defined(HAVE_RPKI)
 static struct cmd_node rpki_node = {RPKI_NODE, "%s(config-rpki)# ", 1};
-#endif
 
 #if HAVE_BFDD > 0
 static struct cmd_node bfd_node = {
@@ -1424,7 +1427,6 @@ DEFUNSH(VTYSH_BGPD, address_family_ipv6_labeled_unicast,
        return CMD_SUCCESS;
 }
 
-#if defined(HAVE_RPKI)
 DEFUNSH(VTYSH_BGPD,
        rpki,
        rpki_cmd,
@@ -1435,8 +1437,6 @@ DEFUNSH(VTYSH_BGPD,
        return CMD_SUCCESS;
 }
 
-#endif
-
 DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
        "address-family <l2vpn evpn>",
        "Enter Address Family command mode\n"
@@ -1653,6 +1653,15 @@ DEFUNSH(VTYSH_ISISD, router_isis, router_isis_cmd, "router isis WORD",
        return CMD_SUCCESS;
 }
 
+DEFUNSH(VTYSH_FABRICD, router_openfabric, router_openfabric_cmd, "router openfabric WORD",
+       ROUTER_STR
+       "OpenFabric routing protocol\n"
+       "ISO Routing area tag\n")
+{
+       vty->node = OPENFABRIC_NODE;
+       return CMD_SUCCESS;
+}
+
 DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd,
        "route-map WORD <deny|permit> (1-65535)",
        "Create route-map or enter route-map command mode\n"
@@ -1767,6 +1776,7 @@ static int vtysh_exit(struct vty *vty)
        case LDP_NODE:
        case LDP_L2VPN_NODE:
        case ISIS_NODE:
+       case OPENFABRIC_NODE:
        case RMAP_NODE:
        case PBRMAP_NODE:
        case VTY_NODE:
@@ -1869,7 +1879,6 @@ DEFUNSH(VTYSH_BGPD, exit_vnc_config, exit_vnc_config_cmd, "exit-vnc",
 
 }
 
-#if defined(HAVE_RPKI)
 DEFUNSH(VTYSH_BGPD, rpki_exit, rpki_exit_cmd, "exit",
        "Exit current mode and down to previous mode\n")
 {
@@ -1882,7 +1891,6 @@ DEFUNSH(VTYSH_BGPD, rpki_quit, rpki_quit_cmd, "quit",
 {
        return rpki_exit(self, vty, argc, argv);
 }
-#endif /* HAVE_RPKI */
 
 DEFUNSH(VTYSH_PIMD|VTYSH_ZEBRA, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf",
        "Exit from VRF configuration mode\n")
@@ -2042,6 +2050,18 @@ ALIAS(vtysh_exit_bfdd, vtysh_quit_bfdd_cmd, "quit",
       "Exit current mode and down to previous mode\n")
 #endif
 
+DEFUNSH(VTYSH_FABRICD, vtysh_exit_fabricd, vtysh_exit_fabricd_cmd, "exit",
+       "Exit current mode and down to previous mode\n")
+{
+       return vtysh_exit(vty);
+}
+
+DEFUNSH(VTYSH_FABRICD, vtysh_quit_fabricd, vtysh_quit_fabricd_cmd, "quit",
+       "Exit current mode and down to previous mode\n")
+{
+       return vtysh_exit_fabricd(self, vty, argc, argv);
+}
+
 DEFUNSH(VTYSH_ALL, vtysh_exit_line_vty, vtysh_exit_line_vty_cmd, "exit",
        "Exit current mode and down to previous mode\n")
 {
@@ -2245,7 +2265,7 @@ DEFUN (vtysh_show_work_queues,
 
 DEFUN (vtysh_show_work_queues_daemon,
        vtysh_show_work_queues_daemon_cmd,
-       "show work-queues <zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|pbrd>",
+       "show work-queues <zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|pbrd|fabricd>",
        SHOW_STR
        "Work Queue information\n"
        "For the zebra daemon\n"
@@ -2255,7 +2275,8 @@ DEFUN (vtysh_show_work_queues_daemon,
        "For the ospfv6 daemon\n"
        "For the bgp daemon\n"
        "For the isis daemon\n"
-       "For the pbr daemon\n")
+       "For the pbr daemon\n"
+       "For the fabricd daemon\n")
 {
        int idx_protocol = 2;
        unsigned int i;
@@ -2593,7 +2614,7 @@ DEFUNSH(VTYSH_ALL, no_vtysh_config_enable_password,
 
 DEFUN (vtysh_write_terminal,
        vtysh_write_terminal_cmd,
-       "write terminal [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|pimd>]",
+       "write terminal [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|fabricd|pimd>]",
        "Write running configuration to memory, network, or terminal\n"
        "Write to terminal\n"
        "For the zebra daemon\n"
@@ -2604,6 +2625,7 @@ DEFUN (vtysh_write_terminal,
        "For the ldpd daemon\n"
        "For the bgp daemon\n"
        "For the isis daemon\n"
+       "For the fabricd daemon\n"
        "For the pim daemon\n")
 {
        unsigned int i;
@@ -2630,7 +2652,7 @@ DEFUN (vtysh_write_terminal,
 
 DEFUN (vtysh_show_running_config,
        vtysh_show_running_config_cmd,
-       "show running-config [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|pimd>]",
+       "show running-config [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|fabricd|pimd>]",
        SHOW_STR
        "Current operating configuration\n"
        "For the zebra daemon\n"
@@ -2641,6 +2663,7 @@ DEFUN (vtysh_show_running_config,
        "For the ldp daemon\n"
        "For the bgp daemon\n"
        "For the isis daemon\n"
+       "For the fabricd daemon\n"
        "For the pim daemon\n")
 {
        return vtysh_write_terminal(self, vty, argc, argv);
@@ -3386,8 +3409,7 @@ void vtysh_readline_init(void)
        rl_initialize();
        rl_bind_key('?', (rl_command_func_t *)vtysh_rl_describe);
        rl_completion_entry_function = vtysh_completion_entry_function;
-       rl_attempted_completion_function =
-               (rl_completion_func_t *)new_completion;
+       rl_attempted_completion_function = new_completion;
 }
 
 char *vtysh_prompt(void)
@@ -3494,10 +3516,9 @@ void vtysh_init_vty(void)
        install_node(&keychain_node, NULL);
        install_node(&keychain_key_node, NULL);
        install_node(&isis_node, NULL);
+       install_node(&openfabric_node, NULL);
        install_node(&vty_node, NULL);
-#if defined(HAVE_RPKI)
        install_node(&rpki_node, NULL);
-#endif
 #if HAVE_BFDD > 0
        install_node(&bfd_node, NULL);
        install_node(&bfd_peer_node, NULL);
@@ -3588,6 +3609,8 @@ void vtysh_init_vty(void)
 #endif
        install_element(ISIS_NODE, &vtysh_exit_isisd_cmd);
        install_element(ISIS_NODE, &vtysh_quit_isisd_cmd);
+       install_element(OPENFABRIC_NODE, &vtysh_exit_fabricd_cmd);
+       install_element(OPENFABRIC_NODE, &vtysh_quit_fabricd_cmd);
        install_element(KEYCHAIN_NODE, &vtysh_exit_ripd_cmd);
        install_element(KEYCHAIN_NODE, &vtysh_quit_ripd_cmd);
        install_element(KEYCHAIN_KEY_NODE, &vtysh_exit_ripd_cmd);
@@ -3648,6 +3671,7 @@ void vtysh_init_vty(void)
        install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd);
        install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd);
        install_element(ISIS_NODE, &vtysh_end_all_cmd);
+       install_element(OPENFABRIC_NODE, &vtysh_end_all_cmd);
        install_element(KEYCHAIN_NODE, &vtysh_end_all_cmd);
        install_element(KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd);
        install_element(RMAP_NODE, &vtysh_end_all_cmd);
@@ -3697,6 +3721,7 @@ void vtysh_init_vty(void)
        install_element(LDP_L2VPN_NODE, &ldp_member_pseudowire_ifname_cmd);
 #endif
        install_element(CONFIG_NODE, &router_isis_cmd);
+       install_element(CONFIG_NODE, &router_openfabric_cmd);
        install_element(CONFIG_NODE, &router_bgp_cmd);
        install_element(BGP_NODE, &address_family_vpnv4_cmd);
        install_element(BGP_NODE, &address_family_vpnv6_cmd);
@@ -3732,12 +3757,10 @@ void vtysh_init_vty(void)
        install_element(BGP_FLOWSPECV4_NODE, &exit_address_family_cmd);
        install_element(BGP_FLOWSPECV6_NODE, &exit_address_family_cmd);
 
-#if defined(HAVE_RPKI)
        install_element(CONFIG_NODE, &rpki_cmd);
        install_element(RPKI_NODE, &rpki_exit_cmd);
        install_element(RPKI_NODE, &rpki_quit_cmd);
        install_element(RPKI_NODE, &vtysh_end_all_cmd);
-#endif
 
        /* EVPN commands */
        install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
index 5bff01a5067826c43d3dae281bcb3195b417e093..ee980d5128d30dfbc1c35ce3aaa3715e73ce66dc 100644 (file)
@@ -41,6 +41,7 @@ DECLARE_MGROUP(MVTYSH)
 #define VTYSH_PBRD      0x04000
 #define VTYSH_STATICD   0x08000
 #define VTYSH_BFDD      0x10000
+#define VTYSH_FABRICD   0x20000
 
 #define VTYSH_WAS_ACTIVE (-2)
 
@@ -49,9 +50,9 @@ DECLARE_MGROUP(MVTYSH)
 /* watchfrr is not in ALL since library CLI functions should not be
  * run on it (logging & co. should stay in a fixed/frozen config, and
  * things like prefix lists are not even initialised) */
-#define VTYSH_ALL        VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_SHARPD|VTYSH_PBRD|VTYSH_STATICD|VTYSH_BFDD
-#define VTYSH_RMAP       VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_SHARPD
-#define VTYSH_INTERFACE          VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_PBRD
+#define VTYSH_ALL        VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_SHARPD|VTYSH_PBRD|VTYSH_STATICD|VTYSH_BFDD|VTYSH_FABRICD
+#define VTYSH_RMAP       VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_SHARPD|VTYSH_FABRICD
+#define VTYSH_INTERFACE          VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_PBRD|VTYSH_FABRICD
 #define VTYSH_NS          VTYSH_ZEBRA
 #define VTYSH_VRF        VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_STATICD
 
index 42f08342c0b299017a9fb396e08706c6adf08586..9f6e20f2be65090e5f984d89849100f049b6df0a 100644 (file)
@@ -245,6 +245,9 @@ void vtysh_config_parse_line(void *arg, const char *line)
                else if (strncmp(line, "router isis", strlen("router isis"))
                         == 0)
                        config = config_get(ISIS_NODE, line);
+               else if (strncmp(line, "router openfabric", strlen("router openfabric"))
+                        == 0)
+                       config = config_get(OPENFABRIC_NODE, line);
                else if (strncmp(line, "route-map", strlen("route-map")) == 0)
                        config = config_get(RMAP_NODE, line);
                else if (strncmp(line, "pbr-map", strlen("pbr-map")) == 0)
index 86fa62f474a44ef13ed536208d27b0e263468745..7e979f2c8f39a5dd9fd0fdec8b7f87d5b7344f73 100644 (file)
 #include <readline/readline.h>
 #include <readline/history.h>
 
+/*
+ * The append_history function only appears in newer versions
+ * of the readline library it appears like.  Since we don't
+ * need this just silently ignore the code on these
+ * ancient platforms.
+ */
+#if !defined HAVE_APPEND_HISTORY
+#define append_history(A, B)
+#endif
+
 #include <lib/version.h>
 #include "getopt.h"
 #include "command.h"
index b8c020c04cbe153a7624c1683e74cf385866c6df..b3f5a6cd91414ec0f453af0a8ae6a6cf18fa3ed4 100644 (file)
@@ -1,16 +1 @@
-!Makefile
-Makefile.in
-*.o
 watchfrr
-tags
-TAGS
-.deps
-.nfs*
-*.lo
-*.la
-*.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
-
index 931f11ef63a5e42155b4a7a52556d0e61c17e885..f0b49c9a8482101ea6386329abf9ce756b122541 100644 (file)
@@ -4,6 +4,8 @@
 
 if WATCHFRR
 sbin_PROGRAMS += watchfrr/watchfrr
+vtysh_scan += $(top_srcdir)/watchfrr/watchfrr_vty.c
+man8 += $(MANBUILD)/watchfrr.8
 endif
 
 noinst_HEADERS += \
index 4a06756a2d56d9574a1ea99c12b05606b8bce18d..41a86e7d753aa49cd75695e8ec263b18a8407303 100644 (file)
@@ -1,15 +1,3 @@
-!Makefile
-Makefile.in
-*.o
 zebra
 zebra.conf
 client
-tags
-TAGS
-.deps
-.nfs*
-.libs
-.arch-inventory
-.arch-ids
-*~
-*.loT
index 5a58fe1751cbc54bbbb131aaf1ccc4007db85284..7ec73ea111cd9b55bbf2d8f7bc0f14d00a3ca28c 100644 (file)
@@ -39,6 +39,7 @@
 #include "zebra/interface.h"
 #include "zebra/ioctl_solaris.h"
 #include "zebra/rib.h"
+#include "zebra/rt.h"
 
 static int if_get_addr(struct interface *, struct sockaddr *, const char *);
 static void interface_info_ioctl(struct interface *);
@@ -55,7 +56,6 @@ static int interface_list_ioctl(int af)
        struct lifconf lifconf;
        struct interface *ifp;
        int n;
-       int save_errno;
        size_t needed, lastneeded = 0;
        char *buf = NULL;
 
@@ -76,13 +76,11 @@ calculate_lifc_len:
                lifn.lifn_flags = LIFC_NOXMIT;
                /* we want NOXMIT interfaces too */
                ret = ioctl(sock, SIOCGLIFNUM, &lifn);
-               save_errno = errno;
-
        }
 
        if (ret < 0) {
                zlog_warn("interface_list_ioctl: SIOCGLIFNUM failed %s",
-                         safe_strerror(save_errno));
+                         safe_strerror(errno));
                close(sock);
                return -1;
        }
index 3683596b41394b9ed3d2a331ad835fafd9a2b98a..8e2cd2e418c303e0bca3a630280363b0f3c0fab7 100644 (file)
@@ -99,7 +99,7 @@ static inline int is_selfroute(int proto)
            || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
            || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)
            || (proto == RTPROT_RIP) || (proto == RTPROT_SHARP)
-           || (proto == RTPROT_PBR)) {
+           || (proto == RTPROT_PBR) || (proto == RTPROT_OPENFABRIC)) {
                return 1;
        }
 
@@ -146,6 +146,9 @@ static inline int zebra2proto(int proto)
        case ZEBRA_ROUTE_PBR:
                proto = RTPROT_PBR;
                break;
+       case ZEBRA_ROUTE_OPENFABRIC:
+               proto = RTPROT_OPENFABRIC;
+               break;
        default:
                /*
                 * When a user adds a new protocol this will show up
@@ -203,6 +206,9 @@ static inline int proto2zebra(int proto, int family)
        case RTPROT_PBR:
                proto = ZEBRA_ROUTE_PBR;
                break;
+       case RTPROT_OPENFABRIC:
+               proto = ZEBRA_ROUTE_OPENFABRIC;
+               break;
        default:
                /*
                 * When a user adds a new protocol this will show up
index c4f21d1504ebfc57d09ab9d790d808ed95e9f45c..cefd1996a96ab782fecc8a9e5ddefe7f2015d86e 100644 (file)
@@ -54,6 +54,7 @@
 #define RTPROT_SHARP       194
 #define RTPROT_PBR         195
 #define RTPROT_ZSTATIC     196
+#define RTPROT_OPENFABRIC  197
 
 void rt_netlink_init(void);
 
index b3aeaf2f76c123e065b98c5d71daec003172acf7..8e5d7fbdbee5d5d6dfc16c669bf0d97f5377e23c 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "zebra/rib.h"
 #include "zebra/rt.h"
+#include "zebra/zebra_pbr.h"
 
 /* Thank you, Solaris, for polluting application symbol namespace. */
 #undef hook_register
index 5dc3750315b14b4ac789700120b9f65cb152f476..a87fcec41f0eda8200fd518d2fb63bc9de51a1c8 100644 (file)
@@ -5,6 +5,22 @@
 if ZEBRA
 sbin_PROGRAMS += zebra/zebra
 dist_examples_DATA += zebra/zebra.conf.sample
+vtysh_scan += \
+       $(top_srcdir)/zebra/debug.c \
+       $(top_srcdir)/zebra/interface.c \
+       $(top_srcdir)/zebra/router-id.c \
+       $(top_srcdir)/zebra/rtadv.c \
+       $(top_srcdir)/zebra/zebra_mpls_vty.c \
+       $(top_srcdir)/zebra/zebra_ptm.c \
+       $(top_srcdir)/zebra/zebra_pw.c \
+       $(top_srcdir)/zebra/zebra_routemap.c \
+       $(top_srcdir)/zebra/zebra_vty.c \
+       $(top_srcdir)/zebra/zserv.c \
+       # end
+
+# can be loaded as DSO - always include for vtysh
+vtysh_scan += $(top_srcdir)/zebra/irdp_interface.c
+vtysh_scan += $(top_srcdir)/zebra/zebra_fpm.c
 
 if IRDP
 module_LTLIBRARIES += zebra/zebra_irdp.la
@@ -16,6 +32,7 @@ if FPM
 module_LTLIBRARIES += zebra/zebra_fpm.la
 endif
 
+man8 += $(MANBUILD)/zebra.8
 ## endif ZEBRA
 endif
 
@@ -132,10 +149,11 @@ zebra_zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 zebra_zebra_snmp_la_LIBADD = lib/libfrrsnmp.la
 
 zebra_zebra_fpm_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
-zebra_zebra_fpm_la_LIBADD = $(Q_FPM_PB_CLIENT_LDOPTS)
+zebra_zebra_fpm_la_LIBADD =
 zebra_zebra_fpm_la_SOURCES = zebra/zebra_fpm.c
 zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_netlink.c
 if HAVE_PROTOBUF
+zebra_zebra_fpm_la_LIBADD += fpm/libfrrfpm_pb.la qpb/libfrr_pb.la $(PROTOBUF_C_LIBS)
 zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_protobuf.c
 if DEV_BUILD
 zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_dt.c
index ebd632270c7d004b855799e55fcd3c2776a3dcd7..be0f6a23be74224f4a83756306b5b30e784d4323 100644 (file)
@@ -129,6 +129,7 @@ static inline int add_nexthop(qpb_allocator_t *allocator, Fpm__AddRoute *msg,
        }
 
        // TODO: Use src.
+       (void)src;
 
        return 1;
 }
index ab07549ec26d13054dde6d5368ebdb2db3a02e74..2c8fa77c32d91a84c3753ea4560ed96b990c1b6d 100644 (file)
@@ -266,7 +266,8 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
          There was a crash because ifp here was coming to be NULL */
        if (ifp)
                if (connected_is_unnumbered(ifp)
-                   || CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) {
+                   || CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)
+                   || CHECK_FLAG(re->flags, ZEBRA_FLAG_ONLINK)) {
                        SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
                }
 
@@ -303,8 +304,10 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
        nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
        nexthop->gate.ipv6 = *ipv6;
        nexthop->ifindex = ifindex;
-       if (CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE))
+       if (CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)
+           || CHECK_FLAG(re->flags, ZEBRA_FLAG_ONLINK)) {
                SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
+       }
 
        route_entry_nexthop_add(re, nexthop);
 
@@ -428,8 +431,12 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
        /* Skip nexthops that have been filtered out due to route-map */
        /* The nexthops are specific to this route and so the same */
        /* nexthop for a different route may not have this flag set */
-       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED))
+       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED)) {
+               if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+                       zlog_debug("\t%s: Nexthop Filtered",
+                                  __PRETTY_FUNCTION__);
                return 0;
+       }
 
        /*
         * Check to see if we should trust the passed in information
@@ -438,13 +445,25 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
         */
        if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) {
                ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
-               if (ifp && connected_is_unnumbered(ifp)) {
+               if ((ifp && connected_is_unnumbered(ifp))
+                   || CHECK_FLAG(re->flags, ZEBRA_FLAG_ONLINK)) {
                        if (if_is_operative(ifp))
                                return 1;
-                       else
+                       else {
+                               if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+                                       zlog_debug(
+                                               "\t%s: Onlink and interface %s is not operative",
+                                               __PRETTY_FUNCTION__, ifp->name);
                                return 0;
-               } else
+                       }
+               } else {
+                       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+                               zlog_debug(
+                                       "\t%s: Interface %s is not unnumbered",
+                                       __PRETTY_FUNCTION__,
+                                       ifp ? ifp->name : "Unknown");
                        return 0;
+               }
        }
 
        /* Make lookup prefix. */
@@ -466,8 +485,12 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
        }
        /* Lookup table.  */
        table = zebra_vrf_table(afi, SAFI_UNICAST, nexthop->vrf_id);
-       if (!table)
+       if (!table) {
+               if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+                       zlog_debug("\t%s: Table not found",
+                                  __PRETTY_FUNCTION__);
                return 0;
+       }
 
        rn = route_node_match(table, (struct prefix *)&p);
        while (rn) {
@@ -480,15 +503,25 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
                 */
                if (top && rn == top)
                        if (((afi == AFI_IP) && (rn->p.prefixlen != 32))
-                           || ((afi == AFI_IP6) && (rn->p.prefixlen != 128)))
+                           || ((afi == AFI_IP6) && (rn->p.prefixlen != 128))) {
+                               if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+                                       zlog_debug(
+                                               "\t%s: Matched against ourself and prefix length is not max bit length",
+                                               __PRETTY_FUNCTION__);
                                return 0;
+                       }
 
                /* Pick up selected route. */
                /* However, do not resolve over default route unless explicitly
                 * allowed. */
                if (is_default_prefix(&rn->p)
-                   && !rnh_resolve_via_default(p.family))
+                   && !rnh_resolve_via_default(p.family)) {
+                       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+                               zlog_debug(
+                                       "\t:%s: Resolved against default route",
+                                       __PRETTY_FUNCTION__);
                        return 0;
+               }
 
                dest = rib_dest_from_rnode(rn);
                if (dest && dest->selected_fib
@@ -540,6 +573,9 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
                        }
                        if (resolved && set)
                                re->nexthop_mtu = match->mtu;
+                       if (!resolved && IS_ZEBRA_DEBUG_RIB_DETAILED)
+                               zlog_debug("\t%s: Recursion failed to find",
+                                          __PRETTY_FUNCTION__);
                        return resolved;
                } else if (re->type == ZEBRA_ROUTE_STATIC) {
                        resolved = 0;
@@ -558,6 +594,11 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
                        }
                        if (resolved && set)
                                re->nexthop_mtu = match->mtu;
+
+                       if (!resolved && IS_ZEBRA_DEBUG_RIB_DETAILED)
+                               zlog_debug(
+                                       "\t%s: Static route unable to resolve",
+                                       __PRETTY_FUNCTION__);
                        return resolved;
                } else {
                        return 0;
@@ -900,8 +941,12 @@ static unsigned nexthop_active_check(struct route_node *rn,
        default:
                break;
        }
-       if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+       if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) {
+               if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+                       zlog_debug("\t%s: Unable to find a active nexthop",
+                                  __PRETTY_FUNCTION__);
                return 0;
+       }
 
        /* XXX: What exactly do those checks do? Do we support
         * e.g. IPv4 routes with IPv6 nexthops or vice versa? */
@@ -2209,7 +2254,6 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
                       union prefixconstptr src_pp,
                       const struct route_entry *re)
 {
-       const struct prefix *p = pp.p;
        const struct prefix *src_p = src_pp.p;
        bool is_srcdst = src_p && src_p->prefixlen;
        char straddr[PREFIX_STRLEN];
@@ -2232,10 +2276,34 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
                   re->nexthop_num, re->nexthop_active_num);
 
        for (ALL_NEXTHOPS(re->ng, nexthop)) {
-               inet_ntop(p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
-               zlog_debug("%s: %s %s[%u] vrf %u with flags %s%s%s", func,
+               struct interface *ifp;
+               struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
+
+               switch (nexthop->type) {
+               case NEXTHOP_TYPE_BLACKHOLE:
+                       sprintf(straddr, "Blackhole");
+                       break;
+               case NEXTHOP_TYPE_IFINDEX:
+                       ifp = if_lookup_by_index(nexthop->ifindex,
+                                                nexthop->vrf_id);
+                       sprintf(straddr, "%s", ifp ? ifp->name : "Unknown");
+                       break;
+               case NEXTHOP_TYPE_IPV4:
+                       /* fallthrough */
+               case NEXTHOP_TYPE_IPV4_IFINDEX:
+                       inet_ntop(AF_INET, &nexthop->gate, straddr,
+                                 INET6_ADDRSTRLEN);
+                       break;
+               case NEXTHOP_TYPE_IPV6:
+               case NEXTHOP_TYPE_IPV6_IFINDEX:
+                       inet_ntop(AF_INET6, &nexthop->gate, straddr,
+                                 INET6_ADDRSTRLEN);
+                       break;
+               }
+               zlog_debug("%s: %s %s[%u] vrf %s(%u) with flags %s%s%s", func,
                           (nexthop->rparent ? "  NH" : "NH"), straddr,
-                          nexthop->ifindex, nexthop->vrf_id,
+                          nexthop->ifindex, vrf ? vrf->name : "Unknown",
+                          nexthop->vrf_id,
                           (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)
                                    ? "ACTIVE "
                                    : ""),
index 33d0bcd23aa2a5434815aa927bb95914a87f074b..eb1b07170129c495c17f0ea86f5917d4abe3dad7 100644 (file)
@@ -207,6 +207,9 @@ static int host_rb_entry_compare(const struct host_rb_entry *hle1,
                        return 1;
 
                return 0;
+       } else if (hle1->p.family == AF_INET6) {
+               return memcmp(&hle1->p.u.prefix6, &hle2->p.u.prefix6,
+                             IPV6_MAX_BYTELEN);
        } else {
                zlog_warn("%s: Unexpected family type: %d", __PRETTY_FUNCTION__,
                          hle1->p.family);