diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000000..cedca17729bf --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,43 @@ +### How to submit an issue +Please use this text as a template and replace text in the sections or remove +the entire section if it does not apply to your issue. For example in case of +a question or feature request, just a description with some example is probably +fine. Also remember to use GitHub Flavored Markdown properly, especially if +posting output or code listings. + +### Things you may try first +(put "x" in "[ ]" if you already tried following) +* [ ] Did you check if this is a duplicate issue? +* [ ] Did you test it on the latest FRRouting/frr master branch? + +**Related Issue:** +[fill here if applicable] + +### Description +[Description of the bug or feature] + +### Steps to Reproduce +1. [First Step] +2. [Second Step] +3. [and so on...] + +**Expected behavior:** +[What you expected to happen] + +**Actual behavior:** +[What actually happened] + +### Components +[bgpd, build, doc, isisd, ospfd, etc.] + +### Versions +* OS: [name] [version] +* Kernel: [Linux/BSD] [version] +* FRR: [version] + +### Attachments +[Attach if applicable. For example log-files, log-lines. etc. etc.] + +You're also welcomed to provide us with any other data you think may be useful. + +Thanks! diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000000..0a8aa03c8db0 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,12 @@ +### Summary +[fill here] + +### Related Issue +[fill here if applicable] + +### Components +[bgpd, build, doc, ripd, ospfd, eigrpd, isisd, etc. etc.] + +Always remember to follow proper coding style etc. as +described in the FRRouting Dev Guide. +http://docs.frrouting.org/projects/dev-guide/en/latest/workflow.html diff --git a/.gitignore b/.gitignore index c5fd0ced9b34..8c62f05539e4 100644 --- a/.gitignore +++ b/.gitignore @@ -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/Makefile.am b/Makefile.am index 3e268f703da3..303881b07731 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,13 +1,78 @@ ## 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@ +# these two targets are provided to easily grab autoconf/Makefile variables +# you can use either: +# eval `make VARFD=3 shvar-CFLAGS 3>&1 1>&2` +# CFLAGS="`make VARFD=3 var-CFLAGS 3>&1 1>&2`" +# where the former can be used to set several variables at once. Note the +# fd redirections -- this is to prevent garbage from make rebuilding other +# targets from causing issues. +.PHONY: shvar-% var-% +VARFD ?= 1 +shvar-%: + @echo "$*=\"$($*)\"" >&$(VARFD) +var-%: + @echo "$($*)" >&$(VARFD) + +# overwriting these vars breaks cross-compilation. let's be helpful and warn. +# +# note: "#AUTODERP# " will be removed from Makefile by configure. These are +# GNU make directives & automake will f*ck them up by trying to process them +# as automake directives. +# +#AUTODERP# null= +#AUTODERP# SPACE=$(null) $(null) +#AUTODERP# mkcheck_CC = $(findstring $(SPACE)CC=, $(SPACE)$(MAKEOVERRIDES)) +#AUTODERP# mkcheck_CFLAGS = $(findstring $(SPACE)CFLAGS=, $(SPACE)$(MAKEOVERRIDES)) +#AUTODERP# mkcheck_CPPFLAGS = $(findstring $(SPACE)CPPFLAGS=,$(SPACE)$(MAKEOVERRIDES)) +#AUTODERP# mkcheck_CCLD = $(findstring $(SPACE)CCLD=, $(SPACE)$(MAKEOVERRIDES)) +#AUTODERP# mkcheck_LD = $(findstring $(SPACE)LD=, $(SPACE)$(MAKEOVERRIDES)) +#AUTODERP# mkcheck_LDFLAGS = $(findstring $(SPACE)LDFLAGS=, $(SPACE)$(MAKEOVERRIDES)) +#AUTODERP# # +#AUTODERP# ifneq ($(mkcheck_CC),) +#AUTODERP# $(warning WARNING: you have overwritten the "CC" variable on the make command line.) +#AUTODERP# endif +#AUTODERP# ifneq ($(mkcheck_CFLAGS),) +#AUTODERP# $(warning WARNING: you have overwritten the "CFLAGS" variable on the make command line.) +#AUTODERP# endif +#AUTODERP# ifneq ($(mkcheck_CPPFLAGS),) +#AUTODERP# $(warning WARNING: you have overwritten the "CPPFLAGS" variable on the make command line.) +#AUTODERP# endif +#AUTODERP# ifneq ($(mkcheck_CCLD),) +#AUTODERP# $(warning WARNING: you have overwritten the "CCLD" variable on the make command line.) +#AUTODERP# endif +#AUTODERP# ifneq ($(mkcheck_LD),) +#AUTODERP# $(warning WARNING: you have overwritten the "LD" variable on the make command line.) +#AUTODERP# endif +#AUTODERP# ifneq ($(mkcheck_LDFLAGS),) +#AUTODERP# $(warning WARNING: you have overwritten the "LDFLAGS" variable on the make command line.) +#AUTODERP# endif +#AUTODERP# # +#AUTODERP# ifneq ($(mkcheck_CC)$(mkcheck_CFLAGS)$(mkcheck_CPPFLAGS)$(mkcheck_CCLD)$(mkcheck_LD)$(mkcheck_LDFLAGS),) +#AUTODERP# $(warning ------) +#AUTODERP# $(warning While overwriting these variables works most of the time, it is not recommended and can cause confusing build errors.) +#AUTODERP# $(warning This is especially problematic when cross-compiling, since tools that run on the build system during the build process will not be compiled correctly.) +#AUTODERP# $(warning All of these variables should be supplied to 'configure', and they will be remembered and correctly applied during 'make'.) +#AUTODERP# $(warning ------) +#AUTODERP# endif + EXTRA_DIST = BUILT_SOURCES = CLEANFILES = @@ -20,11 +85,14 @@ sbin_SCRIPTS = noinst_PROGRAMS = noinst_HEADERS = noinst_LIBRARIES = +nodist_noinst_DATA = lib_LTLIBRARIES = module_LTLIBRARIES = pkginclude_HEADERS = nodist_pkginclude_HEADERS = dist_examples_DATA = +man_MANS = +vtysh_scan = ## libtool, the self-made GNU scourge ## ... this should fix relinking @@ -34,6 +102,10 @@ $(AUTOMAKE_DUMMY)install-moduleLTLIBRARIES: install-libLTLIBRARIES $(AUTOMAKE_DUMMY)install-binPROGRAMS: install-libLTLIBRARIES $(AUTOMAKE_DUMMY)install-sbinPROGRAMS: install-libLTLIBRARIES +include doc/subdir.am +include doc/user/subdir.am +include doc/manpages/subdir.am +include doc/developer/subdir.am include include/subdir.am include lib/subdir.am include zebra/subdir.am @@ -41,7 +113,12 @@ include watchfrr/subdir.am include qpb/subdir.am include fpm/subdir.am 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 @@ -58,17 +135,8 @@ include pbrd/subdir.am include staticd/subdir.am include bfdd/subdir.am -SUBDIRS = . @LIBRFP@ @RFPTEST@ \ - @BGPD@ \ - @VTYSH@ @DOC@ \ - @SOLARIS@ tests - -DIST_SUBDIRS = . bgpd \ - vtysh doc tests \ - solaris bgpd/rfp-example/librfp \ - bgpd/rfp-example/rfptest \ - debianpkg \ - # end +include vtysh/subdir.am +include tests/subdir.am if PKGSRC rcdir=@pkgsrcrcdir@ @@ -106,12 +174,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/babeld/babel_filter.c b/babeld/babel_filter.c index ff5cca42a0a8..31778901a62e 100644 --- a/babeld/babel_filter.c +++ b/babeld/babel_filter.c @@ -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" diff --git a/babeld/kernel.c b/babeld/kernel.c index ba2b58131c96..d4c962af3b43 100644 --- a/babeld/kernel.c +++ b/babeld/kernel.c @@ -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 #include #include diff --git a/babeld/neighbour.c b/babeld/neighbour.c index c1592fb18a11..512b60e29a11 100644 --- a/babeld/neighbour.c +++ b/babeld/neighbour.c @@ -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 #include #include diff --git a/babeld/net.c b/babeld/net.c index ad9a6bad92af..d1f6a4414291 100644 --- a/babeld/net.c +++ b/babeld/net.c @@ -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 #include #include diff --git a/babeld/resend.c b/babeld/resend.c index 1f219774424c..8949075f67d0 100644 --- a/babeld/resend.c +++ b/babeld/resend.c @@ -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 #include #include diff --git a/babeld/source.c b/babeld/source.c index d6dd848952cb..75bca0620639 100644 --- a/babeld/source.c +++ b/babeld/source.c @@ -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 #include #include diff --git a/babeld/subdir.am b/babeld/subdir.am index 6f91f7393079..e1f2cb0a00d7 100644 --- a/babeld/subdir.am +++ b/babeld/subdir.am @@ -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 = \ diff --git a/babeld/util.c b/babeld/util.c index 4a3ecace0cca..880cda2fce7c 100644 --- a/babeld/util.c +++ b/babeld/util.c @@ -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 #include #include diff --git a/bfdd/.gitignore b/bfdd/.gitignore index e554d1b33f68..2b020911fbe3 100644 --- a/bfdd/.gitignore +++ b/bfdd/.gitignore @@ -1,3 +1,2 @@ # ignore binary files -*.a bfdd diff --git a/bfdd/bfd.c b/bfdd/bfd.c index b3253a14d751..cf7c027db5d8 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -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. diff --git a/bfdd/bfd.h b/bfdd/bfd.h index d665448abf79..3a58a8d53cfe 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -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); diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c index 543181a12a1a..8acb9438c564 100644 --- a/bfdd/bfd_packet.c +++ b/bfdd/bfd_packet.c @@ -37,74 +37,26 @@ #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; +} diff --git a/bfdd/bfdctl.h b/bfdd/bfdctl.h index 940efd161447..0da1ca8df6c7 100644 --- a/bfdd/bfdctl.h +++ b/bfdd/bfdctl.h @@ -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]; diff --git a/bfdd/bfdd.c b/bfdd/bfdd.c index 144619088d3a..250f8d21c0d3 100644 --- a/bfdd/bfdd.c +++ b/bfdd/bfdd.c @@ -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); diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index ae6081f01ad3..1c6d03195c8a 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -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) { diff --git a/bfdd/bsd.c b/bfdd/bsd.c index 34a3a1a801e2..e0fb340e30e3 100644 --- a/bfdd/bsd.c +++ b/bfdd/bsd.c @@ -32,39 +32,9 @@ #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 */ diff --git a/bfdd/config.c b/bfdd/config.c index 0e0d8b7d706f..06089780c6ba 100644 --- a/bfdd/config.c +++ b/bfdd/config.c @@ -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); diff --git a/bfdd/event.c b/bfdd/event.c index ba12f5b4e800..63f64077ebd4 100644 --- a/bfdd/event.c +++ b/bfdd/event.c @@ -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); } diff --git a/bfdd/linux.c b/bfdd/linux.c index 5f24ef4d19cc..e260851ddba6 100644 --- a/bfdd/linux.c +++ b/bfdd/linux.c @@ -23,49 +23,8 @@ #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 -#include - -#include - -#include -#include - #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 */ diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index 4287891621f0..a5fae3383cd7 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -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: diff --git a/bfdd/subdir.am b/bfdd/subdir.am index 86923f5cec50..334e974b048a 100644 --- a/bfdd/subdir.am +++ b/bfdd/subdir.am @@ -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 = \ diff --git a/bgpd/.gitignore b/bgpd/.gitignore index 105be2299503..2e77195b9008 100644 --- a/bgpd/.gitignore +++ b/bgpd/.gitignore @@ -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 index 000000000000..b8664a8e23de --- /dev/null +++ b/bgpd/Makefile @@ -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 index b6b125f75296..000000000000 --- a/bgpd/Makefile.am +++ /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 - diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 47dffd146ab6..663bc4894a84 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -530,7 +530,7 @@ void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr) /* * bgp_bfd_show_info - Show the peer BFD information. */ -void bgp_bfd_show_info(struct vty *vty, struct peer *peer, uint8_t use_json, +void bgp_bfd_show_info(struct vty *vty, struct peer *peer, bool use_json, json_object *json_neigh) { bfd_show_info(vty, (struct bfd_info *)peer->bfd_info, diff --git a/bgpd/bgp_bfd.h b/bgpd/bgp_bfd.h index a3cfca9c0d8a..caa5651e3ac6 100644 --- a/bgpd/bgp_bfd.h +++ b/bgpd/bgp_bfd.h @@ -34,8 +34,8 @@ extern void bgp_bfd_deregister_peer(struct peer *peer); extern void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr); -extern void bgp_bfd_show_info(struct vty *vty, struct peer *peer, - uint8_t use_json, json_object *json_neigh); +extern void bgp_bfd_show_info(struct vty *vty, struct peer *peer, bool use_json, + json_object *json_neigh); extern int bgp_bfd_is_peer_multihop(struct peer *peer); diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index bce6056ded4a..071ee6b9c676 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -523,7 +523,7 @@ void bgp_config_write_damp(struct vty *vty) } static const char *bgp_get_reuse_time(unsigned int penalty, char *buf, - size_t len, uint8_t use_json, + size_t len, bool use_json, json_object *json) { time_t reuse_time = 0; @@ -641,7 +641,7 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo, } const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_info *binfo, - char *timebuf, size_t len, uint8_t use_json, + char *timebuf, size_t len, bool use_json, json_object *json) { struct bgp_damp_info *bdi; diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h index d3b0ae42aa08..8326bae69773 100644 --- a/bgpd/bgp_damp.h +++ b/bgpd/bgp_damp.h @@ -140,9 +140,10 @@ extern int bgp_damp_decay(time_t, int); extern void bgp_config_write_damp(struct vty *); extern void bgp_damp_info_vty(struct vty *, struct bgp_info *, json_object *json_path); -extern const char *bgp_damp_reuse_time_vty(struct vty *, struct bgp_info *, - char *, size_t, uint8_t, - json_object *); +extern const char *bgp_damp_reuse_time_vty(struct vty *vty, + struct bgp_info *binfo, + char *timebuf, size_t len, + bool use_json, json_object *json); extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t); #endif /* _QUAGGA_BGP_DAMP_H */ diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 9e814516b73d..a104a2e16d66 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -543,7 +543,7 @@ static void evpn_convert_nexthop_to_ipv6(struct attr *attr) static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, struct prefix_evpn *p, struct in_addr remote_vtep_ip, int add, - uint8_t flags) + uint8_t flags, uint32_t seq) { struct stream *s; int ipa_len; @@ -579,19 +579,22 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, stream_put_in_addr(s, &remote_vtep_ip); /* TX flags - MAC sticky status and/or gateway mac */ - if (add) + /* Also TX the sequence number of the best route. */ + if (add) { stream_putc(s, flags); + stream_putl(s, seq); + } stream_putw_at(s, 0, stream_get_endp(s)); if (bgp_debug_zebra(NULL)) zlog_debug( - "Tx %s MACIP, VNI %u MAC %s IP %s (flags: 0x%x) remote VTEP %s", + "Tx %s MACIP, VNI %u MAC %s IP %s flags 0x%x seq %u remote VTEP %s", add ? "ADD" : "DEL", vpn->vni, prefix_mac2str(&p->prefix.macip_addr.mac, buf1, sizeof(buf1)), ipaddr2str(&p->prefix.macip_addr.ip, - buf3, sizeof(buf3)), flags, + buf3, sizeof(buf3)), flags, seq, inet_ntop(AF_INET, &remote_vtep_ip, buf2, sizeof(buf2))); @@ -875,13 +878,14 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr) /* Install EVPN route into zebra. */ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, struct prefix_evpn *p, - struct in_addr remote_vtep_ip, uint8_t flags) + struct in_addr remote_vtep_ip, uint8_t flags, + uint32_t seq) { int ret; if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip, - 1, flags); + 1, flags, seq); else ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 1); @@ -897,7 +901,7 @@ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip, - 0, 0); + 0, 0, 0); else ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 0); @@ -1141,7 +1145,8 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, ret = evpn_zebra_install( bgp, vpn, (struct prefix_evpn *)&rn->p, - old_select->attr->nexthop, flags); + old_select->attr->nexthop, flags, + mac_mobility_seqnum(old_select->attr)); } UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG); bgp_zebra_clear_route_change_flags(rn); @@ -1177,7 +1182,8 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p, - new_select->attr->nexthop, flags); + new_select->attr->nexthop, flags, + mac_mobility_seqnum(new_select->attr)); /* If an old best existed and it was a "local" route, the only * reason * it would be supplanted is due to MAC mobility procedures. So, @@ -1557,11 +1563,12 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, */ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, afi_t afi, safi_t safi, struct bgp_node *rn, - struct attr *attr, int add, int vni_table, - struct bgp_info **ri, uint8_t flags) + struct attr *attr, int add, + struct bgp_info **ri, uint8_t flags, + uint32_t seq) { struct bgp_info *tmp_ri; - struct bgp_info *local_ri, *remote_ri; + struct bgp_info *local_ri; struct attr *attr_new; mpls_label_t label[BGP_MAX_LABELS]; uint32_t num_labels = 1; @@ -1573,28 +1580,13 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, evp = (struct prefix_evpn *)&rn->p; memset(&label, 0, sizeof(label)); - /* See if this is an update of an existing route, or a new add. Also, - * identify if already known from remote, and if so, the one with the - * highest sequence number; this is only when adding to the VNI routing - * table. - */ - local_ri = remote_ri = NULL; + /* See if this is an update of an existing route, or a new add. */ + local_ri = NULL; for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { if (tmp_ri->peer == bgp->peer_self && tmp_ri->type == ZEBRA_ROUTE_BGP && tmp_ri->sub_type == BGP_ROUTE_STATIC) local_ri = tmp_ri; - if (vni_table) { - if (tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_IMPORTED - && CHECK_FLAG(tmp_ri->flags, BGP_INFO_VALID)) { - if (!remote_ri) - remote_ri = tmp_ri; - else if (mac_mobility_seqnum(tmp_ri->attr) - > mac_mobility_seqnum(remote_ri->attr)) - remote_ri = tmp_ri; - } - } } /* If route doesn't exist already, create a new one, if told to. @@ -1604,22 +1596,11 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, if (!local_ri && !add) return 0; - if (!local_ri) { - /* When learnt locally for the first time but already known from - * remote, we have to initiate appropriate MAC mobility steps. - * This is applicable when updating the VNI routing table. - * We need to skip mobility steps for g/w macs (local mac on g/w - * SVI) advertised in EVPN. - * This will ensure that local routes are preferred for g/w macs - */ - if (remote_ri && !CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) { - uint32_t cur_seqnum; - - /* Add MM extended community to route. */ - cur_seqnum = mac_mobility_seqnum(remote_ri->attr); - add_mac_mobility_to_attr(cur_seqnum + 1, attr); - } + /* For non-GW MACs, update MAC mobility seq number, if needed. */ + if (seq && !CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) + add_mac_mobility_to_attr(seq, attr); + if (!local_ri) { /* Add (or update) attribute to hash. */ attr_new = bgp_attr_intern(attr); @@ -1685,6 +1666,11 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, attr_new = bgp_attr_intern(attr); bgp_info_set_flag(rn, tmp_ri, BGP_INFO_ATTR_CHANGED); + /* Extract MAC mobility sequence number, if any. */ + attr_new->mm_seqnum = + bgp_attr_mac_mobility_seqnum(attr_new, &sticky); + attr_new->sticky = sticky; + /* Restore route, if needed. */ if (CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) bgp_info_restore(rn, tmp_ri); @@ -1706,7 +1692,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, * and schedule for processing. */ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, uint8_t flags) + struct prefix_evpn *p, uint8_t flags, + uint32_t seq) { struct bgp_node *rn; struct attr attr; @@ -1758,7 +1745,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, /* Create or update route entry. */ route_change = update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr, - 1, 1, &ri, flags); + 1, &ri, flags, seq); assert(ri); attr_new = ri->attr; @@ -1778,8 +1765,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, (struct prefix *)p, &vpn->prd); - update_evpn_route_entry(bgp, vpn, afi, safi, rn, attr_new, 1, 0, - &global_ri, flags); + update_evpn_route_entry(bgp, vpn, afi, safi, rn, attr_new, 1, + &global_ri, flags, seq); /* Schedule for processing and unlock node. */ bgp_process(bgp, rn, afi, safi); @@ -1954,58 +1941,14 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) afi_t afi; safi_t safi; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_info *ri, *tmp_ri; struct attr attr; - struct attr attr_sticky; - struct attr attr_def_gw; - struct attr attr_ip6_ll; struct attr *attr_new; + uint32_t seq; int add_l3_ecomm = 0; afi = AFI_L2VPN; safi = SAFI_EVPN; - memset(&attr, 0, sizeof(struct attr)); - memset(&attr_sticky, 0, sizeof(struct attr)); - memset(&attr_def_gw, 0, sizeof(struct attr)); - memset(&attr_ip6_ll, 0, sizeof(struct attr)); - - /* Build path-attribute - multiple type-2 routes for this VNI will share - * the same path attribute, but we need separate structures for sticky - * MACs, default gateway and IPv6 link-local addresses (no L3 RT/RMAC). - */ - bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); - bgp_attr_default_set(&attr_sticky, BGP_ORIGIN_IGP); - bgp_attr_default_set(&attr_def_gw, BGP_ORIGIN_IGP); - attr.nexthop = vpn->originator_ip; - attr.mp_nexthop_global_in = vpn->originator_ip; - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - bgpevpn_get_rmac(vpn, &attr.rmac); - attr_sticky.nexthop = vpn->originator_ip; - attr_sticky.mp_nexthop_global_in = vpn->originator_ip; - attr_sticky.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - attr_sticky.sticky = 1; - bgpevpn_get_rmac(vpn, &attr_sticky.rmac); - attr_def_gw.nexthop = vpn->originator_ip; - attr_def_gw.mp_nexthop_global_in = vpn->originator_ip; - attr_def_gw.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - attr_def_gw.default_gw = 1; - bgpevpn_get_rmac(vpn, &attr_def_gw.rmac); - bgp_attr_default_set(&attr_ip6_ll, BGP_ORIGIN_IGP); - attr_ip6_ll.nexthop = vpn->originator_ip; - attr_ip6_ll.mp_nexthop_global_in = vpn->originator_ip; - attr_ip6_ll.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - - /* Add L3 VNI RTs and RMAC for non IPv6 link-local attributes if - * using L3 VNI for type-2 routes also. - */ - if (CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS) && - bgpevpn_get_l3vni(vpn)) - add_l3_ecomm = 1; - - build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm); - build_evpn_route_extcomm(vpn, &attr_sticky, add_l3_ecomm); - build_evpn_route_extcomm(vpn, &attr_def_gw, add_l3_ecomm); - build_evpn_route_extcomm(vpn, &attr_ip6_ll, 0); /* Walk this VNI's route table and update local type-2 routes. For any * routes updated, update corresponding entry in the global table too. @@ -2019,35 +1962,57 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) continue; - if (is_evpn_prefix_ipaddr_v6(evp) && - IN6_IS_ADDR_LINKLOCAL(&evp->prefix.macip_addr.ip.ipaddr_v6)) - update_evpn_route_entry(bgp, vpn, afi, safi, rn, - &attr_ip6_ll, 0, 1, &ri, 0); - else { - if (evpn_route_is_sticky(bgp, rn)) - update_evpn_route_entry(bgp, vpn, afi, safi, rn, - &attr_sticky, 0, 1, &ri, - 0); - else if (evpn_route_is_def_gw(bgp, rn)) { - if (is_evpn_prefix_ipaddr_v6(evp)) - attr_def_gw.router_flag = 1; - update_evpn_route_entry(bgp, vpn, afi, safi, rn, - &attr_def_gw, 0, 1, &ri, - 0); - } else - update_evpn_route_entry(bgp, vpn, afi, safi, rn, - &attr, 0, 1, &ri, 0); + /* Identify local route. */ + for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { + if (tmp_ri->peer == bgp->peer_self + && tmp_ri->type == ZEBRA_ROUTE_BGP + && tmp_ri->sub_type == BGP_ROUTE_STATIC) + break; } - /* If a local route exists for this prefix, we need to update - * the global routing table too. - */ - if (!ri) + if (!tmp_ri) continue; + /* + * Build attribute per local route as the MAC mobility and + * some other values could differ for different routes. The + * attributes will be shared in the hash table. + */ + bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); + attr.nexthop = vpn->originator_ip; + attr.mp_nexthop_global_in = vpn->originator_ip; + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; + bgpevpn_get_rmac(vpn, &attr.rmac); + + if (evpn_route_is_sticky(bgp, rn)) + attr.sticky = 1; + else if (evpn_route_is_def_gw(bgp, rn)) { + attr.default_gw = 1; + if (is_evpn_prefix_ipaddr_v6(evp)) + attr.router_flag = 1; + } + + /* Add L3 VNI RTs and RMAC for non IPv6 link-local if + * using L3 VNI for type-2 routes also. + */ + if ((is_evpn_prefix_ipaddr_v4(evp) || + !IN6_IS_ADDR_LINKLOCAL( + &evp->prefix.macip_addr.ip.ipaddr_v6)) && + CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS) && + bgpevpn_get_l3vni(vpn)) + add_l3_ecomm = 1; + + /* Set up extended community. */ + build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm); + + seq = mac_mobility_seqnum(tmp_ri->attr); + + /* Update the route entry. */ + update_evpn_route_entry(bgp, vpn, afi, safi, rn, + &attr, 0, &ri, 0, seq); + /* Perform route selection; this is just to set the flags - * correctly - * as local route in the VNI always wins. + * correctly as local route in the VNI always wins. */ evpn_route_select_install(bgp, vpn, rn); @@ -2058,18 +2023,17 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) (struct prefix *)evp, &vpn->prd); assert(rd_rn); update_evpn_route_entry(bgp, vpn, afi, safi, rd_rn, attr_new, 0, - 0, &global_ri, 0); + &global_ri, 0, + mac_mobility_seqnum(attr_new)); /* Schedule for processing and unlock node. */ bgp_process(bgp, rd_rn, afi, safi); bgp_unlock_node(rd_rn); - } - /* Unintern temporary. */ - aspath_unintern(&attr.aspath); - aspath_unintern(&attr_sticky.aspath); - aspath_unintern(&attr_def_gw.aspath); - aspath_unintern(&attr_ip6_ll.aspath); + /* Unintern temporary. */ + aspath_unintern(&attr.aspath); + + } return 0; } @@ -2206,7 +2170,7 @@ static int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) * locally learnt type-2 routes (MACIP) - for this VNI. */ build_evpn_type3_prefix(&p, vpn->originator_ip); - ret = update_evpn_route(bgp, vpn, &p, 0); + ret = update_evpn_route(bgp, vpn, &p, 0, 0); if (ret) return ret; @@ -3451,8 +3415,8 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, (struct prefix *)&p, &vpn->prd); - update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, 0, &ri, - 0); + update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, &ri, + 0, mac_mobility_seqnum(attr)); /* Schedule for processing and unlock node. */ bgp_process(bgp, global_rn, afi, safi); @@ -3485,7 +3449,8 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) (struct prefix *)evp, &vpn->prd); assert(global_rn); update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, - 0, &global_ri, 0); + &global_ri, 0, + mac_mobility_seqnum(attr)); /* Schedule for processing and unlock node. */ bgp_process(bgp, global_rn, afi, safi); @@ -5213,7 +5178,7 @@ int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac, * Handle add of a local MACIP. */ int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac, - struct ipaddr *ip, uint8_t flags) + struct ipaddr *ip, uint8_t flags, uint32_t seq) { struct bgpevpn *vpn; struct prefix_evpn p; @@ -5228,7 +5193,7 @@ int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac, /* Create EVPN type-2 route and schedule for processing. */ build_evpn_type2_prefix(&p, mac, ip); - if (update_evpn_route(bgp, vpn, &p, flags)) { + if (update_evpn_route(bgp, vpn, &p, flags, seq)) { char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; @@ -5525,7 +5490,7 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, /* Create EVPN type-3 route and schedule for processing. */ build_evpn_type3_prefix(&p, vpn->originator_ip); - if (update_evpn_route(bgp, vpn, &p, 0)) { + if (update_evpn_route(bgp, vpn, &p, 0, 0)) { flog_err(BGP_ERR_EVPN_ROUTE_CREATE, "%u: Type3 route creation failure for VNI %u", bgp->vrf_id, vni); diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 91d4c9fac4a7..b002be3d3d70 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -132,7 +132,7 @@ extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac, struct ipaddr *ip); extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac, struct ipaddr *ip, - uint8_t flags); + uint8_t flags, uint32_t seq); extern int bgp_evpn_local_l3vni_add(vni_t vni, vrf_id_t vrf_id, struct ethaddr *rmac, struct in_addr originator_ip, int filter); diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index b553cb42a5ac..a6cc2d9b5361 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -983,7 +983,7 @@ static void show_vni_entry(struct hash_backet *backet, void *args[]) static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, enum bgp_show_type type, void *output_arg, - int option, uint8_t use_json) + int option, bool use_json) { afi_t afi = AFI_L2VPN; struct bgp *bgp; @@ -1276,7 +1276,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes, union sockunion su; struct peer *peer; int ret; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); argv_find(argv, argc, "A.B.C.D", &idx_ipv4); @@ -1336,7 +1336,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes, union sockunion su; struct peer *peer; struct prefix_rd prd; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community); argv_find(argv, argc, "A.B.C.D", &idx_ipv4); @@ -1409,7 +1409,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes, int ret; struct peer *peer; union sockunion su; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); argv_find(argv, argc, "A.B.C.D", &idx_ipv4); @@ -1467,7 +1467,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes, struct peer *peer; struct prefix_rd prd; union sockunion su; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community); argv_find(argv, argc, "A.B.C.D", &idx_ipv4); @@ -3172,7 +3172,7 @@ DEFUN(show_bgp_l2vpn_evpn_vni, struct bgp *bgp_def; vni_t vni; int idx = 0; - uint8_t uj = 0; + bool uj = false; json_object *json = NULL; uint32_t num_l2vnis = 0; uint32_t num_l3vnis = 0; @@ -3255,7 +3255,7 @@ DEFUN(show_bgp_l2vpn_evpn_es, JSON_STR) { int idx = 0; - uint8_t uj = 0; + bool uj = false; esi_t esi; json_object *json = NULL; struct bgp *bgp = NULL; @@ -3312,7 +3312,7 @@ DEFUN(show_bgp_l2vpn_evpn_summary, JSON_STR) { int idx_vrf = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); char *vrf = NULL; if (argv_find(argv, argc, "vrf", &idx_vrf)) @@ -3341,7 +3341,7 @@ DEFUN(show_bgp_l2vpn_evpn_route, struct bgp *bgp; int type_idx = 0; int type = 0; - uint8_t uj = 0; + bool uj = false; json_object *json = NULL; uj = use_json(argc, argv); @@ -3404,7 +3404,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd, int type = 0; int rd_idx = 0; int type_idx = 0; - int uj = 0; + bool uj = false; json_object *json = NULL; bgp = bgp_get_default(); @@ -3477,7 +3477,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd_macip, int rd_idx = 0; int mac_idx = 0; int ip_idx = 0; - int uj = 0; + bool uj = false; json_object *json = NULL; memset(&mac, 0, sizeof(struct ethaddr)); @@ -3541,7 +3541,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_esi, "ESI ID\n" JSON_STR) { - int uj = 0; + bool uj = false; esi_t esi; struct bgp *bgp = NULL; json_object *json = NULL; @@ -3597,7 +3597,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd, struct in_addr vtep_ip; int type = 0; int idx = 0; - int uj = 0; + bool uj = false; json_object *json = NULL; bgp = bgp_get_default(); @@ -3669,7 +3669,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_macip, struct ethaddr mac; struct ipaddr ip; int idx = 0; - int uj = 0; + bool uj = false; json_object *json = NULL; bgp = bgp_get_default(); @@ -3737,7 +3737,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast, int ret; struct in_addr orig_ip; int idx = 0; - int uj = 0; + bool uj = false; json_object *json = NULL; bgp = bgp_get_default(); @@ -3793,7 +3793,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_all, struct bgp *bgp; struct in_addr vtep_ip; int idx = 0; - int uj = 0; + bool uj = false; json_object *json = NULL; bgp = bgp_get_default(); @@ -3841,7 +3841,7 @@ DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt, "Show vrf import route target\n" JSON_STR) { - uint8_t uj = 0; + bool uj = false; struct bgp *bgp_def = NULL; json_object *json = NULL; @@ -3878,7 +3878,7 @@ DEFUN(show_bgp_l2vpn_evpn_import_rt, JSON_STR) { struct bgp *bgp; - uint8_t uj = 0; + bool uj = false; json_object *json = NULL; bgp = bgp_get_default(); @@ -4359,7 +4359,7 @@ DEFUN (show_bgp_vrf_l3vni_info, json_object *json_vnis = NULL; json_object *json_export_rts = NULL; json_object *json_import_rts = NULL; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (uj) { json = json_object_new_object(); diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index ae9d805b055a..c7977a9af4c8 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -391,16 +391,25 @@ static int as_list_dup_check(struct as_list *aslist, struct as_filter *new) return 0; } -DEFUN (ip_as_path, - ip_as_path_cmd, - "ip as-path access-list WORD LINE...", - IP_STR - "BGP autonomous system path filter\n" - "Specify an access list name\n" - "Regular expression access list name\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "A regular-expression to match the BGP AS paths\n") +static int config_bgp_aspath_validate(const char *regstr) +{ + char valid_chars[] = "1234567890_^|[,{}() ]$*+.?-"; + + if (strspn(regstr, valid_chars) == strlen(regstr)) + return 1; + + return 0; +} + +DEFUN(ip_as_path, ip_as_path_cmd, + "ip as-path access-list WORD LINE...", + IP_STR + "BGP autonomous system path filter\n" + "Specify an access list name\n" + "Regular expression access list name\n" + "Specify packets to reject\n" + "Specify packets to forward\n" + "A regular-expression (1234567890_(^|[,{}() ]|$)) to match the BGP AS paths\n") { int idx = 0; enum as_filter_type type; @@ -428,6 +437,12 @@ DEFUN (ip_as_path, return CMD_WARNING_CONFIG_FAILED; } + if (!config_bgp_aspath_validate(regstr)) { + vty_out(vty, "Invalid character in as-path access-list %s\n", + regstr); + return CMD_WARNING_CONFIG_FAILED; + } + asfilter = as_filter_make(regex, regstr, type); XFREE(MTYPE_TMP, regstr); @@ -444,17 +459,15 @@ DEFUN (ip_as_path, return CMD_SUCCESS; } -DEFUN (no_ip_as_path, - no_ip_as_path_cmd, - "no ip as-path access-list WORD LINE...", - NO_STR - IP_STR - "BGP autonomous system path filter\n" - "Specify an access list name\n" - "Regular expression access list name\n" - "Specify packets to reject\n" - "Specify packets to forward\n" - "A regular-expression to match the BGP AS paths\n") +DEFUN(no_ip_as_path, no_ip_as_path_cmd, + "no ip as-path access-list WORD LINE...", + NO_STR IP_STR + "BGP autonomous system path filter\n" + "Specify an access list name\n" + "Regular expression access list name\n" + "Specify packets to reject\n" + "Specify packets to forward\n" + "A regular-expression (1234567890_(^|[,{}() ]|$)) to match the BGP AS paths\n") { int idx = 0; enum as_filter_type type; @@ -488,6 +501,12 @@ DEFUN (no_ip_as_path, argv_find(argv, argc, "LINE", &idx); regstr = argv_concat(argv, argc, idx); + if (!config_bgp_aspath_validate(regstr)) { + vty_out(vty, "Invalid character in as-path access-list %s\n", + regstr); + return CMD_WARNING_CONFIG_FAILED; + } + regex = bgp_regcomp(regstr); if (!regex) { vty_out(vty, "can't compile regexp %s\n", regstr); diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c index e29508bf3680..c604135bfd1b 100644 --- a/bgpd/bgp_flowspec.c +++ b/bgpd/bgp_flowspec.c @@ -18,9 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "math.h" - #include +#include + #include "prefix.h" #include "lib_errors.h" diff --git a/bgpd/bgp_flowspec.h b/bgpd/bgp_flowspec.h index 9f69dbeddac0..f07b696b8d38 100644 --- a/bgpd/bgp_flowspec.h +++ b/bgpd/bgp_flowspec.h @@ -34,9 +34,8 @@ extern void bgp_flowspec_vty_init(void); extern int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi, struct bgp_table *table, - enum bgp_show_type type, - void *output_arg, uint8_t use_json, - int is_last, + enum bgp_show_type type, void *output_arg, + bool use_json, int is_last, unsigned long *output_cum, unsigned long *total_cum); @@ -50,12 +49,10 @@ extern void route_vty_out_flowspec(struct vty *vty, struct prefix *p, extern int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi); -extern int bgp_flowspec_display_match_per_ip(afi_t afi, - struct bgp_table *rib, - struct prefix *match, - int prefix_check, - struct vty *vty, - uint8_t use_json, - json_object *json_paths); +extern int bgp_flowspec_display_match_per_ip(afi_t afi, struct bgp_table *rib, + struct prefix *match, + int prefix_check, struct vty *vty, + bool use_json, + json_object *json_paths); #endif /* _FRR_BGP_FLOWSPEC_H */ diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index 31d2c540fa52..978ce6bf4e14 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -365,9 +365,8 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p, int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi, struct bgp_table *table, enum bgp_show_type type, - void *output_arg, uint8_t use_json, - int is_last, unsigned long *output_cum, - unsigned long *total_cum) + void *output_arg, bool use_json, int is_last, + unsigned long *output_cum, unsigned long *total_cum) { struct bgp_info *ri; struct bgp_node *rn; @@ -527,13 +526,11 @@ DEFUN (bgp_fs_local_install_ifname, return bgp_fs_local_install_interface(bgp, no, ifname); } -extern int bgp_flowspec_display_match_per_ip(afi_t afi, - struct bgp_table *rib, - struct prefix *match, - int prefix_check, - struct vty *vty, - uint8_t use_json, - json_object *json_paths) +extern int bgp_flowspec_display_match_per_ip(afi_t afi, struct bgp_table *rib, + struct prefix *match, + int prefix_check, struct vty *vty, + bool use_json, + json_object *json_paths) { struct bgp_node *rn; struct prefix *prefix; diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c index f81836cc8360..aeb95f91ba4f 100644 --- a/bgpd/bgp_keepalives.c +++ b/bgpd/bgp_keepalives.c @@ -180,11 +180,7 @@ void *bgp_keepalives_start(void *arg) pthread_cond_init(peerhash_cond, &attrs); pthread_condattr_destroy(&attrs); -#ifdef GNU_LINUX - pthread_setname_np(fpt->thread, "bgpd_ka"); -#elif defined(OPEN_BSD) - pthread_set_name_np(fpt->thread, "bgpd_ka"); -#endif + frr_pthread_set_name(fpt, NULL, "bgpd_ka"); /* initialize peer hashtable */ peerhash = hash_create_size(2048, peer_hash_key, peer_hash_cmp, NULL); diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 138788194dba..e0834604b2f0 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -266,6 +266,12 @@ static int bgp_vrf_enable(struct vrf *vrf) bgp = bgp_lookup_by_name(vrf->name); if (bgp) { + if (bgp->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) { + XFREE(MTYPE_BGP, bgp->name); + bgp->name = NULL; + XFREE(MTYPE_BGP, bgp->name_pretty); + bgp->name_pretty = XSTRDUP(MTYPE_BGP, "VRF default"); + } old_vrf_id = bgp->vrf_id; /* We have instance configured, link to VRF and make it "up". */ bgp_vrf_link(bgp, vrf); @@ -332,7 +338,8 @@ static int bgp_vrf_disable(struct vrf *vrf) static void bgp_vrf_init(void) { - vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete); + vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, + bgp_vrf_delete, NULL); } static void bgp_vrf_terminate(void) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index b89edfe45963..459775c8ec0c 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -1775,7 +1775,7 @@ DEFUN (no_vpnv6_network, int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, enum bgp_show_type type, void *output_arg, int tags, - uint8_t use_json) + bool use_json) { struct bgp *bgp; struct bgp_table *table; @@ -1953,7 +1953,7 @@ DEFUN (show_ip_bgp_vpn_all_neighbor_routes, union sockunion su; struct peer *peer; int ret; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); afi_t afi; int idx = 0; @@ -2017,7 +2017,7 @@ DEFUN (show_ip_bgp_vpn_rd_neighbor_routes, union sockunion su; struct peer *peer; struct prefix_rd prd; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); afi_t afi; int idx = 0; @@ -2095,7 +2095,7 @@ DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes, int ret; struct peer *peer; union sockunion su; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); afi_t afi; int idx = 0; @@ -2157,7 +2157,7 @@ DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes, struct peer *peer; struct prefix_rd prd; union sockunion su; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); afi_t afi; int idx = 0; diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 122ae9e905b1..61b87392a218 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -50,7 +50,7 @@ extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, int *index, afi_t *afi); extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, enum bgp_show_type type, void *output_arg, - int tags, uint8_t use_json); + int tags, bool use_json); extern void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, struct bgp *bgp_vrf, struct bgp_info *info_vrf); diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 7fbc0302420e..5bdee5f512fa 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -52,8 +52,8 @@ Next, if we send capability to the peer we want to set my capabilty inforation at each peer. */ -void bgp_capability_vty_out(struct vty *vty, struct peer *peer, - uint8_t use_json, json_object *json_neigh) +void bgp_capability_vty_out(struct vty *vty, struct peer *peer, bool use_json, + json_object *json_neigh) { char *pnt; char *end; diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h index 42ebe97f2e64..0fc321bdf3a6 100644 --- a/bgpd/bgp_open.h +++ b/bgpd/bgp_open.h @@ -86,8 +86,8 @@ struct graceful_restart_af { extern int bgp_open_option_parse(struct peer *, uint8_t, int *); extern void bgp_open_capability(struct stream *, struct peer *); -extern void bgp_capability_vty_out(struct vty *, struct peer *, uint8_t, - json_object *); +extern void bgp_capability_vty_out(struct vty *vty, struct peer *peer, + bool use_json, json_object *json_neigh); extern as_t peek_for_as4_capability(struct peer *, uint8_t); #endif /* _QUAGGA_BGP_OPEN_H */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 50c484d7de7b..32506623c79f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -6755,7 +6755,7 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, /* called from terminal list command */ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, - safi_t safi, uint8_t use_json, json_object *json_ar) + safi_t safi, bool use_json, json_object *json_ar) { json_object *json_status = NULL; json_object *json_net = NULL; @@ -7084,7 +7084,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p, /* dampening route */ static void damp_route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, int display, safi_t safi, - uint8_t use_json, json_object *json) + bool use_json, json_object *json) { struct attr *attr; int len; @@ -7147,7 +7147,7 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p, /* flap route */ static void flap_route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, int display, safi_t safi, - uint8_t use_json, json_object *json) + bool use_json, json_object *json) { struct attr *attr; struct bgp_damp_info *bdi; @@ -8160,12 +8160,12 @@ static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr, afi_t afi, safi_t safi, enum bgp_show_type type); static int bgp_show_community(struct vty *vty, struct bgp *bgp, const char *comstr, int exact, afi_t afi, - safi_t safi, uint8_t use_json); + safi_t safi, bool use_json); static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, struct bgp_table *table, enum bgp_show_type type, - void *output_arg, uint8_t use_json, char *rd, + void *output_arg, bool use_json, char *rd, int is_last, unsigned long *output_cum, unsigned long *total_cum, unsigned long *json_header_depth) @@ -8452,8 +8452,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, struct bgp_table *table, struct prefix_rd *prd_match, - enum bgp_show_type type, void *output_arg, - uint8_t use_json) + enum bgp_show_type type, void *output_arg, bool use_json) { struct bgp_node *rn, *next; unsigned long output_cum = 0; @@ -8493,7 +8492,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, return CMD_SUCCESS; } static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, - enum bgp_show_type type, void *output_arg, uint8_t use_json) + enum bgp_show_type type, void *output_arg, bool use_json) { struct bgp_table *table; unsigned long json_header_depth = 0; @@ -8531,16 +8530,18 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, } static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, - safi_t safi, uint8_t use_json) + safi_t safi, bool use_json) { struct listnode *node, *nnode; struct bgp *bgp; int is_first = 1; + bool route_output = false; if (use_json) vty_out(vty, "{\n"); for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + route_output = true; if (use_json) { if (!is_first) vty_out(vty, ",\n"); @@ -8563,6 +8564,8 @@ static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, if (use_json) vty_out(vty, "}\n"); + else if (!route_output) + vty_out(vty, "%% BGP instance not found\n"); } /* Header of detailed BGP route information */ @@ -8748,8 +8751,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, struct bgp_table *rib, const char *ip_str, afi_t afi, safi_t safi, struct prefix_rd *prd, int prefix_check, - enum bgp_path_type pathtype, - uint8_t use_json) + enum bgp_path_type pathtype, bool use_json) { int ret; int header; @@ -8885,7 +8887,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str, afi_t afi, safi_t safi, struct prefix_rd *prd, int prefix_check, enum bgp_path_type pathtype, - uint8_t use_json) + bool use_json) { if (!bgp) { bgp = bgp_get_default(); @@ -8909,7 +8911,7 @@ static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str, static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc, struct cmd_token **argv, afi_t afi, safi_t safi, - uint8_t uj) + bool uj) { struct lcommunity *lcom; struct buffer *b; @@ -8946,7 +8948,7 @@ static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc, static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp, const char *lcom, afi_t afi, safi_t safi, - uint8_t uj) + bool uj) { struct community_list *list; @@ -8994,7 +8996,7 @@ DEFUN (show_ip_bgp_large_community_list, safi = bgp_vty_safi_from_str(argv[idx]->text); } - int uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct bgp *bgp = bgp_lookup_by_name(vrf); if (bgp == NULL) { @@ -9037,7 +9039,7 @@ DEFUN (show_ip_bgp_large_community, safi = bgp_vty_safi_from_str(argv[idx]->text); } - int uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct bgp *bgp = bgp_lookup_by_name(vrf); if (bgp == NULL) { @@ -9121,7 +9123,7 @@ DEFUN (show_ip_bgp, int idx = 0; bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, - &bgp); + &bgp, false); if (!idx) return CMD_WARNING; @@ -9197,16 +9199,16 @@ DEFUN (show_ip_bgp_json, int idx = 0; int idx_community_type = 0; int exact_match = 0; + bool uj = use_json(argc, argv); + + if (uj) + argc--; bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, - &bgp); + &bgp, uj); if (!idx) return CMD_WARNING; - int uj = use_json(argc, argv); - if (uj) - argc--; - if (argv_find(argv, argc, "cidr-only", &idx)) return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj); @@ -9275,12 +9277,12 @@ DEFUN (show_ip_bgp_route, char *prefix = NULL; struct bgp *bgp = NULL; enum bgp_path_type path_type; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); int idx = 0; bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, - &bgp); + &bgp, uj); if (!idx) return CMD_WARNING; @@ -9343,7 +9345,7 @@ DEFUN (show_ip_bgp_regexp, int idx = 0; bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, - &bgp); + &bgp, false); if (!idx) return CMD_WARNING; @@ -9372,17 +9374,17 @@ DEFUN (show_ip_bgp_instance_all, afi_t afi = AFI_IP; safi_t safi = SAFI_UNICAST; struct bgp *bgp = NULL; - int idx = 0; - bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, - &bgp); - if (!idx) - return CMD_WARNING; + bool uj = use_json(argc, argv); - int uj = use_json(argc, argv); if (uj) argc--; + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp, uj); + if (!idx) + return CMD_WARNING; + bgp_show_all_instances_routes_vty(vty, afi, safi, uj); return CMD_SUCCESS; } @@ -9453,7 +9455,7 @@ static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, static int bgp_show_community(struct vty *vty, struct bgp *bgp, const char *comstr, int exact, afi_t afi, - safi_t safi, uint8_t use_json) + safi_t safi, bool use_json) { struct community *com; int ret = 0; @@ -9512,7 +9514,7 @@ static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, } static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp, - const char *ip_str, uint8_t use_json) + const char *ip_str, bool use_json) { int ret; struct peer *peer; @@ -9899,7 +9901,7 @@ static int bgp_peer_count_walker(struct thread *t) } static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi, - safi_t safi, uint8_t use_json) + safi_t safi, bool use_json) { struct peer_pcounts pcounts = {.peer = peer}; unsigned int i; @@ -10009,16 +10011,16 @@ DEFUN (show_ip_bgp_instance_neighbor_prefix_counts, struct peer *peer; int idx = 0; struct bgp *bgp = NULL; + bool uj = use_json(argc, argv); + + if (uj) + argc--; bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, - &bgp); + &bgp, uj); if (!idx) return CMD_WARNING; - int uj = use_json(argc, argv); - if (uj) - argc--; - argv_find(argv, argc, "neighbors", &idx); peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj); if (!peer) @@ -10045,7 +10047,7 @@ DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts, { int idx_peer = 6; struct peer *peer; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj); if (!peer) @@ -10118,7 +10120,7 @@ DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix, static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, enum bgp_show_adj_route_type type, - const char *rmap_name, uint8_t use_json, + const char *rmap_name, bool use_json, json_object *json) { struct bgp_table *table; @@ -10389,7 +10391,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, enum bgp_show_adj_route_type type, - const char *rmap_name, uint8_t use_json) + const char *rmap_name, bool use_json) { json_object *json = NULL; @@ -10463,18 +10465,17 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, struct bgp *bgp = NULL; struct peer *peer; enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised; - int idx = 0; - bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, - &bgp); - if (!idx) - return CMD_WARNING; - - int uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (uj) argc--; + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp, uj); + if (!idx) + return CMD_WARNING; + /* neighbors */ argv_find(argv, argc, "neighbors", &idx); peerstr = argv[++idx]->arg; @@ -10536,7 +10537,7 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter, argv_find(argv, argc, "neighbors", &idx); peerstr = argv[++idx]->arg; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); ret = str2sockunion(peerstr, &su); if (ret < 0) { @@ -10580,7 +10581,7 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter, static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, - enum bgp_show_type type, uint8_t use_json) + enum bgp_show_type type, bool use_json) { /* labeled-unicast routes live in the unicast table */ if (safi == SAFI_LABELED_UNICAST) @@ -10620,14 +10621,17 @@ DEFUN (show_ip_bgp_flowspec_routes_detailed, safi_t safi = SAFI_UNICAST; struct bgp *bgp = NULL; int idx = 0; + bool uj = use_json(argc, argv); + + if (uj) + argc--; bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, - &bgp); + &bgp, uj); if (!idx) return CMD_WARNING; - return bgp_show(vty, bgp, afi, safi, - bgp_show_type_detail, NULL, use_json(argc, argv)); + return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj); } DEFUN (show_ip_bgp_neighbor_routes, @@ -10655,18 +10659,17 @@ DEFUN (show_ip_bgp_neighbor_routes, safi_t safi = SAFI_UNICAST; struct peer *peer; enum bgp_show_type sh_type = bgp_show_type_neighbor; - int idx = 0; + bool uj = use_json(argc, argv); + + if (uj) + argc--; bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, - &bgp); + &bgp, uj); if (!idx) return CMD_WARNING; - int uj = use_json(argc, argv); - if (uj) - argc--; - /* neighbors */ argv_find(argv, argc, "neighbors", &idx); peerstr = argv[++idx]->arg; diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index dfef9a8f7915..476bb3aa0508 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -435,8 +435,9 @@ extern void route_vty_out(struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *); extern void route_vty_out_tag(struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *); -extern void route_vty_out_tmp(struct vty *, struct prefix *, struct attr *, - safi_t, uint8_t, json_object *); +extern void route_vty_out_tmp(struct vty *vty, struct prefix *p, + struct attr *attr, safi_t safi, bool use_json, + json_object *json_ar); extern void route_vty_out_overlay(struct vty *vty, struct prefix *p, struct bgp_info *binfo, int display, json_object *json); @@ -484,5 +485,5 @@ extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp, extern int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, struct bgp_table *table, struct prefix_rd *prd, enum bgp_show_type type, void *output_arg, - uint8_t use_json); + bool use_json); #endif /* _QUAGGA_BGP_ROUTE_H */ diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 82b268c31d8b..2e0bb1ae6223 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -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" diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c index a771eedf0f74..2b4477dddef4 100644 --- a/bgpd/bgp_vpn.c +++ b/bgpd/bgp_vpn.c @@ -32,7 +32,7 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, struct prefix_rd *prd, afi_t afi, safi_t safi, - uint8_t use_json) + bool use_json) { struct bgp *bgp; struct bgp_table *table; diff --git a/bgpd/bgp_vpn.h b/bgpd/bgp_vpn.h index 98b4d9f1803c..a2e86476a2e5 100644 --- a/bgpd/bgp_vpn.h +++ b/bgpd/bgp_vpn.h @@ -25,6 +25,6 @@ extern int show_adj_route_vpn(struct vty *vty, struct peer *peer, struct prefix_rd *prd, afi_t afi, safi_t safi, - uint8_t use_json); + bool use_json); #endif /* _QUAGGA_BGP_VPN_H */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 1460a26215bb..3669ea773618 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -301,7 +301,7 @@ int argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, struct cmd_token **argv, int argc, int *idx, afi_t *afi, safi_t *safi, - struct bgp **bgp) + struct bgp **bgp, bool use_json) { char *vrf_name = NULL; @@ -312,18 +312,24 @@ int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, if (argv_find(argv, argc, "ip", idx)) *afi = AFI_IP; - if (argv_find(argv, argc, "view", idx) - || argv_find(argv, argc, "vrf", idx)) { + if (argv_find(argv, argc, "view", idx)) vrf_name = argv[*idx + 1]->arg; - + else if (argv_find(argv, argc, "vrf", idx)) { + vrf_name = argv[*idx + 1]->arg; + if (strmatch(vrf_name, VRF_DEFAULT_NAME)) + vrf_name = NULL; + } + if (vrf_name) { if (strmatch(vrf_name, "all")) *bgp = NULL; else { *bgp = bgp_lookup_by_name(vrf_name); if (!*bgp) { - vty_out(vty, - "View/Vrf specified is unknown: %s\n", - vrf_name); + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, "View/Vrf %s is unknown\n", + vrf_name); *idx = 0; return 0; } @@ -331,7 +337,11 @@ int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, } else { *bgp = bgp_get_default(); if (!*bgp) { - vty_out(vty, "Unable to find default BGP instance\n"); + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, + "Default BGP instance not found\n"); *idx = 0; return 0; } @@ -910,9 +920,12 @@ DEFUN_NOSH (router_bgp, if (argc > 3) { name = argv[idx_vrf]->arg; - if (!strcmp(argv[idx_view_vrf]->text, "vrf")) - inst_type = BGP_INSTANCE_TYPE_VRF; - else if (!strcmp(argv[idx_view_vrf]->text, "view")) + if (!strcmp(argv[idx_view_vrf]->text, "vrf")) { + if (strmatch(name, VRF_DEFAULT_NAME)) + name = NULL; + else + inst_type = BGP_INSTANCE_TYPE_VRF; + } else if (!strcmp(argv[idx_view_vrf]->text, "view")) inst_type = BGP_INSTANCE_TYPE_VIEW; } @@ -7144,13 +7157,17 @@ DEFUN (clear_ip_bgp_all, if (argv_find(argv, argc, "ip", &idx)) afi = AFI_IP; - /* [ VIEWVRFNAME] */ - if (argv_find(argv, argc, "view", &idx) - || argv_find(argv, argc, "vrf", &idx)) { + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + idx += 2; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } else if (argv_find(argv, argc, "view", &idx)) { + /* [ VIEWVRFNAME] */ vrf = argv[idx + 1]->arg; idx += 2; } - /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) argv_find_and_parse_safi(argv, argc, &idx, &safi); @@ -7215,8 +7232,16 @@ DEFUN (clear_ip_bgp_prefix, int idx = 0; /* [ VIEWVRFNAME] */ - if (argv_find(argv, argc, "VIEWVRFNAME", &idx)) - vrf = argv[idx]->arg; + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + idx += 2; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } else if (argv_find(argv, argc, "view", &idx)) { + /* [ VIEWVRFNAME] */ + vrf = argv[idx + 1]->arg; + idx += 2; + } prefix = argv[argc - 1]->arg; @@ -7258,16 +7283,23 @@ DEFUN (clear_bgp_instance_ipv6_safi_prefix, "Clear bestpath and re-advertise\n" "IPv6 prefix\n") { - int idx_word = 3; int idx_safi = 0; + int idx_vrfview = 0; int idx_ipv6_prefix = 0; safi_t safi = SAFI_UNICAST; char *prefix = argv_find(argv, argc, "X:X::X:X/M", &idx_ipv6_prefix) ? argv[idx_ipv6_prefix]->arg : NULL; - /* [ VIEWVRFNAME] */ - char *vrfview = argv_find(argv, argc, "VIEWVRFNAME", &idx_word) ? - argv[idx_word]->arg : NULL; + char *vrfview = NULL; + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx_vrfview)) { + vrfview = argv[idx_vrfview + 1]->arg; + if (vrfview && strmatch(vrfview, VRF_DEFAULT_NAME)) + vrfview = NULL; + } else if (argv_find(argv, argc, "view", &idx_vrfview)) { + /* [ VIEWVRFNAME] */ + vrfview = argv[idx_vrfview + 1]->arg; + } argv_find_and_parse_safi(argv, argc, &idx_safi, &safi); return bgp_clear_prefix( @@ -7317,7 +7349,7 @@ DEFUN (show_bgp_vrfs, struct list *inst = bm->bgp; struct listnode *node; struct bgp *bgp; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); json_object *json = NULL; json_object *json_vrfs = NULL; int count = 0; @@ -7458,10 +7490,18 @@ DEFUN(show_bgp_martian_nexthop_db, show_bgp_martian_nexthop_db_cmd, { struct bgp *bgp = NULL; int idx = 0; - - if (argv_find(argv, argc, "view", &idx) - || argv_find(argv, argc, "vrf", &idx)) - bgp = bgp_lookup_by_name(argv[idx + 1]->arg); + char *name = NULL; + + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx)) { + name = argv[idx + 1]->arg; + if (name && strmatch(name, VRF_DEFAULT_NAME)) + name = NULL; + } else if (argv_find(argv, argc, "view", &idx)) + /* [ VIEWVRFNAME] */ + name = argv[idx + 1]->arg; + if (name) + bgp = bgp_lookup_by_name(name); else bgp = bgp_get_default(); @@ -7638,7 +7678,7 @@ static void bgp_show_bestpath_json(struct bgp *bgp, json_object *json) /* Show BGP peer's summary information. */ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, - uint8_t use_json, json_object *json) + bool use_json, json_object *json) { struct peer *peer; struct listnode *node, *nnode; @@ -8055,14 +8095,14 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, } static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, - int safi, uint8_t use_json, + int safi, bool use_json, json_object *json) { int is_first = 1; int afi_wildcard = (afi == AFI_MAX); int safi_wildcard = (safi == SAFI_MAX); int is_wildcard = (afi_wildcard || safi_wildcard); - bool json_output = false; + bool nbr_output = false; if (use_json && is_wildcard) vty_out(vty, "{\n"); @@ -8073,7 +8113,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, safi = 1; /* SAFI_UNICAST */ while (safi < SAFI_MAX) { if (bgp_afi_safi_peer_exists(bgp, afi, safi)) { - json_output = true; + nbr_output = true; if (is_wildcard) { /* * So limit output to those afi/safi @@ -8112,22 +8152,28 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, if (use_json && is_wildcard) vty_out(vty, "}\n"); - else if (use_json && !json_output) - vty_out(vty, "{}\n"); + else if (!nbr_output) { + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, "%% No BGP neighbors found\n"); + } } static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, - safi_t safi, uint8_t use_json) + safi_t safi, bool use_json) { struct listnode *node, *nnode; struct bgp *bgp; json_object *json = NULL; int is_first = 1; + bool nbr_output = false; if (use_json) vty_out(vty, "{\n"); for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + nbr_output = true; if (use_json) { json = json_object_new_object(); @@ -8151,10 +8197,12 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, if (use_json) vty_out(vty, "}\n"); + else if (!nbr_output) + vty_out(vty, "%% BGP instance not found\n"); } int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, - safi_t safi, uint8_t use_json) + safi_t safi, bool use_json) { struct bgp *bgp; @@ -8171,7 +8219,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, vty_out(vty, "{}\n"); else vty_out(vty, - "%% No such BGP instance exist\n"); + "%% BGP instance not found\n"); return CMD_WARNING; } @@ -8185,6 +8233,13 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, if (bgp) bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json, NULL); + else { + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, "%% BGP instance not found\n"); + return CMD_WARNING; + } return CMD_SUCCESS; } @@ -8211,16 +8266,20 @@ DEFUN (show_ip_bgp_summary, /* show [ip] bgp */ if (argv_find(argv, argc, "ip", &idx)) afi = AFI_IP; - /* [ VIEWVRFNAME] */ - if (argv_find(argv, argc, "view", &idx) - || argv_find(argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } else if (argv_find(argv, argc, "view", &idx)) + /* [ VIEWVRFNAME] */ + vrf = argv[idx + 1]->arg; /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { argv_find_and_parse_safi(argv, argc, &idx, &safi); } - int uj = use_json(argc, argv); + bool uj = use_json(argc, argv); return bgp_show_summary_vty(vty, vrf, afi, safi, uj); } @@ -8302,7 +8361,7 @@ static void bgp_show_peer_afi_orf_cap(struct vty *vty, struct peer *p, afi_t afi, safi_t safi, uint16_t adv_smcap, uint16_t adv_rmcap, uint16_t rcv_smcap, uint16_t rcv_rmcap, - uint8_t use_json, json_object *json_pref) + bool use_json, json_object *json_pref) { /* Send-Mode */ if (CHECK_FLAG(p->af_cap[afi][safi], adv_smcap) @@ -8362,7 +8421,7 @@ static void bgp_show_peer_afi_orf_cap(struct vty *vty, struct peer *p, } static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi, - safi_t safi, uint8_t use_json, + safi_t safi, bool use_json, json_object *json_neigh) { struct bgp_filter *filter; @@ -8937,7 +8996,7 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi, } } -static void bgp_show_peer(struct vty *vty, struct peer *p, uint8_t use_json, +static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, json_object *json) { struct bgp *bgp; @@ -10684,12 +10743,13 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, uint8_t use_json, static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp, enum show_type type, union sockunion *su, - const char *conf_if, uint8_t use_json, + const char *conf_if, bool use_json, json_object *json) { struct listnode *node, *nnode; struct peer *peer; int find = 0; + bool nbr_output = false; for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) @@ -10698,6 +10758,7 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp, switch (type) { case show_all: bgp_show_peer(vty, peer, use_json, json); + nbr_output = true; break; case show_peer: if (conf_if) { @@ -10727,6 +10788,9 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp, vty_out(vty, "%% No such neighbor in this view/vrf\n"); } + if (type != show_peer && !nbr_output && !use_json) + vty_out(vty, "%% No BGP neighbors found\n"); + if (use_json) { vty_out(vty, "%s\n", json_object_to_json_string_ext( json, JSON_C_TO_STRING_PRETTY)); @@ -10741,18 +10805,20 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp, static void bgp_show_all_instances_neighbors_vty(struct vty *vty, enum show_type type, const char *ip_str, - uint8_t use_json) + bool use_json) { struct listnode *node, *nnode; struct bgp *bgp; union sockunion su; json_object *json = NULL; int ret, is_first = 1; + bool nbr_output = false; if (use_json) vty_out(vty, "{\n"); for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + nbr_output = true; if (use_json) { if (!(json = json_object_new_object())) { flog_err( @@ -10805,11 +10871,13 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty, if (use_json) vty_out(vty, "}\n"); + else if (!nbr_output) + vty_out(vty, "%% BGP instance not found\n"); } static int bgp_show_neighbor_vty(struct vty *vty, const char *name, enum show_type type, const char *ip_str, - uint8_t use_json) + bool use_json) { int ret; struct bgp *bgp; @@ -10826,8 +10894,6 @@ static int bgp_show_neighbor_vty(struct vty *vty, const char *name, if (!bgp) { if (use_json) { json = json_object_new_object(); - json_object_boolean_true_add( - json, "bgpNoSuchInstance"); vty_out(vty, "%s\n", json_object_to_json_string_ext( json, @@ -10835,7 +10901,7 @@ static int bgp_show_neighbor_vty(struct vty *vty, const char *name, json_object_free(json); } else vty_out(vty, - "%% No such BGP instance exist\n"); + "%% BGP instance not found\n"); return CMD_WARNING; } @@ -10859,6 +10925,11 @@ static int bgp_show_neighbor_vty(struct vty *vty, const char *name, json); } json_object_free(json); + } else { + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, "%% BGP instance not found\n"); } return CMD_SUCCESS; @@ -10884,12 +10955,17 @@ DEFUN (show_ip_bgp_neighbors, char *sh_arg = NULL; enum show_type sh_type; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); int idx = 0; - if (argv_find(argv, argc, "view", &idx) - || argv_find(argv, argc, "vrf", &idx)) + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } else if (argv_find(argv, argc, "view", &idx)) + /* [ VIEWVRFNAME] */ vrf = argv[idx + 1]->arg; idx++; @@ -10994,8 +11070,8 @@ DEFUN (show_ip_bgp_attr_info, return CMD_SUCCESS; } -static int bgp_show_route_leak_vty(struct vty *vty, const char *name, - afi_t afi, safi_t safi, uint8_t use_json) +static int bgp_show_route_leak_vty(struct vty *vty, const char *name, afi_t afi, + safi_t safi, bool use_json) { struct bgp *bgp; struct listnode *node; @@ -11011,16 +11087,9 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, json = json_object_new_object(); - /* Provide context for the block */ - json_object_string_add(json, "vrf", name ? name : "default"); - json_object_string_add(json, "afiSafi", - afi_safi_print(afi, safi)); - bgp = name ? bgp_lookup_by_name(name) : bgp_get_default(); if (!bgp) { - json_object_boolean_true_add(json, - "bgpNoSuchInstance"); vty_out(vty, "%s\n", json_object_to_json_string_ext( json, @@ -11030,6 +11099,11 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, return CMD_WARNING; } + /* Provide context for the block */ + json_object_string_add(json, "vrf", name ? name : "default"); + json_object_string_add(json, "afiSafi", + afi_safi_print(afi, safi)); + if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT)) { json_object_string_add(json, "importFromVrfs", "none"); @@ -11168,7 +11242,7 @@ DEFUN (show_ip_bgp_route_leak, afi_t afi = AFI_MAX; safi_t safi = SAFI_MAX; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); int idx = 0; /* show [ip] bgp */ @@ -11183,8 +11257,11 @@ DEFUN (show_ip_bgp_route_leak, return CMD_WARNING; } - if (argv_find(argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { argv_find_and_parse_safi(argv, argc, &idx, &safi); @@ -11257,10 +11334,14 @@ DEFUN (show_ip_bgp_updgrps, /* show [ip] bgp */ if (argv_find(argv, argc, "ip", &idx)) afi = AFI_IP; - /* [ VIEWVRFNAME] */ - if (argv_find(argv, argc, "view", &idx) - || argv_find(argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } else if (argv_find(argv, argc, "view", &idx)) + /* [ VIEWVRFNAME] */ + vrf = argv[idx + 1]->arg; /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { argv_find_and_parse_safi(argv, argc, &idx, &safi); @@ -11486,7 +11567,7 @@ static int bgp_show_peer_group_vty(struct vty *vty, const char *name, bgp = name ? bgp_lookup_by_name(name) : bgp_get_default(); if (!bgp) { - vty_out(vty, "%% No such BGP instance exists\n"); + vty_out(vty, "%% BGP instance not found\n"); return CMD_WARNING; } diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index afb85f112b85..d9df2b4cfeda 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -69,9 +69,10 @@ extern int argv_find_and_parse_safi(struct cmd_token **argv, int argc, extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, struct cmd_token **argv, int argc, int *idx, afi_t *afi, - safi_t *safi, struct bgp **bgp); + safi_t *safi, struct bgp **bgp, + bool use_json); extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, - safi_t safi, uint8_t use_json); + safi_t safi, bool use_json); extern void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp, afi_t afi); #endif /* _QUAGGA_BGP_VTY_H */ diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index f42c16c1c1d4..43afc317e9b3 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2380,7 +2380,8 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, int ipa_len; char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; - uint8_t flags; + uint8_t flags = 0; + uint32_t seqnum = 0; memset(&ip, 0, sizeof(ip)); s = zclient->ibuf; @@ -2401,20 +2402,24 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 : IPADDR_V6; stream_get(&ip.ip.addr, s, ipa_len); } - flags = stream_getc(s); + if (command == ZEBRA_MACIP_ADD) { + flags = stream_getc(s); + seqnum = stream_getl(s); + } bgp = bgp_lookup_by_vrf_id(vrf_id); if (!bgp) return 0; if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u", + zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u", vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags, prefix_mac2str(&mac, buf, sizeof(buf)), - ipaddr2str(&ip, buf1, sizeof(buf1)), vni); + ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum); if (command == ZEBRA_MACIP_ADD) - return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, flags); + return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, + flags, seqnum); else return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip); } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 7ff5053ce37a..a9707a7fc73a 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -6626,7 +6626,7 @@ int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi, } /* Display peer uptime.*/ -char *peer_uptime(time_t uptime2, char *buf, size_t len, uint8_t use_json, +char *peer_uptime(time_t uptime2, char *buf, size_t len, bool use_json, json_object *json) { time_t uptime1, epoch_tbuf; @@ -7735,10 +7735,8 @@ static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token) struct listnode *next; struct bgp *bgp; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if (vrf->vrf_id != VRF_DEFAULT) - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); - } + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) { if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) @@ -7767,8 +7765,8 @@ static void bgp_pthreads_init() .start = bgp_keepalives_start, .stop = bgp_keepalives_stop, }; - frr_pthread_new(&io, "BGP I/O thread"); - frr_pthread_new(&ka, "BGP Keepalives thread"); + frr_pthread_new(&io, "BGP I/O thread", "bgpd_io"); + frr_pthread_new(&ka, "BGP Keepalives thread", "bgpd_ka"); } void bgp_pthreads_run() diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 06eb86da9555..8a997413901c 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1513,7 +1513,8 @@ extern struct peer *peer_create(union sockunion *, const char *, struct bgp *, struct peer_group *); extern struct peer *peer_create_accept(struct bgp *); extern void peer_xfer_config(struct peer *dst, struct peer *src); -extern char *peer_uptime(time_t, char *, size_t, uint8_t, json_object *); +extern char *peer_uptime(time_t uptime2, char *buf, size_t len, bool use_json, + json_object *json); extern int bgp_config_write(struct vty *); diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index 8553846c9025..f1dd08fda082 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -23,7 +23,7 @@ #include "lib/prefix.h" #include "lib/memory.h" #include "lib/linklist.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/plist.h" #include "lib/routemap.h" @@ -126,10 +126,10 @@ struct rfapi_nve_group_cfg *bgp_rfapi_cfg_match_group(struct rfapi_cfg *hc, struct rfapi_nve_group_cfg *rfg_vn = NULL; struct rfapi_nve_group_cfg *rfg_un = NULL; - struct route_table *rt_vn; - struct route_table *rt_un; - struct route_node *rn_vn; - struct route_node *rn_un; + struct agg_table *rt_vn; + struct agg_table *rt_un; + struct agg_node *rn_vn; + struct agg_node *rn_un; struct rfapi_nve_group_cfg *rfg; struct listnode *node, *nnode; @@ -156,16 +156,16 @@ struct rfapi_nve_group_cfg *bgp_rfapi_cfg_match_group(struct rfapi_cfg *hc, return NULL; } - rn_vn = route_node_match(rt_vn, vn); /* NB locks node */ + rn_vn = agg_node_match(rt_vn, vn); /* NB locks node */ if (rn_vn) { rfg_vn = rn_vn->info; - route_unlock_node(rn_vn); + agg_unlock_node(rn_vn); } - rn_un = route_node_match(rt_un, un); /* NB locks node */ + rn_un = agg_node_match(rt_un, un); /* NB locks node */ if (rn_un) { rfg_un = rn_un->info; - route_unlock_node(rn_un); + agg_unlock_node(rn_un); } #if BGP_VNC_DEBUG_MATCH_GROUP @@ -2304,11 +2304,11 @@ static void bgp_rfapi_delete_nve_group(struct vty *vty, /* NULL = no output */ if (rfg->vn_node) { rfg->vn_node->info = NULL; - route_unlock_node(rfg->vn_node); /* frees */ + agg_unlock_node(rfg->vn_node); /* frees */ } if (rfg->un_node) { rfg->un_node->info = NULL; - route_unlock_node(rfg->un_node); /* frees */ + agg_unlock_node(rfg->un_node); /* frees */ } if (rfg->rfp_cfg) XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg); @@ -2468,8 +2468,8 @@ DEFUN (vnc_nve_group_prefix, VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); struct prefix p; afi_t afi; - struct route_table *rt; - struct route_node *rn; + struct agg_table *rt; + struct agg_node *rn; int is_un_prefix = 0; /* make sure it's still in list */ @@ -2497,12 +2497,12 @@ DEFUN (vnc_nve_group_prefix, rt = bgp->rfapi_cfg->nve_groups_vn[afi]; } - rn = route_node_get(rt, &p); /* NB locks node */ + rn = agg_node_get(rt, &p); /* NB locks node */ if (rn->info) { /* * There is already a group with this prefix */ - route_unlock_node(rn); + agg_unlock_node(rn); if (rn->info != rfg) { /* * different group name: fail @@ -2535,7 +2535,7 @@ DEFUN (vnc_nve_group_prefix, /* detach rfg from previous route table location */ if (rfg->un_node) { rfg->un_node->info = NULL; - route_unlock_node(rfg->un_node); /* frees */ + agg_unlock_node(rfg->un_node); /* frees */ } rfg->un_node = rn; /* back ref */ rfg->un_prefix = p; @@ -2545,7 +2545,7 @@ DEFUN (vnc_nve_group_prefix, /* detach rfg from previous route table location */ if (rfg->vn_node) { rfg->vn_node->info = NULL; - route_unlock_node(rfg->vn_node); /* frees */ + agg_unlock_node(rfg->vn_node); /* frees */ } rfg->vn_node = rn; /* back ref */ rfg->vn_prefix = p; @@ -3761,8 +3761,8 @@ struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg) h->nve_groups_sequential = list_new(); assert(h->nve_groups_sequential); for (afi = AFI_IP; afi < AFI_MAX; afi++) { - h->nve_groups_vn[afi] = route_table_init(); - h->nve_groups_un[afi] = route_table_init(); + h->nve_groups_vn[afi] = agg_table_init(); + h->nve_groups_un[afi] = agg_table_init(); } h->default_response_lifetime = BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT; @@ -3820,8 +3820,8 @@ void bgp_rfapi_cfg_destroy(struct bgp *bgp, struct rfapi_cfg *h) if (h->default_rfp_cfg) XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, h->default_rfp_cfg); for (afi = AFI_IP; afi < AFI_MAX; afi++) { - route_table_finish(h->nve_groups_vn[afi]); - route_table_finish(h->nve_groups_un[afi]); + agg_table_finish(h->nve_groups_vn[afi]); + agg_table_finish(h->nve_groups_un[afi]); } XFREE(MTYPE_RFAPI_CFG, h); } diff --git a/bgpd/rfapi/bgp_rfapi_cfg.h b/bgpd/rfapi/bgp_rfapi_cfg.h index a11b0992fa93..b72d38220be4 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.h +++ b/bgpd/rfapi/bgp_rfapi_cfg.h @@ -47,8 +47,8 @@ typedef enum { } rfapi_group_cfg_type_t; struct rfapi_nve_group_cfg { - struct route_node *vn_node; /* backref */ - struct route_node *un_node; /* backref */ + struct agg_node *vn_node; /* backref */ + struct agg_node *un_node; /* backref */ rfapi_group_cfg_type_t type; /* NVE|VPN */ char *name; /* unique by type! */ @@ -135,8 +135,8 @@ struct rfapi_cfg { struct list *l2_groups; /* rfapi_l2_group_cfg list */ /* three views into the same collection of rfapi_nve_group_cfg */ struct list *nve_groups_sequential; - struct route_table *nve_groups_vn[AFI_MAX]; - struct route_table *nve_groups_un[AFI_MAX]; + struct agg_table *nve_groups_vn[AFI_MAX]; + struct agg_table *nve_groups_un[AFI_MAX]; /* * For Single VRF export to ordinary routing protocols. This is diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 355cf9205343..51504bb0ad50 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -18,12 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include - #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/vty.h" #include "lib/memory.h" #include "lib/routemap.h" @@ -203,11 +200,11 @@ int rfapi_ip_addr_cmp(struct rfapi_ip_addr *a1, struct rfapi_ip_addr *a2) static int rfapi_find_node(struct bgp *bgp, struct rfapi_ip_addr *vn_addr, struct rfapi_ip_addr *un_addr, - struct route_node **node) + struct agg_node **node) { struct rfapi *h; struct prefix p; - struct route_node *rn; + struct agg_node *rn; int rc; afi_t afi; @@ -228,12 +225,12 @@ static int rfapi_find_node(struct bgp *bgp, struct rfapi_ip_addr *vn_addr, if ((rc = rfapiRaddr2Qprefix(un_addr, &p))) return rc; - rn = route_node_lookup(h->un[afi], &p); + rn = agg_node_lookup(h->un[afi], &p); if (!rn) return ENOENT; - route_unlock_node(rn); + agg_unlock_node(rn); *node = rn; @@ -244,7 +241,7 @@ static int rfapi_find_node(struct bgp *bgp, struct rfapi_ip_addr *vn_addr, int rfapi_find_rfd(struct bgp *bgp, struct rfapi_ip_addr *vn_addr, struct rfapi_ip_addr *un_addr, struct rfapi_descriptor **rfd) { - struct route_node *rn; + struct agg_node *rn; int rc; rc = rfapi_find_node(bgp, vn_addr, un_addr, &rn); @@ -1347,8 +1344,8 @@ static int rfapi_open_inner(struct rfapi_descriptor *rfd, struct bgp *bgp, #define RFD_RTINIT_AFI(rh, ary, afi) \ do { \ if (!ary[afi]) { \ - ary[afi] = route_table_init(); \ - ary[afi]->info = rh; \ + ary[afi] = agg_table_init(); \ + agg_set_table_info(ary[afi], rh); \ } \ } while (0) @@ -1394,7 +1391,7 @@ int rfapi_init_and_open(struct bgp *bgp, struct rfapi_descriptor *rfd, char buf_un[BUFSIZ]; afi_t afi_vn, afi_un; struct prefix pfx_un; - struct route_node *rn; + struct agg_node *rn; rfapi_time(&rfd->open_time); @@ -1423,7 +1420,7 @@ int rfapi_init_and_open(struct bgp *bgp, struct rfapi_descriptor *rfd, assert(afi_vn && afi_un); assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx_un)); - rn = route_node_get(h->un[afi_un], &pfx_un); + rn = agg_node_get(h->un[afi_un], &pfx_un); assert(rn); rfd->next = rn->info; rn->info = rfd; @@ -1535,7 +1532,7 @@ rfapi_query_inner(void *handle, struct rfapi_ip_addr *target, afi_t afi; struct prefix p; struct prefix p_original; - struct route_node *rn; + struct agg_node *rn; struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle; struct bgp *bgp = rfd->bgp; struct rfapi_next_hop_entry *pNHE = NULL; @@ -1704,7 +1701,7 @@ rfapi_query_inner(void *handle, struct rfapi_ip_addr *target, } if (rn) { - route_lock_node(rn); /* so we can unlock below */ + agg_lock_node(rn); /* so we can unlock below */ } else { /* * returns locked node. Don't unlock yet because the @@ -1721,7 +1718,7 @@ rfapi_query_inner(void *handle, struct rfapi_ip_addr *target, assert(rn); if (!rn->info) { - route_unlock_node(rn); + agg_unlock_node(rn); vnc_zlog_debug_verbose( "%s: VPN route not found, returning ENOENT", __func__); return ENOENT; @@ -1758,7 +1755,7 @@ rfapi_query_inner(void *handle, struct rfapi_ip_addr *target, &p_original); } - route_unlock_node(rn); + agg_unlock_node(rn); done: if (ppNextHopEntry) { @@ -2170,7 +2167,7 @@ int rfapi_close(void *handle) { struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle; int rc; - struct route_node *node; + struct agg_node *node; struct bgp *bgp; struct rfapi *h; @@ -2276,7 +2273,7 @@ int rfapi_close(void *handle) } } } - route_unlock_node(node); + agg_unlock_node(node); } /* @@ -2928,6 +2925,8 @@ static void test_nexthops_callback( rfapiPrintNhl(stream, next_hops); + fp(out, "\n"); + rfapi_free_next_hop_list(next_hops); } @@ -3049,7 +3048,7 @@ DEFUN (debug_rfapi_close_rfd, DEFUN (debug_rfapi_register_vn_un, debug_rfapi_register_vn_un_cmd, - "debug rfapi-dev register vn un prefix lifetime SECONDS", + "debug rfapi-dev register vn un prefix lifetime SECONDS [cost (0-255)]", DEBUG_STR DEBUG_RFAPI_STR "rfapi_register\n" @@ -3063,7 +3062,9 @@ DEFUN (debug_rfapi_register_vn_un, "IPv4 prefix\n" "IPv6 prefix\n" "indicate lifetime follows\n" - "lifetime\n") + "lifetime\n" + "Cost (localpref = 255-cost)\n" + "0-255\n") { struct rfapi_ip_addr vn; struct rfapi_ip_addr un; @@ -3072,6 +3073,7 @@ DEFUN (debug_rfapi_register_vn_un, uint32_t lifetime; struct rfapi_ip_prefix hpfx; int rc; + uint8_t cost = 100; /* * Get VN addr @@ -3112,8 +3114,12 @@ DEFUN (debug_rfapi_register_vn_un, lifetime = strtoul(argv[10]->arg, NULL, 10); } + if (argc >= 13) + cost = (uint8_t) strtoul(argv[12]->arg, NULL, 10); + hpfx.cost = cost; - rc = rfapi_register(handle, &hpfx, lifetime, NULL, NULL, 0); + rc = rfapi_register(handle, &hpfx, lifetime, NULL, NULL, + RFAPI_REGISTER_ADD); if (rc) { vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc, strerror(rc)); @@ -3213,7 +3219,8 @@ DEFUN (debug_rfapi_register_vn_un_l2o, /* L2 option parsing END */ /* TBD fixme */ - rc = rfapi_register(handle, &hpfx, lifetime, NULL /* &uo */, opt, 0); + rc = rfapi_register(handle, &hpfx, lifetime, NULL /* &uo */, opt, + RFAPI_REGISTER_ADD); if (rc) { vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc, strerror(rc)); @@ -3225,7 +3232,7 @@ DEFUN (debug_rfapi_register_vn_un_l2o, DEFUN (debug_rfapi_unregister_vn_un, debug_rfapi_unregister_vn_un_cmd, - "debug rfapi-dev unregister vn un prefix ", + "debug rfapi-dev unregister vn un prefix [kill]", DEBUG_STR DEBUG_RFAPI_STR "rfapi_register\n" @@ -3233,7 +3240,8 @@ DEFUN (debug_rfapi_unregister_vn_un, "virtual network interface address\n" "indicate xt addr follows\n" "underlay network interface address\n" - "indicate prefix follows\n" "prefix") + "prefix to remove\n" + "Remove without holddown") { struct rfapi_ip_addr vn; struct rfapi_ip_addr un; @@ -3275,7 +3283,9 @@ DEFUN (debug_rfapi_unregister_vn_un, } rfapiQprefix2Rprefix(&pfx, &hpfx); - rfapi_register(handle, &hpfx, 0, NULL, NULL, 1); + rfapi_register(handle, &hpfx, 0, NULL, NULL, + (argc == 10 ? + RFAPI_REGISTER_KILL : RFAPI_REGISTER_WITHDRAW)); return CMD_SUCCESS; } diff --git a/bgpd/rfapi/rfapi_ap.c b/bgpd/rfapi/rfapi_ap.c index 3112505d4b1a..c5fda15d33fc 100644 --- a/bgpd/rfapi/rfapi_ap.c +++ b/bgpd/rfapi/rfapi_ap.c @@ -18,11 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/vty.h" #include "lib/memory.h" #include "lib/routemap.h" diff --git a/bgpd/rfapi/rfapi_descriptor_rfp_utils.c b/bgpd/rfapi/rfapi_descriptor_rfp_utils.c index 3217d34e77b3..ce5acf002c20 100644 --- a/bgpd/rfapi/rfapi_descriptor_rfp_utils.c +++ b/bgpd/rfapi/rfapi_descriptor_rfp_utils.c @@ -18,9 +18,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include - #include "lib/zebra.h" #include "lib/prefix.h" #include "lib/table.h" diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index ac3b6da23011..4601718f1209 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -23,11 +23,9 @@ * Purpose: Handle import of routes from BGP to RFAPI */ -#include - #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/vty.h" #include "lib/memory.h" #include "lib/log.h" @@ -80,7 +78,7 @@ */ struct rfapi_withdraw { struct rfapi_import_table *import_table; - struct route_node *node; + struct agg_node *node; struct bgp_info *info; safi_t safi; /* used only for bulk operations */ /* @@ -88,8 +86,8 @@ struct rfapi_withdraw { * Normally when a timer expires, lockoffset should be 0. However, if * the timer expiration function is called directly (e.g., * rfapiExpireVpnNow), the node could be locked by a preceding - * route_top() or route_next() in a loop, so we need to pass this - * value in. + * agg_route_top() or agg_route_next() in a loop, so we need to pass + * this value in. */ int lockoffset; }; @@ -140,8 +138,8 @@ void rfapiCheckRouteCount() for (it = h->imports; it; it = it->next) { for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - struct route_table *rt; - struct route_node *rn; + struct agg_table *rt; + struct agg_node *rn; int holddown_count = 0; int local_count = 0; @@ -150,7 +148,8 @@ void rfapiCheckRouteCount() rt = it->imported_vpn[afi]; - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; + rn = agg_route_next(rn)) { struct bgp_info *bi; struct bgp_info *next; @@ -211,11 +210,11 @@ void rfapiCheckRouteCount() * Validate reference count for a node in an import table * * Normally lockoffset is 0 for nodes in quiescent state. However, - * route_unlock_node will delete the node if it is called when + * agg_unlock_node will delete the node if it is called when * node->lock == 1, and we have to validate the refcount before * the node is deleted. In this case, we specify lockoffset 1. */ -void rfapiCheckRefcount(struct route_node *rn, safi_t safi, int lockoffset) +void rfapiCheckRefcount(struct agg_node *rn, safi_t safi, int lockoffset) { unsigned int count_bi = 0; unsigned int count_monitor = 0; @@ -613,8 +612,8 @@ struct rfapi_import_table *rfapiMacImportTableGet(struct bgp *bgp, uint32_t lni) it->rt_import_list = enew; for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - it->imported_vpn[afi] = route_table_init(); - it->imported_encap[afi] = route_table_init(); + it->imported_vpn[afi] = agg_table_init(); + it->imported_encap[afi] = agg_table_init(); } it->l2_logical_net_id = lni; @@ -633,10 +632,10 @@ struct rfapi_import_table *rfapiMacImportTableGet(struct bgp *bgp, uint32_t lni) * Returns pointer to the list of moved monitors */ static struct rfapi_monitor_vpn * -rfapiMonitorMoveShorter(struct route_node *original_vpn_node, int lockoffset) +rfapiMonitorMoveShorter(struct agg_node *original_vpn_node, int lockoffset) { struct bgp_info *bi; - struct route_node *par; + struct agg_node *par; struct rfapi_monitor_vpn *m; struct rfapi_monitor_vpn *mlast; struct rfapi_monitor_vpn *moved; @@ -679,7 +678,8 @@ rfapiMonitorMoveShorter(struct route_node *original_vpn_node, int lockoffset) * one route (even if it is only a withdrawn route) with a * valid UN address. Call this node "Node P." */ - for (par = original_vpn_node->parent; par; par = par->parent) { + for (par = agg_node_parent(original_vpn_node); par; + par = agg_node_parent(par)) { for (bi = par->info; bi; bi = bi->next) { struct prefix pfx; if (!rfapiGetUnAddrOfVpnBi(bi, &pfx)) { @@ -699,14 +699,14 @@ rfapiMonitorMoveShorter(struct route_node *original_vpn_node, int lockoffset) */ if (!par) { /* this isn't necessarily 0/0 */ - par = route_top(original_vpn_node->table); + par = agg_route_table_top(original_vpn_node); /* * If we got the top node but it wasn't 0/0, * ignore it */ if (par && par->p.prefixlen) { - route_unlock_node(par); /* maybe free */ + agg_unlock_node(par); /* maybe free */ par = NULL; } @@ -725,7 +725,8 @@ rfapiMonitorMoveShorter(struct route_node *original_vpn_node, int lockoffset) pfx_default.family = original_vpn_node->p.family; /* creates default node if none exists */ - par = route_node_get(original_vpn_node->table, &pfx_default); + par = agg_node_get(agg_get_table(original_vpn_node), + &pfx_default); ++parent_already_refcounted; } @@ -764,18 +765,18 @@ rfapiMonitorMoveShorter(struct route_node *original_vpn_node, int lockoffset) RFAPI_CHECK_REFCOUNT(par, SAFI_MPLS_VPN, parent_already_refcounted - movecount); while (movecount > parent_already_refcounted) { - route_lock_node(par); + agg_lock_node(par); ++parent_already_refcounted; } while (movecount < parent_already_refcounted) { /* unlikely, but code defensively */ - route_unlock_node(par); + agg_unlock_node(par); --parent_already_refcounted; } RFAPI_CHECK_REFCOUNT(original_vpn_node, SAFI_MPLS_VPN, movecount + lockoffset); while (movecount--) { - route_unlock_node(original_vpn_node); + agg_unlock_node(original_vpn_node); } #if DEBUG_MONITOR_MOVE_SHORTER @@ -796,12 +797,12 @@ rfapiMonitorMoveShorter(struct route_node *original_vpn_node, int lockoffset) * Implement MONITOR_MOVE_LONGER(new_node) from * RFAPI-Import-Event-Handling.txt */ -static void rfapiMonitorMoveLonger(struct route_node *new_vpn_node) +static void rfapiMonitorMoveLonger(struct agg_node *new_vpn_node) { struct rfapi_monitor_vpn *monitor; struct rfapi_monitor_vpn *mlast; struct bgp_info *bi; - struct route_node *par; + struct agg_node *par; RFAPI_CHECK_REFCOUNT(new_vpn_node, SAFI_MPLS_VPN, 0); @@ -824,7 +825,8 @@ static void rfapiMonitorMoveLonger(struct route_node *new_vpn_node) /* * Find first parent node that has monitors */ - for (par = new_vpn_node->parent; par; par = par->parent) { + for (par = agg_node_parent(new_vpn_node); par; + par = agg_node_parent(par)) { if (RFAPI_MONITOR_VPN(par)) break; } @@ -860,14 +862,14 @@ static void rfapiMonitorMoveLonger(struct route_node *new_vpn_node) RFAPI_MONITOR_VPN_W_ALLOC(new_vpn_node) = monitor; monitor->node = new_vpn_node; - route_lock_node(new_vpn_node); /* incr refcount */ + agg_lock_node(new_vpn_node); /* incr refcount */ monitor = mlast ? mlast->next : RFAPI_MONITOR_VPN(par); RFAPI_CHECK_REFCOUNT(par, SAFI_MPLS_VPN, 1); /* decr refcount after we're done with par as this might * free it */ - route_unlock_node(par); + agg_unlock_node(par); continue; } @@ -919,10 +921,10 @@ static void rfapiImportTableFlush(struct rfapi_import_table *it) for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - struct route_node *rn; + struct agg_node *rn; - for (rn = route_top(it->imported_vpn[afi]); rn; - rn = route_next(rn)) { + for (rn = agg_route_top(it->imported_vpn[afi]); rn; + rn = agg_route_next(rn)) { /* * Each route_node has: * aggregate: points to rfapi_it_extra with monitor @@ -936,8 +938,8 @@ static void rfapiImportTableFlush(struct rfapi_import_table *it) rfapiMonitorExtraFlush(SAFI_MPLS_VPN, rn); } - for (rn = route_top(it->imported_encap[afi]); rn; - rn = route_next(rn)) { + for (rn = agg_route_top(it->imported_encap[afi]); rn; + rn = agg_route_next(rn)) { /* free bgp_info and its children */ rfapiBgpInfoChainFree(rn->info); rn->info = NULL; @@ -945,8 +947,8 @@ static void rfapiImportTableFlush(struct rfapi_import_table *it) rfapiMonitorExtraFlush(SAFI_ENCAP, rn); } - route_table_finish(it->imported_vpn[afi]); - route_table_finish(it->imported_encap[afi]); + agg_table_finish(it->imported_vpn[afi]); + agg_table_finish(it->imported_encap[afi]); } if (it->monitor_exterior_orphans) { skiplist_free(it->monitor_exterior_orphans); @@ -1293,9 +1295,9 @@ int rfapi_extract_l2o( static struct rfapi_next_hop_entry * rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, - struct bgp_info *bi, /* route to encode */ - uint32_t lifetime, /* use this in nhe */ - struct route_node *rn) /* req for L2 eth addr */ + struct bgp_info *bi, /* route to encode */ + uint32_t lifetime, /* use this in nhe */ + struct agg_node *rn) /* req for L2 eth addr */ { struct rfapi_next_hop_entry *new; int have_vnc_tunnel_un = 0; @@ -1481,7 +1483,7 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, return new; } -int rfapiHasNonRemovedRoutes(struct route_node *rn) +int rfapiHasNonRemovedRoutes(struct agg_node *rn) { struct bgp_info *bi; @@ -1501,7 +1503,7 @@ int rfapiHasNonRemovedRoutes(struct route_node *rn) /* * DEBUG FUNCTION */ -void rfapiDumpNode(struct route_node *rn) +void rfapiDumpNode(struct agg_node *rn) { struct bgp_info *bi; @@ -1527,14 +1529,14 @@ void rfapiDumpNode(struct route_node *rn) #endif static int rfapiNhlAddNodeRoutes( - struct route_node *rn, /* in */ + struct agg_node *rn, /* in */ struct rfapi_ip_prefix *rprefix, /* in */ uint32_t lifetime, /* in */ int removed, /* in */ struct rfapi_next_hop_entry **head, /* in/out */ struct rfapi_next_hop_entry **tail, /* in/out */ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_node *rfd_rib_node, /* preload this NVE rib node */ + struct agg_node *rfd_rib_node, /* preload this NVE rib node */ struct prefix *pfx_target_original) /* query target */ { struct bgp_info *bi; @@ -1544,15 +1546,17 @@ static int rfapiNhlAddNodeRoutes( int count = 0; int is_l2 = (rn->p.family == AF_ETHERNET); - if (rfd_rib_node && rfd_rib_node->table && rfd_rib_node->table->info) { + if (rfd_rib_node) { + struct agg_table *atable = agg_get_table(rfd_rib_node); struct rfapi_descriptor *rfd; - rfd = (struct rfapi_descriptor *)(rfd_rib_node->table->info); - - if (rfapiRibFTDFilterRecentPrefix( - rfd, rn, pfx_target_original)) + if (atable) { + rfd = agg_get_table_info(atable); - return 0; + if (rfapiRibFTDFilterRecentPrefix(rfd, rn, + pfx_target_original)) + return 0; + } } seen_nexthops = @@ -1657,13 +1661,13 @@ static int rfapiNhlAddNodeRoutes( * matches (of course, we still travel down its child subtrees). */ static int rfapiNhlAddSubtree( - struct route_node *rn, /* in */ + struct agg_node *rn, /* in */ uint32_t lifetime, /* in */ struct rfapi_next_hop_entry **head, /* in/out */ struct rfapi_next_hop_entry **tail, /* in/out */ - struct route_node *omit_node, /* in */ + struct agg_node *omit_node, /* in */ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload here */ + struct agg_table *rfd_rib_table, /* preload here */ struct prefix *pfx_target_original) /* query target */ { struct rfapi_ip_prefix rprefix; @@ -1671,65 +1675,67 @@ static int rfapiNhlAddSubtree( /* FIXME: need to find a better way here to work without sticking our * hands in node->link */ - if (rn->l_left && rn->l_left != omit_node) { - if (rn->l_left->info) { + if (agg_node_left(rn) && agg_node_left(rn) != omit_node) { + if (agg_node_left(rn)->info) { int count = 0; - struct route_node *rib_rn = NULL; + struct agg_node *rib_rn = NULL; - rfapiQprefix2Rprefix(&rn->l_left->p, &rprefix); + rfapiQprefix2Rprefix(&agg_node_left(rn)->p, &rprefix); if (rfd_rib_table) { - rib_rn = route_node_get(rfd_rib_table, - &rn->l_left->p); + rib_rn = agg_node_get(rfd_rib_table, + &agg_node_left(rn)->p); } count = rfapiNhlAddNodeRoutes( - rn->l_left, &rprefix, lifetime, 0, head, tail, - exclude_vnaddr, rib_rn, pfx_target_original); + agg_node_left(rn), &rprefix, lifetime, 0, head, + tail, exclude_vnaddr, rib_rn, + pfx_target_original); if (!count) { count = rfapiNhlAddNodeRoutes( - rn->l_left, &rprefix, lifetime, 1, head, - tail, exclude_vnaddr, rib_rn, + agg_node_left(rn), &rprefix, lifetime, + 1, head, tail, exclude_vnaddr, rib_rn, pfx_target_original); } rcount += count; if (rib_rn) - route_unlock_node(rib_rn); + agg_unlock_node(rib_rn); } } - if (rn->l_right && rn->l_right != omit_node) { - if (rn->l_right->info) { + if (agg_node_right(rn) && agg_node_right(rn) != omit_node) { + if (agg_node_right(rn)->info) { int count = 0; - struct route_node *rib_rn = NULL; + struct agg_node *rib_rn = NULL; - rfapiQprefix2Rprefix(&rn->l_right->p, &rprefix); + rfapiQprefix2Rprefix(&agg_node_right(rn)->p, &rprefix); if (rfd_rib_table) { - rib_rn = route_node_get(rfd_rib_table, - &rn->l_right->p); + rib_rn = agg_node_get(rfd_rib_table, + &agg_node_right(rn)->p); } count = rfapiNhlAddNodeRoutes( - rn->l_right, &rprefix, lifetime, 0, head, tail, - exclude_vnaddr, rib_rn, pfx_target_original); + agg_node_right(rn), &rprefix, lifetime, 0, head, + tail, exclude_vnaddr, rib_rn, + pfx_target_original); if (!count) { count = rfapiNhlAddNodeRoutes( - rn->l_right, &rprefix, lifetime, 1, - head, tail, exclude_vnaddr, rib_rn, + agg_node_right(rn), &rprefix, lifetime, + 1, head, tail, exclude_vnaddr, rib_rn, pfx_target_original); } rcount += count; if (rib_rn) - route_unlock_node(rib_rn); + agg_unlock_node(rib_rn); } } - if (rn->l_left) { + if (agg_node_left(rn)) { rcount += rfapiNhlAddSubtree( - rn->l_left, lifetime, head, tail, omit_node, + agg_node_left(rn), lifetime, head, tail, omit_node, exclude_vnaddr, rfd_rib_table, pfx_target_original); } - if (rn->l_right) { + if (agg_node_right(rn)) { rcount += rfapiNhlAddSubtree( - rn->l_right, lifetime, head, tail, omit_node, + agg_node_right(rn), lifetime, head, tail, omit_node, exclude_vnaddr, rfd_rib_table, pfx_target_original); } @@ -1748,17 +1754,17 @@ static int rfapiNhlAddSubtree( * next less-specific node (i.e., this node's parent) at the end. */ struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( - struct route_node *rn, uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload here */ - struct prefix *pfx_target_original) /* query target */ + struct agg_node *rn, uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct agg_table *rfd_rib_table, /* preload here */ + struct prefix *pfx_target_original) /* query target */ { struct rfapi_ip_prefix rprefix; struct rfapi_next_hop_entry *answer = NULL; struct rfapi_next_hop_entry *last = NULL; - struct route_node *parent; + struct agg_node *parent; int count = 0; - struct route_node *rib_rn; + struct agg_node *rib_rn; #if DEBUG_RETURNED_NHL { @@ -1773,7 +1779,7 @@ struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( rfapiQprefix2Rprefix(&rn->p, &rprefix); - rib_rn = rfd_rib_table ? route_node_get(rfd_rib_table, &rn->p) : NULL; + rib_rn = rfd_rib_table ? agg_node_get(rfd_rib_table, &rn->p) : NULL; /* * Add non-withdrawn routes at this node @@ -1795,7 +1801,7 @@ struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( rfapiPrintNhl(NULL, answer); #endif if (rib_rn) - route_unlock_node(rib_rn); + agg_unlock_node(rib_rn); return answer; } @@ -1806,7 +1812,7 @@ struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( exclude_vnaddr, rib_rn, pfx_target_original); if (rib_rn) - route_unlock_node(rib_rn); + agg_unlock_node(rib_rn); // rfapiPrintNhl(NULL, answer); @@ -1814,7 +1820,8 @@ struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( * walk up the tree until we find a node with non-deleted * routes, then add them */ - for (parent = rn->parent; parent; parent = parent->parent) { + for (parent = agg_node_parent(rn); parent; + parent = agg_node_parent(parent)) { if (rfapiHasNonRemovedRoutes(parent)) { break; } @@ -1824,9 +1831,8 @@ struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( * Add non-withdrawn routes from less-specific prefix */ if (parent) { - rib_rn = rfd_rib_table - ? route_node_get(rfd_rib_table, &parent->p) - : NULL; + rib_rn = rfd_rib_table ? agg_node_get(rfd_rib_table, &parent->p) + : NULL; rfapiQprefix2Rprefix(&parent->p, &rprefix); count += rfapiNhlAddNodeRoutes(parent, &rprefix, lifetime, 0, &answer, &last, exclude_vnaddr, @@ -1835,7 +1841,7 @@ struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( rn, exclude_vnaddr, rfd_rib_table, pfx_target_original); if (rib_rn) - route_unlock_node(rib_rn); + agg_unlock_node(rib_rn); } else { /* * There is no parent with non-removed routes. Still need to @@ -1861,19 +1867,18 @@ struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( * Construct nexthop list of all routes in table */ struct rfapi_next_hop_entry *rfapiRouteTable2NextHopList( - struct route_table *rt, - uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload this NVE rib table */ - struct prefix *pfx_target_original) /* query target */ + struct agg_table *rt, uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct agg_table *rfd_rib_table, /* preload this NVE rib table */ + struct prefix *pfx_target_original) /* query target */ { - struct route_node *rn; + struct agg_node *rn; struct rfapi_next_hop_entry *biglist = NULL; struct rfapi_next_hop_entry *nhl; struct rfapi_next_hop_entry *tail = NULL; int count = 0; - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { nhl = rfapiRouteNode2NextHopList(rn, lifetime, exclude_vnaddr, rfd_rib_table, @@ -1898,18 +1903,18 @@ struct rfapi_next_hop_entry *rfapiRouteTable2NextHopList( } struct rfapi_next_hop_entry *rfapiEthRouteNode2NextHopList( - struct route_node *rn, struct rfapi_ip_prefix *rprefix, + struct agg_node *rn, struct rfapi_ip_prefix *rprefix, uint32_t lifetime, /* put into nexthop entries */ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload NVE rib table */ + struct agg_table *rfd_rib_table, /* preload NVE rib table */ struct prefix *pfx_target_original) /* query target */ { int count = 0; struct rfapi_next_hop_entry *answer = NULL; struct rfapi_next_hop_entry *last = NULL; - struct route_node *rib_rn; + struct agg_node *rib_rn; - rib_rn = rfd_rib_table ? route_node_get(rfd_rib_table, &rn->p) : NULL; + rib_rn = rfd_rib_table ? agg_node_get(rfd_rib_table, &rn->p) : NULL; count = rfapiNhlAddNodeRoutes(rn, rprefix, lifetime, 0, &answer, &last, NULL, rib_rn, pfx_target_original); @@ -1928,7 +1933,7 @@ struct rfapi_next_hop_entry *rfapiEthRouteNode2NextHopList( } if (rib_rn) - route_unlock_node(rib_rn); + agg_unlock_node(rib_rn); #if DEBUG_RETURNED_NHL rfapiPrintNhl(NULL, answer); @@ -1945,13 +1950,13 @@ struct rfapi_next_hop_entry *rfapiEthRouteTable2NextHopList( uint32_t logical_net_id, struct rfapi_ip_prefix *rprefix, uint32_t lifetime, /* put into nexthop entries */ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload NVE rib node */ + struct agg_table *rfd_rib_table, /* preload NVE rib node */ struct prefix *pfx_target_original) /* query target */ { struct rfapi_import_table *it; struct bgp *bgp = bgp_get_default(); - struct route_table *rt; - struct route_node *rn; + struct agg_table *rt; + struct agg_node *rn; struct rfapi_next_hop_entry *biglist = NULL; struct rfapi_next_hop_entry *nhl; struct rfapi_next_hop_entry *tail = NULL; @@ -1961,7 +1966,7 @@ struct rfapi_next_hop_entry *rfapiEthRouteTable2NextHopList( it = rfapiMacImportTableGet(bgp, logical_net_id); rt = it->imported_vpn[AFI_L2VPN]; - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { nhl = rfapiEthRouteNode2NextHopList( rn, rprefix, lifetime, exclude_vnaddr, rfd_rib_table, @@ -1989,7 +1994,7 @@ struct rfapi_next_hop_entry *rfapiEthRouteTable2NextHopList( * Insert a new bi to the imported route table node, * keeping the list of BIs sorted best route first */ -static void rfapiBgpInfoAttachSorted(struct route_node *rn, +static void rfapiBgpInfoAttachSorted(struct agg_node *rn, struct bgp_info *info_new, afi_t afi, safi_t safi) { @@ -2031,7 +2036,7 @@ static void rfapiBgpInfoAttachSorted(struct route_node *rn, bgp_attr_intern(info_new->attr); } -static void rfapiBgpInfoDetach(struct route_node *rn, struct bgp_info *bi) +static void rfapiBgpInfoDetach(struct agg_node *rn, struct bgp_info *bi) { /* * Remove the route (doubly-linked) @@ -2127,8 +2132,8 @@ static int rfapi_bi_peer_rd_aux_cmp(void *b1, void *b2) /* * Index on RD and Peer */ -static void rfapiItBiIndexAdd(struct route_node *rn, /* Import table VPN node */ - struct bgp_info *bi) /* new BI */ +static void rfapiItBiIndexAdd(struct agg_node *rn, /* Import table VPN node */ + struct bgp_info *bi) /* new BI */ { struct skiplist *sl; @@ -2153,15 +2158,15 @@ static void rfapiItBiIndexAdd(struct route_node *rn, /* Import table VPN node */ sl = skiplist_new(0, rfapi_bi_peer_rd_cmp, NULL); } RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd = sl; - route_lock_node(rn); /* for skiplist */ + agg_lock_node(rn); /* for skiplist */ } assert(!skiplist_insert(sl, (void *)bi, (void *)bi)); - route_lock_node(rn); /* for skiplist entry */ + agg_lock_node(rn); /* for skiplist entry */ /* NB: BIs in import tables are not refcounted */ } -static void rfapiItBiIndexDump(struct route_node *rn) +static void rfapiItBiIndexDump(struct agg_node *rn) { struct skiplist *sl; void *cursor = NULL; @@ -2192,7 +2197,7 @@ static void rfapiItBiIndexDump(struct route_node *rn) } static struct bgp_info *rfapiItBiIndexSearch( - struct route_node *rn, /* Import table VPN node */ + struct agg_node *rn, /* Import table VPN node */ struct prefix_rd *prd, struct peer *peer, struct prefix *aux_prefix) /* optional L3 addr for L2 ITs */ { @@ -2298,8 +2303,8 @@ static struct bgp_info *rfapiItBiIndexSearch( return bi_result; } -static void rfapiItBiIndexDel(struct route_node *rn, /* Import table VPN node */ - struct bgp_info *bi) /* old BI */ +static void rfapiItBiIndexDel(struct agg_node *rn, /* Import table VPN node */ + struct bgp_info *bi) /* old BI */ { struct skiplist *sl; int rc; @@ -2322,7 +2327,7 @@ static void rfapiItBiIndexDel(struct route_node *rn, /* Import table VPN node */ } assert(!rc); - route_unlock_node(rn); /* for skiplist entry */ + agg_unlock_node(rn); /* for skiplist entry */ /* NB: BIs in import tables are not refcounted */ } @@ -2332,17 +2337,16 @@ static void rfapiItBiIndexDel(struct route_node *rn, /* Import table VPN node */ * refers to it */ static void rfapiMonitorEncapAdd(struct rfapi_import_table *import_table, - struct prefix *p, /* VN address */ - struct route_node *vpn_rn, /* VPN node */ - struct bgp_info *vpn_bi) /* VPN bi/route */ + struct prefix *p, /* VN address */ + struct agg_node *vpn_rn, /* VPN node */ + struct bgp_info *vpn_bi) /* VPN bi/route */ { afi_t afi = family2afi(p->family); - struct route_node *rn; + struct agg_node *rn; struct rfapi_monitor_encap *m; assert(afi); - rn = route_node_get(import_table->imported_encap[afi], - p); /* locks rn */ + rn = agg_node_get(import_table->imported_encap[afi], p); /* locks rn */ assert(rn); m = XCALLOC(MTYPE_RFAPI_MONITOR_ENCAP, @@ -2399,7 +2403,7 @@ static void rfapiMonitorEncapDelete(struct bgp_info *vpn_bi) * freed */ rfapiMonitorExtraPrune(SAFI_ENCAP, hme->rn); - route_unlock_node(hme->rn); /* decr ref count */ + agg_unlock_node(hme->rn); /* decr ref count */ XFREE(MTYPE_RFAPI_MONITOR_ENCAP, hme); vpn_bi->extra->vnc.import.hme = NULL; } @@ -2533,7 +2537,7 @@ static int rfapiWithdrawTimerVPN(struct thread *t) } RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_MPLS_VPN, 1 + wcb->lockoffset); - route_unlock_node(wcb->node); /* decr ref count */ + agg_unlock_node(wcb->node); /* decr ref count */ XFREE(MTYPE_RFAPI_WITHDRAW, wcb); return 0; } @@ -2660,7 +2664,7 @@ static void rfapiCopyUnEncap2VPN(struct bgp_info *encap_bi, */ static int rfapiWithdrawEncapUpdateCachedUn( struct rfapi_import_table *import_table, struct bgp_info *encap_bi, - struct route_node *vpn_rn, struct bgp_info *vpn_bi) + struct agg_node *vpn_rn, struct bgp_info *vpn_bi) { if (!encap_bi) { @@ -2762,7 +2766,7 @@ static int rfapiWithdrawTimerEncap(struct thread *t) /* * for each VPN node referenced in the ENCAP monitors: */ - struct route_node *rn; + struct agg_node *rn; while (!skiplist_first(vpn_node_sl, (void **)&rn, NULL)) { if (!wcb->node->info) { struct rfapi_monitor_vpn *moved; @@ -2783,7 +2787,7 @@ static int rfapiWithdrawTimerEncap(struct thread *t) done: RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_ENCAP, 1); - route_unlock_node(wcb->node); /* decr ref count */ + agg_unlock_node(wcb->node); /* decr ref count */ XFREE(MTYPE_RFAPI_WITHDRAW, wcb); skiplist_free(vpn_node_sl); return 0; @@ -2796,7 +2800,7 @@ static int rfapiWithdrawTimerEncap(struct thread *t) */ static void rfapiBiStartWithdrawTimer(struct rfapi_import_table *import_table, - struct route_node *rn, struct bgp_info *bi, afi_t afi, + struct agg_node *rn, struct bgp_info *bi, afi_t afi, safi_t safi, int (*timer_service_func)(struct thread *)) { @@ -2886,7 +2890,7 @@ typedef void(rfapi_bi_filtered_import_f)(struct rfapi_import_table *, int, static void rfapiExpireEncapNow(struct rfapi_import_table *it, - struct route_node *rn, struct bgp_info *bi) + struct agg_node *rn, struct bgp_info *bi) { struct rfapi_withdraw *wcb; struct thread t; @@ -2939,8 +2943,8 @@ static void rfapiBgpInfoFilteredImportEncap( uint8_t sub_type, /* part of bgp_info */ uint32_t *label) /* part of bgp_info */ { - struct route_table *rt = NULL; - struct route_node *rn; + struct agg_table *rt = NULL; + struct agg_node *rn; struct bgp_info *info_new; struct bgp_info *bi; struct bgp_info *next; @@ -3034,10 +3038,10 @@ static void rfapiBgpInfoFilteredImportEncap( } /* - * route_node_lookup returns a node only if there is at least + * agg_node_lookup returns a node only if there is at least * one route attached. */ - rn = route_node_lookup(rt, p); + rn = agg_node_lookup(rt, p); #if DEBUG_ENCAP_MONITOR vnc_zlog_debug_verbose("%s: initial encap lookup(it=%p) rn=%p", @@ -3047,7 +3051,7 @@ static void rfapiBgpInfoFilteredImportEncap( if (rn) { RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, 1); - route_unlock_node(rn); /* undo lock in route_node_lookup */ + agg_unlock_node(rn); /* undo lock in agg_node_lookup */ /* @@ -3187,9 +3191,9 @@ static void rfapiBgpInfoFilteredImportEncap( if (rn) { if (!replacing) - route_lock_node(rn); /* incr ref count for new BI */ + agg_lock_node(rn); /* incr ref count for new BI */ } else { - rn = route_node_get(rt, p); + rn = agg_node_get(rt, p); } vnc_zlog_debug_verbose( @@ -3254,7 +3258,7 @@ static void rfapiBgpInfoFilteredImportEncap( struct rfapi_monitor_encap *m; struct rfapi_monitor_encap *mnext; - struct route_node *referenced_vpn_prefix; + struct agg_node *referenced_vpn_prefix; /* * Optimized approach: build radix tree on the fly to @@ -3265,9 +3269,9 @@ static void rfapiBgpInfoFilteredImportEncap( * struct rfapi_monitor_encap, each of which refers to a * specific VPN node. */ - struct route_table *referenced_vpn_table; + struct agg_table *referenced_vpn_table; - referenced_vpn_table = route_table_init(); + referenced_vpn_table = agg_table_init(); assert(referenced_vpn_table); /* @@ -3306,8 +3310,8 @@ static void rfapiBgpInfoFilteredImportEncap( * per prefix. */ - referenced_vpn_prefix = route_node_get( - referenced_vpn_table, &m->node->p); + referenced_vpn_prefix = + agg_node_get(referenced_vpn_table, &m->node->p); assert(referenced_vpn_prefix); for (mnext = referenced_vpn_prefix->info; mnext; mnext = mnext->next) { @@ -3320,7 +3324,7 @@ static void rfapiBgpInfoFilteredImportEncap( /* * already have an entry for this VPN node */ - route_unlock_node(referenced_vpn_prefix); + agg_unlock_node(referenced_vpn_prefix); } else { mnext = XCALLOC( MTYPE_RFAPI_MONITOR_ENCAP, @@ -3335,16 +3339,18 @@ static void rfapiBgpInfoFilteredImportEncap( /* * for each VPN node referenced in the ENCAP monitors: */ - for (referenced_vpn_prefix = route_top(referenced_vpn_table); - referenced_vpn_prefix; referenced_vpn_prefix = route_next( - referenced_vpn_prefix)) { + for (referenced_vpn_prefix = + agg_route_top(referenced_vpn_table); + referenced_vpn_prefix; + referenced_vpn_prefix = + agg_route_next(referenced_vpn_prefix)) { while ((m = referenced_vpn_prefix->info)) { - struct route_node *n; + struct agg_node *n; rfapiMonitorMoveLonger(m->node); - for (n = m->node; n; n = n->parent) { + for (n = m->node; n; n = agg_node_parent(n)) { // rfapiDoRouteCallback(import_table, n, // NULL); } @@ -3352,18 +3358,18 @@ static void rfapiBgpInfoFilteredImportEncap( NULL); referenced_vpn_prefix->info = m->next; - route_unlock_node(referenced_vpn_prefix); + agg_unlock_node(referenced_vpn_prefix); XFREE(MTYPE_RFAPI_MONITOR_ENCAP, m); } } - route_table_finish(referenced_vpn_table); + agg_table_finish(referenced_vpn_table); } RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, 0); } static void rfapiExpireVpnNow(struct rfapi_import_table *it, - struct route_node *rn, struct bgp_info *bi, + struct agg_node *rn, struct bgp_info *bi, int lockoffset) { struct rfapi_withdraw *wcb; @@ -3398,9 +3404,9 @@ void rfapiBgpInfoFilteredImportVPN( uint8_t sub_type, /* part of bgp_info */ uint32_t *label) /* part of bgp_info */ { - struct route_table *rt = NULL; - struct route_node *rn; - struct route_node *n; + struct agg_table *rt = NULL; + struct agg_node *rn; + struct agg_node *n; struct bgp_info *info_new; struct bgp_info *bi; struct bgp_info *next; @@ -3408,7 +3414,7 @@ void rfapiBgpInfoFilteredImportVPN( struct prefix vn_prefix; struct prefix un_prefix; int un_prefix_valid = 0; - struct route_node *ern; + struct agg_node *ern; int replacing = 0; int original_had_routes = 0; struct prefix original_nexthop; @@ -3494,17 +3500,17 @@ void rfapiBgpInfoFilteredImportVPN( memset(&original_nexthop, 0, sizeof(original_nexthop)); /* - * route_node_lookup returns a node only if there is at least + * agg_node_lookup returns a node only if there is at least * one route attached. */ - rn = route_node_lookup(rt, p); + rn = agg_node_lookup(rt, p); vnc_zlog_debug_verbose("%s: rn=%p", __func__, rn); if (rn) { RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, 1); - route_unlock_node(rn); /* undo lock in route_node_lookup */ + agg_unlock_node(rn); /* undo lock in agg_node_lookup */ if (rn->info) original_had_routes = 1; @@ -3667,10 +3673,10 @@ void rfapiBgpInfoFilteredImportVPN( /* * lookup un address in encap table */ - ern = route_node_match(import_table->imported_encap[afi], &vn_prefix); + ern = agg_node_match(import_table->imported_encap[afi], &vn_prefix); if (ern) { rfapiCopyUnEncap2VPN(ern->info, info_new); - route_unlock_node(ern); /* undo lock in route_note_match */ + agg_unlock_node(ern); /* undo lock in route_note_match */ } else { char buf[PREFIX_STRLEN]; @@ -3683,13 +3689,13 @@ void rfapiBgpInfoFilteredImportVPN( if (rn) { if (!replacing) - route_lock_node(rn); + agg_lock_node(rn); } else { /* * No need to increment reference count, so only "get" * if the node is not there already */ - rn = route_node_get(rt, p); + rn = agg_node_get(rt, p); } /* @@ -3856,7 +3862,7 @@ void rfapiBgpInfoFilteredImportVPN( } if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) { - for (n = rn; n; n = n->parent) { + for (n = rn; n; n = agg_node_parent(n)) { // rfapiDoRouteCallback(import_table, n, NULL); } rfapiMonitorItNodeChanged(import_table, rn, NULL); @@ -4108,9 +4114,9 @@ static void rfapiProcessPeerDownRt(struct peer *peer, struct rfapi_import_table *import_table, afi_t afi, safi_t safi) { - struct route_node *rn; + struct agg_node *rn; struct bgp_info *bi; - struct route_table *rt; + struct agg_table *rt; int (*timer_service_func)(struct thread *); assert(afi == AFI_IP || afi == AFI_IP6); @@ -4131,7 +4137,7 @@ static void rfapiProcessPeerDownRt(struct peer *peer, } - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { for (bi = rn->info; bi; bi = bi->next) { if (bi->peer == peer) { @@ -4274,7 +4280,7 @@ struct rfapi *bgp_rfapi_new(struct bgp *bgp) h = (struct rfapi *)XCALLOC(MTYPE_RFAPI, sizeof(struct rfapi)); for (afi = AFI_IP; afi < AFI_MAX; afi++) { - h->un[afi] = route_table_init(); + h->un[afi] = agg_table_init(); } /* @@ -4282,10 +4288,10 @@ struct rfapi *bgp_rfapi_new(struct bgp *bgp) */ h->it_ce = XCALLOC(MTYPE_RFAPI_IMPORTTABLE, sizeof(struct rfapi_import_table)); - h->it_ce->imported_vpn[AFI_IP] = route_table_init(); - h->it_ce->imported_vpn[AFI_IP6] = route_table_init(); - h->it_ce->imported_encap[AFI_IP] = route_table_init(); - h->it_ce->imported_encap[AFI_IP6] = route_table_init(); + h->it_ce->imported_vpn[AFI_IP] = agg_table_init(); + h->it_ce->imported_vpn[AFI_IP6] = agg_table_init(); + h->it_ce->imported_encap[AFI_IP] = agg_table_init(); + h->it_ce->imported_encap[AFI_IP6] = agg_table_init(); rfapiBgpTableFilteredImport(bgp, h->it_ce, AFI_IP, SAFI_MPLS_VPN); rfapiBgpTableFilteredImport(bgp, h->it_ce, AFI_IP6, SAFI_MPLS_VPN); @@ -4317,10 +4323,10 @@ void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h) h->resolve_nve_nexthop = NULL; } - route_table_finish(h->it_ce->imported_vpn[AFI_IP]); - route_table_finish(h->it_ce->imported_vpn[AFI_IP6]); - route_table_finish(h->it_ce->imported_encap[AFI_IP]); - route_table_finish(h->it_ce->imported_encap[AFI_IP6]); + agg_table_finish(h->it_ce->imported_vpn[AFI_IP]); + agg_table_finish(h->it_ce->imported_vpn[AFI_IP6]); + agg_table_finish(h->it_ce->imported_encap[AFI_IP]); + agg_table_finish(h->it_ce->imported_encap[AFI_IP6]); if (h->import_mac) { struct rfapi_import_table *it; @@ -4346,7 +4352,7 @@ void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h) rfp_stop(h->rfp); for (afi = AFI_IP; afi < AFI_MAX; afi++) { - route_table_finish(h->un[afi]); + agg_table_finish(h->un[afi]); } XFREE(MTYPE_RFAPI_IMPORTTABLE, h->it_ce); @@ -4394,8 +4400,8 @@ rfapiImportTableRefAdd(struct bgp *bgp, struct ecommunity *rt_import_list, */ for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - it->imported_vpn[afi] = route_table_init(); - it->imported_encap[afi] = route_table_init(); + it->imported_vpn[afi] = agg_table_init(); + it->imported_encap[afi] = agg_table_init(); rfapiBgpTableFilteredImport(bgp, it, afi, SAFI_MPLS_VPN); @@ -4452,8 +4458,8 @@ static void rfapiDeleteRemotePrefixesIt( for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - struct route_table *rt; - struct route_node *rn; + struct agg_table *rt; + struct agg_node *rn; if (p && (family2afi(p->family) != afi)) { continue; @@ -4466,7 +4472,7 @@ static void rfapiDeleteRemotePrefixesIt( vnc_zlog_debug_verbose("%s: scanning rt for afi=%d", __func__, afi); - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { struct bgp_info *bi; struct bgp_info *next; diff --git a/bgpd/rfapi/rfapi_import.h b/bgpd/rfapi/rfapi_import.h index 84b7ca3a7699..ae3d248367fa 100644 --- a/bgpd/rfapi/rfapi_import.h +++ b/bgpd/rfapi/rfapi_import.h @@ -40,10 +40,10 @@ struct rfapi_import_table { struct ecommunity *rt_import_list; /* copied from nve grp */ int refcount; /* nve grps and nves */ uint32_t l2_logical_net_id; /* L2 only: EVPN Eth Seg Id */ - struct route_table *imported_vpn[AFI_MAX]; + struct agg_table *imported_vpn[AFI_MAX]; struct rfapi_monitor_vpn *vpn0_queries[AFI_MAX]; struct rfapi_monitor_eth *eth0_queries; - struct route_table *imported_encap[AFI_MAX]; + struct agg_table *imported_encap[AFI_MAX]; struct skiplist *monitor_exterior_orphans; int local_count[AFI_MAX]; int remote_count[AFI_MAX]; @@ -80,7 +80,7 @@ extern void rfapiCheckRouteCount(void); extern void rfapiPrintBi(void *stream, struct bgp_info *bi); extern void rfapiShowImportTable(void *stream, const char *label, - struct route_table *rt, int isvpn); + struct agg_table *rt, int isvpn); extern struct rfapi_import_table * rfapiImportTableRefAdd(struct bgp *bgp, struct ecommunity *rt_import_list, @@ -100,32 +100,31 @@ extern void rfapiImportTableRefDelByIt(struct bgp *bgp, * next less-specific node (i.e., this node's parent) at the end. */ extern struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( - struct route_node *rn, uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload this NVE rib table */ - struct prefix *pfx_target_original); /* query target */ + struct agg_node *rn, uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct agg_table *rfd_rib_table, /* preload this NVE rib table */ + struct prefix *pfx_target_original); /* query target */ extern struct rfapi_next_hop_entry *rfapiRouteTable2NextHopList( - struct route_table *rt, - uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload this NVE rib table */ - struct prefix *pfx_target_original); /* query target */ + struct agg_table *rt, uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct agg_table *rfd_rib_table, /* preload this NVE rib table */ + struct prefix *pfx_target_original); /* query target */ extern struct rfapi_next_hop_entry *rfapiEthRouteTable2NextHopList( uint32_t logical_net_id, struct rfapi_ip_prefix *rprefix, uint32_t lifetime, /* put into nexthop entries */ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rib_route_table, /* preload NVE rib node */ + struct agg_table *rib_route_table, /* preload NVE rib node */ struct prefix *pfx_target_original); /* query target */ extern int rfapiEcommunitiesIntersect(struct ecommunity *e1, struct ecommunity *e2); -extern void rfapiCheckRefcount(struct route_node *rn, safi_t safi, +extern void rfapiCheckRefcount(struct agg_node *rn, safi_t safi, int lockoffset); -extern int rfapiHasNonRemovedRoutes(struct route_node *rn); +extern int rfapiHasNonRemovedRoutes(struct agg_node *rn); extern int rfapiProcessDeferredClose(struct thread *t); @@ -153,10 +152,10 @@ extern void rfapiBgpInfoFilteredImportVPN( uint32_t *label); /* part of bgp_info */ extern struct rfapi_next_hop_entry *rfapiEthRouteNode2NextHopList( - struct route_node *rn, struct rfapi_ip_prefix *rprefix, + struct agg_node *rn, struct rfapi_ip_prefix *rprefix, uint32_t lifetime, /* put into nexthop entries */ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rib_route_table, /* preload NVE rib table */ + struct agg_table *rib_route_table, /* preload NVE rib table */ struct prefix *pfx_target_original); /* query target */ extern struct rfapi_import_table *rfapiMacImportTableGetNoAlloc(struct bgp *bgp, diff --git a/bgpd/rfapi/rfapi_monitor.c b/bgpd/rfapi/rfapi_monitor.c index 30182ba7a6d9..f18c6bfe1299 100644 --- a/bgpd/rfapi/rfapi_monitor.c +++ b/bgpd/rfapi/rfapi_monitor.c @@ -24,11 +24,9 @@ /* TBD remove unneeded includes */ -#include - #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/vty.h" #include "lib/memory.h" #include "lib/log.h" @@ -68,10 +66,10 @@ static void rfapiMonitorEthDetachImport(struct bgp *bgp, /* * Debug function, special case */ -void rfapiMonitorEthSlCheck(struct route_node *rn, const char *tag1, +void rfapiMonitorEthSlCheck(struct agg_node *rn, const char *tag1, const char *tag2) { - struct route_node *rn_saved = NULL; + struct agg_node *rn_saved = NULL; static struct skiplist *sl_saved = NULL; struct skiplist *sl; @@ -118,12 +116,13 @@ void rfapiMonitorDupCheck(struct bgp *bgp) struct rfapi_descriptor *rfd; for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, hnode, rfd)) { - struct route_node *mrn; + struct agg_node *mrn; if (!rfd->mon) continue; - for (mrn = route_top(rfd->mon); mrn; mrn = route_next(mrn)) { + for (mrn = agg_route_top(rfd->mon); mrn; + mrn = agg_route_next(mrn)) { struct rfapi_monitor_vpn *m; for (m = (struct rfapi_monitor_vpn *)(mrn->info); m; m = m->next) @@ -132,12 +131,13 @@ void rfapiMonitorDupCheck(struct bgp *bgp) } for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, hnode, rfd)) { - struct route_node *mrn; + struct agg_node *mrn; if (!rfd->mon) continue; - for (mrn = route_top(rfd->mon); mrn; mrn = route_next(mrn)) { + for (mrn = agg_route_top(rfd->mon); mrn; + mrn = agg_route_next(mrn)) { struct rfapi_monitor_vpn *m; for (m = (struct rfapi_monitor_vpn *)(mrn->info); m; @@ -158,15 +158,17 @@ void rfapiMonitorCleanCheck(struct bgp *bgp) assert(!rfd->import_table->vpn0_queries[AFI_IP]); assert(!rfd->import_table->vpn0_queries[AFI_IP6]); - struct route_node *rn; + struct agg_node *rn; - for (rn = route_top(rfd->import_table->imported_vpn[AFI_IP]); - rn; rn = route_next(rn)) { + for (rn = agg_route_top( + rfd->import_table->imported_vpn[AFI_IP]); + rn; rn = agg_route_next(rn)) { assert(!RFAPI_MONITOR_VPN(rn)); } - for (rn = route_top(rfd->import_table->imported_vpn[AFI_IP6]); - rn; rn = route_next(rn)) { + for (rn = agg_route_top( + rfd->import_table->imported_vpn[AFI_IP6]); + rn; rn = agg_route_next(rn)) { assert(!RFAPI_MONITOR_VPN(rn)); } @@ -180,7 +182,7 @@ void rfapiMonitorCheckAttachAllowed(void) assert(!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)); } -void rfapiMonitorExtraFlush(safi_t safi, struct route_node *rn) +void rfapiMonitorExtraFlush(safi_t safi, struct agg_node *rn) { struct rfapi_it_extra *hie; struct rfapi_monitor_vpn *v; @@ -202,7 +204,7 @@ void rfapiMonitorExtraFlush(safi_t safi, struct route_node *rn) e_next = e->next; e->next = NULL; XFREE(MTYPE_RFAPI_MONITOR_ENCAP, e); - route_unlock_node(rn); + agg_unlock_node(rn); } hie->u.encap.e = NULL; break; @@ -212,33 +214,33 @@ void rfapiMonitorExtraFlush(safi_t safi, struct route_node *rn) v_next = v->next; v->next = NULL; XFREE(MTYPE_RFAPI_MONITOR, e); - route_unlock_node(rn); + agg_unlock_node(rn); } hie->u.vpn.v = NULL; if (hie->u.vpn.e.source) { while (!skiplist_delete_first(hie->u.vpn.e.source)) { - route_unlock_node(rn); + agg_unlock_node(rn); } skiplist_free(hie->u.vpn.e.source); hie->u.vpn.e.source = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } if (hie->u.vpn.idx_rd) { /* looping through bi->extra->vnc.import.rd is tbd */ while (!skiplist_delete_first(hie->u.vpn.idx_rd)) { - route_unlock_node(rn); + agg_unlock_node(rn); } skiplist_free(hie->u.vpn.idx_rd); hie->u.vpn.idx_rd = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } if (hie->u.vpn.mon_eth) { while (!skiplist_delete_first(hie->u.vpn.mon_eth)) { - route_unlock_node(rn); + agg_unlock_node(rn); } skiplist_free(hie->u.vpn.mon_eth); hie->u.vpn.mon_eth = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } break; @@ -247,13 +249,13 @@ void rfapiMonitorExtraFlush(safi_t safi, struct route_node *rn) } XFREE(MTYPE_RFAPI_IT_EXTRA, hie); rn->aggregate = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } /* * If the child lists are empty, release the rfapi_it_extra struct */ -void rfapiMonitorExtraPrune(safi_t safi, struct route_node *rn) +void rfapiMonitorExtraPrune(safi_t safi, struct agg_node *rn) { struct rfapi_it_extra *hie; @@ -279,28 +281,28 @@ void rfapiMonitorExtraPrune(safi_t safi, struct route_node *rn) return; skiplist_free(hie->u.vpn.mon_eth); hie->u.vpn.mon_eth = NULL; - route_unlock_node(rn); /* uncount skiplist */ + agg_unlock_node(rn); /* uncount skiplist */ } if (hie->u.vpn.e.source) { if (skiplist_count(hie->u.vpn.e.source)) return; skiplist_free(hie->u.vpn.e.source); hie->u.vpn.e.source = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } if (hie->u.vpn.idx_rd) { if (skiplist_count(hie->u.vpn.idx_rd)) return; skiplist_free(hie->u.vpn.idx_rd); hie->u.vpn.idx_rd = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } if (hie->u.vpn.mon_eth) { if (skiplist_count(hie->u.vpn.mon_eth)) return; skiplist_free(hie->u.vpn.mon_eth); hie->u.vpn.mon_eth = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } break; @@ -309,17 +311,17 @@ void rfapiMonitorExtraPrune(safi_t safi, struct route_node *rn) } XFREE(MTYPE_RFAPI_IT_EXTRA, hie); rn->aggregate = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } /* * returns locked node */ -struct route_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, - struct prefix *p) +struct agg_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, + struct prefix *p) { afi_t afi; - struct route_node *rn; + struct agg_node *rn; if (RFAPI_0_PREFIX(p)) { assert(1); @@ -341,7 +343,7 @@ struct route_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, * if a monitor is moved to another node, there must be * corresponding unlock/locks */ - for (rn = route_node_match(rfd->import_table->imported_vpn[afi], p); + for (rn = agg_node_match(rfd->import_table->imported_vpn[afi], p); rn;) { struct bgp_info *bi; @@ -369,9 +371,9 @@ struct route_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, if (bi) break; - route_unlock_node(rn); - if ((rn = rn->parent)) { - route_lock_node(rn); + agg_unlock_node(rn); + if ((rn = agg_node_parent(rn))) { + agg_lock_node(rn); } } @@ -383,8 +385,8 @@ struct route_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, /* creates default node if none exists, and increments ref count */ - rn = route_node_get(rfd->import_table->imported_vpn[afi], - &pfx_default); + rn = agg_node_get(rfd->import_table->imported_vpn[afi], + &pfx_default); } return rn; @@ -396,10 +398,10 @@ struct route_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, * returned (for the benefit of caller which might like to use it * to generate an immediate query response). */ -static struct route_node *rfapiMonitorAttachImport(struct rfapi_descriptor *rfd, - struct rfapi_monitor_vpn *m) +static struct agg_node *rfapiMonitorAttachImport(struct rfapi_descriptor *rfd, + struct rfapi_monitor_vpn *m) { - struct route_node *rn; + struct agg_node *rn; rfapiMonitorCheckAttachAllowed(); @@ -438,7 +440,7 @@ static struct route_node *rfapiMonitorAttachImport(struct rfapi_descriptor *rfd, */ void rfapiMonitorAttachImportHd(struct rfapi_descriptor *rfd) { - struct route_node *mrn; + struct agg_node *mrn; if (!rfd->mon) { /* @@ -447,7 +449,7 @@ void rfapiMonitorAttachImportHd(struct rfapi_descriptor *rfd) return; } - for (mrn = route_top(rfd->mon); mrn; mrn = route_next(mrn)) { + for (mrn = agg_route_top(rfd->mon); mrn; mrn = agg_route_next(mrn)) { if (!mrn->info) continue; @@ -467,11 +469,11 @@ void rfapiMonitorAttachImportHd(struct rfapi_descriptor *rfd) * are disabled, this function will not perform a lookup, and the * caller will have to do its own lookup. */ -struct route_node * -rfapiMonitorAdd(struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *p) +struct agg_node *rfapiMonitorAdd(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct prefix *p) { struct rfapi_monitor_vpn *m; - struct route_node *rn; + struct agg_node *rn; /* * Initialize nve's monitor list if needed @@ -480,15 +482,15 @@ rfapiMonitorAdd(struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *p) * or be 0/0 so they won't get mixed up. */ if (!rfd->mon) { - rfd->mon = route_table_init(); + rfd->mon = agg_table_init(); } - rn = route_node_get(rfd->mon, p); + rn = agg_node_get(rfd->mon, p); if (rn->info) { /* * received this query before, no further action needed */ rfapiMonitorTimerRestart((struct rfapi_monitor_vpn *)rn->info); - route_unlock_node(rn); + agg_unlock_node(rn); return NULL; } @@ -575,7 +577,7 @@ rfapiMonitorDetachImport(struct rfapi_monitor_vpn *m) this->next; } RFAPI_CHECK_REFCOUNT(m->node, SAFI_MPLS_VPN, 1); - route_unlock_node(m->node); + agg_unlock_node(m->node); } m->node = NULL; } @@ -586,12 +588,12 @@ rfapiMonitorDetachImport(struct rfapi_monitor_vpn *m) void rfapiMonitorDetachImportHd(struct rfapi_descriptor *rfd) { - struct route_node *rn; + struct agg_node *rn; if (!rfd->mon) return; - for (rn = route_top(rfd->mon); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rfd->mon); rn; rn = agg_route_next(rn)) { if (rn->info) { rfapiMonitorDetachImport( (struct rfapi_monitor_vpn *)(rn->info)); @@ -602,11 +604,11 @@ void rfapiMonitorDetachImportHd(struct rfapi_descriptor *rfd) void rfapiMonitorDel(struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *p) { - struct route_node *rn; + struct agg_node *rn; struct rfapi_monitor_vpn *m; assert(rfd->mon); - rn = route_node_get(rfd->mon, p); /* locks node */ + rn = agg_node_get(rfd->mon, p); /* locks node */ m = rn->info; assert(m); @@ -628,8 +630,8 @@ void rfapiMonitorDel(struct bgp *bgp, struct rfapi_descriptor *rfd, */ XFREE(MTYPE_RFAPI_MONITOR, m); rn->info = NULL; - route_unlock_node(rn); /* undo original lock when created */ - route_unlock_node(rn); /* undo lock in route_node_get */ + agg_unlock_node(rn); /* undo original lock when created */ + agg_unlock_node(rn); /* undo lock in agg_node_get */ --rfd->monitor_count; --bgp->rfapi->monitor_count; @@ -640,7 +642,7 @@ void rfapiMonitorDel(struct bgp *bgp, struct rfapi_descriptor *rfd, */ int rfapiMonitorDelHd(struct rfapi_descriptor *rfd) { - struct route_node *rn; + struct agg_node *rn; struct bgp *bgp; int count = 0; @@ -649,7 +651,8 @@ int rfapiMonitorDelHd(struct rfapi_descriptor *rfd) bgp = bgp_get_default(); if (rfd->mon) { - for (rn = route_top(rfd->mon); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rfd->mon); rn; + rn = agg_route_next(rn)) { struct rfapi_monitor_vpn *m; if ((m = rn->info)) { if (!(bgp->rfapi_cfg->flags @@ -664,14 +667,14 @@ int rfapiMonitorDelHd(struct rfapi_descriptor *rfd) XFREE(MTYPE_RFAPI_MONITOR, m); rn->info = NULL; - route_unlock_node(rn); /* undo original lock + agg_unlock_node(rn); /* undo original lock when created */ ++count; --rfd->monitor_count; --bgp->rfapi->monitor_count; } } - route_table_finish(rfd->mon); + agg_table_finish(rfd->mon); rfd->mon = NULL; } @@ -788,7 +791,7 @@ static void rfapiMonitorTimerRestart(struct rfapi_monitor_vpn *m) */ void rfapiMonitorTimersRestart(struct rfapi_descriptor *rfd, struct prefix *p) { - struct route_node *rn; + struct agg_node *rn; if (AF_ETHERNET == p->family) { struct rfapi_monitor_eth *mon_eth; @@ -812,7 +815,8 @@ void rfapiMonitorTimersRestart(struct rfapi_descriptor *rfd, struct prefix *p) } } else { - for (rn = route_top(rfd->mon); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rfd->mon); rn; + rn = agg_route_next(rn)) { struct rfapi_monitor_vpn *m; if (!((m = rn->info))) @@ -831,11 +835,11 @@ void rfapiMonitorTimersRestart(struct rfapi_descriptor *rfd, struct prefix *p) * rfapiRibUpdatePendingNode with this node and all corresponding NVEs. */ void rfapiMonitorItNodeChanged( - struct rfapi_import_table *import_table, struct route_node *it_node, + struct rfapi_import_table *import_table, struct agg_node *it_node, struct rfapi_monitor_vpn *monitor_list) /* for base it node, NULL=all */ { struct skiplist *nves_seen; - struct route_node *rn = it_node; + struct agg_node *rn = it_node; struct bgp *bgp = bgp_get_default(); afi_t afi = family2afi(rn->p.family); #if DEBUG_L2_EXTRA @@ -909,7 +913,8 @@ void rfapiMonitorItNodeChanged( * to them * because we haven't sent them an initial route. */ - if (!rn->parent && !rn->info && it_node->parent) + if (!agg_node_parent(rn) && !rn->info + && it_node->parent) break; for (; m; m = m->next) { @@ -947,7 +952,7 @@ void rfapiMonitorItNodeChanged( m->rfd->response_lifetime); } } - rn = rn->parent; + rn = agg_node_parent(rn); if (rn) m = RFAPI_MONITOR_VPN(rn); } while (rn); @@ -1023,8 +1028,7 @@ void rfapiMonitorItNodeChanged( * omit old node and its subtree */ void rfapiMonitorMovedUp(struct rfapi_import_table *import_table, - struct route_node *old_node, - struct route_node *new_node, + struct agg_node *old_node, struct agg_node *new_node, struct rfapi_monitor_vpn *monitor_list) { struct bgp *bgp = bgp_get_default(); @@ -1125,7 +1129,7 @@ static int mon_eth_cmp(void *a, void *b) static void rfapiMonitorEthAttachImport( struct rfapi_import_table *it, - struct route_node *rn, /* it node attach point if non-0 */ + struct agg_node *rn, /* it node attach point if non-0 */ struct rfapi_monitor_eth *mon) /* monitor struct to attach */ { struct skiplist *sl; @@ -1162,7 +1166,7 @@ static void rfapiMonitorEthAttachImport( if (!sl) { sl = RFAPI_MONITOR_ETH_W_ALLOC(rn) = skiplist_new(0, NULL, NULL); - route_lock_node(rn); /* count skiplist mon_eth */ + agg_lock_node(rn); /* count skiplist mon_eth */ } #if DEBUG_L2_EXTRA @@ -1175,7 +1179,7 @@ static void rfapiMonitorEthAttachImport( assert(!rc); /* count eth monitor */ - route_lock_node(rn); + agg_lock_node(rn); } /* @@ -1202,7 +1206,7 @@ static void rfapiMonitorEthAttachImportHd(struct bgp *bgp, struct rfapi_import_table *it; struct prefix pfx_mac_buf; - struct route_node *rn; + struct agg_node *rn; it = rfapiMacImportTableGet(bgp, mon->logical_net_id); assert(it); @@ -1212,7 +1216,7 @@ static void rfapiMonitorEthAttachImportHd(struct bgp *bgp, pfx_mac_buf.prefixlen = 48; pfx_mac_buf.u.prefix_eth = mon->macaddr; - rn = route_node_get(it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); + rn = agg_node_get(it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); assert(rn); (void)rfapiMonitorEthAttachImport(it, rn, mon); @@ -1226,7 +1230,7 @@ static void rfapiMonitorEthDetachImport( struct rfapi_import_table *it; struct prefix pfx_mac_buf; struct skiplist *sl; - struct route_node *rn; + struct agg_node *rn; int rc; it = rfapiMacImportTableGet(bgp, mon->logical_net_id); @@ -1262,7 +1266,7 @@ static void rfapiMonitorEthDetachImport( pfx_mac_buf.prefixlen = 48; pfx_mac_buf.u.prefix_eth = mon->macaddr; - rn = route_node_get(it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); + rn = agg_node_get(it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); assert(rn); #if DEBUG_L2_EXTRA @@ -1288,19 +1292,19 @@ static void rfapiMonitorEthDetachImport( assert(!rc); /* uncount eth monitor */ - route_unlock_node(rn); + agg_unlock_node(rn); } -struct route_node *rfapiMonitorEthAdd(struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct ethaddr *macaddr, - uint32_t logical_net_id) +struct agg_node *rfapiMonitorEthAdd(struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct ethaddr *macaddr, + uint32_t logical_net_id) { int rc; struct rfapi_monitor_eth mon_buf; struct rfapi_monitor_eth *val; struct rfapi_import_table *it; - struct route_node *rn = NULL; + struct agg_node *rn = NULL; struct prefix pfx_mac_buf; if (!rfd->mon_eth) { @@ -1323,7 +1327,7 @@ struct route_node *rfapiMonitorEthAdd(struct bgp *bgp, pfx_mac_buf.u.prefix_eth = *macaddr; if (!RFAPI_0_ETHERADDR(macaddr)) { - rn = route_node_get(it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); + rn = agg_node_get(it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); assert(rn); } @@ -1453,8 +1457,8 @@ void rfapiMonitorCallbacksOff(struct bgp *bgp) { struct rfapi_import_table *it; afi_t afi; - struct route_table *rt; - struct route_node *rn; + struct agg_table *rt; + struct agg_node *rn; void *cursor; int rc; struct rfapi *h = bgp->rfapi; @@ -1485,7 +1489,8 @@ void rfapiMonitorCallbacksOff(struct bgp *bgp) rt = it->imported_vpn[afi]; - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; + rn = agg_route_next(rn)) { m = RFAPI_MONITOR_VPN(rn); if (RFAPI_MONITOR_VPN(rn)) RFAPI_MONITOR_VPN_W_ALLOC(rn) = NULL; @@ -1494,7 +1499,7 @@ void rfapiMonitorCallbacksOff(struct bgp *bgp) m->next = NULL; /* gratuitous safeness */ m->node = NULL; - route_unlock_node(rn); /* uncount */ + agg_unlock_node(rn); /* uncount */ } } @@ -1531,12 +1536,12 @@ void rfapiMonitorCallbacksOff(struct bgp *bgp) * Find non-0 monitors (i.e., actual addresses, not FTD * monitors) */ - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { struct skiplist *sl; sl = RFAPI_MONITOR_ETH(rn); while (!skiplist_delete_first(sl)) { - route_unlock_node(rn); /* uncount monitor */ + agg_unlock_node(rn); /* uncount monitor */ } } diff --git a/bgpd/rfapi/rfapi_monitor.h b/bgpd/rfapi/rfapi_monitor.h index edc9744cdb69..9b85f6248e41 100644 --- a/bgpd/rfapi/rfapi_monitor.h +++ b/bgpd/rfapi/rfapi_monitor.h @@ -30,10 +30,10 @@ * to indicate which nves are interested in a prefix/target */ struct rfapi_monitor_vpn { - struct rfapi_monitor_vpn *next; /* chain from struct route_node */ + struct rfapi_monitor_vpn *next; /* chain from struct agg_node */ struct rfapi_descriptor *rfd; /* which NVE requested the route */ struct prefix p; /* constant: pfx in original request */ - struct route_node *node; /* node we're currently attached to */ + struct agg_node *node; /* node we're currently attached to */ uint32_t flags; #define RFAPI_MON_FLAG_NEEDCALLBACK 0x00000001 /* deferred callback */ @@ -44,9 +44,9 @@ struct rfapi_monitor_vpn { struct rfapi_monitor_encap { struct rfapi_monitor_encap *next; struct rfapi_monitor_encap *prev; - struct route_node *node; /* VPN node */ + struct agg_node *node; /* VPN node */ struct bgp_info *bi; /* VPN bi */ - struct route_node *rn; /* parent node */ + struct agg_node *rn; /* parent node */ }; struct rfapi_monitor_eth { @@ -98,7 +98,7 @@ struct rfapi_it_extra { ((struct rfapi_it_extra \ *)((rn)->aggregate \ ? (rn)->aggregate \ - : (route_lock_node(rn), \ + : (agg_lock_node(rn), \ (rn)->aggregate = XCALLOC( \ MTYPE_RFAPI_IT_EXTRA, \ sizeof(struct rfapi_it_extra))))) @@ -138,16 +138,16 @@ extern void rfapiMonitorCleanCheck(struct bgp *bgp); extern void rfapiMonitorCheckAttachAllowed(void); -extern void rfapiMonitorExtraFlush(safi_t safi, struct route_node *rn); +extern void rfapiMonitorExtraFlush(safi_t safi, struct agg_node *rn); -extern struct route_node * -rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, struct prefix *p); +extern struct agg_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, + struct prefix *p); extern void rfapiMonitorAttachImportHd(struct rfapi_descriptor *rfd); -extern struct route_node *rfapiMonitorAdd(struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *p); +extern struct agg_node *rfapiMonitorAdd(struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct prefix *p); extern void rfapiMonitorDetachImportHd(struct rfapi_descriptor *rfd); @@ -164,24 +164,24 @@ extern void rfapiMonitorResponseRemovalOff(struct bgp *bgp); extern void rfapiMonitorResponseRemovalOn(struct bgp *bgp); -extern void rfapiMonitorExtraPrune(safi_t safi, struct route_node *rn); +extern void rfapiMonitorExtraPrune(safi_t safi, struct agg_node *rn); extern void rfapiMonitorTimersRestart(struct rfapi_descriptor *rfd, struct prefix *p); extern void rfapiMonitorItNodeChanged(struct rfapi_import_table *import_table, - struct route_node *it_node, + struct agg_node *it_node, struct rfapi_monitor_vpn *monitor_list); extern void rfapiMonitorMovedUp(struct rfapi_import_table *import_table, - struct route_node *old_node, - struct route_node *new_node, + struct agg_node *old_node, + struct agg_node *new_node, struct rfapi_monitor_vpn *monitor_list); -extern struct route_node *rfapiMonitorEthAdd(struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct ethaddr *macaddr, - uint32_t logical_net_id); +extern struct agg_node *rfapiMonitorEthAdd(struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct ethaddr *macaddr, + uint32_t logical_net_id); extern void rfapiMonitorEthDel(struct bgp *bgp, struct rfapi_descriptor *rfd, struct ethaddr *macaddr, diff --git a/bgpd/rfapi/rfapi_nve_addr.c b/bgpd/rfapi/rfapi_nve_addr.c index 0fb887912c15..ee54d88c3f46 100644 --- a/bgpd/rfapi/rfapi_nve_addr.c +++ b/bgpd/rfapi/rfapi_nve_addr.c @@ -21,7 +21,7 @@ #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/vty.h" #include "lib/memory.h" #include "lib/skiplist.h" diff --git a/bgpd/rfapi/rfapi_private.h b/bgpd/rfapi/rfapi_private.h index 9c759fc47eba..4d8072a49bdd 100644 --- a/bgpd/rfapi/rfapi_private.h +++ b/bgpd/rfapi/rfapi_private.h @@ -47,7 +47,7 @@ struct rfapi_advertised_prefixes { }; struct rfapi_descriptor { - struct route_node *un_node; /* backref to un table */ + struct agg_node *un_node; /* backref to un table */ struct rfapi_descriptor *next; /* next vn_addr */ @@ -76,7 +76,7 @@ struct rfapi_descriptor { struct rfapi_import_table *import_table; uint32_t monitor_count; - struct route_table *mon; /* rfapi_monitors */ + struct agg_table *mon; /* rfapi_monitors */ struct skiplist *mon_eth; /* ethernet monitors */ /* @@ -85,10 +85,10 @@ struct rfapi_descriptor { * rsp_times last time we sent response containing pfx */ uint32_t rib_prefix_count; /* pfxes with routes */ - struct route_table *rib[AFI_MAX]; - struct route_table *rib_pending[AFI_MAX]; + struct agg_table *rib[AFI_MAX]; + struct agg_table *rib_pending[AFI_MAX]; struct work_queue *updated_responses_queue; - struct route_table *rsp_times[AFI_MAX]; + struct agg_table *rsp_times[AFI_MAX]; uint32_t rsp_counter; /* dedup initial rsp */ time_t rsp_time; /* dedup initial rsp */ @@ -171,7 +171,7 @@ struct rfapi_global_stats { * check vn address to get exact match. */ struct rfapi { - struct route_table *un[AFI_MAX]; + struct agg_table *un[AFI_MAX]; struct rfapi_import_table *imports; /* IPv4, IPv6 */ struct list descriptors; /* debug & resolve-nve imports */ @@ -198,8 +198,8 @@ struct rfapi { * bgp unicast or zebra, we need to keep track of information * related to expiring the routes according to the VNC lifetime */ - struct route_table *rt_export_bgp[AFI_MAX]; - struct route_table *rt_export_zebra[AFI_MAX]; + struct agg_table *rt_export_bgp[AFI_MAX]; + struct agg_table *rt_export_zebra[AFI_MAX]; /* * For VNC->BGP unicast exports in CE mode, we need a diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index 60534fece0b9..008da30118a5 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -23,11 +23,9 @@ * Purpose: maintain per-nve ribs and generate change lists */ -#include - #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/vty.h" #include "lib/memory.h" #include "lib/log.h" @@ -150,10 +148,10 @@ void rfapiRibCheckCounts( for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - struct route_node *rn; + struct agg_node *rn; - for (rn = route_top(rfd->rib[afi]); rn; - rn = route_next(rn)) { + for (rn = agg_route_top(rfd->rib[afi]); rn; + rn = agg_route_next(rn)) { struct skiplist *sl = rn->info; struct skiplist *dsl = rn->aggregate; @@ -175,8 +173,8 @@ void rfapiRibCheckCounts( ++t_pfx_deleted; } } - for (rn = route_top(rfd->rib_pending[afi]); rn; - rn = route_next(rn)) { + for (rn = agg_route_top(rfd->rib_pending[afi]); rn; + rn = agg_route_next(rn)) { struct list *l = rn->info; /* sorted by cost */ struct skiplist *sl = rn->aggregate; @@ -286,7 +284,7 @@ struct rfapi_rib_tcb { struct rfapi_descriptor *rfd; struct skiplist *sl; struct rfapi_info *ri; - struct route_node *rn; + struct agg_node *rn; int flags; #define RFAPI_RIB_TCB_FLAG_DELETED 0x00000001 }; @@ -325,7 +323,7 @@ static int rfapiRibExpireTimer(struct thread *t) RFAPI_RIB_PREFIX_COUNT_DECR(tcb->rfd, bgp->rfapi); } skiplist_free(tcb->sl); - route_unlock_node(tcb->rn); + agg_unlock_node(tcb->rn); } XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb); @@ -335,10 +333,10 @@ static int rfapiRibExpireTimer(struct thread *t) return 0; } -static void -rfapiRibStartTimer(struct rfapi_descriptor *rfd, struct rfapi_info *ri, - struct route_node *rn, /* route node attached to */ - int deleted) +static void rfapiRibStartTimer(struct rfapi_descriptor *rfd, + struct rfapi_info *ri, + struct agg_node *rn, /* route node attached to */ + int deleted) { struct thread *t = ri->timer; struct rfapi_rib_tcb *tcb = NULL; @@ -486,12 +484,12 @@ void rfapiRibClear(struct rfapi_descriptor *rfd) #endif for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - struct route_node *pn; - struct route_node *rn; + struct agg_node *pn; + struct agg_node *rn; if (rfd->rib_pending[afi]) { - for (pn = route_top(rfd->rib_pending[afi]); pn; - pn = route_next(pn)) { + for (pn = agg_route_top(rfd->rib_pending[afi]); pn; + pn = agg_route_next(pn)) { if (pn->aggregate) { /* * free references into the rfapi_info @@ -502,7 +500,7 @@ void rfapiRibClear(struct rfapi_descriptor *rfd) (struct skiplist *)(pn->aggregate)); pn->aggregate = NULL; - route_unlock_node( + agg_unlock_node( pn); /* skiplist deleted */ } /* @@ -516,13 +514,13 @@ void rfapiRibClear(struct rfapi_descriptor *rfd) } pn->info = NULL; /* linklist or 1 deleted */ - route_unlock_node(pn); + agg_unlock_node(pn); } } } if (rfd->rib[afi]) { - for (rn = route_top(rfd->rib[afi]); rn; - rn = route_next(rn)) { + for (rn = agg_route_top(rfd->rib[afi]); rn; + rn = agg_route_next(rn)) { if (rn->info) { struct rfapi_info *ri; @@ -541,7 +539,7 @@ void rfapiRibClear(struct rfapi_descriptor *rfd) skiplist_free( (struct skiplist *)rn->info); rn->info = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); RFAPI_RIB_PREFIX_COUNT_DECR(rfd, bgp->rfapi); } @@ -566,7 +564,7 @@ void rfapiRibClear(struct rfapi_descriptor *rfd) *)(rn->aggregate)); rn->aggregate = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } } } @@ -601,15 +599,18 @@ void rfapiRibFree(struct rfapi_descriptor *rfd) * Free radix trees */ for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - route_table_finish(rfd->rib_pending[afi]); + if (rfd->rib_pending[afi]) + agg_table_finish(rfd->rib_pending[afi]); rfd->rib_pending[afi] = NULL; - route_table_finish(rfd->rib[afi]); + if (rfd->rib[afi]) + agg_table_finish(rfd->rib[afi]); rfd->rib[afi] = NULL; - /* NB route_table_finish frees only prefix nodes, not chained + /* NB agg_table_finish frees only prefix nodes, not chained * info */ - route_table_finish(rfd->rsp_times[afi]); + if (rfd->rsp_times[afi]) + agg_table_finish(rfd->rsp_times[afi]); rfd->rib[afi] = NULL; } } @@ -730,7 +731,7 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri, * !0 do not include route in response */ int rfapiRibPreloadBi( - struct route_node *rfd_rib_node, /* NULL = don't preload or filter */ + struct agg_node *rfd_rib_node, /* NULL = don't preload or filter */ struct prefix *pfx_vn, struct prefix *pfx_un, uint32_t lifetime, struct bgp_info *bi) { @@ -738,7 +739,7 @@ int rfapiRibPreloadBi( struct skiplist *slRibPt = NULL; struct rfapi_info *ori = NULL; struct rfapi_rib_key rk; - struct route_node *trn; + struct agg_node *trn; afi_t afi; if (!rfd_rib_node) @@ -746,7 +747,7 @@ int rfapiRibPreloadBi( afi = family2afi(rfd_rib_node->p.family); - rfd = (struct rfapi_descriptor *)(rfd_rib_node->table->info); + rfd = agg_get_table_info(agg_get_table(rfd_rib_node)); memset((void *)&rk, 0, sizeof(rk)); rk.vn = *pfx_vn; @@ -784,7 +785,7 @@ int rfapiRibPreloadBi( if (!slRibPt) { slRibPt = skiplist_new(0, rfapi_rib_key_cmp, NULL); rfd_rib_node->info = slRibPt; - route_lock_node(rfd_rib_node); + agg_lock_node(rfd_rib_node); RFAPI_RIB_PREFIX_COUNT_INCR(rfd, rfd->bgp->rfapi); } skiplist_insert(slRibPt, &ori->rk, ori); @@ -802,11 +803,11 @@ int rfapiRibPreloadBi( /* * Update last sent time for prefix */ - trn = route_node_get(rfd->rsp_times[afi], - &rfd_rib_node->p); /* locks trn */ + trn = agg_node_get(rfd->rsp_times[afi], + &rfd_rib_node->p); /* locks trn */ trn->info = (void *)(uintptr_t)bgp_clock(); if (trn->lock > 1) - route_unlock_node(trn); + agg_unlock_node(trn); return 0; } @@ -837,7 +838,7 @@ int rfapiRibPreloadBi( */ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, afi_t afi, - struct route_node *pn, /* pending node */ + struct agg_node *pn, /* pending node */ struct rfapi_next_hop_entry **head, struct rfapi_next_hop_entry **tail) { @@ -845,7 +846,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, struct listnode *nnode = NULL; struct rfapi_info *ri = NULL; /* happy valgrind */ struct rfapi_ip_prefix hp = {0}; /* pfx to put in NHE */ - struct route_node *rn = NULL; + struct agg_node *rn = NULL; struct skiplist *slRibPt = NULL; /* rib list */ struct skiplist *slPendPt = NULL; struct list *lPendCost = NULL; @@ -875,7 +876,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, /* * Find corresponding RIB node */ - rn = route_node_get(rfd->rib[afi], &pn->p); /* locks rn */ + rn = agg_node_get(rfd->rib[afi], &pn->p); /* locks rn */ /* * RIB skiplist has key=rfapi_addr={vn,un}, val = rfapi_info, @@ -945,30 +946,30 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, skiplist_free(slRibPt); rn->info = slRibPt = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); lPendCost = pn->info = NULL; - route_unlock_node(pn); + agg_unlock_node(pn); goto callback; } if (slRibPt) { skiplist_free(slRibPt); rn->info = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } assert(!slPendPt); if (slPendPt) { /* TBD I think we can toss this block */ skiplist_free(slPendPt); pn->aggregate = NULL; - route_unlock_node(pn); + agg_unlock_node(pn); } pn->info = NULL; - route_unlock_node(pn); + agg_unlock_node(pn); - route_unlock_node(rn); /* route_node_get() */ + agg_unlock_node(rn); /* agg_node_get() */ if (rib_node_started_nonempty) { RFAPI_RIB_PREFIX_COUNT_DECR(rfd, bgp->rfapi); @@ -1076,7 +1077,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, if (skiplist_empty(slRibPt)) { skiplist_free(slRibPt); slRibPt = rn->info = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } } } @@ -1142,7 +1143,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, slRibPt = skiplist_new( 0, rfapi_rib_key_cmp, NULL); rn->info = slRibPt; - route_lock_node(rn); + agg_lock_node(rn); } skiplist_insert(slRibPt, &ori->rk, ori); @@ -1192,7 +1193,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, for (ALL_LIST_ELEMENTS(lPendCost, node, nnode, ri)) { struct rfapi_next_hop_entry *new; - struct route_node *trn; + struct agg_node *trn; new = XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_next_hop_entry)); @@ -1244,11 +1245,11 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, /* * update this NVE's timestamp for this prefix */ - trn = route_node_get(rfd->rsp_times[afi], - &pn->p); /* locks trn */ + trn = agg_node_get(rfd->rsp_times[afi], + &pn->p); /* locks trn */ trn->info = (void *)(uintptr_t)bgp_clock(); if (trn->lock > 1) - route_unlock_node(trn); + agg_unlock_node(trn); rfapiRfapiIpAddr2Str(&new->vn_address, buf, BUFSIZ); rfapiRfapiIpAddr2Str(&new->un_address, buf2, BUFSIZ); @@ -1347,7 +1348,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, 0, rfapi_rib_key_cmp, (void (*)(void *)) rfapi_info_free); - route_lock_node(rn); + agg_lock_node(rn); } RFAPI_RIB_CHECK_COUNTS(0, delete_list->count); @@ -1438,18 +1439,18 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, RFAPI_RIB_CHECK_COUNTS(0, 0); /* - * Reset pending lists. The final route_unlock_node() will probably + * Reset pending lists. The final agg_unlock_node() will probably * cause the pending node to be released. */ if (slPendPt) { skiplist_free(slPendPt); pn->aggregate = NULL; - route_unlock_node(pn); + agg_unlock_node(pn); } if (lPendCost) { list_delete_and_null(&lPendCost); pn->info = NULL; - route_unlock_node(pn); + agg_unlock_node(pn); } RFAPI_RIB_CHECK_COUNTS(0, 0); @@ -1466,7 +1467,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, if (sendingsomeroutes) rfapiMonitorTimersRestart(rfd, &pn->p); - route_unlock_node(rn); /* route_node_get() */ + agg_unlock_node(rn); /* agg_node_get() */ RFAPI_RIB_CHECK_COUNTS(1, 0); } @@ -1484,7 +1485,7 @@ static void rib_do_callback_onepass(struct rfapi_descriptor *rfd, afi_t afi) struct bgp *bgp = bgp_get_default(); struct rfapi_next_hop_entry *head = NULL; struct rfapi_next_hop_entry *tail = NULL; - struct route_node *rn; + struct agg_node *rn; #if DEBUG_L2_EXTRA vnc_zlog_debug_verbose("%s: rfd=%p, afi=%d", __func__, rfd, afi); @@ -1495,7 +1496,8 @@ static void rib_do_callback_onepass(struct rfapi_descriptor *rfd, afi_t afi) assert(bgp->rfapi); - for (rn = route_top(rfd->rib_pending[afi]); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rfd->rib_pending[afi]); rn; + rn = agg_route_next(rn)) { process_pending_node(bgp, rfd, afi, rn, &head, &tail); } @@ -1585,11 +1587,11 @@ static void updated_responses_queue_init(struct rfapi_descriptor *rfd) void rfapiRibUpdatePendingNode( struct bgp *bgp, struct rfapi_descriptor *rfd, struct rfapi_import_table *it, /* needed for L2 */ - struct route_node *it_node, uint32_t lifetime) + struct agg_node *it_node, uint32_t lifetime) { struct prefix *prefix; struct bgp_info *bi; - struct route_node *pn; + struct agg_node *pn; afi_t afi; uint32_t queued_flag; int count = 0; @@ -1609,7 +1611,7 @@ void rfapiRibUpdatePendingNode( prefix2str(prefix, buf, sizeof(buf)); vnc_zlog_debug_verbose("%s: prefix=%s", __func__, buf); - pn = route_node_get(rfd->rib_pending[afi], prefix); + pn = agg_node_get(rfd->rib_pending[afi], prefix); assert(pn); vnc_zlog_debug_verbose("%s: pn->info=%p, pn->aggregate=%p", __func__, @@ -1622,7 +1624,7 @@ void rfapiRibUpdatePendingNode( */ skiplist_free((struct skiplist *)(pn->aggregate)); pn->aggregate = NULL; - route_unlock_node(pn); /* skiplist deleted */ + agg_unlock_node(pn); /* skiplist deleted */ } @@ -1634,7 +1636,7 @@ void rfapiRibUpdatePendingNode( list_delete_and_null((struct list **)(&pn->info)); } pn->info = NULL; - route_unlock_node(pn); /* linklist or 1 deleted */ + agg_unlock_node(pn); /* linklist or 1 deleted */ } /* @@ -1689,7 +1691,7 @@ void rfapiRibUpdatePendingNode( if (!pn->aggregate) { pn->aggregate = skiplist_new(0, rfapi_rib_key_cmp, NULL); - route_lock_node(pn); + agg_lock_node(pn); } /* @@ -1715,7 +1717,7 @@ void rfapiRibUpdatePendingNode( pn->info = list_new(); ((struct list *)(pn->info))->del = (void (*)(void *))rfapi_info_free; - route_lock_node(pn); + agg_lock_node(pn); } listnode_add((struct list *)(pn->info), ri); @@ -1730,10 +1732,10 @@ void rfapiRibUpdatePendingNode( assert(!pn->aggregate); pn->info = (void *)1; /* magic value means this node has no routes */ - route_lock_node(pn); + agg_lock_node(pn); } - route_unlock_node(pn); /* route_node_get */ + agg_unlock_node(pn); /* agg_node_get */ queued_flag = RFAPI_QUEUED_FLAG(afi); @@ -1757,25 +1759,30 @@ void rfapiRibUpdatePendingNode( void rfapiRibUpdatePendingNodeSubtree( struct bgp *bgp, struct rfapi_descriptor *rfd, - struct rfapi_import_table *it, struct route_node *it_node, - struct route_node *omit_subtree, /* may be NULL */ + struct rfapi_import_table *it, struct agg_node *it_node, + struct agg_node *omit_subtree, /* may be NULL */ uint32_t lifetime) { /* FIXME: need to find a better way here to work without sticking our * hands in node->link */ - if (it_node->l_left && (it_node->l_left != omit_subtree)) { - if (it_node->l_left->info) - rfapiRibUpdatePendingNode(bgp, rfd, it, it_node->l_left, - lifetime); - rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it, it_node->l_left, + if (agg_node_left(it_node) + && (agg_node_left(it_node) != omit_subtree)) { + if (agg_node_left(it_node)->info) + rfapiRibUpdatePendingNode( + bgp, rfd, it, agg_node_left(it_node), lifetime); + rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it, + agg_node_left(it_node), omit_subtree, lifetime); } - if (it_node->l_right && (it_node->l_right != omit_subtree)) { - if (it_node->l_right->info) + if (agg_node_right(it_node) + && (agg_node_right(it_node) != omit_subtree)) { + if (agg_node_right(it_node)->info) rfapiRibUpdatePendingNode(bgp, rfd, it, - it_node->l_right, lifetime); - rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it, it_node->l_right, + agg_node_right(it_node), + lifetime); + rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it, + agg_node_right(it_node), omit_subtree, lifetime); } } @@ -1788,13 +1795,13 @@ void rfapiRibUpdatePendingNodeSubtree( */ int rfapiRibFTDFilterRecentPrefix( struct rfapi_descriptor *rfd, - struct route_node *it_rn, /* import table node */ + struct agg_node *it_rn, /* import table node */ struct prefix *pfx_target_original) /* query target */ { struct bgp *bgp = rfd->bgp; afi_t afi = family2afi(it_rn->p.family); time_t prefix_time; - struct route_node *trn; + struct agg_node *trn; /* * Not in FTD mode, so allow prefix @@ -1833,10 +1840,10 @@ int rfapiRibFTDFilterRecentPrefix( /* * check this NVE's timestamp for this prefix */ - trn = route_node_get(rfd->rsp_times[afi], &it_rn->p); /* locks trn */ + trn = agg_node_get(rfd->rsp_times[afi], &it_rn->p); /* locks trn */ prefix_time = (time_t)trn->info; if (trn->lock > 1) - route_unlock_node(trn); + agg_unlock_node(trn); #if DEBUG_FTD_FILTER_RECENT vnc_zlog_debug_verbose("%s: last sent time %lu, last allowed time %lu", @@ -1883,9 +1890,9 @@ rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd, afi_t afi; struct rfapi_info *ri; int need_insert; - struct route_node *rn; + struct agg_node *rn; int rib_node_started_nonempty = 0; - struct route_node *trn; + struct agg_node *trn; int allowed = 0; /* save in case we delete nhp */ @@ -1947,13 +1954,13 @@ rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd, /* * Look up prefix in RIB */ - rn = route_node_get(rfd->rib[afi], &pfx); /* locks rn */ + rn = agg_node_get(rfd->rib[afi], &pfx); /* locks rn */ if (rn->info) { rib_node_started_nonempty = 1; } else { rn->info = skiplist_new(0, rfapi_rib_key_cmp, NULL); - route_lock_node(rn); + agg_lock_node(rn); } /* @@ -2063,15 +2070,15 @@ rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd, rfapiRibStartTimer(rfd, ri, rn, 0); RFAPI_RIB_CHECK_COUNTS(0, 0); - route_unlock_node(rn); + agg_unlock_node(rn); /* * update this NVE's timestamp for this prefix */ - trn = route_node_get(rfd->rsp_times[afi], &pfx); /* locks trn */ + trn = agg_node_get(rfd->rsp_times[afi], &pfx); /* locks trn */ trn->info = (void *)(uintptr_t)bgp_clock(); if (trn->lock > 1) - route_unlock_node(trn); + agg_unlock_node(trn); { char str_pfx[PREFIX_STRLEN]; @@ -2108,7 +2115,7 @@ rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd, } void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it, - afi_t afi, struct route_node *it_node) + afi_t afi, struct agg_node *it_node) { struct rfapi_descriptor *rfd; struct listnode *node; @@ -2124,7 +2131,7 @@ void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it, * identifies the rfd that owns it. */ struct rfapi_monitor_eth *m; - struct route_node *rn; + struct agg_node *rn; struct skiplist *sl; void *cursor; int rc; @@ -2154,12 +2161,12 @@ void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it, * NVE, it's OK to send an update with the * delete */ - if ((rn = route_node_lookup(m->rfd->rib[afi], - &it_node->p))) { + if ((rn = agg_node_lookup(m->rfd->rib[afi], + &it_node->p))) { rfapiRibUpdatePendingNode( bgp, m->rfd, it, it_node, m->rfd->response_lifetime); - route_unlock_node(rn); + agg_unlock_node(rn); } } } @@ -2177,8 +2184,8 @@ void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it, * this * NVE, it's OK to send an update with the delete */ - if ((rn = route_node_lookup(m->rfd->rib[afi], - &it_node->p))) { + if ((rn = agg_node_lookup(m->rfd->rib[afi], + &it_node->p))) { rfapiRibUpdatePendingNode( bgp, m->rfd, it, it_node, m->rfd->response_lifetime); @@ -2192,7 +2199,7 @@ void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it, for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) { - struct route_node *rn; + struct agg_node *rn; vnc_zlog_debug_verbose( "%s: comparing rfd(%p)->import_table=%p to it=%p", @@ -2209,12 +2216,12 @@ void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it, * prefix * previously, we should send an updated response. */ - if ((rn = route_node_lookup(rfd->rib[afi], - &it_node->p))) { + if ((rn = agg_node_lookup(rfd->rib[afi], + &it_node->p))) { rfapiRibUpdatePendingNode( bgp, rfd, it, it_node, rfd->response_lifetime); - route_unlock_node(rn); + agg_unlock_node(rn); } } } @@ -2406,13 +2413,13 @@ void rfapiRibShowResponses(void *stream, struct prefix *pfx_match, for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - struct route_node *rn; + struct agg_node *rn; if (!rfd->rib[afi]) continue; - for (rn = route_top(rfd->rib[afi]); rn; - rn = route_next(rn)) { + for (rn = agg_route_top(rfd->rib[afi]); rn; + rn = agg_route_next(rn)) { struct skiplist *sl; char str_pfx[PREFIX_STRLEN]; diff --git a/bgpd/rfapi/rfapi_rib.h b/bgpd/rfapi/rfapi_rib.h index 0542727c2e4d..a8872295cd30 100644 --- a/bgpd/rfapi/rfapi_rib.h +++ b/bgpd/rfapi/rfapi_rib.h @@ -93,17 +93,17 @@ extern void rfapiRibFree(struct rfapi_descriptor *rfd); extern void rfapiRibUpdatePendingNode(struct bgp *bgp, struct rfapi_descriptor *rfd, struct rfapi_import_table *it, - struct route_node *it_node, + struct agg_node *it_node, uint32_t lifetime); extern void rfapiRibUpdatePendingNodeSubtree(struct bgp *bgp, struct rfapi_descriptor *rfd, struct rfapi_import_table *it, - struct route_node *it_node, - struct route_node *omit_subtree, + struct agg_node *it_node, + struct agg_node *omit_subtree, uint32_t lifetime); -extern int rfapiRibPreloadBi(struct route_node *rfd_rib_node, +extern int rfapiRibPreloadBi(struct agg_node *rfd_rib_node, struct prefix *pfx_vn, struct prefix *pfx_un, uint32_t lifetime, struct bgp_info *bi); @@ -113,7 +113,7 @@ rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd, extern void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it, afi_t afi, - struct route_node *it_node); + struct agg_node *it_node); extern void rfapiRibShowResponsesSummary(void *stream); @@ -124,7 +124,7 @@ extern void rfapiRibShowResponses(void *stream, struct prefix *pfx_match, extern int rfapiRibFTDFilterRecentPrefix( struct rfapi_descriptor *rfd, - struct route_node *it_rn, /* import table node */ + struct agg_node *it_rn, /* import table node */ struct prefix *pfx_target_original); /* query target */ extern void rfapiFreeRfapiUnOptionChain(struct rfapi_un_option *p); diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index cd12edbccb1f..cd751319eb5d 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -18,12 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include - #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/vty.h" #include "lib/memory.h" #include "lib/routemap.h" @@ -742,7 +739,7 @@ static void rfapiDebugPrintMonitorEncap(void *stream, m->bi, HVTYNL); } -void rfapiShowItNode(void *stream, struct route_node *rn) +void rfapiShowItNode(void *stream, struct agg_node *rn) { struct bgp_info *bi; char buf[BUFSIZ]; @@ -766,10 +763,10 @@ void rfapiShowItNode(void *stream, struct route_node *rn) /* doesn't show montors */ } -void rfapiShowImportTable(void *stream, const char *label, - struct route_table *rt, int isvpn) +void rfapiShowImportTable(void *stream, const char *label, struct agg_table *rt, + int isvpn) { - struct route_node *rn; + struct agg_node *rn; char buf[BUFSIZ]; int (*fp)(void *, const char *, ...); @@ -782,7 +779,7 @@ void rfapiShowImportTable(void *stream, const char *label, fp(out, "Import Table [%s]%s", label, HVTYNL); - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { struct bgp_info *bi; if (rn->p.family == AF_ETHERNET) { @@ -851,7 +848,7 @@ int rfapiShowVncQueries(void *stream, struct prefix *pfx_match) for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) { - struct route_node *rn; + struct agg_node *rn; int printedquerier = 0; @@ -868,8 +865,8 @@ int rfapiShowVncQueries(void *stream, struct prefix *pfx_match) * IP Queries */ if (rfd->mon) { - for (rn = route_top(rfd->mon); rn; - rn = route_next(rn)) { + for (rn = agg_route_top(rfd->mon); rn; + rn = agg_route_next(rn)) { struct rfapi_monitor_vpn *m; char buf_remain[BUFSIZ]; char buf_pfx[BUFSIZ]; @@ -1012,7 +1009,7 @@ int rfapiShowVncQueries(void *stream, struct prefix *pfx_match) } static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream, - struct route_node *rn, struct bgp_info *bi) + struct agg_node *rn, struct bgp_info *bi) { int (*fp)(void *, const char *, ...); struct vty *vty; @@ -1218,13 +1215,13 @@ static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream, for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - struct route_node *rn; + struct agg_node *rn; if (!it->imported_vpn[afi]) continue; - for (rn = route_top(it->imported_vpn[afi]); rn; - rn = route_next(rn)) { + for (rn = agg_route_top(it->imported_vpn[afi]); rn; + rn = agg_route_next(rn)) { struct bgp_info *bi; int count_only; diff --git a/bgpd/rfapi/rfapi_vty.h b/bgpd/rfapi/rfapi_vty.h index a08183aa461d..8b881292ac18 100644 --- a/bgpd/rfapi/rfapi_vty.h +++ b/bgpd/rfapi/rfapi_vty.h @@ -124,7 +124,7 @@ extern char *rfapiMonitorVpn2Str(struct rfapi_monitor_vpn *m, char *buf, extern const char *rfapiRfapiIpPrefix2Str(struct rfapi_ip_prefix *p, char *buf, int bufsize); -extern void rfapiShowItNode(void *stream, struct route_node *rn); +extern void rfapiShowItNode(void *stream, struct agg_node *rn); extern char *rfapiEthAddr2Str(const struct ethaddr *ea, char *buf, int bufsize); diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c index 69426670a12d..62891756457c 100644 --- a/bgpd/rfapi/vnc_export_bgp.c +++ b/bgpd/rfapi/vnc_export_bgp.c @@ -25,7 +25,7 @@ #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/vty.h" #include "lib/log.h" #include "lib/stream.h" @@ -54,7 +54,7 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg, - struct route_node *rn, struct attr *attr, + struct agg_node *rn, struct attr *attr, afi_t afi, struct rfapi_descriptor *irfd); @@ -172,7 +172,7 @@ static int getce(struct bgp *bgp, struct attr *attr, struct prefix *pfx_ce) } -void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct route_node *rn, +void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn, struct bgp_info *bi) { struct attr *attr = bi->attr; @@ -327,7 +327,7 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct route_node *rn, /* * "Withdrawing a Route" export process */ -void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct route_node *rn, +void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn, struct bgp_info *bi) { afi_t afi = family2afi(rn->p.family); @@ -404,7 +404,7 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct route_node *rn, static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi) { - struct route_node *rn; + struct agg_node *rn; struct bgp_info *ri; vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi); @@ -430,8 +430,8 @@ static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi) /* * Go through entire ce import table and export to BGP unicast. */ - for (rn = route_top(bgp->rfapi->it_ce->imported_vpn[afi]); rn; - rn = route_next(rn)) { + for (rn = agg_route_top(bgp->rfapi->it_ce->imported_vpn[afi]); rn; + rn = agg_route_next(rn)) { if (!rn->info) continue; @@ -513,7 +513,7 @@ static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi) * Export methods that proxy nexthop BEGIN ***********************************************************************/ -static struct ecommunity *vnc_route_origin_ecom(struct route_node *rn) +static struct ecommunity *vnc_route_origin_ecom(struct agg_node *rn) { struct ecommunity *new; struct bgp_info *bi; @@ -586,8 +586,8 @@ static struct ecommunity *vnc_route_origin_ecom_single(struct in_addr *origin) static int encap_attr_export(struct attr *new, struct attr *orig, struct prefix *new_nexthop, - struct route_node *rn) /* for VN addrs for ecom list */ - /* if rn is 0, use route's nexthop */ + struct agg_node *rn) /* for VN addrs for ecom list */ + /* if rn is 0, use route's nexthop */ { struct prefix orig_nexthop; struct prefix *use_nexthop; @@ -692,7 +692,7 @@ encap_attr_export(struct attr *new, struct attr *orig, */ void vnc_direct_bgp_add_prefix(struct bgp *bgp, struct rfapi_import_table *import_table, - struct route_node *rn) + struct agg_node *rn) { struct attr attr = {0}; struct listnode *node, *nnode; @@ -803,7 +803,7 @@ void vnc_direct_bgp_add_prefix(struct bgp *bgp, */ void vnc_direct_bgp_del_prefix(struct bgp *bgp, struct rfapi_import_table *import_table, - struct route_node *rn) + struct agg_node *rn) { struct listnode *node, *nnode; struct rfapi_rfg_name *rfgn; @@ -965,8 +965,8 @@ void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) */ if (rfgn->rfg == rfg) { - struct route_table *rt = NULL; - struct route_node *rn; + struct agg_table *rt = NULL; + struct agg_node *rn; struct attr attr = {0}; struct rfapi_import_table *import_table; @@ -987,7 +987,8 @@ void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) /* * Walk the NVE-Group's VNC Import table */ - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; + rn = agg_route_next(rn)) { if (rn->info) { @@ -1111,8 +1112,8 @@ void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) */ if (rfg && rfgn->rfg == rfg) { - struct route_table *rt = NULL; - struct route_node *rn; + struct agg_table *rt = NULL; + struct agg_node *rn; struct rfapi_import_table *import_table; import_table = rfg->rfapi_import_table; @@ -1128,7 +1129,8 @@ void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) /* * Walk the NVE-Group's VNC Import table */ - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; + rn = agg_route_next(rn)) { if (rn->info) { @@ -1159,7 +1161,7 @@ void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) static void vnc_direct_add_rn_group_rd(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg, - struct route_node *rn, struct attr *attr, + struct agg_node *rn, struct attr *attr, afi_t afi, struct rfapi_descriptor *irfd) { struct prefix nhp; @@ -1279,8 +1281,8 @@ static void vnc_direct_bgp_add_group_afi(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg, afi_t afi) { - struct route_table *rt = NULL; - struct route_node *rn; + struct agg_table *rt = NULL; + struct agg_node *rn; struct attr attr = {0}; struct rfapi_import_table *import_table; @@ -1311,7 +1313,7 @@ static void vnc_direct_bgp_add_group_afi(struct bgp *bgp, /* * Walk the NVE-Group's VNC Import table */ - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { if (rn->info) { @@ -1366,7 +1368,7 @@ void vnc_direct_bgp_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg) static void vnc_direct_del_rn_group_rd(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg, - struct route_node *rn, afi_t afi, + struct agg_node *rn, afi_t afi, struct rfapi_descriptor *irfd) { if (irfd == NULL) @@ -1388,8 +1390,8 @@ static void vnc_direct_bgp_del_group_afi(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg, afi_t afi) { - struct route_table *rt = NULL; - struct route_node *rn; + struct agg_table *rt = NULL; + struct agg_node *rn; struct rfapi_import_table *import_table; vnc_zlog_debug_verbose("%s: entry", __func__); @@ -1412,7 +1414,7 @@ static void vnc_direct_bgp_del_group_afi(struct bgp *bgp, /* * Walk the NVE-Group's VNC Import table */ - for (rn = route_top(rt); rn; rn = route_next(rn)) + for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) if (rn->info) { if (rfg->type == RFAPI_GROUP_CFG_VRF) vnc_direct_del_rn_group_rd(bgp, rfg, rn, afi, @@ -1473,14 +1475,14 @@ void vnc_direct_bgp_reexport_group_afi(struct bgp *bgp, } -static void vnc_direct_bgp_unexport_table(afi_t afi, struct route_table *rt, +static void vnc_direct_bgp_unexport_table(afi_t afi, struct agg_table *rt, struct list *nve_list) { if (nve_list) { - struct route_node *rn; + struct agg_node *rn; - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { if (rn->info) { diff --git a/bgpd/rfapi/vnc_export_bgp_p.h b/bgpd/rfapi/vnc_export_bgp_p.h index c164a35432d5..e074c3eaad27 100644 --- a/bgpd/rfapi/vnc_export_bgp_p.h +++ b/bgpd/rfapi/vnc_export_bgp_p.h @@ -29,19 +29,19 @@ #include "rfapi_private.h" -extern void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct route_node *rn, +extern void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn, struct bgp_info *bi); -extern void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct route_node *rn, +extern void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn, struct bgp_info *bi); extern void vnc_direct_bgp_add_prefix(struct bgp *bgp, struct rfapi_import_table *import_table, - struct route_node *rn); + struct agg_node *rn); extern void vnc_direct_bgp_del_prefix(struct bgp *bgp, struct rfapi_import_table *import_table, - struct route_node *rn); + struct agg_node *rn); extern void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd); diff --git a/bgpd/rfapi/vnc_export_table.c b/bgpd/rfapi/vnc_export_table.c index bbdb59c1251d..5e00a1017ba3 100644 --- a/bgpd/rfapi/vnc_export_table.c +++ b/bgpd/rfapi/vnc_export_table.c @@ -21,7 +21,7 @@ #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/memory.h" #include "lib/vty.h" @@ -33,11 +33,11 @@ #include "bgpd/rfapi/rfapi_import.h" #include "bgpd/rfapi/vnc_debug.h" -struct route_node *vnc_etn_get(struct bgp *bgp, vnc_export_type_t type, - struct prefix *p) +struct agg_node *vnc_etn_get(struct bgp *bgp, vnc_export_type_t type, + struct prefix *p) { - struct route_table *t = NULL; - struct route_node *rn = NULL; + struct agg_table *t = NULL; + struct agg_node *rn = NULL; afi_t afi; if (!bgp || !bgp->rfapi) @@ -49,27 +49,27 @@ struct route_node *vnc_etn_get(struct bgp *bgp, vnc_export_type_t type, switch (type) { case EXPORT_TYPE_BGP: if (!bgp->rfapi->rt_export_bgp[afi]) - bgp->rfapi->rt_export_bgp[afi] = route_table_init(); + bgp->rfapi->rt_export_bgp[afi] = agg_table_init(); t = bgp->rfapi->rt_export_bgp[afi]; break; case EXPORT_TYPE_ZEBRA: if (!bgp->rfapi->rt_export_zebra[afi]) - bgp->rfapi->rt_export_zebra[afi] = route_table_init(); + bgp->rfapi->rt_export_zebra[afi] = agg_table_init(); t = bgp->rfapi->rt_export_zebra[afi]; break; } if (t) - rn = route_node_get(t, p); + rn = agg_node_get(t, p); return rn; } -struct route_node *vnc_etn_lookup(struct bgp *bgp, vnc_export_type_t type, - struct prefix *p) +struct agg_node *vnc_etn_lookup(struct bgp *bgp, vnc_export_type_t type, + struct prefix *p) { - struct route_table *t = NULL; - struct route_node *rn = NULL; + struct agg_table *t = NULL; + struct agg_node *rn = NULL; afi_t afi; if (!bgp || !bgp->rfapi) @@ -81,19 +81,19 @@ struct route_node *vnc_etn_lookup(struct bgp *bgp, vnc_export_type_t type, switch (type) { case EXPORT_TYPE_BGP: if (!bgp->rfapi->rt_export_bgp[afi]) - bgp->rfapi->rt_export_bgp[afi] = route_table_init(); + bgp->rfapi->rt_export_bgp[afi] = agg_table_init(); t = bgp->rfapi->rt_export_bgp[afi]; break; case EXPORT_TYPE_ZEBRA: if (!bgp->rfapi->rt_export_zebra[afi]) - bgp->rfapi->rt_export_zebra[afi] = route_table_init(); + bgp->rfapi->rt_export_zebra[afi] = agg_table_init(); t = bgp->rfapi->rt_export_zebra[afi]; break; } if (t) - rn = route_node_lookup(t, p); + rn = agg_node_lookup(t, p); return rn; } @@ -101,7 +101,7 @@ struct vnc_export_info *vnc_eti_get(struct bgp *bgp, vnc_export_type_t etype, struct prefix *p, struct peer *peer, uint8_t type, uint8_t subtype) { - struct route_node *etn; + struct agg_node *etn; struct vnc_export_info *eti; etn = vnc_etn_get(bgp, etype, p); @@ -116,7 +116,7 @@ struct vnc_export_info *vnc_eti_get(struct bgp *bgp, vnc_export_type_t etype, } if (eti) { - route_unlock_node(etn); + agg_unlock_node(etn); } else { eti = XCALLOC(MTYPE_RFAPI_ETI, sizeof(struct vnc_export_info)); assert(eti); @@ -134,7 +134,7 @@ struct vnc_export_info *vnc_eti_get(struct bgp *bgp, vnc_export_type_t etype, void vnc_eti_delete(struct vnc_export_info *goner) { - struct route_node *etn; + struct agg_node *etn; struct vnc_export_info *eti; struct vnc_export_info *eti_prev = NULL; @@ -160,7 +160,7 @@ void vnc_eti_delete(struct vnc_export_info *goner) goner->node = NULL; XFREE(MTYPE_RFAPI_ETI, goner); - route_unlock_node(etn); + agg_unlock_node(etn); } struct vnc_export_info *vnc_eti_checktimer(struct bgp *bgp, @@ -168,7 +168,7 @@ struct vnc_export_info *vnc_eti_checktimer(struct bgp *bgp, struct prefix *p, struct peer *peer, uint8_t type, uint8_t subtype) { - struct route_node *etn; + struct agg_node *etn; struct vnc_export_info *eti; etn = vnc_etn_lookup(bgp, etype, p); @@ -183,7 +183,7 @@ struct vnc_export_info *vnc_eti_checktimer(struct bgp *bgp, } } - route_unlock_node(etn); + agg_unlock_node(etn); if (eti && eti->timer) return eti; diff --git a/bgpd/rfapi/vnc_export_table.h b/bgpd/rfapi/vnc_export_table.h index 3ccf8661e7c5..fdb35e81e173 100644 --- a/bgpd/rfapi/vnc_export_table.h +++ b/bgpd/rfapi/vnc_export_table.h @@ -37,7 +37,7 @@ typedef enum vnc_export_type { struct vnc_export_info { struct vnc_export_info *next; - struct route_node *node; + struct agg_node *node; struct peer *peer; uint8_t type; uint8_t subtype; @@ -45,11 +45,11 @@ struct vnc_export_info { struct thread *timer; }; -extern struct route_node *vnc_etn_get(struct bgp *bgp, vnc_export_type_t type, - struct prefix *p); +extern struct agg_node *vnc_etn_get(struct bgp *bgp, vnc_export_type_t type, + struct prefix *p); -extern struct route_node * -vnc_etn_lookup(struct bgp *bgp, vnc_export_type_t type, struct prefix *p); +extern struct agg_node *vnc_etn_lookup(struct bgp *bgp, vnc_export_type_t type, + struct prefix *p); extern struct vnc_export_info *vnc_eti_get(struct bgp *bgp, vnc_export_type_t etype, diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c index 72363f7cfe26..6022e4cc24ac 100644 --- a/bgpd/rfapi/vnc_import_bgp.c +++ b/bgpd/rfapi/vnc_import_bgp.c @@ -25,7 +25,7 @@ #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/vty.h" #include "lib/log.h" #include "lib/memory.h" @@ -1737,9 +1737,9 @@ static void vnc_import_bgp_exterior_add_route_it( rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop); for (it = h->imports; it; it = it->next) { - struct route_table *table; - struct route_node *rn; - struct route_node *par; + struct agg_table *table; + struct agg_node *rn; + struct agg_node *par; struct bgp_info *bi_interior; int have_usable_route; @@ -1753,7 +1753,7 @@ static void vnc_import_bgp_exterior_add_route_it( table = it->imported_vpn[afi]; - for (rn = route_node_match(table, &pfx_orig_nexthop), + for (rn = agg_node_match(table, &pfx_orig_nexthop), have_usable_route = 0; (!have_usable_route) && rn;) { @@ -1821,9 +1821,9 @@ static void vnc_import_bgp_exterior_add_route_it( 0, NULL, (void (*)(void *)) prefix_free); - route_lock_node(rn); /* for skiplist */ + agg_lock_node(rn); /* for skiplist */ } - route_lock_node(rn); /* for skiplist entry */ + agg_lock_node(rn); /* for skiplist entry */ prefix_copy(pfx_mon, prefix); if (!skiplist_insert( RFAPI_MONITOR_EXTERIOR(rn)->source, @@ -1832,14 +1832,14 @@ static void vnc_import_bgp_exterior_add_route_it( bgp_info_lock(info); } } - par = rn->parent; + par = agg_node_parent(rn); if (par) - route_lock_node(par); - route_unlock_node(rn); + agg_lock_node(par); + agg_unlock_node(rn); rn = par; } if (rn) - route_unlock_node(rn); + agg_unlock_node(rn); if (!have_usable_route) { struct prefix *pfx_mon = prefix_new(); @@ -1928,15 +1928,15 @@ void vnc_import_bgp_exterior_del_route( rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop); for (it = h->imports; it; it = it->next) { - struct route_table *table; - struct route_node *rn; - struct route_node *par; + struct agg_table *table; + struct agg_node *rn; + struct agg_node *par; struct bgp_info *bi_interior; int have_usable_route; table = it->imported_vpn[afi]; - for (rn = route_node_match(table, &pfx_orig_nexthop), + for (rn = agg_node_match(table, &pfx_orig_nexthop), have_usable_route = 0; (!have_usable_route) && rn;) { @@ -1987,9 +1987,9 @@ void vnc_import_bgp_exterior_del_route( info, NULL)) { bgp_info_unlock(info); - route_unlock_node( + agg_unlock_node( rn); /* sl entry - */ + */ } if (skiplist_empty( RFAPI_MONITOR_EXTERIOR( @@ -2002,7 +2002,7 @@ void vnc_import_bgp_exterior_del_route( RFAPI_MONITOR_EXTERIOR( rn) ->source = NULL; - route_unlock_node( + agg_unlock_node( rn); /* skiplist itself */ @@ -2010,14 +2010,14 @@ void vnc_import_bgp_exterior_del_route( } } } - par = rn->parent; + par = agg_node_parent(rn); if (par) - route_lock_node(par); - route_unlock_node(rn); + agg_lock_node(par); + agg_unlock_node(rn); rn = par; } if (rn) - route_unlock_node(rn); + agg_unlock_node(rn); if (!have_usable_route) { if (!skiplist_delete(it->monitor_exterior_orphans, info, @@ -2038,11 +2038,11 @@ void vnc_import_bgp_exterior_del_route( */ void vnc_import_bgp_exterior_add_route_interior( struct bgp *bgp, struct rfapi_import_table *it, - struct route_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior) /* VPN IT route */ + struct agg_node *rn_interior, /* VPN IT node */ + struct bgp_info *bi_interior) /* VPN IT route */ { afi_t afi = family2afi(rn_interior->p.family); - struct route_node *par; + struct agg_node *par; struct bgp_info *bi_exterior; struct prefix *pfx_exterior; /* exterior pfx */ void *cursor; @@ -2161,7 +2161,8 @@ void vnc_import_bgp_exterior_add_route_interior( * Look up the tree for possible pulldown candidates. * Find nearest parent with an exterior route monitor */ - for (par = rn_interior->parent; par; par = par->parent) { + for (par = agg_node_parent(rn_interior); par; + par = agg_node_parent(par)) { if (RFAPI_HAS_MONITOR_EXTERIOR(par)) break; } @@ -2211,13 +2212,13 @@ void vnc_import_bgp_exterior_add_route_interior( ->source = skiplist_new( 0, NULL, (void (*)(void *))prefix_free); - route_lock_node(rn_interior); + agg_lock_node(rn_interior); } skiplist_insert( RFAPI_MONITOR_EXTERIOR(rn_interior) ->source, bi_exterior, pfx_mon); - route_lock_node(rn_interior); + agg_lock_node(rn_interior); /* * Delete constructed exterior routes based on @@ -2291,12 +2292,12 @@ void vnc_import_bgp_exterior_add_route_interior( skiplist_delete(RFAPI_MONITOR_EXTERIOR(par)->source, bi_exterior, NULL); - route_unlock_node(par); /* sl entry */ + agg_unlock_node(par); /* sl entry */ } if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par)->source)) { skiplist_free(RFAPI_MONITOR_EXTERIOR(par)->source); RFAPI_MONITOR_EXTERIOR(par)->source = NULL; - route_unlock_node(par); /* sl itself */ + agg_unlock_node(par); /* sl itself */ } } @@ -2353,12 +2354,12 @@ void vnc_import_bgp_exterior_add_route_interior( skiplist_new( 0, NULL, (void (*)(void *))prefix_free); - route_lock_node(rn_interior); /* sl */ + agg_lock_node(rn_interior); /* sl */ } skiplist_insert( RFAPI_MONITOR_EXTERIOR(rn_interior)->source, bi_exterior, pfx_mon); - route_lock_node(rn_interior); /* sl entry */ + agg_lock_node(rn_interior); /* sl entry */ if (!list_adopted) { list_adopted = list_new(); } @@ -2397,7 +2398,7 @@ void vnc_import_bgp_exterior_add_route_interior( } if (list_adopted) { struct listnode *node; - struct route_node *bi_exterior; + struct agg_node *bi_exterior; for (ALL_LIST_ELEMENTS_RO(list_adopted, node, bi_exterior)) { skiplist_delete(it->monitor_exterior_orphans, @@ -2419,11 +2420,11 @@ void vnc_import_bgp_exterior_add_route_interior( */ void vnc_import_bgp_exterior_del_route_interior( struct bgp *bgp, struct rfapi_import_table *it, - struct route_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior) /* VPN IT route */ + struct agg_node *rn_interior, /* VPN IT node */ + struct bgp_info *bi_interior) /* VPN IT route */ { afi_t afi = family2afi(rn_interior->p.family); - struct route_node *par; + struct agg_node *par; struct bgp_info *bi_exterior; struct prefix *pfx_exterior; /* exterior pfx */ void *cursor; @@ -2509,7 +2510,8 @@ void vnc_import_bgp_exterior_del_route_interior( * If none is found, par will end up NULL, and we will move * the monitors to the orphan list for this import table */ - for (par = rn_interior->parent; par; par = par->parent) { + for (par = agg_node_parent(rn_interior); par; + par = agg_node_parent(par)) { if (RFAPI_MONITOR_EXTERIOR(par)->valid_interior_count) break; } @@ -2540,11 +2542,11 @@ void vnc_import_bgp_exterior_del_route_interior( skiplist_new( 0, NULL, (void (*)(void *))prefix_free); - route_lock_node(par); /* sl */ + agg_lock_node(par); /* sl */ } skiplist_insert(RFAPI_MONITOR_EXTERIOR(par)->source, bi_exterior, pfx_mon); - route_lock_node(par); /* sl entry */ + agg_lock_node(par); /* sl entry */ /* Add constructed exterior routes based on parent */ for (bi = par->info; bi; bi = bi->next) { @@ -2596,12 +2598,12 @@ void vnc_import_bgp_exterior_del_route_interior( skiplist_delete_first( RFAPI_MONITOR_EXTERIOR(rn_interior)->source); - route_unlock_node(rn_interior); /* sl entry */ + agg_unlock_node(rn_interior); /* sl entry */ } if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior)->source)) { skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior)->source); RFAPI_MONITOR_EXTERIOR(rn_interior)->source = NULL; - route_unlock_node(rn_interior); /* sl itself */ + agg_unlock_node(rn_interior); /* sl itself */ } } diff --git a/bgpd/rfapi/vnc_import_bgp_p.h b/bgpd/rfapi/vnc_import_bgp_p.h index b38fa2276ae4..a6fcae926dff 100644 --- a/bgpd/rfapi/vnc_import_bgp_p.h +++ b/bgpd/rfapi/vnc_import_bgp_p.h @@ -29,13 +29,13 @@ extern void vnc_import_bgp_exterior_add_route_interior( struct bgp *bgp, struct rfapi_import_table *it, - struct route_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior); /* VPN IT route */ + struct agg_node *rn_interior, /* VPN IT node */ + struct bgp_info *bi_interior); /* VPN IT route */ extern void vnc_import_bgp_exterior_del_route_interior( struct bgp *bgp, struct rfapi_import_table *it, - struct route_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior); /* VPN IT route */ + struct agg_node *rn_interior, /* VPN IT node */ + struct bgp_info *bi_interior); /* VPN IT route */ extern void vnc_import_bgp_exterior_redist_enable_it(struct bgp *bgp, afi_t afi, diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index a2871188e69b..a93fb6073573 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -25,7 +25,7 @@ #include "lib/zebra.h" #include "lib/prefix.h" -#include "lib/table.h" +#include "lib/agg_table.h" #include "lib/log.h" #include "lib/command.h" #include "lib/zclient.h" @@ -556,7 +556,7 @@ static void import_table_to_nve_list_zebra(struct bgp *bgp, static void vnc_zebra_add_del_prefix(struct bgp *bgp, struct rfapi_import_table *import_table, - struct route_node *rn, + struct agg_node *rn, int add) /* !0 = add, 0 = del */ { struct list *nves; @@ -611,14 +611,14 @@ static void vnc_zebra_add_del_prefix(struct bgp *bgp, void vnc_zebra_add_prefix(struct bgp *bgp, struct rfapi_import_table *import_table, - struct route_node *rn) + struct agg_node *rn) { vnc_zebra_add_del_prefix(bgp, import_table, rn, 1); } void vnc_zebra_del_prefix(struct bgp *bgp, struct rfapi_import_table *import_table, - struct route_node *rn) + struct agg_node *rn) { vnc_zebra_add_del_prefix(bgp, import_table, rn, 0); } @@ -678,8 +678,8 @@ static void vnc_zebra_add_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd, */ if (rfgn->rfg == rfg) { - struct route_table *rt = NULL; - struct route_node *rn; + struct agg_table *rt = NULL; + struct agg_node *rn; struct rfapi_import_table *import_table; import_table = rfg->rfapi_import_table; @@ -692,7 +692,8 @@ static void vnc_zebra_add_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd, /* * Walk the NVE-Group's VNC Import table */ - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; + rn = agg_route_next(rn)) { if (rn->info) { @@ -721,8 +722,8 @@ static void vnc_zebra_add_del_group_afi(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg, afi_t afi, int add) { - struct route_table *rt = NULL; - struct route_node *rn; + struct agg_table *rt = NULL; + struct agg_node *rn; struct rfapi_import_table *import_table; uint8_t family = afi2family(afi); @@ -773,7 +774,8 @@ static void vnc_zebra_add_del_group_afi(struct bgp *bgp, /* * Walk the NVE-Group's VNC Import table */ - for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (rn = agg_route_top(rt); rn; + rn = agg_route_next(rn)) { if (rn->info) { vnc_zebra_route_msg(&rn->p, nexthop_count, diff --git a/bgpd/rfapi/vnc_zebra.h b/bgpd/rfapi/vnc_zebra.h index 708aaeef501b..b8c1cb15c401 100644 --- a/bgpd/rfapi/vnc_zebra.h +++ b/bgpd/rfapi/vnc_zebra.h @@ -29,11 +29,11 @@ extern void vnc_zebra_add_prefix(struct bgp *bgp, struct rfapi_import_table *import_table, - struct route_node *rn); + struct agg_node *rn); extern void vnc_zebra_del_prefix(struct bgp *bgp, struct rfapi_import_table *import_table, - struct route_node *rn); + struct agg_node *rn); extern void vnc_zebra_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd); diff --git a/bgpd/rfp-example/librfp/Makefile b/bgpd/rfp-example/librfp/Makefile new file mode 100644 index 000000000000..8deb93d7456e --- /dev/null +++ b/bgpd/rfp-example/librfp/Makefile @@ -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 index fc66a40f000f..000000000000 --- a/bgpd/rfp-example/librfp/Makefile.am +++ /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) diff --git a/bgpd/rfp-example/librfp/rfp_example.c b/bgpd/rfp-example/librfp/rfp_example.c index cde2d7b35231..af3092232cf8 100644 --- a/bgpd/rfp-example/librfp/rfp_example.c +++ b/bgpd/rfp-example/librfp/rfp_example.c @@ -18,6 +18,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* stub rfp */ #include "rfp_internal.h" #include "bgpd/rfapi/rfapi.h" @@ -55,6 +59,54 @@ DEFUN (rfp_example_config_value, return CMD_SUCCESS; } +DEFUN (rfp_holddown_factor, + rfp_holddown_factor_cmd, + "rfp holddown-factor (0-4294967295)", + RFP_SHOW_STR + "Set Hold-Down Factor as a percentage of registration lifetime.\n" + "Percentage of registration lifetime\n") +{ + struct rfp_instance_t *rfi; + uint32_t value = 0; + + value = strtoul((argv[--argc]->arg), NULL, 10); + rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */ + if (!rfi) { + vty_out(vty, "VNC not configured\n"); + return CMD_WARNING; + } + rfi->rfapi_config.holddown_factor = value; + rfapi_rfp_set_configuration(rfi, &rfi->rfapi_config); + return CMD_SUCCESS; +} + + +DEFUN (rfp_full_table_download, + rfp_full_table_download_cmd, + "rfp full-table-download ", + RFP_SHOW_STR + "RFP full table download support (default=on)\n" + "Enable RFP full table download\n" + "Disable RFP full table download\n") +{ + struct rfp_instance_t *rfi; + rfapi_rfp_download_type old; + + rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */ + if (!rfi) { + vty_out(vty, "VNC not configured\n"); + return CMD_WARNING; + } + old = rfi->rfapi_config.download_type; + if (argv[--argc]->arg[1] == 'n' || argv[argc]->arg[1] == 'N') + rfi->rfapi_config.download_type = RFAPI_RFP_DOWNLOAD_FULL; + else + rfi->rfapi_config.download_type = RFAPI_RFP_DOWNLOAD_PARTIAL; + if (old != rfi->rfapi_config.download_type) + rfapi_rfp_set_configuration(rfi, &rfi->rfapi_config); + return CMD_SUCCESS; +} + static void rfp_vty_install() { static int installed = 0; @@ -63,6 +115,8 @@ static void rfp_vty_install() installed = 1; /* example of new cli command */ install_element(BGP_NODE, &rfp_example_config_value_cmd); + install_element(BGP_NODE, &rfp_holddown_factor_cmd); + install_element(BGP_NODE, &rfp_full_table_download_cmd); } /*********************************************************************** @@ -196,7 +250,15 @@ static int rfp_cfg_write_cb(struct vty *vty, void *rfp_start_val) vty_out(vty, "\n"); write++; } - + if (rfi->rfapi_config.holddown_factor != 0) { + vty_out(vty, " rfp holddown-factor %u\n", + rfi->rfapi_config.holddown_factor); + write++; + } + if (rfi->rfapi_config.download_type != RFAPI_RFP_DOWNLOAD_FULL) { + vty_out(vty, " rfp full-table-download off\n"); + write++; + } return write; } @@ -230,7 +292,7 @@ void *rfp_start(struct thread_master *master, struct rfapi_rfp_cfg **cfgp, /* initilize struct rfapi_rfp_cfg, see rfapi.h */ global_rfi.rfapi_config.download_type = - RFAPI_RFP_DOWNLOAD_FULL; /* default=partial */ + RFAPI_RFP_DOWNLOAD_PARTIAL; /* default=partial */ global_rfi.rfapi_config.ftd_advertisement_interval = RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL; global_rfi.rfapi_config.holddown_factor = diff --git a/bgpd/rfp-example/librfp/subdir.am b/bgpd/rfp-example/librfp/subdir.am new file mode 100644 index 000000000000..254ab716d5bf --- /dev/null +++ b/bgpd/rfp-example/librfp/subdir.am @@ -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 index 000000000000..659a9ceb1701 --- /dev/null +++ b/bgpd/rfp-example/rfptest/Makefile @@ -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 index f5db852dbb07..000000000000 --- a/bgpd/rfp-example/rfptest/Makefile.am +++ /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 = diff --git a/bgpd/rfp-example/rfptest/rfptest.c b/bgpd/rfp-example/rfptest/rfptest.c index 53e1c33cfbb0..48df6c0cc768 100644 --- a/bgpd/rfp-example/rfptest/rfptest.c +++ b/bgpd/rfp-example/rfptest/rfptest.c @@ -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 diff --git a/bgpd/rfp-example/rfptest/subdir.am b/bgpd/rfp-example/rfptest/subdir.am new file mode 100644 index 000000000000..fa7c66011641 --- /dev/null +++ b/bgpd/rfp-example/rfptest/subdir.am @@ -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 index 000000000000..42913885675f --- /dev/null +++ b/bgpd/subdir.am @@ -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 index 73f36eed1a21..000000000000 --- 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@ @WERROR@ -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 diff --git a/configure.ac b/configure.ac index be1c2763a1ef..0f5ca0da203e 100755 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ(2.60) -AC_INIT(frr, 5.1-dev, [https://github.com/frrouting/frr/issues]) +AC_INIT(frr, 6.1-dev, [https://github.com/frrouting/frr/issues]) PACKAGE_URL="https://frrouting.org/" AC_SUBST(PACKAGE_URL) PACKAGE_FULLNAME="FRRouting" @@ -132,25 +132,29 @@ dnl - specifically, options to control warnings AC_USE_SYSTEM_EXTENSIONS AC_DEFUN([AC_C_FLAG], [{ + m4_pushdef([cachename],[m4_translit([frr_cv_$1],[ =-],[___])]) + AC_CACHE_CHECK([[whether $CC supports $1]], cachename, [ AC_LANG_PUSH(C) ac_c_flag_save="$CFLAGS" CFLAGS="$CFLAGS $1" - AC_MSG_CHECKING([[whether $CC supports $1]]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[]])], [ - AC_MSG_RESULT([yes]) - m4_if([$3], [], [], [ - CFLAGS="$ac_c_flag_save" - $3 - ]) + cachename=yes ], [ - CFLAGS="$ac_c_flag_save" - AC_MSG_RESULT([no]) - $2 + cachename=no ]) + CFLAGS="$ac_c_flag_save" AC_LANG_POP(C) - }]) + ]) + if test "${cachename}" = yes; then + m4_if([$3], [], [CFLAGS="$CFLAGS $1"], [$3]) + else + : + $2 + fi + m4_popdef([cachename]) +}]) AC_DEFUN([AC_LINK_IFELSE_FLAGS], [{ AC_LANG_PUSH(C) @@ -185,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 @@ -283,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 @@ -309,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 -------------- @@ -317,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 ------- @@ -343,6 +319,8 @@ AC_ARG_ENABLE(vtysh, AS_HELP_STRING([--disable-vtysh], [do not build integrated vty shell for FRR])) AC_ARG_ENABLE(doc, AS_HELP_STRING([--disable-doc], [do not build docs])) +AC_ARG_ENABLE(doc-html, + AS_HELP_STRING([--enable-doc-html], [build HTML docs])) AC_ARG_ENABLE(zebra, AS_HELP_STRING([--disable-zebra], [do not build zebra daemon])) AC_ARG_ENABLE(bgpd, @@ -375,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, @@ -454,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) @@ -525,25 +509,10 @@ AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"]) # # Python for clippy # -AS_IF([test "$host" = "$build"], [ - PYTHONCONFIG="" - - # ordering: - # 1. try python3, but respect the user's preference on which minor ver - # 2. try python, which might be py3 or py2 again on the user's preference - # 3. try python2 (can really only be 2.7 but eh) - # 4. try 3.5 > 3.4 > 3.3 > 3.2 > 2.7 through pkg-config (no user pref) - # - # (AX_PYTHON_DEVEL has no clue about py3 vs py2) - # (AX_PYTHON does not do what we need) - - AC_CHECK_TOOLS([PYTHONCONFIG], [python3-config python-config python2-config]) - if test -n "$PYTHONCONFIG"; then - PYTHON_CFLAGS="`\"${PYTHONCONFIG}\" --includes`" - PYTHON_LIBS="`\"${PYTHONCONFIG}\" --libs`" - AC_MSG_CHECKING([whether we found a working Python version]) - AC_LINK_IFELSE_FLAGS([$PYTHON_CFLAGS], [$PYTHON_LIBS], [AC_LANG_PROGRAM([ +AC_DEFUN([FRR_PYTHON_CHECK_WORKING], [ + AC_MSG_CHECKING([whether we found a working Python version]) + AC_LINK_IFELSE_FLAGS([$PYTHON_CFLAGS], [$PYTHON_LIBS], [AC_LANG_PROGRAM([ #include #if PY_VERSION_HEX < 0x02070000 #error python too old @@ -556,23 +525,8 @@ int main(void); return 0; } ])], [ - PYTHONCONFIG="" - unset PYTHON_LIBS - unset PYTHON_CFLAGS - ]) - fi - - if test -z "$PYTHONCONFIG"; then - PKG_CHECK_MODULES([PYTHON], python-3.5, [], [ - PKG_CHECK_MODULES([PYTHON], python-3.4, [], [ - PKG_CHECK_MODULES([PYTHON], python-3.3, [], [ - PKG_CHECK_MODULES([PYTHON], python-3.2, [], [ - PKG_CHECK_MODULES([PYTHON], python-2.7, [], [ - AC_MSG_FAILURE([could not find python-config or pkg-config python, please install Python development files from libpython-dev or similar]) - ])])])])]) - - - AC_MSG_CHECKING([whether we found a working Python version]) + # some python installs are missing the zlib dependency... + PYTHON_LIBS="${PYTHON_LIBS} -lz" AC_LINK_IFELSE_FLAGS([$PYTHON_CFLAGS], [$PYTHON_LIBS], [AC_LANG_PROGRAM([ #include #if PY_VERSION_HEX < 0x02070000 @@ -586,6 +540,56 @@ int main(void); return 0; } ])], [ + m4_if([$1], [], [ + PYTHONCONFIG="" + unset PYTHON_LIBS + unset PYTHON_CFLAGS + ], [$1]) + ]) + ]) +]) + +AS_IF([test "$host" = "$build"], [ + PYTHONCONFIG="" + + # ordering: + # 1. try python3, but respect the user's preference on which minor ver + # 2. try python, which might be py3 or py2 again on the user's preference + # 3. try python2 (can really only be 2.7 but eh) + # 4. try 3.6 > 3.5 > 3.4 > 3.3 > 3.2 > 2.7 through pkg-config (no user pref) + # + # (AX_PYTHON_DEVEL has no clue about py3 vs py2) + # (AX_PYTHON does not do what we need) + + AC_CHECK_TOOLS([PYTHONCONFIG], [ \ + python3-config \ + python-config \ + python2-config \ + python3.6-config \ + python3.5-config \ + python3.4-config \ + python3.3-config \ + python3.2-config \ + python2.7-config ]) + if test -n "$PYTHONCONFIG"; then + PYTHON_CFLAGS="`\"${PYTHONCONFIG}\" --includes`" + PYTHON_LIBS="`\"${PYTHONCONFIG}\" --ldflags`" + + FRR_PYTHON_CHECK_WORKING([]) + fi + + if test -z "$PYTHONCONFIG"; then + PKG_CHECK_MODULES([PYTHON], python-3.6, [], [ + PKG_CHECK_MODULES([PYTHON], python-3.5, [], [ + PKG_CHECK_MODULES([PYTHON], python-3.4, [], [ + PKG_CHECK_MODULES([PYTHON], python-3.3, [], [ + PKG_CHECK_MODULES([PYTHON], python-3.2, [], [ + PKG_CHECK_MODULES([PYTHON], python-2.7, [], [ + AC_MSG_FAILURE([could not find python-config or pkg-config python, please install Python development files from libpython-dev or similar]) + ])])])])])]) + + + FRR_PYTHON_CHECK_WORKING([ AC_MSG_FAILURE([could not find python-config or pkg-config python, please install Python development files from libpython-dev or similar]) ]) fi @@ -597,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. @@ -626,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. # @@ -824,10 +815,15 @@ int main(int argc, char **argv) { ]) ]) +AC_CHECK_HEADERS([pthread_np.h],,, [ +#include +]) +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 @@ -920,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) @@ -1023,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) @@ -1171,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 @@ -1313,12 +1315,14 @@ FRR_INCLUDES ])dnl dnl disable doc check -if test "${enable_doc}" = "no";then - DOC="" -else - AC_CHECK_PROGS([SPHINXBUILD], [sphinx-build sphinx-build3 sphinx-build2], [no]) - DOC="doc" +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 -------------------- dnl Daemon disable check @@ -1406,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) @@ -1413,34 +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(DOC) -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)]) @@ -1518,8 +1501,8 @@ AC_SEARCH_LIBS(dlopen, [dl dld], [], [ AC_CHECK_HEADERS([link.h]) -AC_MSG_CHECKING([for dlinfo(RTLD_DI_ORIGIN)]) -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +AC_CACHE_CHECK([for dlinfo(RTLD_DI_ORIGIN)], [frr_cv_rtld_di_origin], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #ifdef HAVE_LINK_H #include @@ -1529,14 +1512,17 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ char origin[1]; dlinfo (NULL, RTLD_DI_ORIGIN, &origin); ]])], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_DLINFO_ORIGIN, 1, [Have dlinfo RTLD_DI_ORIGIN]) -], [ - AC_MSG_RESULT(no) + frr_cv_rtld_di_origin=yes + ], [ + frr_cv_rtld_di_origin=no + ]) ]) +if test "$frr_cv_rtld_di_origin" = yes; then + AC_DEFINE(HAVE_DLINFO_ORIGIN, 1, [Have dlinfo RTLD_DI_ORIGIN]) +fi -AC_MSG_CHECKING([for dlinfo(RTLD_DI_LINKMAP)]) -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +AC_CACHE_CHECK([for dlinfo(RTLD_DI_LINKMAP)], [frr_cv_rtld_di_linkmap], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #ifdef HAVE_LINK_H #include @@ -1546,12 +1532,14 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ struct link_map *lm = NULL; dlinfo (NULL, RTLD_DI_LINKMAP, &lm); ]])], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_DLINFO_LINKMAP, 1, [Have dlinfo RTLD_DI_LINKMAP]) -], [ - AC_MSG_RESULT(no) + frr_cv_rtld_di_linkmap=yes + ], [ + frr_cv_rtld_di_linkmap=no + ]) ]) - +if test "$frr_cv_rtld_di_linkmap" = yes; then + AC_DEFINE(HAVE_DLINFO_LINKMAP, 1, [Have dlinfo RTLD_DI_LINKMAP]) +fi AM_CONDITIONAL(SNMP, test "x$SNMP_METHOD" = "xagentx") @@ -1806,24 +1794,30 @@ 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_MSG_CHECKING(whether mallinfo is available) -AC_LINK_IFELSE([AC_LANG_PROGRAM([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 #endif +#ifdef HAVE_MALLOC_NP_H +#include +#endif #ifdef HAVE_MALLOC_MALLOC_H #include #endif ]], [[ struct mallinfo ac_x; ac_x = mallinfo (); ]])], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_MALLINFO,,mallinfo) -], [ - AC_MSG_RESULT(no) + frr_cv_mallinfo=yes + ], [ + frr_cv_mallinfo=no + ]) ]) +if test "$frr_cv_mallinfo" = yes; then + AC_DEFINE(HAVE_MALLINFO,,mallinfo) +fi AC_MSG_CHECKING(whether malloc_usable_size is available) AC_LINK_IFELSE([AC_LANG_PROGRAM([FRR_INCLUDES [ @@ -1953,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.])] ) @@ -1983,18 +1976,11 @@ AC_CACHE_VAL(ac_cv_htonl_works, ) AC_MSG_RESULT($ac_cv_htonl_works) -AC_CONFIG_FILES([Makefile - bgpd/Makefile - vtysh/Makefile - doc/Makefile - doc/user/Makefile - doc/manpages/Makefile - doc/developer/Makefile - tests/Makefile - bgpd/rfp-example/rfptest/Makefile - bgpd/rfp-example/librfp/Makefile +AC_CONFIG_FILES([Makefile],[sed -e 's/^#AUTODERP# //' -i Makefile]) + +AC_CONFIG_FILES([ redhat/frr.spec - debianpkg/Makefile + solaris/Makefile debianpkg/changelog alpine/APKBUILD snapcraft/snapcraft.yaml @@ -2004,14 +1990,6 @@ AC_CONFIG_FILES([Makefile 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([solaris/Makefile]) - AC_CONFIG_FILES([vtysh/extract.pl],[chmod +x vtysh/extract.pl]) AC_CONFIG_COMMANDS([lib/route_types.h], [ @@ -2053,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}\`` @@ -2065,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 diff --git a/debianpkg/Makefile.am b/debianpkg/Makefile.am deleted file mode 100644 index e7ae4bb58ded..000000000000 --- a/debianpkg/Makefile.am +++ /dev/null @@ -1,47 +0,0 @@ - -EXTRA_DIST = README.Debian README.Maintainer \ - changelog compat control copyright \ - rules source/format tests/control \ - tests/daemons watchfrr.rc \ - backports/README backports/rules \ - backports/debian8/debian/source/format \ - backports/debian8/exclude \ - backports/debian8/versionext \ - backports/debian9/debian/source/format \ - backports/debian9/exclude \ - backports/debian9/versionext \ - backports/ubuntu12.04/debian/control \ - backports/ubuntu12.04/debian/frr.install \ - backports/ubuntu12.04/debian/frr.postinst \ - backports/ubuntu12.04/debian/frr.postrm \ - backports/ubuntu12.04/debian/rules \ - backports/ubuntu12.04/debian/source/format \ - backports/ubuntu12.04/exclude \ - backports/ubuntu12.04/versionext \ - backports/ubuntu14.04/debian/control \ - backports/ubuntu14.04/debian/frr.install \ - backports/ubuntu14.04/debian/frr.postinst \ - backports/ubuntu14.04/debian/frr.postrm \ - backports/ubuntu14.04/debian/rules \ - backports/ubuntu14.04/debian/source/format \ - backports/ubuntu14.04/exclude \ - backports/ubuntu14.04/versionext \ - backports/ubuntu16.04/debian/source/format \ - backports/ubuntu16.04/exclude \ - backports/ubuntu16.04/versionext \ - backports/ubuntu17.10/debian/control \ - backports/ubuntu17.10/debian/source/format \ - backports/ubuntu17.10/exclude \ - backports/ubuntu17.10/versionext \ - backports/ubuntu18.04/debian/control \ - backports/ubuntu18.04/debian/source/format \ - backports/ubuntu18.04/exclude \ - backports/ubuntu18.04/versionext \ - frr-doc.docs frr-doc.info frr-doc.install \ - frr-doc.lintian-overrides frr.conf \ - frr-dbg.lintian-overrides \ - frr.dirs frr.docs frr.install \ - frr.lintian-overrides frr.logrotate \ - frr.manpages frr.pam frr.postinst frr.postrm \ - frr.preinst frr.prerm \ - frr-pythontools.install diff --git a/debianpkg/subdir.am b/debianpkg/subdir.am new file mode 100644 index 000000000000..b6251962b7c9 --- /dev/null +++ b/debianpkg/subdir.am @@ -0,0 +1,72 @@ +# +# debianpkg +# + +EXTRA_DIST += \ + debianpkg/README.Debian \ + debianpkg/README.Maintainer \ + debianpkg/changelog \ + debianpkg/compat \ + debianpkg/control \ + debianpkg/copyright \ + debianpkg/rules \ + debianpkg/source/format \ + debianpkg/tests/control \ + debianpkg/tests/daemons \ + debianpkg/watchfrr.rc \ + \ + debianpkg/backports/README \ + debianpkg/backports/rules \ + debianpkg/backports/debian8/debian/source/format \ + debianpkg/backports/debian8/exclude \ + debianpkg/backports/debian8/versionext \ + debianpkg/backports/debian9/debian/source/format \ + debianpkg/backports/debian9/exclude \ + debianpkg/backports/debian9/versionext \ + debianpkg/backports/ubuntu12.04/debian/control \ + debianpkg/backports/ubuntu12.04/debian/frr.install \ + debianpkg/backports/ubuntu12.04/debian/frr.postinst \ + debianpkg/backports/ubuntu12.04/debian/frr.postrm \ + debianpkg/backports/ubuntu12.04/debian/rules \ + debianpkg/backports/ubuntu12.04/debian/source/format \ + debianpkg/backports/ubuntu12.04/exclude \ + debianpkg/backports/ubuntu12.04/versionext \ + debianpkg/backports/ubuntu14.04/debian/control \ + debianpkg/backports/ubuntu14.04/debian/frr.install \ + debianpkg/backports/ubuntu14.04/debian/frr.postinst \ + debianpkg/backports/ubuntu14.04/debian/frr.postrm \ + debianpkg/backports/ubuntu14.04/debian/rules \ + debianpkg/backports/ubuntu14.04/debian/source/format \ + debianpkg/backports/ubuntu14.04/exclude \ + debianpkg/backports/ubuntu14.04/versionext \ + debianpkg/backports/ubuntu16.04/debian/source/format \ + debianpkg/backports/ubuntu16.04/exclude \ + debianpkg/backports/ubuntu16.04/versionext \ + debianpkg/backports/ubuntu17.10/debian/control \ + debianpkg/backports/ubuntu17.10/debian/source/format \ + debianpkg/backports/ubuntu17.10/exclude \ + debianpkg/backports/ubuntu17.10/versionext \ + debianpkg/backports/ubuntu18.04/debian/control \ + debianpkg/backports/ubuntu18.04/debian/source/format \ + debianpkg/backports/ubuntu18.04/exclude \ + debianpkg/backports/ubuntu18.04/versionext \ + \ + debianpkg/frr-dbg.lintian-overrides \ + debianpkg/frr-doc.docs \ + debianpkg/frr-doc.info \ + debianpkg/frr-doc.install \ + debianpkg/frr-doc.lintian-overrides \ + debianpkg/frr-pythontools.install \ + debianpkg/frr.conf \ + debianpkg/frr.dirs \ + debianpkg/frr.docs \ + debianpkg/frr.install \ + debianpkg/frr.lintian-overrides \ + debianpkg/frr.logrotate \ + debianpkg/frr.manpages \ + debianpkg/frr.pam \ + debianpkg/frr.postinst \ + debianpkg/frr.postrm \ + debianpkg/frr.preinst \ + debianpkg/frr.prerm \ + # end diff --git a/doc/.gitignore b/doc/.gitignore index e539d9a97b1a..fa2b50832168 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -1,5 +1,3 @@ -Makefile -Makefile.in mdate-sh draft-zebra-00.txt *.pdf @@ -7,7 +5,6 @@ draft-zebra-00.txt frr.ps frr.dvi stamp-vti -.nfs* *.aux *.cp *.cps @@ -21,8 +18,4 @@ stamp-vti *.toc *.tp *.vr -.arch-inventory -.arch-ids -*~ -*.loT refix diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 000000000000..3b4d3d24abde --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,18 @@ +all: ALWAYS + @$(MAKE) -s -C .. doc +%: ALWAYS + @$(MAKE) -s -C .. doc/$@ +html: + @$(MAKE) -s -C .. doc/user/_build/html/.buildinfo +info: + @$(MAKE) -s -C .. doc/user/_build/texinfo/frr.info +pdf: + @$(MAKE) -s -C .. doc/user/_build/latexpdf +frr.info: info +frr.pdf: pdf + +Makefile: + #nothing +ALWAYS: +.PHONY: ALWAYS makefiles html info frr.info pdf frr.pdf +.SUFFIXES: diff --git a/doc/Makefile.am b/doc/Makefile.am deleted file mode 100644 index f4218650545f..000000000000 --- a/doc/Makefile.am +++ /dev/null @@ -1,293 +0,0 @@ -## Process this file with automake to produce Makefile.in. - -# Pass down make invocation to each subdirectory. -# -# Each of these directories contains a Sphinx-generated Makefile that has been -# modified to implement all the targets required by Automake, as documented in -# the 'Third-Party Makefiles' section of the Automake docs. -# -# Note the absence of the 'developer' directory here; development docs are -# never built as part of a regular build. They are only built when explicitly -# asked for. See comment further down. - -# Sphinx is not designed to be invoked multiple times against the same toctree. -.NOTPARALLEL: - -SUBDIRS = manpages user -AM_MAKEFLAGS = DESTDIR=${DESTDIR} infodir=${infodir} - -MANPAGE_BUILDDIR = manpages/_build/man - -# This is a hack, see comment further down. -man_MANS = $(MANPAGE_BUILDDIR)/frr.1 - -if PIMD -man_MANS += $(MANPAGE_BUILDDIR)/pimd.8 -man_MANS += $(MANPAGE_BUILDDIR)/mtracebis.8 -endif - -if PBRD -man_MANS += $(MANPAGE_BUILDDIR)/pbrd.8 -endif - -if BGPD -man_MANS += $(MANPAGE_BUILDDIR)/bgpd.8 -endif - -if ISISD -man_MANS += $(MANPAGE_BUILDDIR)/isisd.8 -endif - -if OSPF6D -man_MANS += $(MANPAGE_BUILDDIR)/ospf6d.8 -endif - -if OSPFCLIENT -man_MANS += $(MANPAGE_BUILDDIR)/ospfclient.8 -endif - -if OSPFD -man_MANS += $(MANPAGE_BUILDDIR)/ospfd.8 -endif - -if LDPD -man_MANS += $(MANPAGE_BUILDDIR)/ldpd.8 -endif - -if RIPD -man_MANS += $(MANPAGE_BUILDDIR)/ripd.8 -endif - -if RIPNGD -man_MANS += $(MANPAGE_BUILDDIR)/ripngd.8 -endif - -if NHRPD -man_MANS += $(MANPAGE_BUILDDIR)/nhrpd.8 -endif - -if VTYSH -man_MANS += $(MANPAGE_BUILDDIR)/vtysh.1 -endif - -if WATCHFRR -man_MANS += $(MANPAGE_BUILDDIR)/watchfrr.8 -endif - -if ZEBRA -man_MANS += $(MANPAGE_BUILDDIR)/zebra.8 -endif - -if EIGRPD -man_MANS += $(MANPAGE_BUILDDIR)/eigrpd.8 -endif - -if SHARPD -man_MANS += $(MANPAGE_BUILDDIR)/sharpd.8 -endif - -if STATICD -man_MANS += $(MANPAGE_BUILDDIR)/staticd.8 -endif - -if BFDD -man_MANS += $(MANPAGE_BUILDDIR)/bfdd.8 -endif - -# Automake is particular about manpages. It is aware of them and has some -# special facilities for handling them, but it assumes that manpages are always -# given in groff source and so these facilities are limited to simply -# specifying the path to the groff sources in a special variable. There is no -# target for building manpages that can be extended, as there are for pdf, -# html, dvi, etc. Unfortunately this leaves us with hijacking the -# 'install-data' and 'all' targets in the 3rd-party Makefile in manpages/ to -# make sure manpages are always built, and then using the special Automake -# variable defined above in order to take advantage of automatic installation. -# -# However, it is conceivable that someone may want to build just the manpages, -# so here's an explicit target for that. -man: - $(MAKE) -C manpages man - -# Automake automatically defines targets for various document formats. All of -# the child 3rd-party Makefiles are aware of all Automake targets and implement -# the ones we are interested in. -# -# The SUBDIRS variable at the top of this Makefile.am causes the following -# implicit Automake targets to only build user documentation, and not developer -# documentation: -# - info -# - html -# - pdf -# -# If you wish to build developer documentation, use these targets: -developer-info: - $(MAKE) -C developer info - -developer-pdf: - $(MAKE) -C developer latexpdf - -developer-html: - $(MAKE) -C developer html - -# If you want to build the developer's docs in other formats, try the -# following: -# -# $ cd developer -# $ make help - -# dist tarballs want doc sources -EXTRA_DIST = frr-sphinx.mk \ - manpages/bgpd.rst \ - manpages/common-options.rst \ - manpages/conf.py \ - manpages/defines.rst \ - manpages/eigrpd.rst \ - manpages/epilogue.rst \ - manpages/frr.rst \ - manpages/index.rst \ - manpages/isisd.rst \ - manpages/ldpd.rst \ - manpages/Makefile.am \ - manpages/mtracebis.rst \ - manpages/nhrpd.rst \ - manpages/ospf6d.rst \ - manpages/ospfclient.rst \ - manpages/ospfd.rst \ - manpages/pimd.rst \ - manpages/ripd.rst \ - manpages/pbrd.rst \ - manpages/ripngd.rst \ - manpages/sharpd.rst \ - manpages/staticd.rst \ - manpages/vtysh.rst \ - manpages/watchfrr.rst \ - manpages/zebra.rst \ - manpages/bfdd.rst \ - manpages/bfd-options.rst \ - developer/bgpd.rst \ - developer/bgp-typecodes.rst \ - developer/building-frr-on-alpine.rst \ - developer/building-frr-on-centos6.rst \ - developer/building-frr-on-centos7.rst \ - developer/building-frr-on-debian8.rst \ - developer/building-frr-on-debian9.rst \ - developer/building-frr-on-fedora24.rst \ - developer/building-frr-on-freebsd10.rst \ - developer/building-frr-on-freebsd11.rst \ - developer/building-frr-on-freebsd9.rst \ - developer/building-frr-on-lede-openwrt.rst \ - developer/building-frr-on-netbsd6.rst \ - developer/building-frr-on-netbsd7.rst \ - developer/building-frr-on-omnios.rst \ - developer/building-frr-on-openbsd6.rst \ - developer/building-frr-on-ubuntu1204.rst \ - developer/building-frr-on-ubuntu1404.rst \ - developer/building-frr-on-ubuntu1604.rst \ - developer/building-frr-on-ubuntu1804.rst \ - developer/building.rst \ - developer/cli.rst \ - developer/conf.py \ - developer/draft-zebra-00.ms \ - developer/hooks.rst \ - developer/index.rst \ - developer/ldpd-basic-test-setup.md \ - developer/library.rst \ - developer/logging.rst \ - developer/Makefile.in \ - developer/maintainer-release-build.rst \ - developer/memtypes.rst \ - developer/modules.rst \ - developer/next-hop-tracking.rst \ - developer/ospf-api.rst \ - developer/ospf.rst \ - developer/ospf-sr.rst \ - developer/workflow.rst \ - developer/zebra.rst \ - user/babeld.rst \ - user/ldpd.rst \ - user/basic.rst \ - user/bgp.rst \ - user/bugs.rst \ - user/conf.py \ - user/eigrpd.rst \ - user/filter.rst \ - user/glossary.rst \ - user/index.rst \ - user/installation.rst \ - user/ipv6.rst \ - user/isisd.rst \ - user/kernel.rst \ - user/Makefile.am \ - user/nhrpd.rst \ - user/ospf6d.rst \ - user/ospfd.rst \ - user/ospf_fundamentals.rst \ - user/overview.rst \ - user/packet-dumps.rst \ - user/pim.rst \ - user/ripd.rst \ - user/pbr.rst \ - user/ripngd.rst \ - user/routemap.rst \ - user/routeserver.rst \ - user/rpki.rst \ - user/setup.rst \ - user/sharp.rst \ - user/snmp.rst \ - user/snmptrap.rst \ - user/static.rst \ - user/Useful_Sysctl_Settings.md \ - user/vnc.rst \ - user/vtysh.rst \ - user/zebra.rst \ - user/bfd.rst \ - user/flowspec.rst \ - mpls/ChangeLog.opaque.txt \ - mpls/ospfd.conf \ - mpls/cli_summary.txt \ - mpls/opaque_lsa.txt \ - figures/cligraph.png \ - figures/cligraph.svg \ - figures/fig-normal-processing.dia \ - figures/fig-normal-processing.png \ - figures/fig-normal-processing.txt \ - figures/fig-rs-processing.dia \ - figures/fig-rs-processing.png \ - figures/fig-rs-processing.txt \ - figures/fig_topologies_full.dia \ - figures/fig_topologies_full.png \ - figures/fig_topologies_full.txt \ - figures/fig_topologies_rs.dia \ - figures/fig_topologies_rs.png \ - figures/fig_topologies_rs.txt \ - figures/fig-vnc-commercial-route-reflector.dia \ - figures/fig-vnc-commercial-route-reflector.png \ - figures/fig-vnc-commercial-route-reflector.txt \ - figures/fig-vnc-frr-route-reflector.dia \ - figures/fig-vnc-frr-route-reflector.png \ - figures/fig-vnc-frr-route-reflector.txt \ - figures/fig-vnc-gw.dia \ - figures/fig-vnc-gw.png \ - figures/fig-vnc-gw-rr.dia \ - figures/fig-vnc-gw-rr.png \ - figures/fig-vnc-gw-rr.txt \ - figures/fig-vnc-gw.txt \ - figures/fig-vnc-mesh.dia \ - figures/fig-vnc-mesh.png \ - figures/fig-vnc-mesh.txt \ - figures/fig-vnc-redundant-route-reflectors.dia \ - figures/fig-vnc-redundant-route-reflectors.png \ - figures/fig-vnc-redundant-route-reflectors.txt \ - figures/frr-icon.svg \ - figures/frr-logo-icon.png \ - figures/frr-logo-medium.png \ - figures/frr-logo.png \ - figures/frr-logo-small.png \ - figures/git_branches.png \ - figures/git_branches.svg \ - figures/ospf_api_architecture.png \ - figures/ospf_api_msghdr.png \ - figures/ospf_api_msgs1.png \ - figures/ospf_api_msgs2.png \ - extra/frrlexer.py diff --git a/doc/developer/Makefile b/doc/developer/Makefile new file mode 100644 index 000000000000..38afb43a7003 --- /dev/null +++ b/doc/developer/Makefile @@ -0,0 +1,16 @@ +all: ALWAYS + @$(MAKE) -s -C ../.. developer-html +help: ALWAYS + @$(MAKE) -s -C ../.. doc/help +pdf: ALWAYS + @$(MAKE) -s -C ../.. doc/developer/_build/latexpdf +info: ALWAYS + @$(MAKE) -s -C ../.. doc/developer/_build/texinfo/frr.info +%: ALWAYS + @$(MAKE) -s -C ../.. doc/developer/_build/$@ + +Makefile: + #nothing +ALWAYS: +.PHONY: ALWAYS makefiles +.SUFFIXES: diff --git a/doc/developer/Makefile.am b/doc/developer/Makefile.am deleted file mode 100644 index 76758f924232..000000000000 --- a/doc/developer/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -# This is necessary to support VPATH builds. -srcdir = @srcdir@ -VPATH = @srcdir@ - -# This variable is used as the documentation source location in frr-sphinx.mk -SOURCESDIR = @srcdir@ - -include @srcdir@/../frr-sphinx.mk diff --git a/doc/developer/building-frr-on-alpine.rst b/doc/developer/building-frr-for-alpine.rst similarity index 100% rename from doc/developer/building-frr-on-alpine.rst rename to doc/developer/building-frr-for-alpine.rst diff --git a/doc/developer/building-frr-on-centos6.rst b/doc/developer/building-frr-for-centos6.rst similarity index 53% rename from doc/developer/building-frr-on-centos6.rst rename to doc/developer/building-frr-for-centos6.rst index d50376548fb5..fd75854452eb 100644 --- a/doc/developer/building-frr-on-centos6.rst +++ b/doc/developer/building-frr-for-centos6.rst @@ -40,98 +40,96 @@ Install required packages Add packages: -:: +.. code-block:: shell - sudo yum install git autoconf automake libtool make gawk \ + sudo yum install git autoconf automake libtool make gawk \ readline-devel texinfo net-snmp-devel groff pkgconfig \ json-c-devel pam-devel flex epel-release perl-XML-LibXML \ c-ares-devel -Install newer version of bison (CentOS 6 package source is too old) from -CentOS 7 +Install newer version of bison (CentOS 6 package source is too old) from CentOS +7: -:: +.. code-block:: shell - sudo yum install rpm-build - curl -O http://vault.centos.org/7.0.1406/os/Source/SPackages/bison-2.7-4.el7.src.rpm - rpmbuild --rebuild ./bison-2.7-4.el7.src.rpm - sudo yum install ./rpmbuild/RPMS/x86_64/bison-2.7-4.el6.x86_64.rpm - rm -rf rpmbuild + sudo yum install rpm-build + curl -O http://vault.centos.org/7.0.1406/os/Source/SPackages/bison-2.7-4.el7.src.rpm + rpmbuild --rebuild ./bison-2.7-4.el7.src.rpm + sudo yum install ./rpmbuild/RPMS/x86_64/bison-2.7-4.el6.x86_64.rpm + rm -rf rpmbuild -Install newer version of autoconf and automake (Package versions are too -old) +Install newer version of autoconf and automake (Package versions are too old): -:: +.. code-block:: shell - curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz - tar xvf autoconf-2.69.tar.gz - cd autoconf-2.69 - ./configure --prefix=/usr - make - sudo make install - cd .. + curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz + tar xvf autoconf-2.69.tar.gz + cd autoconf-2.69 + ./configure --prefix=/usr + make + sudo make install + cd .. - curl -O http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz - tar xvf automake-1.15.tar.gz - cd automake-1.15 - ./configure --prefix=/usr - make - sudo make install - cd .. + curl -O http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz + tar xvf automake-1.15.tar.gz + cd automake-1.15 + ./configure --prefix=/usr + make + sudo make install + cd .. -Install ``Python 2.7`` in parallel to default 2.6. Make sure you've -install EPEL (``epel-release`` as above). Then install current -``python27``, ``python27-devel`` and ``pytest`` +Install ``Python 2.7`` in parallel to default 2.6. Make sure you've install +EPEL (``epel-release`` as above). Then install current ``python27``: +``python27-devel`` and ``pytest`` -:: +.. code-block:: shell - sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm - sudo rpm -ivh https://centos6.iuscommunity.org/ius-release.rpm - sudo yum install python27 python27-pip python27-devel - sudo pip2.7 install pytest + sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm + sudo rpm -ivh https://centos6.iuscommunity.org/ius-release.rpm + sudo yum install python27 python27-pip python27-devel + sudo pip2.7 install pytest -Please note that ``CentOS 6`` needs to keep python pointing to version -2.6 for ``yum`` to keep working, so don't create a symlink for python2.7 -to python +Please note that ``CentOS 6`` needs to keep python pointing to version 2.6 for +``yum`` to keep working, so don't create a symlink for python2.7 to python. -Install newer ``Sphinx-Build`` based on ``Python 2.7`` +Install newer ``Sphinx-Build`` based on ``Python 2.7``. Create a new repo ``/etc/yum.repos.d/puias6.repo`` with the following contents: :: - ### Name: RPM Repository for RHEL 6 - PUIAS (used for Sphinx-Build) - ### URL: http://springdale.math.ias.edu/data/puias/computational - [puias-computational] - name = RPM Repository for RHEL 6 - Sphinx-Build - baseurl = http://springdale.math.ias.edu/data/puias/computational/$releasever/$basearch - #mirrorlist = - enabled = 1 - protect = 0 - gpgkey = - gpgcheck = 0 + ### Name: RPM Repository for RHEL 6 - PUIAS (used for Sphinx-Build) + ### URL: http://springdale.math.ias.edu/data/puias/computational + [puias-computational] + name = RPM Repository for RHEL 6 - Sphinx-Build + baseurl = http://springdale.math.ias.edu/data/puias/computational/$releasever/$basearch + #mirrorlist = + enabled = 1 + protect = 0 + gpgkey = + gpgcheck = 0 Update rpm database & Install newer sphinx -:: +.. code-block:: shell - sudo yum update - sudo yum install python27-sphinx + sudo yum update + sudo yum install python27-sphinx Get FRR, compile it and install it (from Git) --------------------------------------------- -**This assumes you want to build and install FRR from source and not -using any packages** +**This assumes you want to build and install FRR from source and not using any +packages** 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 -g 92 frr + sudo groupadd -r -g 85 frrvt + sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \ -c "FRR FRRouting suite" -d /var/run/frr frr Download Source, configure and compile it @@ -140,7 +138,7 @@ Download Source, configure and compile it (You may prefer different options on configure statement. These are just an example.) -:: +.. code-block:: shell git clone https://github.com/frrouting/frr.git frr cd frr @@ -170,40 +168,59 @@ 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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:: +.. code-block:: shell - sudo mkdir /var/log/frr - sudo mkdir /etc/frr - sudo touch /etc/frr/zebra.conf - sudo touch /etc/frr/bgpd.conf - sudo touch /etc/frr/ospfd.conf - sudo touch /etc/frr/ospf6d.conf - sudo touch /etc/frr/isisd.conf - sudo touch /etc/frr/ripd.conf - sudo touch /etc/frr/ripngd.conf - sudo touch /etc/frr/nhrpd.conf - sudo touch /etc/frr/eigrpd.conf - sudo touch /etc/frr/babeld.conf - sudo chown -R frr:frr /etc/frr/ - sudo touch /etc/frr/vtysh.conf - sudo chown frr:frrvt /etc/frr/vtysh.conf - sudo chmod 640 /etc/frr/*.conf + sudo mkdir /var/log/frr + sudo mkdir /etc/frr + +For integrated config file: + +.. code-block:: shell + + sudo touch /etc/frr/frr.conf + +For individual config files: + +.. note:: Integrated config is preferred to individual config. + +.. code-block:: shell + + sudo touch /etc/frr/babeld.conf + sudo touch /etc/frr/bfdd.conf + sudo touch /etc/frr/bgpd.conf + sudo touch /etc/frr/eigrpd.conf + sudo touch /etc/frr/isisd.conf + sudo touch /etc/frr/ldpd.conf + sudo touch /etc/frr/nhrpd.conf + sudo touch /etc/frr/ospf6d.conf + sudo touch /etc/frr/ospfd.conf + sudo touch /etc/frr/pbrd.conf + sudo touch /etc/frr/pimd.conf + sudo touch /etc/frr/ripd.conf + sudo touch /etc/frr/ripngd.conf + sudo touch /etc/frr/staticd.conf + sudo touch /etc/frr/zebra.conf + sudo chown -R frr:frr /etc/frr/ + sudo touch /etc/frr/vtysh.conf + sudo chown frr:frrvty /etc/frr/vtysh.conf + sudo chmod 640 /etc/frr/*.conf Install daemon config file ^^^^^^^^^^^^^^^^^^^^^^^^^^ -:: +.. code-block:: shell - sudo install -p -m 644 redhat/daemons /etc/frr/ - sudo chown frr:frr /etc/frr/daemons + sudo install -p -m 644 redhat/daemons /etc/frr/ + sudo chown frr:frr /etc/frr/daemons Edit /etc/frr/daemons as needed to select the required daemons ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -214,42 +231,40 @@ Enable the daemons as required by changing the value to ``yes`` Enable IP & IPv6 forwarding ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Edit ``/etc/sysctl.conf`` and set the following values (ignore the other -settings) - -:: +Edit :file:`/etc/sysctl.conf` and set the following values (ignore the other +settings):: - # Controls IP packet forwarding - net.ipv4.ip_forward = 1 - net.ipv6.conf.all.forwarding=1 + # Controls IP packet forwarding + net.ipv4.ip_forward = 1 + net.ipv6.conf.all.forwarding=1 - # Controls source route verification - net.ipv4.conf.default.rp_filter = 0 + # Controls source route verification + net.ipv4.conf.default.rp_filter = 0 Load the modifed sysctl's on the system: -:: +.. code-block:: shell - sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf + sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf Add init.d startup files ^^^^^^^^^^^^^^^^^^^^^^^^ -:: +.. code-block:: - sudo install -p -m 755 redhat/frr.init /etc/init.d/frr - sudo chkconfig --add frr + sudo install -p -m 755 redhat/frr.init /etc/init.d/frr + sudo chkconfig --add frr -Enable frr daemon at startup +Enable FRR daemon at startup ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:: +.. code-block:: - sudo chkconfig frr on + sudo chkconfig frr on Start FRR manually (or reboot) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:: +.. code-block:: - sudo /etc/init.d/frr start + sudo /etc/init.d/frr start diff --git a/doc/developer/building-frr-on-centos7.rst b/doc/developer/building-frr-for-centos7.rst similarity index 100% rename from doc/developer/building-frr-on-centos7.rst rename to doc/developer/building-frr-for-centos7.rst diff --git a/doc/developer/building-frr-on-debian8.rst b/doc/developer/building-frr-for-debian8.rst similarity index 100% rename from doc/developer/building-frr-on-debian8.rst rename to doc/developer/building-frr-for-debian8.rst diff --git a/doc/developer/building-frr-on-debian9.rst b/doc/developer/building-frr-for-debian9.rst similarity index 100% rename from doc/developer/building-frr-on-debian9.rst rename to doc/developer/building-frr-for-debian9.rst diff --git a/doc/developer/building-frr-on-fedora24.rst b/doc/developer/building-frr-for-fedora24.rst similarity index 100% rename from doc/developer/building-frr-on-fedora24.rst rename to doc/developer/building-frr-for-fedora24.rst diff --git a/doc/developer/building-frr-on-freebsd10.rst b/doc/developer/building-frr-for-freebsd10.rst similarity index 65% rename from doc/developer/building-frr-on-freebsd10.rst rename to doc/developer/building-frr-for-freebsd10.rst index 5d14db5fa741..95f09e8c2298 100644 --- a/doc/developer/building-frr-on-freebsd10.rst +++ b/doc/developer/building-frr-for-freebsd10.rst @@ -78,21 +78,41 @@ an example) Create empty FRR configuration files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:: +.. code-block:: shell + + sudo mkdir /usr/local/etc/frr + +For integrated config file: + +.. code-block:: shell + + sudo touch /usr/local/etc/frr/frr.conf + +For individual config files: + +.. note:: Integrated config is preferred to individual config. + +.. code-block:: shell - sudo mkdir /usr/local/etc/frr - sudo touch /usr/local/etc/frr/zebra.conf - sudo touch /usr/local/etc/frr/bgpd.conf - sudo touch /usr/local/etc/frr/ospfd.conf - sudo touch /usr/local/etc/frr/ospf6d.conf - sudo touch /usr/local/etc/frr/isisd.conf - sudo touch /usr/local/etc/frr/ripd.conf - sudo touch /usr/local/etc/frr/ripngd.conf - sudo touch /usr/local/etc/frr/pimd.conf - sudo chown -R frr:frr /usr/local/etc/frr - sudo touch /usr/local/etc/frr/vtysh.conf - sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf - sudo chmod 640 /usr/local/etc/frr/*.conf + sudo touch /usr/local/etc/frr/babeld.conf + sudo touch /usr/local/etc/frr/bfdd.conf + sudo touch /usr/local/etc/frr/bgpd.conf + sudo touch /usr/local/etc/frr/eigrpd.conf + sudo touch /usr/local/etc/frr/isisd.conf + sudo touch /usr/local/etc/frr/ldpd.conf + sudo touch /usr/local/etc/frr/nhrpd.conf + sudo touch /usr/local/etc/frr/ospf6d.conf + sudo touch /usr/local/etc/frr/ospfd.conf + sudo touch /usr/local/etc/frr/pbrd.conf + sudo touch /usr/local/etc/frr/pimd.conf + sudo touch /usr/local/etc/frr/ripd.conf + sudo touch /usr/local/etc/frr/ripngd.conf + sudo touch /usr/local/etc/frr/staticd.conf + sudo touch /usr/local/etc/frr/zebra.conf + sudo chown -R frr:frr /usr/local/etc/frr/ + sudo touch /usr/local/etc/frr/vtysh.conf + sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf + sudo chmod 640 /usr/local/etc/frr/*.conf Enable IP & IPv6 forwarding ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -101,9 +121,8 @@ Add the following lines to the end of ``/etc/sysctl.conf``: :: - # Routing: We need to forward packets - net.inet.ip.forwarding=1 - net.inet6.ip6.forwarding=1 + # Routing: We need to forward packets + net.inet.ip.forwarding=1 + net.inet6.ip6.forwarding=1 -**Reboot** or use ``sysctl`` to apply the same config to the running -system +**Reboot** or use ``sysctl`` to apply the same config to the running system. diff --git a/doc/developer/building-frr-for-freebsd11.rst b/doc/developer/building-frr-for-freebsd11.rst new file mode 100644 index 000000000000..ce5941440c37 --- /dev/null +++ b/doc/developer/building-frr-for-freebsd11.rst @@ -0,0 +1,133 @@ +FreeBSD 11 +========== + +FreeBSD 11 restrictions: +------------------------ + +- MPLS is not supported on ``FreeBSD``. MPLS requires a Linux Kernel + (4.5 or higher). LDP can be built, but may have limited use without + MPLS + +Install required packages +------------------------- + +Add packages: (Allow the install of the package managment tool if this +is first package install and asked) + +.. code-block:: shell + + pkg install git autoconf automake libtool gmake gawk json-c pkgconf \ + bison flex py27-pytest c-ares python3 py36-sphinx texinfo + +Make sure there is no /usr/bin/flex preinstalled (and use the newly +installed in /usr/local/bin): (FreeBSD frequently provides a older flex +as part of the base OS which takes preference in path) + +.. code-block:: shell + + rm -f /usr/bin/flex + +Get FRR, compile it and install it (from Git) +--------------------------------------------- + +**This assumes you want to build and install FRR from source and not using any +packages** + +Add frr group and user +^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: shell + + pw groupadd frr -g 101 + pw groupadd frrvty -g 102 + pw adduser frr -g 101 -u 101 -G 102 -c "FRR suite" \ + -d /usr/local/etc/frr -s /usr/sbin/nologin + + +Download Source, configure and compile it +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +(You may prefer different options on configure statement. These are just +an example) + +.. code-block:: shell + + git clone https://github.com/frrouting/frr.git frr + cd frr + ./bootstrap.sh + setenv MAKE gmake + setenv LDFLAGS -L/usr/local/lib + setenv CPPFLAGS -I/usr/local/include + ln -s /usr/local/bin/sphinx-build-3.6 /usr/local/bin/sphinx-build + ./configure \ + --sysconfdir=/usr/local/etc/frr \ + --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ + --localstatedir=/var/run/frr \ + --prefix=/usr/local \ + --enable-ospfclient=yes \ + --enable-ospfapi=yes \ + --enable-multipath=64 \ + --enable-user=frr \ + --enable-group=frr \ + --enable-vty-group=frrvty \ + --enable-configfile-mask=0640 \ + --enable-logfile-mask=0640 \ + --enable-rtadv \ + --enable-fpm \ + --with-pkg-git-version \ + --with-pkg-extra-version=-MyOwnFRRVersion + gmake + gmake check + sudo gmake install + +Create empty FRR configuration files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: shell + + sudo mkdir /usr/local/etc/frr + +For integrated config file: + +.. code-block:: shell + + sudo touch /usr/local/etc/frr/frr.conf + +For individual config files: + +.. note:: Integrated config is preferred to individual config. + +.. code-block:: shell + + sudo touch /usr/local/etc/frr/babeld.conf + sudo touch /usr/local/etc/frr/bfdd.conf + sudo touch /usr/local/etc/frr/bgpd.conf + sudo touch /usr/local/etc/frr/eigrpd.conf + sudo touch /usr/local/etc/frr/isisd.conf + sudo touch /usr/local/etc/frr/ldpd.conf + sudo touch /usr/local/etc/frr/nhrpd.conf + sudo touch /usr/local/etc/frr/ospf6d.conf + sudo touch /usr/local/etc/frr/ospfd.conf + sudo touch /usr/local/etc/frr/pbrd.conf + sudo touch /usr/local/etc/frr/pimd.conf + sudo touch /usr/local/etc/frr/ripd.conf + sudo touch /usr/local/etc/frr/ripngd.conf + sudo touch /usr/local/etc/frr/staticd.conf + sudo touch /usr/local/etc/frr/zebra.conf + sudo chown -R frr:frr /usr/local/etc/frr/ + sudo touch /usr/local/etc/frr/vtysh.conf + sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf + sudo chmod 640 /usr/local/etc/frr/*.conf + +Enable IP & IPv6 forwarding +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Add the following lines to the end of ``/etc/sysctl.conf``: + +:: + + # Routing: We need to forward packets + net.inet.ip.forwarding=1 + net.inet6.ip6.forwarding=1 + +**Reboot** or use ``sysctl`` to apply the same config to the running system. diff --git a/doc/developer/building-frr-on-freebsd9.rst b/doc/developer/building-frr-for-freebsd9.rst similarity index 69% rename from doc/developer/building-frr-on-freebsd9.rst rename to doc/developer/building-frr-for-freebsd9.rst index 02279debea8a..4f859d3510fb 100644 --- a/doc/developer/building-frr-on-freebsd9.rst +++ b/doc/developer/building-frr-for-freebsd9.rst @@ -91,21 +91,41 @@ an example) Create empty FRR configuration files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:: +.. code-block:: shell + + sudo mkdir /usr/local/etc/frr + +For integrated config file: + +.. code-block:: shell + + sudo touch /usr/local/etc/frr/frr.conf + +For individual config files: + +.. note:: Integrated config is preferred to individual config. + +.. code-block:: shell - sudo mkdir /usr/local/etc/frr - sudo touch /usr/local/etc/frr/zebra.conf - sudo touch /usr/local/etc/frr/bgpd.conf - sudo touch /usr/local/etc/frr/ospfd.conf - sudo touch /usr/local/etc/frr/ospf6d.conf - sudo touch /usr/local/etc/frr/isisd.conf - sudo touch /usr/local/etc/frr/ripd.conf - sudo touch /usr/local/etc/frr/ripngd.conf - sudo touch /usr/local/etc/frr/pimd.conf - sudo chown -R frr:frr /usr/local/etc/frr - sudo touch /usr/local/etc/frr/vtysh.conf - sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf - sudo chmod 640 /usr/local/etc/frr/*.conf + sudo touch /usr/local/etc/frr/babeld.conf + sudo touch /usr/local/etc/frr/bfdd.conf + sudo touch /usr/local/etc/frr/bgpd.conf + sudo touch /usr/local/etc/frr/eigrpd.conf + sudo touch /usr/local/etc/frr/isisd.conf + sudo touch /usr/local/etc/frr/ldpd.conf + sudo touch /usr/local/etc/frr/nhrpd.conf + sudo touch /usr/local/etc/frr/ospf6d.conf + sudo touch /usr/local/etc/frr/ospfd.conf + sudo touch /usr/local/etc/frr/pbrd.conf + sudo touch /usr/local/etc/frr/pimd.conf + sudo touch /usr/local/etc/frr/ripd.conf + sudo touch /usr/local/etc/frr/ripngd.conf + sudo touch /usr/local/etc/frr/staticd.conf + sudo touch /usr/local/etc/frr/zebra.conf + sudo chown -R frr:frr /usr/local/etc/frr/ + sudo touch /usr/local/etc/frr/vtysh.conf + sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf + sudo chmod 640 /usr/local/etc/frr/*.conf Enable IP & IPv6 forwarding ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -114,9 +134,8 @@ Add the following lines to the end of ``/etc/sysctl.conf``: :: - # Routing: We need to forward packets - net.inet.ip.forwarding=1 - net.inet6.ip6.forwarding=1 + # Routing: We need to forward packets + net.inet.ip.forwarding=1 + net.inet6.ip6.forwarding=1 -**Reboot** or use ``sysctl`` to apply the same config to the running -system +**Reboot** or use ``sysctl`` to apply the same config to the running system. diff --git a/doc/developer/building-frr-on-netbsd6.rst b/doc/developer/building-frr-for-netbsd6.rst similarity index 100% rename from doc/developer/building-frr-on-netbsd6.rst rename to doc/developer/building-frr-for-netbsd6.rst diff --git a/doc/developer/building-frr-on-netbsd7.rst b/doc/developer/building-frr-for-netbsd7.rst similarity index 100% rename from doc/developer/building-frr-on-netbsd7.rst rename to doc/developer/building-frr-for-netbsd7.rst diff --git a/doc/developer/building-frr-on-omnios.rst b/doc/developer/building-frr-for-omnios.rst similarity index 100% rename from doc/developer/building-frr-on-omnios.rst rename to doc/developer/building-frr-for-omnios.rst diff --git a/doc/developer/building-frr-on-openbsd6.rst b/doc/developer/building-frr-for-openbsd6.rst similarity index 100% rename from doc/developer/building-frr-on-openbsd6.rst rename to doc/developer/building-frr-for-openbsd6.rst diff --git a/doc/developer/building-frr-for-openwrt.rst b/doc/developer/building-frr-for-openwrt.rst new file mode 100644 index 000000000000..b9be1b52260e --- /dev/null +++ b/doc/developer/building-frr-for-openwrt.rst @@ -0,0 +1,77 @@ +OpenWRT +======= + +Prepare build environment +------------------------- + +For Debian based distributions, run: + +:: + + sudo apt-get install git build-essential libssl-dev libncurses5-dev \ + unzip gawk zlib1g-dev subversion mercurial + +For other environments, instructions can be found in the +`official documentation +`_. + + +Get OpenWRT Sources (from Git) +------------------------------ + +.. note:: + The OpenWRT build will fail if you run it as root. So take care to run it as a nonprivileged user. + +Clone the OpenWRT sources and retrieve the package feeds + +:: + + git clone https://github.com/openwrt/openwrt.git + cd openwrt + ./scripts/feeds update -a + ./scripts/feeds install -a + cd feeds/routing + git fetch origin pull/319/head + git read-tree --prefix=frr/ -u FETCH_HEAD:frr + cd ../../package/feeds/routing/ + ln -sv ../../../feeds/routing/frr . + cd ../../.. + +Configure OpenWRT for your target and select the needed FRR packages in Network -> Routing and Redirection -> frr, +exit and save + +:: + + make menuconfig + +Then, to compile either a complete OpenWRT image, or the FRR packages, run: + +:: + + make or make package/frr/compile + +It may be possible that on first build ``make package/frr/compile`` not +to work and it may be needed to run a ``make`` for the entire build +environment. Add ``V=s`` to get more debugging output. + +Work with sources +----------------- + +To update to a newer version, or change other options, you need to edit the ``feeds/routing/frr/Makefile``. + +Usage +----- + +Edit ``/usr/sbin/frr.init`` and add/remove the daemons name in section +``DAEMONS=`` or don't install unneded packages For example: zebra bgpd ldpd +isisd nhrpd ospfd ospf6d pimd ripd ripngd + +Enable the serivce +^^^^^^^^^^^^^^^^^^ + +- ``service frr enable`` + +Start the service +^^^^^^^^^^^^^^^^^ + +- ``service frr start`` diff --git a/doc/developer/building-frr-on-ubuntu1204.rst b/doc/developer/building-frr-for-ubuntu1204.rst similarity index 100% rename from doc/developer/building-frr-on-ubuntu1204.rst rename to doc/developer/building-frr-for-ubuntu1204.rst diff --git a/doc/developer/building-frr-on-ubuntu1404.rst b/doc/developer/building-frr-for-ubuntu1404.rst similarity index 100% rename from doc/developer/building-frr-on-ubuntu1404.rst rename to doc/developer/building-frr-for-ubuntu1404.rst diff --git a/doc/developer/building-frr-on-ubuntu1604.rst b/doc/developer/building-frr-for-ubuntu1604.rst similarity index 100% rename from doc/developer/building-frr-on-ubuntu1604.rst rename to doc/developer/building-frr-for-ubuntu1604.rst diff --git a/doc/developer/building-frr-on-ubuntu1804.rst b/doc/developer/building-frr-for-ubuntu1804.rst similarity index 100% rename from doc/developer/building-frr-on-ubuntu1804.rst rename to doc/developer/building-frr-for-ubuntu1804.rst diff --git a/doc/developer/building-frr-on-freebsd11.rst b/doc/developer/building-frr-on-freebsd11.rst deleted file mode 100644 index 87fb30226db4..000000000000 --- a/doc/developer/building-frr-on-freebsd11.rst +++ /dev/null @@ -1,109 +0,0 @@ -FreeBSD 11 -========================================== - -FreeBSD 11 restrictions: ------------------------- - -- MPLS is not supported on ``FreeBSD``. MPLS requires a Linux Kernel - (4.5 or higher). LDP can be built, but may have limited use without - MPLS - -Install required packages -------------------------- - -Add packages: (Allow the install of the package managment tool if this -is first package install and asked) - -:: - - pkg install git autoconf automake libtool gmake gawk json-c pkgconf \ - bison flex py27-pytest c-ares python3 py-sphinx - -Make sure there is no /usr/bin/flex preinstalled (and use the newly -installed in /usr/local/bin): (FreeBSD frequently provides a older flex -as part of the base OS which takes preference in path) - -:: - - rm -f /usr/bin/flex - -Get FRR, compile it and install it (from Git) ---------------------------------------------- - -**This assumes you want to build and install FRR from source and not -using any packages** - -Add frr group and user -^^^^^^^^^^^^^^^^^^^^^^ - -:: - - pw groupadd frr -g 101 - pw groupadd frrvty -g 102 - pw adduser frr -g 101 -u 101 -G 102 -c "FRR suite" \ - -d /usr/local/etc/frr -s /usr/sbin/nologin - -(You may prefer different options on configure statement. These are just -an example) - -:: - - git clone https://github.com/frrouting/frr.git frr - cd frr - ./bootstrap.sh - export MAKE=gmake - export LDFLAGS="-L/usr/local/lib" - export CPPFLAGS="-I/usr/local/include" - ./configure \ - --sysconfdir=/usr/local/etc/frr \ - --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ - --localstatedir=/var/run/frr \ - --prefix=/usr/local \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ - --enable-multipath=64 \ - --enable-user=frr \ - --enable-group=frr \ - --enable-vty-group=frrvty \ - --enable-configfile-mask=0640 \ - --enable-logfile-mask=0640 \ - --enable-rtadv \ - --enable-fpm \ - --with-pkg-git-version \ - --with-pkg-extra-version=-MyOwnFRRVersion - gmake - gmake check - sudo gmake install - -Create empty FRR configuration files -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -:: - - sudo mkdir /usr/local/etc/frr - sudo touch /usr/local/etc/frr/zebra.conf - sudo touch /usr/local/etc/frr/bgpd.conf - sudo touch /usr/local/etc/frr/ospfd.conf - sudo touch /usr/local/etc/frr/ospf6d.conf - sudo touch /usr/local/etc/frr/isisd.conf - sudo touch /usr/local/etc/frr/ripd.conf - sudo touch /usr/local/etc/frr/ripngd.conf - sudo touch /usr/local/etc/frr/pimd.conf - sudo chown -R frr:frr /usr/local/etc/frr - sudo touch /usr/local/etc/frr/vtysh.conf - sudo chown frr:frrvty /usr/local/etc/frr/vtysh.conf - sudo chmod 640 /usr/local/etc/frr/*.conf - -Enable IP & IPv6 forwarding -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Add the following lines to the end of ``/etc/sysctl.conf``: - -:: - - # Routing: We need to forward packets - net.inet.ip.forwarding=1 - net.inet6.ip6.forwarding=1 - -**Reboot** or use ``sysctl`` to apply the same config to the running -system diff --git a/doc/developer/building-frr-on-lede-openwrt.rst b/doc/developer/building-frr-on-lede-openwrt.rst deleted file mode 100644 index d14754b37fcd..000000000000 --- a/doc/developer/building-frr-on-lede-openwrt.rst +++ /dev/null @@ -1,108 +0,0 @@ -OpenWRT/LEDE -============================================= - -- for the moment because of cross compile problems, master is not - supported, only up to 3.0 -- LDP can't be built because of missing Perl-XML-LibXML in OpenWRT/LEDE - tree - -Prepare build environment -------------------------- - -https://lede-project.org/docs/guide-developer/install-buildsystem - -for - -Ubuntu 12.04LTS: - -:: - - sudo apt-get install build-essential subversion git-core \ - libncurses5-dev zlib1g-dev gawk flex quilt libssl-dev xsltproc \ - libxml-parser-perl mercurial bzr ecj cvs unzip python3-sphinx - -Ubuntu 64bit: - -:: - - sudo apt-get install build-essential subversion libncurses5-dev zlib1g-dev \ - gawk gcc-multilib flex git-core gettext libssl-dev python3-sphinx - -Debian 8 Jessie: - -:: - - sudo apt-get install build-essential libncurses5-dev gawk git subversion \ - libssl-dev gettext unzip zlib1g-dev file python python3-sphinx - -Debian 9 Stretch: - -:: - - sudo apt-get install build-essential libncurses5-dev gawk git subversion \ - libssl-dev gettext zlib1g-dev python3-sphinx - -Centos x86-64 (some packages require EPEL): - -:: - - yum install subversion binutils bzip2 gcc gcc-c++ gawk gettext flex \ - ncurses-devel zlib-devel zlib-static make patch unzip glibc glibc-devel \ - perl-ExtUtils-MakeMaker glibc-static quilt ncurses-libs sed sdcc bison \ - intltool sharutils wget git-core openssl-devel xz python-sphinx - -Fedora 24 - 64Bit: - -:: - - dnf install -y subversion binutils bzip2 gcc gcc-c++ gawk gettext git-core \ - unzip ncurses-devel ncurses-compat-libs zlib-devel zlib-static make \ - flex patch perl-ExtUtils-MakeMaker perl-Thread-Queue glibc glibc-devel \ - glibc-static quilt sed sdcc intltool sharutils bison wget openssl-devel \ - python3-sphinx - -Get LEDE Sources (from Git) ---------------------------- - -LEDE and OpenWRT is planned to remerge and won't cover the similar -OpenWRT build As normal user: git clone -https://git.lede-project.org/source.git lede cd lede ./scripts/feeds -update -a ./scripts/feeds install -a cd feeds/routing git pull origin -pull/319/head ln -s ../../../feeds/routing/frr/ -../../package/feeds/routing/ cd ../.. make menuconfig - -Select the needed target then select needed packages in Network -> -Routing and Redirection -> frr, exit and save - -:: - - make or make package/frr/compile - -It may be possible that on first build ``make package/frr/compile`` not -to work and it may be needed to run a ``make`` for the entire build -envronment, add V=s for debugging - -Work with sources ------------------ - -To update the rc1 version or add other options, the Makefile is found in -feeds/routing/frr - -edit: PKG\_VERSION:= PKG\_SOURCE\_VERSION:= - -Usage ------ - -Edit ``/usr/sbin/frr.init`` and add/remove the daemons name in section -DAEMONS= or don't install unneded packages For example: zebra bgpd ldpd -isisd nhrpd ospfd ospf6d pimd ripd ripngd - -Enable the serivce -^^^^^^^^^^^^^^^^^^ - -- service frr enable - -Start the service -^^^^^^^^^^^^^^^^^ - -- service frr start diff --git a/doc/developer/building.rst b/doc/developer/building.rst index 051611a65dfc..4c18445f9d18 100644 --- a/doc/developer/building.rst +++ b/doc/developer/building.rst @@ -7,21 +7,21 @@ Building FRR .. toctree:: :maxdepth: 2 - building-frr-on-lede-openwrt - building-frr-on-alpine - building-frr-on-centos6 - building-frr-on-centos7 - building-frr-on-debian8 - building-frr-on-debian9 - building-frr-on-fedora24 - building-frr-on-freebsd10 - building-frr-on-freebsd11 - building-frr-on-freebsd9 - building-frr-on-netbsd6 - building-frr-on-netbsd7 - building-frr-on-omnios - building-frr-on-openbsd6 - building-frr-on-ubuntu1204 - building-frr-on-ubuntu1404 - building-frr-on-ubuntu1604 - building-frr-on-ubuntu1804 + building-frr-for-alpine + building-frr-for-centos6 + building-frr-for-centos7 + building-frr-for-debian8 + building-frr-for-debian9 + building-frr-for-fedora24 + building-frr-for-freebsd10 + building-frr-for-freebsd11 + building-frr-for-freebsd9 + building-frr-for-netbsd6 + building-frr-for-netbsd7 + building-frr-for-omnios + building-frr-for-openbsd6 + building-frr-for-openwrt + building-frr-for-ubuntu1204 + building-frr-for-ubuntu1404 + building-frr-for-ubuntu1604 + building-frr-for-ubuntu1804 diff --git a/doc/developer/cli.rst b/doc/developer/cli.rst index 20391c47bcfe..c0716a5c9319 100644 --- a/doc/developer/cli.rst +++ b/doc/developer/cli.rst @@ -450,8 +450,6 @@ is no ordering requirement) .. code-block:: make - include ../common.am - # ... # if linked into a LTLIBRARY (.la/.so): diff --git a/doc/developer/subdir.am b/doc/developer/subdir.am new file mode 100644 index 000000000000..43d129004433 --- /dev/null +++ b/doc/developer/subdir.am @@ -0,0 +1,72 @@ +# +# doc/developer +# + +dev_RSTFILES = \ + doc/developer/bgp-typecodes.rst \ + doc/developer/bgpd.rst \ + doc/developer/building-frr-for-openwrt.rst \ + doc/developer/building-frr-for-alpine.rst \ + doc/developer/building-frr-for-centos6.rst \ + doc/developer/building-frr-for-centos7.rst \ + doc/developer/building-frr-for-debian8.rst \ + doc/developer/building-frr-for-debian9.rst \ + doc/developer/building-frr-for-fedora24.rst \ + doc/developer/building-frr-for-freebsd10.rst \ + doc/developer/building-frr-for-freebsd11.rst \ + doc/developer/building-frr-for-freebsd9.rst \ + doc/developer/building-frr-for-netbsd6.rst \ + doc/developer/building-frr-for-netbsd7.rst \ + doc/developer/building-frr-for-omnios.rst \ + doc/developer/building-frr-for-openbsd6.rst \ + doc/developer/building-frr-for-ubuntu1204.rst \ + doc/developer/building-frr-for-ubuntu1404.rst \ + doc/developer/building-frr-for-ubuntu1604.rst \ + doc/developer/building-frr-for-ubuntu1804.rst \ + doc/developer/building.rst \ + doc/developer/cli.rst \ + doc/developer/conf.py \ + doc/developer/hooks.rst \ + doc/developer/index.rst \ + doc/developer/library.rst \ + doc/developer/logging.rst \ + doc/developer/maintainer-release-build.rst \ + doc/developer/memtypes.rst \ + doc/developer/modules.rst \ + doc/developer/next-hop-tracking.rst \ + doc/developer/ospf-api.rst \ + doc/developer/ospf-sr.rst \ + doc/developer/ospf.rst \ + doc/developer/workflow.rst \ + doc/developer/zebra.rst \ + # end + +EXTRA_DIST += \ + $(dev_RSTFILES) \ + doc/developer/draft-zebra-00.ms \ + doc/developer/ldpd-basic-test-setup.md \ + # end + +DEVBUILD = doc/developer/_build +$(DEVBUILD)/.doctrees/environment.pickle: $(dev_RSTFILES) + +# +# nothing built automatically for "all" target. +# + +# +# standard targets +# + +developer-info: $(DEVBUILD)/texinfo/frr.info +developer-html: $(DEVBUILD)/html/.buildinfo +developer-pdf: $(DEVBUILD)/latexpdf + +# +# hook-in for clean +# + +.PHONY: clean-devdocs +clean-local: clean-devdocs +clean-devdocs: + -rm -rf "$(DEVBUILD)" diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst index 358cb9ac7bf7..d316de0f3870 100644 --- a/doc/developer/workflow.rst +++ b/doc/developer/workflow.rst @@ -135,6 +135,11 @@ systems. Once the automated tests succeed, other developers will review your code for quality and correctness. After any concerns are resolved, your code will be merged into the branch it was submitted against. +The title of the pull request should provide a high level technical +summary of the included patches. The description should provide +additional details that will help the reviewer to understand the context +of the included patches. + Patch Submission via Mailing List --------------------------------- @@ -330,6 +335,11 @@ Guidelines for code review - For a PR you marked with "Changes requested", please respond to updates in a timely manner to avoid impeding the flow of development. +- Rejected or obsolete PRs are generally closed by the submitter based + on requests and/or agreement captured in a PR comment. The comment + may originate with a reviewer or document agreement reached on Slack, + the Development mailing list, or the weekly technical meeting. + Coding Practices & Style ======================== diff --git a/doc/frr-sphinx.mk b/doc/frr-sphinx.mk deleted file mode 100644 index 3e4c67d37407..000000000000 --- a/doc/frr-sphinx.mk +++ /dev/null @@ -1,229 +0,0 @@ -# Makefile for Sphinx documentation -# - -# Sphinx is not designed to be invoked multiple times against the same toctree. -.NOTPARALLEL: - -# You can set these variables from the command line. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -PAPER ?= -BUILDDIR = _build - -# This is a custom FRR variable just for this docs subdirectory used to support -# VPATH builds. Makefiles which include this file should override it to point -# to the correct sources path. -SOURCESDIR ?= . - -# User-friendly check for sphinx-build -ifneq ($(MAKECMDGOALS), clean) - ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) - SPHINXBUILD = sphinx-1.0-build - endif - ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) - $(error "The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD make variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/") - endif -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCESDIR) -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCESDIR) - -.PHONY: help -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " applehelp to make an Apple Help Book" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - @echo " coverage to run coverage check of the documentation (if enabled)" - -.PHONY: clean -clean: - rm -rf $(BUILDDIR)/* - -.PHONY: html -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -.PHONY: dirhtml -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -.PHONY: singlehtml -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -.PHONY: pickle -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -.PHONY: json -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -.PHONY: htmlhelp -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -.PHONY: qthelp -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/FRR.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/FRR.qhc" - -.PHONY: applehelp -applehelp: - $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp - @echo - @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." - @echo "N.B. You won't be able to view it unless you put it in" \ - "~/Library/Documentation/Help or install it in your application" \ - "bundle." - -.PHONY: devhelp -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/FRR" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/FRR" - @echo "# devhelp" - -.PHONY: epub -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -.PHONY: latex -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -.PHONY: latexpdf -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -.PHONY: latexpdfja -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -.PHONY: text -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -.PHONY: man -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -.PHONY: texinfo -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -.PHONY: info -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - $(MAKE) -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -.PHONY: gettext -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -.PHONY: changes -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -.PHONY: linkcheck -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -.PHONY: doctest -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -.PHONY: coverage -coverage: - $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage - @echo "Testing of coverage in the sources finished, look at the " \ - "results in $(BUILDDIR)/coverage/python.txt." - -.PHONY: xml -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -.PHONY: pseudoxml -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/doc/manpages/Makefile b/doc/manpages/Makefile new file mode 100644 index 000000000000..7cccfa2a3d27 --- /dev/null +++ b/doc/manpages/Makefile @@ -0,0 +1,12 @@ +all: ALWAYS + @$(MAKE) -s -C ../.. doc/manpages/man.stamp +help: ALWAYS + @$(MAKE) -s -C ../.. doc/help +%: ALWAYS + @$(MAKE) -s -C ../.. doc/manpages/_build/$@ + +Makefile: + #nothing +ALWAYS: +.PHONY: ALWAYS makefiles +.SUFFIXES: diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am deleted file mode 100644 index 009c72382313..000000000000 --- a/doc/manpages/Makefile.am +++ /dev/null @@ -1,48 +0,0 @@ -# This is necessary to support VPATH builds. -srcdir = @srcdir@ -VPATH = @srcdir@ - -# This variable is used as the documentation source location in frr-sphinx.mk -SOURCESDIR = @srcdir@ - -include @srcdir@/../frr-sphinx.mk - -# ----------------------------------------------------------------------------- -# Automake requires that 3rd-party Makefiles recognize these targets. -# ----------------------------------------------------------------------------- -# install -# install-data -# install-exec -# uninstall -# install-dvi -# install-html -# install-info -# install-ps -# install-pdf -# installdirs -# check -# installcheck -# mostlyclean -# clean -# distclean -# maintainer-clean -# dvi -# pdf -# ps -# info -# html -# tags -# ctags - -# These targets are automatically generated by Sphinx but conflict with -# implicitly defined Automake rules, so we manually override them to nothing. -# The other option is deleting the Sphinx-generated rules, which suppresses the -# warning but kinda screws up the symmetry between Makefiles. -info: ; -html: ; - -all: man - -install-data: man - -install: install-data diff --git a/doc/manpages/common-options.rst b/doc/manpages/common-options.rst index 5fff6fca6651..74d3eb7bbdcc 100644 --- a/doc/manpages/common-options.rst +++ b/doc/manpages/common-options.rst @@ -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. diff --git a/doc/manpages/conf.py b/doc/manpages/conf.py index e540d236ea14..f57bc1d27868 100644 --- a/doc/manpages/conf.py +++ b/doc/manpages/conf.py @@ -333,6 +333,7 @@ ('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 index 000000000000..c14c07661e94 --- /dev/null +++ b/doc/manpages/fabricd.rst @@ -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 + diff --git a/doc/manpages/index.rst b/doc/manpages/index.rst index c62835c7701f..053555c4e427 100644 --- a/doc/manpages/index.rst +++ b/doc/manpages/index.rst @@ -10,6 +10,7 @@ bgpd eigrpd isisd + fabricd ldpd nhrpd ospf6d diff --git a/doc/manpages/subdir.am b/doc/manpages/subdir.am new file mode 100644 index 000000000000..4a9aa4de4d58 --- /dev/null +++ b/doc/manpages/subdir.am @@ -0,0 +1,73 @@ +# +# doc/manpages +# + +man_RSTFILES = \ + doc/manpages/bgpd.rst \ + doc/manpages/common-options.rst \ + doc/manpages/conf.py \ + 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 \ + doc/manpages/ldpd.rst \ + doc/manpages/mtracebis.rst \ + doc/manpages/nhrpd.rst \ + doc/manpages/ospf6d.rst \ + doc/manpages/ospfclient.rst \ + doc/manpages/ospfd.rst \ + doc/manpages/pimd.rst \ + doc/manpages/ripd.rst \ + doc/manpages/pbrd.rst \ + doc/manpages/ripngd.rst \ + doc/manpages/sharpd.rst \ + doc/manpages/staticd.rst \ + doc/manpages/vtysh.rst \ + doc/manpages/watchfrr.rst \ + doc/manpages/zebra.rst \ + doc/manpages/bfdd.rst \ + doc/manpages/bfd-options.rst \ + # end + +EXTRA_DIST += $(man_RSTFILES) + +MANBUILD = doc/manpages/_build/man +doc/manpages/_build/.doctrees/environment.pickle: $(man_RSTFILES) + +# +# automake integration +# + +rstman1dir = $(mandir)/man1 +rstman8dir = $(mandir)/man8 + +rstman1_DATA = +rstman8_DATA = + +if DOC +rstman1_DATA += $(man1) +rstman8_DATA += $(man8) +endif # DOC + +man1 = $(MANBUILD)/frr.1 +man8 = + +# dependency +$(man8) $(man1): $(MANBUILD)/man.stamp + +# +# hook-ins for clean / doc +# (install is handled by automake _DATA) +# + +clean-local: clean-manpages +.PHONY: clean-manpages +clean-manpages: + -rm -rf $(MANBUILD) + +doc: doc-man +.PHONY: doc-man +doc-man: $(rstman8_DATA) $(rstman1_DATA) diff --git a/doc/mpls/.gitignore b/doc/mpls/.gitignore deleted file mode 100644 index b0a4a4619fb7..000000000000 --- a/doc/mpls/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.arch-ids -.arch-inventory -*~ -*.loT - diff --git a/doc/subdir.am b/doc/subdir.am new file mode 100644 index 000000000000..41701016559e --- /dev/null +++ b/doc/subdir.am @@ -0,0 +1,176 @@ +# +# doc +# + +# You can set these variables from the command line. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +PAPER ?= + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) + +### + +AM_V_SPHINX = $(am__v_SPHINX_$(V)) +am__v_SPHINX_ = $(am__v_SPHINX_$(AM_DEFAULT_VERBOSITY)) +am__v_SPHINX_0 = @echo " SPHINX " $@; +am__v_SPHINX_1 = +AM_V_MAKEINFO = $(am__v_MAKEINFO_$(V)) +am__v_MAKEINFO_ = $(am__v_MAKEINFO_$(AM_DEFAULT_VERBOSITY)) +am__v_MAKEINFO_0 = @echo " MAKEINFO" $@; +am__v_MAKEINFO_1 = + +# +# real-file sphinx targets that work for dependencies +# + +doc/%/_build/.doctrees/environment.pickle: + $(AM_V_SPHINX) ( \ + subdoc="$@"; subdoc="$${subdoc#doc/}"; subdoc="doc/$${subdoc%%/*}"; \ + $(SPHINXBUILD) -a -q -b text -d "$${subdoc}/_build/.doctrees" \ + $(ALLSPHINXOPTS) "$(top_srcdir)/$${subdoc}" "$${subdoc}/_build/text" \ + ) +doc/%/_build/html/.buildinfo: doc/%/_build/.doctrees/environment.pickle + $(AM_V_SPHINX) ( \ + subdoc="$@"; subdoc="$${subdoc#doc/}"; subdoc="doc/$${subdoc%%/*}"; \ + $(SPHINXBUILD) -q -b html -d "$${subdoc}/_build/.doctrees" \ + $(ALLSPHINXOPTS) "$(top_srcdir)/$${subdoc}" "$${subdoc}/_build/html" \ + ) +.PRECIOUS: doc/%/_build/texinfo/frr.texi +doc/%/_build/texinfo/frr.texi: doc/%/_build/.doctrees/environment.pickle + $(AM_V_SPHINX) ( \ + subdoc="$@"; subdoc="$${subdoc#doc/}"; subdoc="doc/$${subdoc%%/*}"; \ + $(SPHINXBUILD) -q -b texinfo -d "$${subdoc}/_build/.doctrees" \ + $(ALLSPHINXOPTS) "$(top_srcdir)/$${subdoc}" "$${subdoc}/_build/texinfo" \ + ) +doc/%/_build/texinfo/frr.info: doc/%/_build/texinfo/frr.texi + $(AM_V_MAKEINFO)$(MAKEINFO) --no-split -o '$@' '$<' +doc/%/_build/man/man.stamp: doc/%/_build/.doctrees/environment.pickle + $(AM_V_SPHINX) ( \ + subdoc="$@"; subdoc="$${subdoc#doc/}"; subdoc="doc/$${subdoc%%/*}"; \ + $(MKDIR_P) "$${subdoc}/_build/man"; touch $@.tmp; \ + $(SPHINXBUILD) -a -q -b man -d "$${subdoc}/_build/.doctrees" \ + $(ALLSPHINXOPTS) "$(top_srcdir)/$${subdoc}" "$${subdoc}/_build/man" && \ + mv $@.tmp $@ \ + ) + +# +# auxiliary sphinx targets (output name = directory, +# deps will not work very well) +# + +SPHINXTARGETS = \ + html dirhtml singlehtml pickle json \ + htmlhelp qthelp applehelp devhelp \ + epub latex text man texinfo gettext \ + changes linkcheck doctest coverage \ + xml pseudoxml \ + # end + +M_SPHINXTARGETS = $(addprefix doc/%/_build/,$(SPHINXTARGETS)) +.PRECIOUS: $(M_SPHINXTARGETS) +$(M_SPHINXTARGETS): doc/%/_build/.doctrees/environment.pickle + $(AM_V_SPHINX) ( \ + target="$@"; \ + builder="$${target##*/}"; \ + subdoc="$${target#doc/}"; subdoc="doc/$${subdoc%%/*}"; \ + rm -rf "$@"; \ + $(SPHINXBUILD) -q -b $${builder} -d $${subdoc}/_build/.doctrees \ + $(ALLSPHINXOPTS) $(top_srcdir)/$${subdoc} $@ \ + ) + +.PHONY: doc/%/_build/latexpdf +doc/%/_build/latexpdf: doc/%/_build/latex + @make -C $< all-pdf + +# If you want to build the developer's docs in other formats, try the +# following: +# +# $ cd developer +# $ make help + +# dist tarballs want doc sources +EXTRA_DIST += \ + doc/mpls/ChangeLog.opaque.txt \ + doc/mpls/ospfd.conf \ + doc/mpls/cli_summary.txt \ + doc/mpls/opaque_lsa.txt \ + doc/figures/cligraph.png \ + doc/figures/cligraph.svg \ + doc/figures/fig-normal-processing.dia \ + doc/figures/fig-normal-processing.png \ + doc/figures/fig-normal-processing.txt \ + doc/figures/fig-rs-processing.dia \ + doc/figures/fig-rs-processing.png \ + doc/figures/fig-rs-processing.txt \ + doc/figures/fig_topologies_full.dia \ + doc/figures/fig_topologies_full.png \ + doc/figures/fig_topologies_full.txt \ + doc/figures/fig_topologies_rs.dia \ + doc/figures/fig_topologies_rs.png \ + doc/figures/fig_topologies_rs.txt \ + doc/figures/fig-vnc-commercial-route-reflector.dia \ + doc/figures/fig-vnc-commercial-route-reflector.png \ + doc/figures/fig-vnc-commercial-route-reflector.txt \ + doc/figures/fig-vnc-frr-route-reflector.dia \ + doc/figures/fig-vnc-frr-route-reflector.png \ + doc/figures/fig-vnc-frr-route-reflector.txt \ + doc/figures/fig-vnc-gw.dia \ + doc/figures/fig-vnc-gw.png \ + doc/figures/fig-vnc-gw-rr.dia \ + doc/figures/fig-vnc-gw-rr.png \ + doc/figures/fig-vnc-gw-rr.txt \ + doc/figures/fig-vnc-gw.txt \ + doc/figures/fig-vnc-mesh.dia \ + doc/figures/fig-vnc-mesh.png \ + doc/figures/fig-vnc-mesh.txt \ + doc/figures/fig-vnc-redundant-route-reflectors.dia \ + doc/figures/fig-vnc-redundant-route-reflectors.png \ + doc/figures/fig-vnc-redundant-route-reflectors.txt \ + doc/figures/frr-icon.svg \ + doc/figures/frr-logo-icon.png \ + doc/figures/frr-logo-medium.png \ + doc/figures/frr-logo.png \ + doc/figures/frr-logo-small.png \ + doc/figures/git_branches.png \ + doc/figures/git_branches.svg \ + doc/figures/ospf_api_architecture.png \ + doc/figures/ospf_api_msghdr.png \ + doc/figures/ospf_api_msgs1.png \ + doc/figures/ospf_api_msgs2.png \ + doc/extra/frrlexer.py \ + # end + + +.PHONY: doc/help +doc/help: + @echo "Please use \`make doc/{user,manpages,developer}/' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" diff --git a/doc/user/Makefile b/doc/user/Makefile new file mode 100644 index 000000000000..840ee5b8a929 --- /dev/null +++ b/doc/user/Makefile @@ -0,0 +1,16 @@ +all: ALWAYS + @$(MAKE) -s -C ../.. doc-user +help: ALWAYS + @$(MAKE) -s -C ../.. doc/help +pdf: ALWAYS + @$(MAKE) -s -C ../.. doc/user/_build/latexpdf +info: ALWAYS + @$(MAKE) -s -C ../.. doc/user/_build/texinfo/frr.info +%: ALWAYS + @$(MAKE) -s -C ../.. doc/user/_build/$@ + +Makefile: + #nothing +ALWAYS: +.PHONY: ALWAYS makefiles +.SUFFIXES: diff --git a/doc/user/Makefile.am b/doc/user/Makefile.am deleted file mode 100644 index 64af2ff145fb..000000000000 --- a/doc/user/Makefile.am +++ /dev/null @@ -1,55 +0,0 @@ -# This is necessary to support VPATH builds. -srcdir = @srcdir@ -VPATH = @srcdir@ - -# This variable is used as the documentation source location in frr-sphinx.mk -SOURCESDIR = @srcdir@ - -include @srcdir@/../frr-sphinx.mk - -# ----------------------------------------------------------------------------- -# Automake requires that 3rd-party Makefiles recognize these targets. -# ----------------------------------------------------------------------------- -# install -# install-data -# install-exec -# uninstall -# install-dvi -# install-html -# install-info -# install-ps -# install-pdf -# installdirs -# check -# installcheck -# mostlyclean -# clean -# distclean -# maintainer-clean -# dvi -# pdf -# ps -# info -# html -# tags -# ctags - -# When building 'all', the logic is that we want to make docs that are easily -# readable by the person that just built them. Technically the reST source is -# readable in its own right, but we'll also build info and html because those -# offer sequentially better reading experiences. PDF is not built by default -# because it takes quite a while. -all: info - -# info and html already have built-in sphinx rules; pdf goes to latexpdf -pdf: latexpdf - -# install user manual as info file -install-info: info - install -d ${DESTDIR}${infodir} - gzip < _build/texinfo/frr.info > ${DESTDIR}${infodir}/frr.info.gz - install-info _build/texinfo/frr.info ${DESTDIR}${infodir}/dir - -install-data: install-info - -install: install-data diff --git a/doc/user/_static/overrides.css b/doc/user/_static/overrides.css index 3143f8bb6530..41fcc66f8d2e 100644 --- a/doc/user/_static/overrides.css +++ b/doc/user/_static/overrides.css @@ -19,11 +19,6 @@ table.mark th { table.mark td { vertical-align: middle; } -table.mark td[colspan="7"] { - text-align: center; - padding-top: 8pt; - padding-bottom: 2pt; -} table.mark cite { font-weight: bold; } @@ -32,6 +27,13 @@ table.mark cite { td.mark { width: 4.5em; } +table.mark strong { + display:block; + text-align: center; + margin:auto; + padding-top: 8pt; + padding-bottom: 2pt; +} td.mark span { display: block; padding: 3px 1px; @@ -39,6 +41,12 @@ td.mark span { width: 36pt; margin:auto; } +table.mark tr td:first-child { + padding-left:1.5em; +} +table.mark tr td:first-child cite { + margin-left:-1.5em; +} span.mark-y { background-color: #77ffaa; } span.mark-geq { background-color: #aaff77; } span.mark-cp { background-color: #ffbb55; } diff --git a/doc/user/fabricd.rst b/doc/user/fabricd.rst new file mode 100644 index 000000000000..cf0f937c13cc --- /dev/null +++ b/doc/user/fabricd.rst @@ -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] +.. clicmd:: domain-password [clear | md5] + +.. 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] +.. clicmd:: openfabric password [clear | md5] + +.. 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 +.. clicmd:: show openfabric interface + + 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 +.. clicmd:: show openfabric neighbor + +.. 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 [detail] +.. clicmd:: show openfabric database [detail] + +.. index:: show openfabric database detail +.. clicmd:: show openfabric database detail + + 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 diff --git a/doc/user/index.rst b/doc/user/index.rst index 5818551343ae..8190415bf4c3 100644 --- a/doc/user/index.rst +++ b/doc/user/index.rst @@ -42,6 +42,7 @@ Protocols bfd bgp babeld + fabricd ldpd eigrpd isisd diff --git a/doc/user/installation.rst b/doc/user/installation.rst index 3da5a6cd3037..da431916aec6 100644 --- a/doc/user/installation.rst +++ b/doc/user/installation.rst @@ -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. diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index 54f82f683255..ee681858d1a4 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -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 diff --git a/doc/user/overview.rst b/doc/user/overview.rst index 51bd6228e3eb..e90b84b02bc5 100644 --- a/doc/user/overview.rst +++ b/doc/user/overview.rst @@ -166,69 +166,69 @@ features with system dependencies are included here. will look somewhat shoddy on other sphinx targets like PDF or info (but should still be readable.) -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ | Daemon / Feature | Linux | OpenBSD | FreeBSD | NetBSD | Solaris | -+==+================================+================+==============+============+============+============+ -| FRR Core | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++===================================+================+==============+============+============+============+ +| **FRR Core** | | | | | | ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `zebra` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | VRF | :mark:`≥4.8` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | MPLS | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| VRF | :mark:`≥4.8` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| MPLS | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `pbrd` (Policy Routing) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| WAN / Carrier protocols | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| **WAN / Carrier protocols** | | | | | | ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `bgpd` (BGP) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | VRF / L3VPN | :mark:`≥4.8` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | -| | | :mark:`†4.3` | | | | | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | EVPN | :mark:`≥4.18` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | -| | | :mark:`†4.9` | | | | | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | VNC (Virtual Network Control) | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | Flowspec | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| VRF / L3VPN | :mark:`≥4.8` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | +| | :mark:`†4.3` | | | | | ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| EVPN | :mark:`≥4.18` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | +| | :mark:`†4.9` | | | | | ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| VNC (Virtual Network Control) | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| Flowspec | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `ldpd` (LDP) | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | VPWS / PW | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | :mark:`N` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | VPLS | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | :mark:`N` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| VPWS / PW | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| VPLS | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `nhrpd` (NHRP) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| Link-State Routing | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| **Link-State Routing** | | | | | | ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `ospfd` (OSPFv2) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | Segment Routing | :mark:`≥4.12` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| Segment Routing | :mark:`≥4.12` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `ospf6d` (OSPFv3) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `isisd` (IS-IS) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| Distance-Vector Routing | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| **Distance-Vector Routing** | | | | | | ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `ripd` (RIPv2) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `ripngd` (RIPng) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `babeld` (BABEL) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `eigrpd` (EIGRP) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| Multicast Routing | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| **Multicast Routing** | | | | | | ++-----------------------------------+----------------+--------------+------------+------------+------------+ | `pimd` (PIM) | :mark:`≥4.18` | :mark:`N` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | SSM (Source Specific) | :mark:`Y` | :mark:`N` | :mark:`Y` | :mark:`Y` | :mark:`Y` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ -| | ASM (Any Source) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | -+--+--------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| SSM (Source Specific) | :mark:`Y` | :mark:`N` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+------------+ +| ASM (Any Source) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+------------+ The indicators have the following semantics: diff --git a/doc/user/setup.rst b/doc/user/setup.rst index 68ce14982be9..8a76a61e787a 100644 --- a/doc/user/setup.rst +++ b/doc/user/setup.rst @@ -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 diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst index e27da63b536f..8831c0159b13 100644 --- a/doc/user/sharp.rst +++ b/doc/user/sharp.rst @@ -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 (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. diff --git a/doc/user/subdir.am b/doc/user/subdir.am new file mode 100644 index 000000000000..53d36052ac8d --- /dev/null +++ b/doc/user/subdir.am @@ -0,0 +1,111 @@ +# +# doc/user +# + +user_RSTFILES = \ + doc/user/babeld.rst \ + doc/user/ldpd.rst \ + doc/user/basic.rst \ + doc/user/bgp.rst \ + 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 \ + doc/user/installation.rst \ + doc/user/ipv6.rst \ + doc/user/isisd.rst \ + doc/user/kernel.rst \ + doc/user/nhrpd.rst \ + doc/user/ospf6d.rst \ + doc/user/ospfd.rst \ + doc/user/ospf_fundamentals.rst \ + doc/user/overview.rst \ + doc/user/packet-dumps.rst \ + doc/user/pim.rst \ + doc/user/ripd.rst \ + doc/user/pbr.rst \ + doc/user/ripngd.rst \ + doc/user/routemap.rst \ + doc/user/routeserver.rst \ + doc/user/rpki.rst \ + doc/user/setup.rst \ + doc/user/sharp.rst \ + doc/user/snmp.rst \ + doc/user/snmptrap.rst \ + doc/user/static.rst \ + doc/user/vnc.rst \ + doc/user/vtysh.rst \ + doc/user/zebra.rst \ + doc/user/bfd.rst \ + doc/user/flowspec.rst \ + # end + +EXTRA_DIST += \ + $(user_RSTFILES) \ + doc/user/Useful_Sysctl_Settings.md \ + # end + +USERBUILD = doc/user/_build +$(USERBUILD)/.doctrees/environment.pickle: $(user_RSTFILES) + +# +# automake integration (things that should be built in "all") +# + +if DOC +nodist_noinst_DATA += $(USERBUILD)/texinfo/frr.info +endif +if DOC_HTML +nodist_noinst_DATA += $(USERBUILD)/html/.buildinfo +endif + +# +# standard targets +# + +.PHONY: info html pdf +info: $(USERBUILD)/texinfo/frr.info +html: $(USERBUILD)/html/.buildinfo +pdf: $(USERBUILD)/latexpdf + +# +# hook-ins for clean / install / doc +# + +.PHONY: clean-userdocs +clean-local: clean-userdocs +clean-userdocs: + -rm -rf "$(USERBUILD)" + +# INSTALL_INFO=install-info +.PHONY: install-info uninstall-info install-html uninstall-html + +install-info: $(USERBUILD)/texinfo/frr.info + $(MKDIR_P) "$(DESTDIR)$(infodir)" + $(INSTALL_DATA) "$<" "$(DESTDIR)$(infodir)" + [ -z "${DESTDIR}" ] && $(INSTALL_INFO) --info-dir="$(DESTDIR)$(infodir)" "$<" || true +uninstall-info: $(USERBUILD)/texinfo/frr.info + -rm -f "$(DESTDIR)$(infodir)/$<" + [ -z "${DESTDIR}" ] && $(INSTALL_INFO) --delete --info-dir="$(DESTDIR)$(infodir)" "$<" || true + +install-html: $(USERBUILD)/html/.buildinfo + $(MKDIR_P) "$(DESTDIR)$(htmldir)" + cp -r "$(USERBUILD)/html" "$(DESTDIR)$(htmldir)" +uninstall-html: + -rm -rf "$(DESTDIR)$(htmldir)/html" + +.PHONY: install-data-local uninstall-local +if DOC +DOC_INFO=info +install-data-local: install-info +uninstall-local: uninstall-info +endif +if DOC_HTML +DOC_HTML=html +install-data-local: install-html +uninstall-local: uninstall-html +endif +doc: $(DOC_INFO) $(DOC_HTML) diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index af8e4b8d4760..e3e5d1325a62 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -48,6 +48,13 @@ Besides the common invocation options (:ref:`common-invocation-options`), the .. seealso:: :ref:`zebra-vrf` +.. option:: -o, --vrfdefaultname + + When *Zebra* starts with this option, the default VRF name is changed to the + parameter. + + .. seealso:: :ref:`zebra-vrf` + .. option:: --v6-rr-semantics The linux kernel is receiving the ability to use the same route @@ -355,6 +362,38 @@ commands in relationship to VRF. Here is an extract of some of those commands: will dump the routing table ``TABLENO`` of the *Linux network namespace* ``VRF``. +By using the :option:`-n` option, the *Linux network namespace* will be mapped +over the *Zebra* VRF. One nice feature that is possible by handling *Linux +network namespace* is the ability to name default VRF. At startup, *Zebra* +discovers the available *Linux network namespace* by parsing folder +`/var/run/netns`. Each file stands for a *Linux network namespace*, but not all +*Linux network namespaces* are available under that folder. This is the case for +default VRF. It is possible to name the default VRF, by creating a file, by +executing following commands. + +.. code-block:: shell + + touch /var/run/netns/vrf0 + mount --bind /proc/self/ns/net /var/run/netns/vrf0 + +Above command illustrates what happens when the default VRF is visible under +`var/run/netns/`. Here, the default VRF file is `vrf0`. +At startup, FRR detects the presence of that file. It detects that the file +statistics information matches the same file statistics information as +`/proc/self/ns/net` ( through stat() function). As statistics information +matches, then `vrf0` stands for the new default namespace name. +Consequently, the VRF naming `Default` will be overriden by the new discovered +namespace name `vrf0`. + +For those who don't use VRF backend with *Linux network namespace*, it is +possible to statically configure and recompile FRR. It is possible to choose an +alternate name for default VRF. Then, the default VRF naming will automatically +be updated with the new name. To illustrate, if you want to recompile with +`global` value, use the following command: + +.. code-block:: linux + + ./configure --with-defaultvrfname=global .. _zebra-mpls: diff --git a/eigrpd/.gitignore b/eigrpd/.gitignore index 5b72399e727f..0303c6f0d437 100644 --- a/eigrpd/.gitignore +++ b/eigrpd/.gitignore @@ -1,18 +1,2 @@ -!Makefile -Makefile.in -*.o -*.a eigrpd eigrpd.conf -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.libs -.arch-inventory -.arch-ids -*~ -*.loT - diff --git a/eigrpd/eigrp_fsm.c b/eigrpd/eigrp_fsm.c index eeefc519688c..d291cab4c0c7 100644 --- a/eigrpd/eigrp_fsm.c +++ b/eigrpd/eigrp_fsm.c @@ -67,8 +67,8 @@ * 7- state not changed, usually by receiving not last reply */ -#include #include +#include #include "prefix.h" #include "table.h" diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index 31101a52d4f4..9e9c4649fcb2 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -170,7 +170,7 @@ int main(int argc, char **argv, char **envp) master = eigrp_om->master; eigrp_error_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); /*EIGRPd init*/ eigrp_if_init(); diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c index 190c18777e23..311fbce4ab68 100644 --- a/eigrpd/eigrp_vty.c +++ b/eigrpd/eigrp_vty.c @@ -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 diff --git a/eigrpd/subdir.am b/eigrpd/subdir.am index 2635d555d9a2..bc48173bba11 100644 --- a/eigrpd/subdir.am +++ b/eigrpd/subdir.am @@ -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 index 17e90443e977..000000000000 --- a/fpm/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -!Makefile -Makefile.in -*.o -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.a -*.libs -.arch-inventory -.arch-ids -*~ -*.loT diff --git a/fpm/subdir.am b/fpm/subdir.am index 795535596b6f..05cec5a52824 100644 --- a/fpm/subdir.am +++ b/fpm/subdir.am @@ -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 index 30b4bc99ec18..000000000000 --- a/init/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -Makefile -Makefile.in -.nfs* -*~ -*.loT - diff --git a/isisd/.gitignore b/isisd/.gitignore index a882bbf67544..b6184ca0f54b 100644 --- a/isisd/.gitignore +++ b/isisd/.gitignore @@ -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 index 000000000000..7951efe5a114 --- /dev/null +++ b/isisd/fabricd.c @@ -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 +#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 index 000000000000..be9e33ba6275 --- /dev/null +++ b/isisd/fabricd.conf.sample @@ -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 index 000000000000..76c182f2d278 --- /dev/null +++ b/isisd/fabricd.h @@ -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 diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index 4b3d78421e8c..a41d6ff81522 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -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); diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index 7e8a4a4edaba..28750278b017 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -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); diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index cd4b76139f74..817a44bafe66 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -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; } diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index 8dbd7ac492b9..ea68767fe0fb 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -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 */ diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 66c97ae89744..e8777e9b53a1 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -56,6 +56,8 @@ #include "isisd/isis_te.h" #include "isisd/isis_mt.h" #include "isisd/isis_tlvs.h" +#include "isisd/fabricd.h" +#include "isisd/isis_tx_queue.h" static int lsp_l1_refresh(struct thread *thread); static int lsp_l2_refresh(struct thread *thread); @@ -117,10 +119,9 @@ static void lsp_destroy(struct isis_lsp *lsp) return; for (ALL_LIST_ELEMENTS_RO(lsp->area->circuit_list, cnode, circuit)) - isis_circuit_cancel_queued_lsp(circuit, lsp); + isis_tx_queue_del(circuit->tx_queue, lsp); ISIS_FLAGS_CLEAR_ALL(lsp->SSNflags); - ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags); lsp_clear_data(lsp); @@ -352,7 +353,21 @@ void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno) isis_spf_schedule(lsp->area, lsp->level); } -static void lsp_purge(struct isis_lsp *lsp, int level) +static void lsp_purge_add_poi(struct isis_lsp *lsp, + const uint8_t *sender) +{ + if (!lsp->area->purge_originator) + return; + + /* add purge originator identification */ + if (!lsp->tlvs) + lsp->tlvs = isis_alloc_tlvs(); + isis_tlvs_set_purge_originator(lsp->tlvs, isis->sysid, sender); + isis_tlvs_set_dynamic_hostname(lsp->tlvs, cmd_hostname_get()); +} + +static void lsp_purge(struct isis_lsp *lsp, int level, + const uint8_t *sender) { /* reset stream */ lsp_clear_data(lsp); @@ -364,8 +379,10 @@ static void lsp_purge(struct isis_lsp *lsp, int level) lsp->level = level; lsp->age_out = lsp->area->max_lsp_lifetime[level - 1]; + lsp_purge_add_poi(lsp, sender); + lsp_pack_pdu(lsp); - lsp_set_all_srmflags(lsp); + lsp_flood(lsp, NULL); } /* @@ -385,7 +402,7 @@ static void lsp_seqno_update(struct isis_lsp *lsp0) if (lsp->tlvs) lsp_inc_seqno(lsp, 0); else - lsp_purge(lsp, lsp0->level); + lsp_purge(lsp, lsp0->level, NULL); } return; @@ -425,7 +442,8 @@ static void lsp_update_data(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, lsp->tlvs = tlvs; - if (area->dynhostname && lsp->tlvs->hostname) { + if (area->dynhostname && lsp->tlvs->hostname + && lsp->hdr.rem_lifetime) { isis_dynhn_insert(lsp->hdr.lsp_id, lsp->tlvs->hostname, (lsp->hdr.lsp_bits & LSPBIT_IST) == IS_LEVEL_1_AND_2 @@ -462,10 +480,10 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, lsp->own_lsp = 0; } - lsp_update_data(lsp, hdr, tlvs, stream, area, level); if (confusion) { - lsp->hdr.rem_lifetime = hdr->rem_lifetime = 0; - put_lsp_hdr(lsp, NULL, true); + lsp_purge(lsp, level, NULL); + } else { + lsp_update_data(lsp, hdr, tlvs, stream, area, level); } if (LSP_FRAGMENT(lsp->hdr.lsp_id) && !lsp->lspu.zero_lsp) { @@ -928,6 +946,14 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) lsp_debug("ISIS (%s): Adding circuit specific information.", area->area_tag); + if (fabricd) { + lsp_debug( + "ISIS (%s): Adding tier %" PRIu8 " spine-leaf-extension tlv.", + area->area_tag, fabricd_tier(area)); + isis_tlvs_add_spine_leaf(lsp->tlvs, fabricd_tier(area), true, + false, false, false); + } + struct isis_circuit *circuit; for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { if (!circuit->interface) @@ -1091,9 +1117,16 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) */ subtlv_len = 0; + uint32_t neighbor_metric; + if (fabricd_tier(area) == 0) { + neighbor_metric = 0xffe; + } else { + neighbor_metric = metric; + } + tlvs_add_mt_p2p(lsp->tlvs, circuit, - ne_id, metric, subtlvs, - subtlv_len); + ne_id, neighbor_metric, + subtlvs, subtlv_len); } } else { lsp_debug( @@ -1192,7 +1225,7 @@ int lsp_generate(struct isis_area *area, int level) /* time to calculate our checksum */ lsp_seqno_update(newlsp); newlsp->last_generated = time(NULL); - lsp_set_all_srmflags(newlsp); + lsp_flood(newlsp, NULL); refresh_time = lsp_refresh_time(newlsp, rem_lifetime); @@ -1223,7 +1256,7 @@ int lsp_generate(struct isis_area *area, int level) } /* - * Search own LSPs, update holding time and set SRM + * Search own LSPs, update holding time and flood */ static int lsp_regenerate(struct isis_area *area, int level) { @@ -1255,7 +1288,7 @@ static int lsp_regenerate(struct isis_area *area, int level) rem_lifetime = lsp_rem_lifetime(area, level); lsp->hdr.rem_lifetime = rem_lifetime; lsp->last_generated = time(NULL); - lsp_set_all_srmflags(lsp); + lsp_flood(lsp, NULL); for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) { frag->hdr.lsp_bits = lsp_bits_generate( level, area->overload_bit, area->attached_bit); @@ -1265,7 +1298,7 @@ static int lsp_regenerate(struct isis_area *area, int level) */ frag->hdr.rem_lifetime = rem_lifetime; frag->age_out = ZERO_AGE_LIFETIME; - lsp_set_all_srmflags(frag); + lsp_flood(frag, NULL); } lsp_seqno_update(lsp); @@ -1565,7 +1598,7 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level) lsp_pack_pdu(lsp); lsp->own_lsp = 1; lsp_insert(lsp, lspdb); - lsp_set_all_srmflags(lsp); + lsp_flood(lsp, NULL); refresh_time = lsp_refresh_time(lsp, rem_lifetime); THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); @@ -1624,7 +1657,7 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level) lsp_build_pseudo(lsp, circuit, level); lsp_inc_seqno(lsp, 0); lsp->last_generated = time(NULL); - lsp_set_all_srmflags(lsp); + lsp_flood(lsp, NULL); refresh_time = lsp_refresh_time(lsp, rem_lifetime); if (level == IS_LEVEL_1) @@ -1800,30 +1833,25 @@ int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level) /* * Walk through LSPs for an area * - set remaining lifetime - * - set LSPs with SRMflag set for sending */ int lsp_tick(struct thread *thread) { struct isis_area *area; - struct isis_circuit *circuit; struct isis_lsp *lsp; - struct list *lsp_list; - struct listnode *lspnode, *cnode; dnode_t *dnode, *dnode_next; int level; uint16_t rem_lifetime; - time_t now = monotime(NULL); - - lsp_list = list_new(); + bool fabricd_sync_incomplete = false; area = THREAD_ARG(thread); assert(area); area->t_tick = NULL; thread_add_timer(master, lsp_tick, area, 1, &area->t_tick); + struct isis_circuit *fabricd_init_c = fabricd_initial_sync_circuit(area); + /* - * Build a list of LSPs with (any) SRMflag set - * and removed the ones that have aged out + * Remove LSPs which have aged out */ for (level = 0; level < ISIS_LEVELS; level++) { if (area->lspdb[level] && dict_count(area->lspdb[level]) > 0) { @@ -1854,17 +1882,14 @@ int lsp_tick(struct thread *thread) */ if (rem_lifetime == 1 && lsp->hdr.seqno != 0) { /* 7.3.16.4 a) set SRM flags on all */ - lsp_set_all_srmflags(lsp); - /* 7.3.16.4 b) retain only the header - * FIXME */ + /* 7.3.16.4 b) retain only the header */ + if (lsp->area->purge_originator) + lsp_purge(lsp, lsp->level, NULL); + else + lsp_flood(lsp, NULL); /* 7.3.16.4 c) record the time to purge * FIXME */ - /* run/schedule spf */ - /* isis_spf_schedule is called inside - * lsp_destroy() below; - * so it is not needed here. */ - /* isis_spf_schedule (lsp->area, - * lsp->level); */ + isis_spf_schedule(lsp->area, lsp->level); } if (lsp->age_out == 0) { @@ -1878,44 +1903,22 @@ int lsp_tick(struct thread *thread) lsp = NULL; dict_delete_free(area->lspdb[level], dnode); - } else if (flags_any_set(lsp->SRMflags)) - listnode_add(lsp_list, lsp); - } - - /* - * Send LSPs on circuits indicated by the SRMflags - */ - if (listcount(lsp_list) > 0) { - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, - cnode, circuit)) { - if (!circuit->lsp_queue) - continue; - - if (now - circuit->lsp_queue_last_push[level] - < MIN_LSP_RETRANS_INTERVAL) { - continue; - } + } - 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); + } +} diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index d531cb1576c1..4e6379447cf5 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -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 index c521f42b3c77..000000000000 --- a/isisd/isis_lsp_hash.c +++ /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 - -#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_main.c b/isisd/isis_main.c index 5b18ab0a2c0d..4d6a6da5d602 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -54,11 +54,13 @@ #include "isisd/isis_zebra.h" #include "isisd/isis_te.h" #include "isisd/isis_errors.h" +#include "isisd/isis_vty_common.h" /* Default configuration file name */ #define ISISD_DEFAULT_CONFIG "isisd.conf" /* Default vty port */ #define ISISD_VTY_PORT 2608 +#define FABRICD_VTY_PORT 2618 /* isisd privileges */ zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND}; @@ -145,9 +147,15 @@ struct quagga_signal_t isisd_signals[] = { }, }; +#ifdef FABRICD +FRR_DAEMON_INFO(fabricd, OPEN_FABRIC, .vty_port = FABRICD_VTY_PORT, + + .proghelp = "Implementation of the OpenFabric routing protocol.", +#else FRR_DAEMON_INFO(isisd, ISIS, .vty_port = ISISD_VTY_PORT, .proghelp = "Implementation of the IS-IS routing protocol.", +#endif .copyright = "Copyright (c) 2001-2002 Sampo Saaristo," " Ofer Wald and Hannes Gredler", @@ -164,7 +172,11 @@ int main(int argc, char **argv, char **envp) { int opt; +#ifdef FABRICD + frr_preinit(&fabricd_di, argc, argv); +#else frr_preinit(&isisd_di, argc, argv); +#endif frr_opt_add("", longopts, ""); /* Command line argument treatment. */ @@ -192,10 +204,11 @@ int main(int argc, char **argv, char **envp) */ isis_error_init(); access_list_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); prefix_list_init(); isis_init(); isis_circuit_init(); + isis_vty_init(); isis_spf_cmds_init(); isis_redist_init(); isis_route_map_init(); diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c index 2155bf584ec1..2dfccf9830bd 100644 --- a/isisd/isis_mt.c +++ b/isisd/isis_mt.c @@ -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++; } } diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 5c4e3a35bcb4..88575f531943 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -56,6 +56,8 @@ #include "isisd/isis_mt.h" #include "isisd/isis_tlvs.h" #include "isisd/isis_errors.h" +#include "isisd/fabricd.h" +#include "isisd/isis_tx_queue.h" static int ack_lsp(struct isis_lsp_hdr *hdr, struct isis_circuit *circuit, int level) @@ -207,6 +209,12 @@ static int process_p2p_hello(struct iih_info *iih) thread_add_timer(master, isis_adj_expire, adj, (long)adj->hold_time, &adj->t_expire); + /* While fabricds initial sync is in progress, ignore hellos from other + * interfaces than the one we are performing the initial sync on. */ + if (fabricd_initial_sync_is_in_progress(iih->circuit->area) + && fabricd_initial_sync_circuit(iih->circuit->area) != iih->circuit) + return ISIS_OK; + /* 8.2.5.2 a) a match was detected */ if (isis_tlvs_area_addresses_match(iih->tlvs, iih->circuit->area->area_addrs)) { @@ -671,7 +679,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, goto out; } - iih.v4_usable = (circuit->ip_addrs && listcount(circuit->ip_addrs) + iih.v4_usable = (fabricd_ip_addrs(circuit) && iih.tlvs->ipv4_address.count); iih.v6_usable = (circuit->ipv6_link && listcount(circuit->ipv6_link) @@ -700,14 +708,37 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, * 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 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, * 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 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, 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 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, * 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 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, } /* 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 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, 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 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, } /* 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 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, if (!lsp0) { zlog_debug( "Got lsp frag, while zero lsp not in database"); - return ISIS_OK; + goto out; } } /* i */ @@ -1023,10 +1061,8 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, 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 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, } /* 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 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, } /* 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 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, 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 @@ int send_lsp(struct thread *thread) * to clear * the fag. */ - ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); + isis_tx_queue_del(circuit->tx_queue, lsp); } - - return retval; } diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h index c69bfedeae78..3d2420eb036a 100644 --- a/isisd/isis_pdu.h +++ b/isisd/isis_pdu.h @@ -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); diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index cd3ca44379c3..ab7584ed3e04 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -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 " FRR_REDIST_STR_ISISD " []", + "redistribute " PROTO_REDIST_STR +#ifndef FABRICD + " " +#endif + " []", 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 " FRR_REDIST_STR_ISISD " ", - NO_STR + "no redistribute " PROTO_REDIST_STR +#ifndef FABRICD + " " +#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 [always] []", + "default-information originate " +#ifndef FABRICD + " " +#endif + " [always] []", "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 ", - NO_STR + "no default-information originate " +#ifndef FABRICD + " " +#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); } diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 341921146bb5..6a7528623c08 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -31,14 +31,10 @@ #include "command.h" #include "memory.h" #include "prefix.h" -#include "hash.h" #include "if.h" #include "table.h" #include "spf_backoff.h" -#include "jhash.h" -#include "skiplist.h" #include "srcdest_table.h" -#include "lib_errors.h" #include "isis_constants.h" #include "isis_common.h" @@ -56,256 +52,11 @@ #include "isis_csm.h" #include "isis_mt.h" #include "isis_tlvs.h" +#include "fabricd.h" +#include "isis_spf_private.h" DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info"); -enum vertextype { - VTYPE_PSEUDO_IS = 1, - VTYPE_PSEUDO_TE_IS, - VTYPE_NONPSEUDO_IS, - VTYPE_NONPSEUDO_TE_IS, - VTYPE_ES, - VTYPE_IPREACH_INTERNAL, - VTYPE_IPREACH_EXTERNAL, - VTYPE_IPREACH_TE, - VTYPE_IP6REACH_INTERNAL, - VTYPE_IP6REACH_EXTERNAL -}; - -#define VTYPE_IS(t) ((t) >= VTYPE_PSEUDO_IS && (t) <= VTYPE_NONPSEUDO_TE_IS) -#define VTYPE_ES(t) ((t) == VTYPE_ES) -#define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL) - -struct prefix_pair { - struct prefix dest; - struct prefix_ipv6 src; -}; - -/* - * Triple - */ -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 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree, 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 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree, 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 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree, } } - 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 []", - SHOW_STR - "IS-IS information\n" + "show " PROTO_NAME " topology" +#ifndef FABRICD + " []" +#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"); } diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h index 9a73ca8783dd..f4db98cfed53 100644 --- a/isisd/isis_spf.h +++ b/isisd/isis_spf.h @@ -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 index 000000000000..af552e0ed1d3 --- /dev/null +++ b/isisd/isis_spf_private.h @@ -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 + * + * 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 + */ +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 diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 44ba64ce26f8..08b905c65032 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -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; } diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c index a433fcdb41a8..b22460a0b540 100644 --- a/isisd/isis_tlvs.c +++ b/isisd/isis_tlvs.c @@ -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 @@ static int pack_items_(uint16_t mtid, enum isis_tlv_context context, 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)); + } +} diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h index bd1fa3e6768d..4144809fa3ae 100644 --- a/isisd/isis_tlvs.h +++ b/isisd/isis_tlvs.h @@ -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 index 000000000000..32427628ad47 --- /dev/null +++ b/isisd/isis_tx_queue.c @@ -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 + +#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_lsp_hash.h b/isisd/isis_tx_queue.h similarity index 51% rename from isisd/isis_lsp_hash.h rename to isisd/isis_tx_queue.h index b50aa09dc164..ddecdf1e4f55 100644 --- a/isisd/isis_lsp_hash.h +++ b/isisd/isis_tx_queue.h @@ -1,7 +1,7 @@ /* - * IS-IS Rout(e)ing protocol - LSP Hash + * IS-IS Rout(e)ing protocol - LSP TX Queuing logic * - * Copyright (C) 2017 Christian Franke + * Copyright (C) 2018 Christian Franke * * This file is part of FreeRangeRouting (FRR) * @@ -19,16 +19,31 @@ * with this program; see the file COPYING; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef ISIS_LSP_HASH_H -#define ISIS_LSP_HASH_H - -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); +#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 index ce2952c13565..000000000000 --- a/isisd/isis_vty.c +++ /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 - -#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 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 ", - "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 ", - 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 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 [ 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 ", - "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 ", - "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 ", - 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 [] (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 [] [(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 [[] (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 [] (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 [] [(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 [] (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 [] [(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 ]", - "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 ]", - "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 ]", - "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 ]", - "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 ", - 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 index 000000000000..2b98a88b3422 --- /dev/null +++ b/isisd/isis_vty_common.c @@ -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 + +#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 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 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 [ 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 WORD [authenticate snp ]", + "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 index 000000000000..b726b4ee8387 --- /dev/null +++ b/isisd/isis_vty_common.h @@ -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 index 000000000000..95ebe0de81dd --- /dev/null +++ b/isisd/isis_vty_fabricd.c @@ -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 + +#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 index 000000000000..95aaeae81690 --- /dev/null +++ b/isisd/isis_vty_isisd.c @@ -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 + +#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 ", + "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 ", + 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) ", + "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)] ", + 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) ", + "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)] ", + 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) ", + "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)] ", + 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) ", + "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)] ", + 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) ", + "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)] ", + 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) ", + "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)] ", + 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 ", + "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 ", + "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 ", + 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 (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 [(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 (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 [(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 (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 [(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 (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 [(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 WORD [authenticate snp ]", + "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); +} diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 9bc0f2ef350f..33d8a0f77172 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -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; diff --git a/isisd/isisd.c b/isisd/isisd.c index a19f287453f4..e3ff3b8d93e3 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -56,6 +56,7 @@ #include "isisd/isis_events.h" #include "isisd/isis_te.h" #include "isisd/isis_mt.h" +#include "isisd/fabricd.h" struct isis *isis = NULL; @@ -95,6 +96,7 @@ void isis_new(unsigned long process_id) */ /* isis->debugs = 0xFFFF; */ isisMplsTE.status = disable; /* Only support TE metric */ + QOBJ_REG(isis, isis); } @@ -105,10 +107,13 @@ struct isis_area *isis_area_create(const char *area_tag) area = XCALLOC(MTYPE_ISIS_AREA, sizeof(struct isis_area)); /* - * The first instance is level-1-2 rest are level-1, unless otherwise - * configured + * Fabricd runs only as level-2. + * For IS-IS, the first instance is level-1-2 rest are level-1, + * unless otherwise configured */ - if (listcount(isis->area_list) > 0) + if (fabricd) { + area->is_type = IS_LEVEL_2; + } else if (listcount(isis->area_list) > 0) area->is_type = IS_LEVEL_1; else area->is_type = IS_LEVEL_1_AND_2; @@ -153,6 +158,8 @@ struct isis_area *isis_area_create(const char *area_tag) listnode_add(isis->area_list, area); area->isis = isis; + if (fabricd) + area->fabricd = fabricd_new(area); QOBJ_REG(area, isis_area); return area; @@ -179,7 +186,7 @@ int isis_area_get(struct vty *vty, const char *area_tag) area = isis_area_lookup(area_tag); if (area) { - VTY_PUSH_CONTEXT(ISIS_NODE, area); + VTY_PUSH_CONTEXT(ROUTER_NODE, area); return CMD_SUCCESS; } @@ -188,7 +195,7 @@ int isis_area_get(struct vty *vty, const char *area_tag) if (isis->debugs & DEBUG_EVENTS) zlog_debug("New IS-IS area instance %s", area->area_tag); - VTY_PUSH_CONTEXT(ISIS_NODE, area); + VTY_PUSH_CONTEXT(ROUTER_NODE, area); return CMD_SUCCESS; } @@ -209,6 +216,9 @@ int isis_area_destroy(struct vty *vty, const char *area_tag) QOBJ_UNREG(area); + if (fabricd) + fabricd_finish(area->fabricd); + if (area->circuit_list) { for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode, circuit)) { @@ -463,9 +473,9 @@ int show_isis_interface_common(struct vty *vty, const char *ifname, char detail) DEFUN (show_isis_interface, show_isis_interface_cmd, - "show isis interface", + "show " PROTO_NAME " interface", SHOW_STR - "ISIS network information\n" + PROTO_HELP "ISIS interface\n") { return show_isis_interface_common(vty, NULL, ISIS_UI_LEVEL_BRIEF); @@ -473,9 +483,9 @@ DEFUN (show_isis_interface, DEFUN (show_isis_interface_detail, show_isis_interface_detail_cmd, - "show isis interface detail", + "show " PROTO_NAME " interface detail", SHOW_STR - "ISIS network information\n" + PROTO_HELP "ISIS interface\n" "show detailed information\n") { @@ -484,9 +494,9 @@ DEFUN (show_isis_interface_detail, DEFUN (show_isis_interface_arg, show_isis_interface_arg_cmd, - "show isis interface WORD", + "show " PROTO_NAME " interface WORD", SHOW_STR - "ISIS network information\n" + PROTO_HELP "ISIS interface\n" "ISIS interface name\n") { @@ -634,9 +644,9 @@ int clear_isis_neighbor_common(struct vty *vty, const char *id) DEFUN (show_isis_neighbor, show_isis_neighbor_cmd, - "show isis neighbor", + "show " PROTO_NAME " neighbor", SHOW_STR - "ISIS network information\n" + PROTO_HELP "ISIS neighbor adjacencies\n") { return show_isis_neighbor_common(vty, NULL, ISIS_UI_LEVEL_BRIEF); @@ -644,9 +654,9 @@ DEFUN (show_isis_neighbor, DEFUN (show_isis_neighbor_detail, show_isis_neighbor_detail_cmd, - "show isis neighbor detail", + "show " PROTO_NAME " neighbor detail", SHOW_STR - "ISIS network information\n" + PROTO_HELP "ISIS neighbor adjacencies\n" "show detailed information\n") { @@ -655,9 +665,9 @@ DEFUN (show_isis_neighbor_detail, DEFUN (show_isis_neighbor_arg, show_isis_neighbor_arg_cmd, - "show isis neighbor WORD", + "show " PROTO_NAME " neighbor WORD", SHOW_STR - "ISIS network information\n" + PROTO_HELP "ISIS neighbor adjacencies\n" "System id\n") { @@ -668,19 +678,19 @@ DEFUN (show_isis_neighbor_arg, DEFUN (clear_isis_neighbor, clear_isis_neighbor_cmd, - "clear isis neighbor", + "clear " PROTO_NAME " neighbor", CLEAR_STR - "Reset ISIS network information\n" - "Reset ISIS neighbor adjacencies\n") + PROTO_HELP + "ISIS neighbor adjacencies\n") { return clear_isis_neighbor_common(vty, NULL); } DEFUN (clear_isis_neighbor_arg, clear_isis_neighbor_arg_cmd, - "clear isis neighbor WORD", + "clear " PROTO_NAME " neighbor WORD", CLEAR_STR - "ISIS network information\n" + PROTO_HELP "ISIS neighbor adjacencies\n" "System id\n") { @@ -734,16 +744,18 @@ void print_debug(struct vty *vty, int flags, int onoff) vty_out(vty, "IS-IS LSP generation debugging is %s\n", onoffs); if (flags & DEBUG_LSP_SCHED) vty_out(vty, "IS-IS LSP scheduling debugging is %s\n", onoffs); + if (flags & DEBUG_FABRICD_FLOODING) + vty_out(vty, "OpenFabric Flooding debugging is %s\n", onoffs); } DEFUN_NOSH (show_debugging, show_debugging_isis_cmd, - "show debugging [isis]", + "show debugging [" PROTO_NAME "]", SHOW_STR "State of each debugging option\n" - ISIS_STR) + PROTO_HELP) { - vty_out(vty, "IS-IS debugging status:\n"); + vty_out(vty, PROTO_NAME " debugging status:\n"); if (isis->debugs) print_debug(vty, isis->debugs, 1); @@ -760,59 +772,63 @@ static int config_write_debug(struct vty *vty) int flags = isis->debugs; if (flags & DEBUG_ADJ_PACKETS) { - vty_out(vty, "debug isis adj-packets\n"); + vty_out(vty, "debug " PROTO_NAME " adj-packets\n"); write++; } if (flags & DEBUG_CHECKSUM_ERRORS) { - vty_out(vty, "debug isis checksum-errors\n"); + vty_out(vty, "debug " PROTO_NAME " checksum-errors\n"); write++; } if (flags & DEBUG_LOCAL_UPDATES) { - vty_out(vty, "debug isis local-updates\n"); + vty_out(vty, "debug " PROTO_NAME " local-updates\n"); write++; } if (flags & DEBUG_PROTOCOL_ERRORS) { - vty_out(vty, "debug isis protocol-errors\n"); + vty_out(vty, "debug " PROTO_NAME " protocol-errors\n"); write++; } if (flags & DEBUG_SNP_PACKETS) { - vty_out(vty, "debug isis snp-packets\n"); + vty_out(vty, "debug " PROTO_NAME " snp-packets\n"); write++; } if (flags & DEBUG_SPF_EVENTS) { - vty_out(vty, "debug isis spf-events\n"); + vty_out(vty, "debug " PROTO_NAME " spf-events\n"); write++; } if (flags & DEBUG_SPF_STATS) { - vty_out(vty, "debug isis spf-statistics\n"); + vty_out(vty, "debug " PROTO_NAME " spf-statistics\n"); write++; } if (flags & DEBUG_SPF_TRIGGERS) { - vty_out(vty, "debug isis spf-triggers\n"); + vty_out(vty, "debug " PROTO_NAME " spf-triggers\n"); write++; } if (flags & DEBUG_UPDATE_PACKETS) { - vty_out(vty, "debug isis update-packets\n"); + vty_out(vty, "debug " PROTO_NAME " update-packets\n"); write++; } if (flags & DEBUG_RTE_EVENTS) { - vty_out(vty, "debug isis route-events\n"); + vty_out(vty, "debug " PROTO_NAME " route-events\n"); write++; } if (flags & DEBUG_EVENTS) { - vty_out(vty, "debug isis events\n"); + vty_out(vty, "debug " PROTO_NAME " events\n"); write++; } if (flags & DEBUG_PACKET_DUMP) { - vty_out(vty, "debug isis packet-dump\n"); + vty_out(vty, "debug " PROTO_NAME " packet-dump\n"); write++; } if (flags & DEBUG_LSP_GEN) { - vty_out(vty, "debug isis lsp-gen\n"); + vty_out(vty, "debug " PROTO_NAME " lsp-gen\n"); write++; } if (flags & DEBUG_LSP_SCHED) { - vty_out(vty, "debug isis lsp-sched\n"); + vty_out(vty, "debug " PROTO_NAME " lsp-sched\n"); + write++; + } + if (flags & DEBUG_FABRICD_FLOODING) { + vty_out(vty, "debug " PROTO_NAME " flooding\n"); write++; } write += spf_backoff_write_config(vty); @@ -822,9 +838,9 @@ static int config_write_debug(struct vty *vty) DEFUN (debug_isis_adj, debug_isis_adj_cmd, - "debug isis adj-packets", + "debug " PROTO_NAME " adj-packets", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Adjacency related packets\n") { isis->debugs |= DEBUG_ADJ_PACKETS; @@ -835,10 +851,10 @@ DEFUN (debug_isis_adj, DEFUN (no_debug_isis_adj, no_debug_isis_adj_cmd, - "no debug isis adj-packets", + "no debug " PROTO_NAME " adj-packets", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Adjacency related packets\n") { isis->debugs &= ~DEBUG_ADJ_PACKETS; @@ -849,9 +865,9 @@ DEFUN (no_debug_isis_adj, DEFUN (debug_isis_csum, debug_isis_csum_cmd, - "debug isis checksum-errors", + "debug " PROTO_NAME " checksum-errors", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS LSP checksum errors\n") { isis->debugs |= DEBUG_CHECKSUM_ERRORS; @@ -862,10 +878,10 @@ DEFUN (debug_isis_csum, DEFUN (no_debug_isis_csum, no_debug_isis_csum_cmd, - "no debug isis checksum-errors", + "no debug " PROTO_NAME " checksum-errors", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS LSP checksum errors\n") { isis->debugs &= ~DEBUG_CHECKSUM_ERRORS; @@ -876,9 +892,9 @@ DEFUN (no_debug_isis_csum, DEFUN (debug_isis_lupd, debug_isis_lupd_cmd, - "debug isis local-updates", + "debug " PROTO_NAME " local-updates", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS local update packets\n") { isis->debugs |= DEBUG_LOCAL_UPDATES; @@ -889,10 +905,10 @@ DEFUN (debug_isis_lupd, DEFUN (no_debug_isis_lupd, no_debug_isis_lupd_cmd, - "no debug isis local-updates", + "no debug " PROTO_NAME " local-updates", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS local update packets\n") { isis->debugs &= ~DEBUG_LOCAL_UPDATES; @@ -903,9 +919,9 @@ DEFUN (no_debug_isis_lupd, DEFUN (debug_isis_err, debug_isis_err_cmd, - "debug isis protocol-errors", + "debug " PROTO_NAME " protocol-errors", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS LSP protocol errors\n") { isis->debugs |= DEBUG_PROTOCOL_ERRORS; @@ -916,10 +932,10 @@ DEFUN (debug_isis_err, DEFUN (no_debug_isis_err, no_debug_isis_err_cmd, - "no debug isis protocol-errors", + "no debug " PROTO_NAME " protocol-errors", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS LSP protocol errors\n") { isis->debugs &= ~DEBUG_PROTOCOL_ERRORS; @@ -930,9 +946,9 @@ DEFUN (no_debug_isis_err, DEFUN (debug_isis_snp, debug_isis_snp_cmd, - "debug isis snp-packets", + "debug " PROTO_NAME " snp-packets", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS CSNP/PSNP packets\n") { isis->debugs |= DEBUG_SNP_PACKETS; @@ -943,10 +959,10 @@ DEFUN (debug_isis_snp, DEFUN (no_debug_isis_snp, no_debug_isis_snp_cmd, - "no debug isis snp-packets", + "no debug " PROTO_NAME " snp-packets", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS CSNP/PSNP packets\n") { isis->debugs &= ~DEBUG_SNP_PACKETS; @@ -957,9 +973,9 @@ DEFUN (no_debug_isis_snp, DEFUN (debug_isis_upd, debug_isis_upd_cmd, - "debug isis update-packets", + "debug " PROTO_NAME " update-packets", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Update related packets\n") { isis->debugs |= DEBUG_UPDATE_PACKETS; @@ -970,10 +986,10 @@ DEFUN (debug_isis_upd, DEFUN (no_debug_isis_upd, no_debug_isis_upd_cmd, - "no debug isis update-packets", + "no debug " PROTO_NAME " update-packets", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Update related packets\n") { isis->debugs &= ~DEBUG_UPDATE_PACKETS; @@ -984,9 +1000,9 @@ DEFUN (no_debug_isis_upd, DEFUN (debug_isis_spfevents, debug_isis_spfevents_cmd, - "debug isis spf-events", + "debug " PROTO_NAME " spf-events", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Shortest Path First Events\n") { isis->debugs |= DEBUG_SPF_EVENTS; @@ -997,10 +1013,10 @@ DEFUN (debug_isis_spfevents, DEFUN (no_debug_isis_spfevents, no_debug_isis_spfevents_cmd, - "no debug isis spf-events", + "no debug " PROTO_NAME " spf-events", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Shortest Path First Events\n") { isis->debugs &= ~DEBUG_SPF_EVENTS; @@ -1011,9 +1027,9 @@ DEFUN (no_debug_isis_spfevents, DEFUN (debug_isis_spfstats, debug_isis_spfstats_cmd, - "debug isis spf-statistics ", + "debug " PROTO_NAME " spf-statistics ", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS SPF Timing and Statistic Data\n") { isis->debugs |= DEBUG_SPF_STATS; @@ -1024,10 +1040,10 @@ DEFUN (debug_isis_spfstats, DEFUN (no_debug_isis_spfstats, no_debug_isis_spfstats_cmd, - "no debug isis spf-statistics", + "no debug " PROTO_NAME " spf-statistics", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS SPF Timing and Statistic Data\n") { isis->debugs &= ~DEBUG_SPF_STATS; @@ -1038,9 +1054,9 @@ DEFUN (no_debug_isis_spfstats, DEFUN (debug_isis_spftrigg, debug_isis_spftrigg_cmd, - "debug isis spf-triggers", + "debug " PROTO_NAME " spf-triggers", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS SPF triggering events\n") { isis->debugs |= DEBUG_SPF_TRIGGERS; @@ -1051,10 +1067,10 @@ DEFUN (debug_isis_spftrigg, DEFUN (no_debug_isis_spftrigg, no_debug_isis_spftrigg_cmd, - "no debug isis spf-triggers", + "no debug " PROTO_NAME " spf-triggers", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS SPF triggering events\n") { isis->debugs &= ~DEBUG_SPF_TRIGGERS; @@ -1065,9 +1081,9 @@ DEFUN (no_debug_isis_spftrigg, DEFUN (debug_isis_rtevents, debug_isis_rtevents_cmd, - "debug isis route-events", + "debug " PROTO_NAME " route-events", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Route related events\n") { isis->debugs |= DEBUG_RTE_EVENTS; @@ -1078,10 +1094,10 @@ DEFUN (debug_isis_rtevents, DEFUN (no_debug_isis_rtevents, no_debug_isis_rtevents_cmd, - "no debug isis route-events", + "no debug " PROTO_NAME " route-events", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Route related events\n") { isis->debugs &= ~DEBUG_RTE_EVENTS; @@ -1092,9 +1108,9 @@ DEFUN (no_debug_isis_rtevents, DEFUN (debug_isis_events, debug_isis_events_cmd, - "debug isis events", + "debug " PROTO_NAME " events", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Events\n") { isis->debugs |= DEBUG_EVENTS; @@ -1105,10 +1121,10 @@ DEFUN (debug_isis_events, DEFUN (no_debug_isis_events, no_debug_isis_events_cmd, - "no debug isis events", + "no debug " PROTO_NAME " events", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Events\n") { isis->debugs &= ~DEBUG_EVENTS; @@ -1119,9 +1135,9 @@ DEFUN (no_debug_isis_events, DEFUN (debug_isis_packet_dump, debug_isis_packet_dump_cmd, - "debug isis packet-dump", + "debug " PROTO_NAME " packet-dump", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS packet dump\n") { isis->debugs |= DEBUG_PACKET_DUMP; @@ -1132,10 +1148,10 @@ DEFUN (debug_isis_packet_dump, DEFUN (no_debug_isis_packet_dump, no_debug_isis_packet_dump_cmd, - "no debug isis packet-dump", + "no debug " PROTO_NAME " packet-dump", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS packet dump\n") { isis->debugs &= ~DEBUG_PACKET_DUMP; @@ -1146,9 +1162,9 @@ DEFUN (no_debug_isis_packet_dump, DEFUN (debug_isis_lsp_gen, debug_isis_lsp_gen_cmd, - "debug isis lsp-gen", + "debug " PROTO_NAME " lsp-gen", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS generation of own LSPs\n") { isis->debugs |= DEBUG_LSP_GEN; @@ -1159,10 +1175,10 @@ DEFUN (debug_isis_lsp_gen, DEFUN (no_debug_isis_lsp_gen, no_debug_isis_lsp_gen_cmd, - "no debug isis lsp-gen", + "no debug " PROTO_NAME " lsp-gen", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS generation of own LSPs\n") { isis->debugs &= ~DEBUG_LSP_GEN; @@ -1173,9 +1189,9 @@ DEFUN (no_debug_isis_lsp_gen, DEFUN (debug_isis_lsp_sched, debug_isis_lsp_sched_cmd, - "debug isis lsp-sched", + "debug " PROTO_NAME " lsp-sched", DEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS scheduling of LSP generation\n") { isis->debugs |= DEBUG_LSP_SCHED; @@ -1186,10 +1202,10 @@ DEFUN (debug_isis_lsp_sched, DEFUN (no_debug_isis_lsp_sched, no_debug_isis_lsp_sched_cmd, - "no debug isis lsp-sched", + "no debug " PROTO_NAME " lsp-sched", NO_STR UNDEBUG_STR - "IS-IS information\n" + PROTO_HELP "IS-IS scheduling of LSP generation\n") { isis->debugs &= ~DEBUG_LSP_SCHED; @@ -1200,9 +1216,9 @@ DEFUN (no_debug_isis_lsp_sched, DEFUN (show_hostname, show_hostname_cmd, - "show isis hostname", + "show " PROTO_NAME " hostname", SHOW_STR - "IS-IS information\n" + PROTO_HELP "IS-IS Dynamic hostname mapping\n") { dynhn_print_all(vty); @@ -1212,10 +1228,10 @@ DEFUN (show_hostname, DEFUN (show_isis_spf_ietf, show_isis_spf_ietf_cmd, - "show isis spf-delay-ietf", + "show " PROTO_NAME " spf-delay-ietf", SHOW_STR - "IS-IS information\n" - "IS-IS SPF delay IETF information\n") + PROTO_HELP + "SPF delay IETF information\n") { if (!isis) { vty_out(vty, "ISIS is not running\n"); @@ -1261,15 +1277,15 @@ DEFUN (show_isis_spf_ietf, DEFUN (show_isis_summary, show_isis_summary_cmd, - "show isis summary", - SHOW_STR "IS-IS information\n" "IS-IS summary\n") + "show " PROTO_NAME " summary", + SHOW_STR PROTO_HELP "summary\n") { struct listnode *node, *node2; struct isis_area *area; int level; if (isis == NULL) { - vty_out(vty, "ISIS is not running\n"); + vty_out(vty, PROTO_NAME " is not running\n"); return CMD_SUCCESS; } @@ -1289,6 +1305,14 @@ DEFUN (show_isis_summary, vty_out(vty, "Area %s:\n", area->area_tag ? area->area_tag : "null"); + if (fabricd) { + uint8_t tier = fabricd_tier(area); + if (tier == ISIS_TIER_UNDEFINED) + vty_out(vty, " Tier: undefined\n"); + else + vty_out(vty, " Tier: %" PRIu8 "\n", tier); + } + if (listcount(area->area_addrs) > 0) { struct area_addr *area_addr; for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node2, @@ -1471,10 +1495,10 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) DEFUN (show_database, show_database_cmd, - "show isis database [detail] [WORD]", + "show " PROTO_NAME " database [detail] [WORD]", SHOW_STR - "IS-IS information\n" - "IS-IS link state database\n" + PROTO_HELP + "Link state database\n" "Detailed information\n" "LSP ID\n") { @@ -1491,9 +1515,9 @@ DEFUN (show_database, */ DEFUN_NOSH (router_isis, router_isis_cmd, - "router isis WORD", + "router " PROTO_NAME " WORD", ROUTER_STR - "ISO IS-IS\n" + PROTO_HELP "ISO Routing area tag\n") { int idx_word = 2; @@ -1505,8 +1529,11 @@ DEFUN_NOSH (router_isis, */ DEFUN (no_router_isis, no_router_isis_cmd, - "no router isis WORD", - "no\n" ROUTER_STR "ISO IS-IS\n" "ISO Routing area tag\n") + "no router " PROTO_NAME " WORD", + NO_STR + ROUTER_STR + PROTO_HELP + "ISO Routing area tag\n") { int idx_word = 3; return isis_area_destroy(vty, argv[idx_word]->arg); @@ -1869,7 +1896,7 @@ int isis_config_write(struct vty *vty) for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { /* ISIS - Area name */ - vty_out(vty, "router isis %s\n", area->area_tag); + vty_out(vty, "router " PROTO_NAME " %s\n", area->area_tag); write++; /* ISIS - Net */ if (listcount(area->area_addrs) > 0) { @@ -1893,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(); } diff --git a/isisd/isisd.h b/isisd/isisd.h index ce602e4402b3..864021428aa8 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -33,12 +33,32 @@ #include "isis_memory.h" #include "qobj.h" +#ifdef FABRICD +static const bool fabricd = true; +#define PROTO_TYPE ZEBRA_ROUTE_OPENFABRIC +#define PROTO_NAME "openfabric" +#define PROTO_HELP "OpenFabric routing protocol\n" +#define PROTO_REDIST_STR FRR_REDIST_STR_FABRICD +#define PROTO_REDIST_HELP FRR_REDIST_HELP_STR_FABRICD +#define ROUTER_NODE OPENFABRIC_NODE +#else +static const bool fabricd = false; +#define PROTO_TYPE ZEBRA_ROUTE_ISIS +#define PROTO_NAME "isis" +#define PROTO_HELP "IS-IS routing protocol\n" +#define PROTO_REDIST_STR FRR_REDIST_STR_ISISD +#define PROTO_REDIST_HELP FRR_REDIST_HELP_STR_ISISD +#define ROUTER_NODE ISIS_NODE +#endif + extern struct zebra_privs_t isisd_privs; /* uncomment if you are a developer in bug hunt */ /* #define EXTREME_DEBUG */ /* #define EXTREME_DICT_DEBUG */ +struct fabricd; + struct isis { unsigned long process_id; int sysid_set; @@ -93,6 +113,8 @@ struct isis_area { */ int lsp_regenerate_pending[ISIS_LEVELS]; + struct fabricd *fabricd; + /* * Configurables */ @@ -126,6 +148,7 @@ struct isis_area { /* multi topology settings */ struct list *mt_settings; int ipv6_circuits; + bool purge_originator; /* Counters */ uint32_t circuit_state_changes; struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT] @@ -168,7 +191,6 @@ int isis_area_passwd_cleartext_set(struct isis_area *area, int level, const char *passwd, uint8_t snp_auth); int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level, const char *passwd, uint8_t snp_auth); -void isis_vty_init(void); /* Master of threads. */ extern struct thread_master *master; @@ -188,6 +210,7 @@ extern struct thread_master *master; #define DEBUG_PACKET_DUMP (1<<12) #define DEBUG_LSP_GEN (1<<13) #define DEBUG_LSP_SCHED (1<<14) +#define DEBUG_FABRICD_FLOODING (1<<15) #define lsp_debug(...) \ do { \ diff --git a/isisd/subdir.am b/isisd/subdir.am index 7b8be46167cf..7571255e5925 100644 --- a/isisd/subdir.am +++ b/isisd/subdir.am @@ -6,35 +6,23 @@ if ISISD noinst_LIBRARIES += isisd/libisis.a sbin_PROGRAMS += isisd/isisd dist_examples_DATA += isisd/isisd.conf.sample +vtysh_scan += \ + $(top_srcdir)/isisd/isis_redist.c \ + $(top_srcdir)/isisd/isis_spf.c \ + $(top_srcdir)/isisd/isis_te.c \ + $(top_srcdir)/isisd/isis_vty_common.c \ + $(top_srcdir)/isisd/isis_vty_fabricd.c \ + $(top_srcdir)/isisd/isis_vty_isisd.c \ + $(top_srcdir)/isisd/isisd.c \ + # end +man8 += $(MANBUILD)/isisd.8 endif -isisd_libisis_a_SOURCES = \ - isisd/dict.c \ - isisd/isis_adjacency.c \ - isisd/isis_circuit.c \ - isisd/isis_csm.c \ - isisd/isis_dr.c \ - isisd/isis_dynhn.c \ - isisd/isis_errors.c \ - isisd/isis_events.c \ - isisd/isis_flags.c \ - isisd/isis_lsp.c \ - isisd/isis_lsp_hash.c \ - isisd/isis_memory.c \ - isisd/isis_misc.c \ - isisd/isis_mt.c \ - isisd/isis_pdu.c \ - isisd/isis_redist.c \ - isisd/isis_route.c \ - isisd/isis_routemap.c \ - isisd/isis_spf.c \ - isisd/isis_te.c \ - isisd/isis_tlvs.c \ - isisd/isis_vty.c \ - isisd/isis_zebra.c \ - isisd/isisd.c \ - isisd/iso_checksum.c \ - # end +if FABRICD +noinst_LIBRARIES += isisd/libfabric.a +sbin_PROGRAMS += isisd/fabricd +dist_examples_DATA += isisd/fabricd.conf.sample +endif noinst_HEADERS += \ isisd/dict.h \ @@ -49,7 +37,6 @@ noinst_HEADERS += \ isisd/isis_events.h \ isisd/isis_flags.h \ isisd/isis_lsp.h \ - isisd/isis_lsp_hash.h \ isisd/isis_memory.h \ isisd/isis_misc.h \ isisd/isis_mt.h \ @@ -59,17 +46,73 @@ noinst_HEADERS += \ isisd/isis_route.h \ isisd/isis_routemap.h \ isisd/isis_spf.h \ + isisd/isis_spf_private.h \ isisd/isis_te.h \ isisd/isis_tlvs.h \ + isisd/isis_tx_queue.h \ + isisd/isis_vty_common.h \ isisd/isis_zebra.h \ isisd/isisd.h \ isisd/iso_checksum.h \ + isisd/fabricd.h \ # end -isisd_isisd_LDADD = isisd/libisis.a lib/libfrr.la @LIBCAP@ -isisd_isisd_SOURCES = \ +LIBISIS_SOURCES = \ + isisd/dict.c \ + isisd/isis_adjacency.c \ + isisd/isis_circuit.c \ + isisd/isis_csm.c \ + isisd/isis_dr.c \ + isisd/isis_dynhn.c \ + isisd/isis_errors.c \ + isisd/isis_events.c \ + isisd/isis_flags.c \ + isisd/isis_lsp.c \ + isisd/isis_memory.c \ + isisd/isis_misc.c \ + isisd/isis_mt.c \ + isisd/isis_pdu.c \ + isisd/isis_redist.c \ + isisd/isis_route.c \ + isisd/isis_routemap.c \ + isisd/isis_spf.c \ + isisd/isis_te.c \ + isisd/isis_tlvs.c \ + isisd/isis_tx_queue.c \ + isisd/isis_vty_common.c \ + isisd/isis_zebra.c \ + isisd/isisd.c \ + isisd/iso_checksum.c \ + isisd/fabricd.c \ + # end + +ISIS_SOURCES = \ isisd/isis_bpf.c \ isisd/isis_dlpi.c \ isisd/isis_main.c \ isisd/isis_pfpacket.c \ # end + +ISIS_LDADD_COMMON = lib/libfrr.la @LIBCAP@ + +# Building isisd + +isisd_libisis_a_SOURCES = \ + $(LIBISIS_SOURCES) \ + isisd/isis_vty_isisd.c \ + #end +isisd_isisd_LDADD = isisd/libisis.a $(ISIS_LDADD_COMMON) +isisd_isisd_SOURCES = $(ISIS_SOURCES) + +# Building fabricd + +FABRICD_CPPFLAGS = -DFABRICD=1 $(AM_CPPFLAGS) + +isisd_libfabric_a_SOURCES = \ + $(LIBISIS_SOURCES) \ + isisd/isis_vty_fabricd.c \ + #end +isisd_libfabric_a_CPPFLAGS = $(FABRICD_CPPFLAGS) +isisd_fabricd_LDADD = isisd/libfabric.a $(ISIS_LDADD_COMMON) +isisd_fabricd_SOURCES = $(ISIS_SOURCES) +isisd_fabricd_CPPFLAGS = $(FABRICD_CPPFLAGS) diff --git a/ldpd/.gitignore b/ldpd/.gitignore index a2f4b51698ba..ec8a5c40863d 100644 --- a/ldpd/.gitignore +++ b/ldpd/.gitignore @@ -1,17 +1,2 @@ -!Makefile -Makefile.in -*.o ldpd ldpd.conf -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.a -*.libs -.arch-inventory -.arch-ids -*~ -*.loT diff --git a/ldpd/lde.c b/ldpd/lde.c index 03b62b482b26..81043988863b 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -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) diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index e830263ded81..935e95959658 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -330,7 +330,7 @@ main(int argc, char *argv[]) master = frr_init(); vty_config_lockless(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); access_list_init(); ldp_vty_init(); ldp_zebra_init(master); diff --git a/ldpd/pfkey.c b/ldpd/pfkey.c index 906737217c0e..a719d0cbb706 100644 --- a/ldpd/pfkey.c +++ b/ldpd/pfkey.c @@ -17,6 +17,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef __OpenBSD__ #include #include diff --git a/ldpd/subdir.am b/ldpd/subdir.am index 2d87be0cda80..24e738d6227a 100644 --- a/ldpd/subdir.am +++ b/ldpd/subdir.am @@ -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 = \ diff --git a/lib/.gitignore b/lib/.gitignore index 072146dbd548..6176b30f8d2f 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -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 diff --git a/lib/agg_table.c b/lib/agg_table.c new file mode 100644 index 000000000000..6033fc3f0567 --- /dev/null +++ b/lib/agg_table.c @@ -0,0 +1,59 @@ +/* + * Aggregate Route + * Copyright (C) 2018 Cumulus Networks, Inc. + * Donald Sharp + * + * 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 "agg_table.h" + + +static struct route_node *agg_node_create(route_table_delegate_t *delegate, + struct route_table *table) +{ + struct agg_node *node; + + node = XCALLOC(MTYPE_TMP, sizeof(struct agg_node)); + + return agg_node_to_rnode(node); +} + +static void agg_node_destroy(route_table_delegate_t *delegate, + struct route_table *table, struct route_node *node) + +{ + struct agg_node *anode = agg_node_from_rnode(node); + + XFREE(MTYPE_TMP, anode); +} + +route_table_delegate_t agg_table_delegate = { + .create_node = agg_node_create, + .destroy_node = agg_node_destroy, +}; + +struct agg_table *agg_table_init(void) +{ + struct agg_table *at; + + at = XCALLOC(MTYPE_TMP, sizeof(struct agg_table)); + + at->route_table = route_table_init_with_delegate(&agg_table_delegate); + at->route_table->info = at; + + return at; +} diff --git a/lib/agg_table.h b/lib/agg_table.h new file mode 100644 index 000000000000..235f0d37a390 --- /dev/null +++ b/lib/agg_table.h @@ -0,0 +1,153 @@ +/* + * agg_table - Aggregate Table Header + * Copyright (C) 2018 Cumulus Networks, Inc. + * Donald Sharp + * + * 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 __AGG_TABLE_H__ +#define __AGG_TABLE_H__ + +#include "prefix.h" +#include "table.h" + +struct agg_table { + struct route_table *route_table; + + void *info; +}; + +struct agg_node { + /* + * Caution these must be the very first fields + * @see agg_node_to_rnode + * @see agg_node_from_rnode + */ + ROUTE_NODE_FIELDS + + /* Aggregation. */ + void *aggregate; +}; + +static inline struct route_node *agg_node_to_rnode(struct agg_node *node) +{ + return (struct route_node *)node; +} + +static inline struct agg_node *agg_node_from_rnode(struct route_node *node) +{ + return (struct agg_node *)node; +} + +static inline struct agg_node *agg_lock_node(struct agg_node *node) +{ + return (struct agg_node *)route_lock_node(agg_node_to_rnode(node)); +} + +static inline void agg_unlock_node(struct agg_node *node) +{ + return route_unlock_node(agg_node_to_rnode(node)); +} + +static inline void agg_set_table_info(struct agg_table *atable, void *data) +{ + atable->info = data; +} + +static inline void *agg_get_table_info(struct agg_table *atable) +{ + return atable->info; +} + +static inline struct agg_node *agg_route_top(struct agg_table *table) +{ + return agg_node_from_rnode(route_top(table->route_table)); +} + +static inline struct agg_node *agg_route_next(struct agg_node *node) +{ + return agg_node_from_rnode(route_next(agg_node_to_rnode(node))); +} + +static inline struct agg_node *agg_node_get(struct agg_table *table, + struct prefix *p) +{ + return agg_node_from_rnode(route_node_get(table->route_table, p)); +} + +static inline struct agg_node * +agg_node_lookup(const struct agg_table *const table, struct prefix *p) +{ + return agg_node_from_rnode(route_node_lookup(table->route_table, p)); +} + +static inline struct agg_node *agg_route_next_until(struct agg_node *node, + struct agg_node *limit) +{ + struct route_node *rnode; + + rnode = route_next_until(agg_node_to_rnode(node), + agg_node_to_rnode(limit)); + + return agg_node_from_rnode(rnode); +} + +static inline struct agg_node *agg_node_match(struct agg_table *table, + struct prefix *p) +{ + return agg_node_from_rnode(route_node_match(table->route_table, p)); +} + +static inline struct agg_node *agg_node_parent(struct agg_node *node) +{ + struct route_node *rn = agg_node_to_rnode(node); + + return agg_node_from_rnode(rn->parent); +} + +static inline struct agg_node *agg_node_left(struct agg_node *node) +{ + struct route_node *rn = agg_node_to_rnode(node); + + return agg_node_from_rnode(rn->l_left); +} + +static inline struct agg_node *agg_node_right(struct agg_node *node) +{ + struct route_node *rn = agg_node_to_rnode(node); + + return agg_node_from_rnode(rn->l_right); +} + +extern struct agg_table *agg_table_init(void); + +static inline void agg_table_finish(struct agg_table *atable) +{ + route_table_finish(atable->route_table); + atable->route_table = NULL; + + XFREE(MTYPE_TMP, atable); +} + +static inline struct agg_node *agg_route_table_top(struct agg_node *node) +{ + return (struct agg_node *)route_top(node->table); +} + +static inline struct agg_table *agg_get_table(struct agg_node *node) +{ + return (struct agg_table *)node->table->info; +} +#endif diff --git a/lib/bfd.c b/lib/bfd.c index 0eddb47514d5..1dfe583caf77 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -342,7 +342,7 @@ static void bfd_last_update(time_t last_update, char *buf, size_t len) * bfd_show_param - Show the BFD parameter information. */ void bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag, - int extra_space, uint8_t use_json, json_object *json_obj) + int extra_space, bool use_json, json_object *json_obj) { json_object *json_bfd = NULL; @@ -378,7 +378,7 @@ void bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag, * bfd_show_status - Show the BFD status information. */ static void bfd_show_status(struct vty *vty, struct bfd_info *bfd_info, - int bfd_tag, int extra_space, uint8_t use_json, + int bfd_tag, int extra_space, bool use_json, json_object *json_bfd) { char time_buf[32]; @@ -402,7 +402,7 @@ static void bfd_show_status(struct vty *vty, struct bfd_info *bfd_info, * bfd_show_info - Show the BFD information. */ void bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop, - int extra_space, uint8_t use_json, json_object *json_obj) + int extra_space, bool use_json, json_object *json_obj) { json_object *json_bfd = NULL; diff --git a/lib/bfd.h b/lib/bfd.h index f824b0fd9b54..b1e490a62279 100644 --- a/lib/bfd.h +++ b/lib/bfd.h @@ -91,11 +91,11 @@ extern struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp, const char *bfd_get_status_str(int status); extern void bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, - int bfd_tag, int extra_space, uint8_t use_json, + int bfd_tag, int extra_space, bool use_json, json_object *json_obj); extern void bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, - int multihop, int extra_space, uint8_t use_json, + int multihop, int extra_space, bool use_json, json_object *json_obj); extern void bfd_client_sendmsg(struct zclient *zclient, int command); diff --git a/lib/command.c b/lib/command.c index 1df644210723..26afc762fba2 100644 --- a/lib/command.c +++ b/lib/command.c @@ -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: diff --git a/lib/command.h b/lib/command.h index 75b69507ec7b..8e51641b88cf 100644 --- a/lib/command.h +++ b/lib/command.h @@ -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 \ "" -#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" diff --git a/lib/command_lex.l b/lib/command_lex.l index 0d6e6ee7e5fc..3b18b58a2e9e 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -22,6 +22,11 @@ * 02111-1307, USA. */ +%top{ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +} %{ /* ignore flex generated code in static analyzer */ #ifndef __clang_analyzer__ diff --git a/lib/csv.c b/lib/csv.c index ce84783aa6f7..582106ebd429 100644 --- a/lib/csv.c +++ b/lib/csv.c @@ -17,6 +17,11 @@ * 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 #include #include @@ -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)); diff --git a/lib/defun_lex.l b/lib/defun_lex.l index d901c26a2ed3..6c0805a4fa9b 100644 --- a/lib/defun_lex.l +++ b/lib/defun_lex.l @@ -1,4 +1,3 @@ -%{ /* * clippy (CLI preparator in python) C pseudo-lexer * Copyright (C) 2016-2017 David Lamparter for NetDEF, Inc. @@ -34,6 +33,12 @@ * 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" diff --git a/lib/ferr.c b/lib/ferr.c index 17ec51c4bfa9..afef196cec4c 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -14,6 +14,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -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[sizeof(ubuf) - 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); diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c index f5a6383f48d9..d48b23f38a9a 100644 --- a/lib/frr_pthread.c +++ b/lib/frr_pthread.c @@ -19,6 +19,9 @@ #include #include +#ifdef HAVE_PTHREAD_NP_H +#include +#endif #include #include "frr_pthread.h" @@ -85,7 +88,7 @@ void frr_pthread_finish() } struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr, - const char *name) + const char *name, const char *os_name) { static struct frr_pthread holder = {}; struct frr_pthread *fpt = NULL; @@ -107,6 +110,9 @@ struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr, fpt->attr = *attr; name = (name ? name : "Anonymous thread"); fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); + if (os_name) + snprintf(fpt->os_name, OS_THREAD_NAMELEN, + "%s", os_name); if (attr == &frr_pthread_attr_default) fpt->attr.id = frr_pthread_get_id(); /* initialize startup synchronization primitives */ @@ -140,16 +146,38 @@ void frr_pthread_destroy(struct frr_pthread *fpt) XFREE(MTYPE_FRR_PTHREAD, fpt); } -void frr_pthread_set_name(struct frr_pthread *fpt, const char *name) +int frr_pthread_set_name(struct frr_pthread *fpt, const char *name, + const char *os_name) { - pthread_mutex_lock(&fpt->mtx); - { - if (fpt->name) - XFREE(MTYPE_FRR_PTHREAD, fpt->name); - fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); + int ret = 0; + + if (name) { + pthread_mutex_lock(&fpt->mtx); + { + if (fpt->name) + XFREE(MTYPE_FRR_PTHREAD, fpt->name); + fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); + } + pthread_mutex_unlock(&fpt->mtx); + thread_master_set_name(fpt->master, name); } - pthread_mutex_unlock(&fpt->mtx); - thread_master_set_name(fpt->master, name); + + if (os_name) { + pthread_mutex_lock(&fpt->mtx); + snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", os_name); + pthread_mutex_unlock(&fpt->mtx); +#ifdef HAVE_PTHREAD_SETNAME_NP +# ifdef GNU_LINUX + ret = pthread_setname_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 + } + + return ret; } struct frr_pthread *frr_pthread_get(uint32_t id) @@ -311,6 +339,9 @@ static void *fpt_run(void *arg) fpt->master->handle_signals = false; + if (fpt->os_name[0]) + frr_pthread_set_name(fpt, NULL, fpt->os_name); + frr_pthread_notify_running(fpt); struct thread task; diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h index 91002dd8eff6..732e2925fef6 100644 --- a/lib/frr_pthread.h +++ b/lib/frr_pthread.h @@ -28,6 +28,8 @@ DECLARE_MTYPE(FRR_PTHREAD); DECLARE_MTYPE(PTHREAD_PRIM); +#define OS_THREAD_NAMELEN 16 + struct frr_pthread; struct frr_pthread_attr; @@ -89,6 +91,9 @@ struct frr_pthread { * Requires: mtx */ char *name; + + /* Used in pthread_set_name max 16 characters */ + char os_name[OS_THREAD_NAMELEN]; }; extern struct frr_pthread_attr frr_pthread_attr_default; @@ -122,18 +127,23 @@ void frr_pthread_finish(void); * * @param attr - the thread attributes * @param name - Human-readable name + * @param os_name - 16 characters (including '\0') thread name to set in os, * @return the created frr_pthread upon success, or NULL upon failure */ struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr, - const char *name); + const char *name, const char *os_name); /* * Changes the name of the frr_pthread. * * @param fpt - the frr_pthread to operate on * @param name - Human-readable name + * @param os_name - 16 characters thread name , including the null + * terminator ('\0') to set in os. + * @return - on success returns 0 otherwise nonzero error number. */ -void frr_pthread_set_name(struct frr_pthread *fpt, const char *name); +int frr_pthread_set_name(struct frr_pthread *fpt, const char *name, + const char *os_name); /* * Destroys an frr_pthread. @@ -224,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 */ diff --git a/lib/frratomic.h b/lib/frratomic.h index 689b25255d9e..1f1d1b569a59 100644 --- a/lib/frratomic.h +++ b/lib/frratomic.h @@ -29,6 +29,12 @@ #ifdef HAVE_STDATOMIC_H #include +/* These are available in gcc, but not in stdatomic */ +#define atomic_add_fetch_explicit __atomic_add_fetch +#define atomic_sub_fetch_explicit __atomic_sub_fetch +#define atomic_and_fetch_explicit __atomic_and_fetch +#define atomic_or_fetch_explicit __atomic_or_fetch + /* gcc 4.7 and newer */ #elif defined(HAVE___ATOMIC) @@ -49,6 +55,11 @@ #define atomic_fetch_and_explicit __atomic_fetch_and #define atomic_fetch_or_explicit __atomic_fetch_or +#define atomic_add_fetch_explicit __atomic_add_fetch +#define atomic_sub_fetch_explicit __atomic_sub_fetch +#define atomic_and_fetch_explicit __atomic_and_fetch +#define atomic_or_fetch_explicit __atomic_or_fetch + #define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, \ mem2) \ __atomic_compare_exchange_n(atom, expect, desire, 1, mem1, mem2) @@ -137,6 +148,7 @@ *_expect = rval; \ ret; \ }) + #define atomic_fetch_and_explicit(ptr, val, mem) \ ({ \ __sync_synchronize(); \ @@ -152,6 +164,36 @@ rval; \ }) +#define atomic_add_fetch_explicit(ptr, val, mem) \ + ({ \ + __sync_synchronize(); \ + typeof(*ptr) rval = __sync_add_and_fetch((ptr), (val)); \ + __sync_synchronize(); \ + rval; \ + }) +#define atomic_sub_fetch_explicit(ptr, val, mem) \ + ({ \ + __sync_synchronize(); \ + typeof(*ptr) rval = __sync_sub_and_fetch((ptr), (val)); \ + __sync_synchronize(); \ + rval; \ + }) + +#define atomic_and_fetch_explicit(ptr, val, mem) \ + ({ \ + __sync_synchronize(); \ + typeof(*ptr) rval = __sync_and_and_fetch(ptr, val); \ + __sync_synchronize(); \ + rval; \ + }) +#define atomic_or_fetch_explicit(ptr, val, mem) \ + ({ \ + __sync_synchronize(); \ + typeof(*ptr) rval = __sync_or_and_fetch(ptr, val); \ + __sync_synchronize(); \ + rval; \ + }) + #else /* !HAVE___ATOMIC && !HAVE_STDATOMIC_H */ #error no atomic functions... #endif diff --git a/lib/frrstr.c b/lib/frrstr.c index 715e67b868c2..85d968182b04 100644 --- a/lib/frrstr.c +++ b/lib/frrstr.c @@ -18,6 +18,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 51e7a3987e00..ef03e85217b4 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -23,6 +23,10 @@ * 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" diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c index 264c7c48f00e..c9c942f9bf89 100644 --- a/lib/grammar_sandbox_main.c +++ b/lib/grammar_sandbox_main.c @@ -23,6 +23,10 @@ * 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" diff --git a/lib/hook.c b/lib/hook.c index 935064f4d2ae..4fe305f28268 100644 --- a/lib/hook.c +++ b/lib/hook.c @@ -20,6 +20,10 @@ * DEALINGS IN THE SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "memory.h" #include "hook.h" diff --git a/lib/if.c b/lib/if.c index 2bf0c6e6b5ae..a03c9da6f91e 100644 --- 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; diff --git a/lib/imsg-buffer.c b/lib/imsg-buffer.c index b83f1f76f2a6..c2f4052b8f5e 100644 --- a/lib/imsg-buffer.c +++ b/lib/imsg-buffer.c @@ -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 @@ int msgbuf_write(struct msgbuf *msgbuf) 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); diff --git a/lib/imsg.c b/lib/imsg.c index 54241407205d..935d13772752 100644 --- a/lib/imsg.c +++ b/lib/imsg.c @@ -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); diff --git a/lib/json.c b/lib/json.c index 40b6aadaa3ca..4ea20ba178ad 100644 --- a/lib/json.c +++ b/lib/json.c @@ -28,15 +28,15 @@ * is the *last* keyword on the line no matter * what. */ -int use_json(const int argc, struct cmd_token *argv[]) +bool use_json(const int argc, struct cmd_token *argv[]) { if (argc == 0) - return 0; + return false; if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "json")) - return 1; + return true; - return 0; + return false; } void json_object_string_add(struct json_object *obj, const char *key, diff --git a/lib/json.h b/lib/json.h index 788d1d6efa1d..d34916230473 100644 --- a/lib/json.h +++ b/lib/json.h @@ -52,7 +52,7 @@ extern int json_object_object_get_ex(struct json_object *obj, const char *key, #include "command.h" -extern int use_json(const int argc, struct cmd_token *argv[]); +extern bool use_json(const int argc, struct cmd_token *argv[]); extern void json_object_string_add(struct json_object *obj, const char *key, const char *s); extern void json_object_int_add(struct json_object *obj, const char *key, diff --git a/lib/lib_errors.c b/lib/lib_errors.c index 332a5b1d453a..2ddc571e6889 100644 --- a/lib/lib_errors.c +++ b/lib/lib_errors.c @@ -18,6 +18,10 @@ * 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 */ diff --git a/lib/log.c b/lib/log.c index b067018e08de..521783e4b098 100644 --- a/lib/log.c +++ b/lib/log.c @@ -925,7 +925,6 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_IMPORT_ROUTE_REGISTER), DESC_ENTRY(ZEBRA_IMPORT_ROUTE_UNREGISTER), DESC_ENTRY(ZEBRA_IMPORT_CHECK_UPDATE), - DESC_ENTRY(ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD), DESC_ENTRY(ZEBRA_BFD_DEST_REGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE), @@ -1075,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")) @@ -1103,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; } diff --git a/lib/memory.c b/lib/memory.c index 87cba69fc515..fee23a75ac67 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -20,6 +20,9 @@ #ifdef HAVE_MALLOC_H #include #endif +#ifdef HAVE_MALLOC_NP_H +#include +#endif #ifdef HAVE_MALLOC_MALLOC_H #include #endif @@ -36,9 +39,19 @@ DEFINE_MTYPE(LIB, PREFIX_FLOWSPEC, "Prefix Flowspec") static inline void mt_count_alloc(struct memtype *mt, size_t size, void *ptr) { + size_t current; size_t oldsize; - atomic_fetch_add_explicit(&mt->n_alloc, 1, memory_order_relaxed); + current = 1 + atomic_fetch_add_explicit(&mt->n_alloc, 1, + memory_order_relaxed); + + oldsize = atomic_load_explicit(&mt->n_max, memory_order_relaxed); + if (current > oldsize) + /* note that this may fail, but approximation is sufficient */ + atomic_compare_exchange_weak_explicit(&mt->n_max, &oldsize, + current, + memory_order_relaxed, + memory_order_relaxed); oldsize = atomic_load_explicit(&mt->size, memory_order_relaxed); if (oldsize == 0) @@ -51,7 +64,15 @@ static inline void mt_count_alloc(struct memtype *mt, size_t size, void *ptr) #ifdef HAVE_MALLOC_USABLE_SIZE size_t mallocsz = malloc_usable_size(ptr); - atomic_fetch_add_explicit(&mt->total, mallocsz, memory_order_relaxed); + current = mallocsz + atomic_fetch_add_explicit(&mt->total, mallocsz, + memory_order_relaxed); + oldsize = atomic_load_explicit(&mt->max_size, memory_order_relaxed); + if (current > oldsize) + /* note that this may fail, but approximation is sufficient */ + atomic_compare_exchange_weak_explicit(&mt->max_size, &oldsize, + current, + memory_order_relaxed, + memory_order_relaxed); #endif } diff --git a/lib/memory.h b/lib/memory.h index c39f34e3a7f8..2d6c1447786a 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -34,9 +34,11 @@ struct memtype { struct memtype *next, **ref; const char *name; _Atomic size_t n_alloc; + _Atomic size_t n_max; _Atomic size_t size; #ifdef HAVE_MALLOC_USABLE_SIZE _Atomic size_t total; + _Atomic size_t max_size; #endif }; diff --git a/lib/memory_vty.c b/lib/memory_vty.c index 9ee2e52ec751..5fd9c3b90043 100644 --- a/lib/memory_vty.c +++ b/lib/memory_vty.c @@ -28,7 +28,9 @@ #include #endif #include +#ifdef HAVE_LINK_H #include +#endif #include "log.h" #include "memory.h" @@ -73,27 +75,45 @@ static int show_memory_mallinfo(struct vty *vty) static int qmem_walker(void *arg, struct memgroup *mg, struct memtype *mt) { struct vty *vty = arg; - if (!mt) + if (!mt) { vty_out(vty, "--- qmem %s ---\n", mg->name); - else { + vty_out(vty, "%-30s: %8s %-8s%s %8s %9s\n", + "Type", "Current#", " Size", +#ifdef HAVE_MALLOC_USABLE_SIZE + " Total", +#else + "", +#endif + "Max#", +#ifdef HAVE_MALLOC_USABLE_SIZE + "MaxBytes" +#else + "" +#endif + ); + } else { if (mt->n_alloc != 0) { char size[32]; snprintf(size, sizeof(size), "%6zu", mt->size); - #ifdef HAVE_MALLOC_USABLE_SIZE #define TSTR " %9zu" #define TARG , mt->total +#define TARG2 , mt->max_size #else #define TSTR "" #define TARG +#define TARG2 #endif - vty_out(vty, "%-30s: %10zu %-16s"TSTR"\n", mt->name, + vty_out(vty, "%-30s: %8zu %-8s"TSTR" %8zu"TSTR"\n", + mt->name, mt->n_alloc, mt->size == 0 ? "" : mt->size == SIZE_VAR - ? "(variably sized)" + ? "variable" : size - TARG); + TARG, + mt->n_max + TARG2); } } return 0; diff --git a/lib/netns_linux.c b/lib/netns_linux.c index b8eaa72c22af..33338ac89c2c 100644 --- a/lib/netns_linux.c +++ b/lib/netns_linux.c @@ -468,21 +468,12 @@ void ns_init(void) if (ns_initialised == 1) return; errno = 0; -#ifdef HAVE_NETNS - if (have_netns_enabled < 0) { + if (have_netns()) ns_default_ns_fd = open(NS_DEFAULT_NAME, O_RDONLY); - if (ns_default_ns_fd == -1) - flog_err(LIB_ERR_NS, - "NS initialization failure %d(%s)", errno, - safe_strerror(errno)); - } else { + else { ns_default_ns_fd = -1; default_ns = NULL; } -#else - ns_default_ns_fd = -1; - default_ns = NULL; -#endif /* HAVE_NETNS */ ns_current_ns_fd = -1; ns_initialised = 1; } diff --git a/lib/openbsd-tree.c b/lib/openbsd-tree.c index 35bfce3a890d..e8d13339b633 100644 --- a/lib/openbsd-tree.c +++ b/lib/openbsd-tree.c @@ -41,6 +41,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include diff --git a/lib/plist.c b/lib/plist.c index 2b666f256fce..57460801279a 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -396,7 +396,7 @@ static int64_t prefix_new_seq_get(struct prefix_list *plist) newseq = ((maxseq / 5) * 5) + 5; - return newseq; + return (newseq > UINT_MAX) ? UINT_MAX : newseq; } /* Return prefix list entry which has same seq number. */ @@ -1900,7 +1900,7 @@ void prefix_bgp_orf_remove_all(afi_t afi, char *name) /* return prefix count */ int prefix_bgp_show_prefix_list(struct vty *vty, afi_t afi, char *name, - uint8_t use_json) + bool use_json) { struct prefix_list *plist; struct prefix_list_entry *pentry; diff --git a/lib/plist.h b/lib/plist.h index fecbe0e2ce68..8a4fa8d3ce6c 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -72,6 +72,7 @@ extern struct stream *prefix_bgp_orf_entry(struct stream *, uint8_t, uint8_t); extern int prefix_bgp_orf_set(char *, afi_t, struct orf_prefix *, int, int); extern void prefix_bgp_orf_remove_all(afi_t, char *); -extern int prefix_bgp_show_prefix_list(struct vty *, afi_t, char *, uint8_t); +extern int prefix_bgp_show_prefix_list(struct vty *vty, afi_t afi, char *name, + bool use_json); #endif /* _QUAGGA_PLIST_H */ diff --git a/lib/ptm_lib.c b/lib/ptm_lib.c index 69fd61e2a069..7f868beda419 100644 --- a/lib/ptm_lib.c +++ b/lib/ptm_lib.c @@ -17,6 +17,11 @@ * 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 #include #include diff --git a/lib/queue.h b/lib/queue.h index 04fbeee7004c..11e28b4c9125 100644 --- a/lib/queue.h +++ b/lib/queue.h @@ -72,4 +72,17 @@ #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 */ diff --git a/lib/route_types.txt b/lib/route_types.txt index 72f59a1b7860..c5eff44ca7f0 100644 --- a/lib/route_types.txt +++ b/lib/route_types.txt @@ -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" diff --git a/lib/routemap.c b/lib/routemap.c index 4125bb53aee6..e5613c208153 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -891,6 +891,14 @@ static void vty_show_route_map_entry(struct vty *vty, struct route_map *map) } } +static int sort_route_map(const void **map1, const void **map2) +{ + const struct route_map *m1 = *map1; + const struct route_map *m2 = *map2; + + return strcmp(m1->name, m2->name); +} + static int vty_show_route_map(struct vty *vty, const char *name) { struct route_map *map; @@ -907,9 +915,19 @@ static int vty_show_route_map(struct vty *vty, const char *name) return CMD_SUCCESS; } } else { + + struct list *maplist = list_new(); + struct listnode *ln; + for (map = route_map_master.head; map; map = map->next) - if (!map->deleted) - vty_show_route_map_entry(vty, map); + listnode_add(maplist, map); + + list_sort(maplist, sort_route_map); + + for (ALL_LIST_ELEMENTS_RO(maplist, ln, map)) + vty_show_route_map_entry(vty, map); + + list_delete_and_null(&maplist); } return CMD_SUCCESS; } diff --git a/lib/skiplist.c b/lib/skiplist.c index a36bf47139c3..585cf859e574 100644 --- a/lib/skiplist.c +++ b/lib/skiplist.c @@ -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; diff --git a/lib/stream.c b/lib/stream.c index 55e7f6435826..589a22925682 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -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); diff --git a/lib/strlcat.c b/lib/strlcat.c index be211f82a8e5..39773d9ac89e 100644 --- a/lib/strlcat.c +++ b/lib/strlcat.c @@ -20,11 +20,13 @@ /* adapted for Quagga from glibc patch submission originally from * Florian Weimer , 2016-05-18 */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include -#include "config.h" - #ifndef HAVE_STRLCAT #undef strlcat diff --git a/lib/strlcpy.c b/lib/strlcpy.c index b0c33ca7f42b..71ee9f1a5452 100644 --- a/lib/strlcpy.c +++ b/lib/strlcpy.c @@ -20,9 +20,11 @@ /* adapted for Quagga from glibc patch submission originally from * Florian Weimer , 2016-05-18 */ -#include - +#ifdef HAVE_CONFIG_H #include "config.h" +#endif + +#include #ifndef HAVE_STRLCPY #undef strlcpy diff --git a/lib/subdir.am b/lib/subdir.am index 50cfd70a571f..499bb94920d6 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -6,6 +6,7 @@ lib_libfrr_la_LDFLAGS = -version-info 0:0:0 lib_libfrr_la_LIBADD = @LIBCAP@ lib_libfrr_la_SOURCES = \ + lib/agg_table.c \ lib/bfd.c \ lib/buffer.c \ lib/checksum.c \ @@ -83,12 +84,29 @@ 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) lib/nexthop_group.lo: lib/nexthop_group_clippy.c pkginclude_HEADERS += \ + lib/agg_table.h \ lib/bfd.h \ lib/bitfield.h \ lib/buffer.h \ @@ -150,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 \ @@ -235,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 \ @@ -250,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 @@ -291,7 +331,7 @@ if GIT_VERSION # (even if gitversion.h's file timestamp doesn't change, make will think it # did, because of .PHONY...) -.PHONY: lib/gitversion.h.tmp +PHONY_GITVERSION=lib/gitversion.h.tmp .SILENT: lib/gitversion.h lib/gitversion.h.tmp GITH=lib/gitversion.h lib/gitversion.h.tmp: $(top_srcdir)/.git @@ -300,7 +340,8 @@ lib/gitversion.h: lib/gitversion.h.tmp { test -f ${GITH} && diff -s -q ${GITH}.tmp ${GITH}; } || cp ${GITH}.tmp ${GITH} else -.PHONY: lib/gitversion.h +PHONY_GITVERSION=lib/gitversion.h lib/gitversion.h: true endif +.PHONY: $(PHONY_GITVERSION) diff --git a/lib/table.h b/lib/table.h index 8304abe59b38..711ace111ec1 100644 --- a/lib/table.h +++ b/lib/table.h @@ -126,9 +126,6 @@ struct route_table { \ /* Each node of route. */ \ void *info; \ - \ - /* Aggregation. */ \ - void *aggregate; /* Each routing entry. */ diff --git a/lib/vrf.c b/lib/vrf.c index ecd09a6b9154..1fb1b786c7d4 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -39,6 +39,7 @@ /* default VRF ID value used when VRF backend is not NETNS */ #define VRF_DEFAULT_INTERNAL 0 +#define VRF_DEFAULT_NAME_INTERNAL "default" DEFINE_MTYPE_STATIC(LIB, VRF, "VRF") DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map") @@ -56,6 +57,7 @@ struct vrf_name_head vrfs_by_name = RB_INITIALIZER(&vrfs_by_name); static int vrf_backend; static struct zebra_privs_t *vrf_daemon_privs; +static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL; /* * Turn on/off debug code @@ -69,6 +71,7 @@ struct vrf_master { int (*vrf_delete_hook)(struct vrf *); int (*vrf_enable_hook)(struct vrf *); int (*vrf_disable_hook)(struct vrf *); + int (*vrf_update_name_hook)(struct vrf *vrf); } vrf_master = { 0, }; @@ -165,6 +168,13 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name) */ if (name) vrf = vrf_lookup_by_name(name); + if (vrf && vrf_id != VRF_UNKNOWN + && vrf->vrf_id != VRF_UNKNOWN + && vrf->vrf_id != vrf_id) { + zlog_debug("VRF_GET: avoid %s creation(%u), same name exists (%u)", + name, vrf_id, vrf->vrf_id); + return NULL; + } /* Try to find VRF both by ID and name */ if (!vrf && vrf_id != VRF_UNKNOWN) vrf = vrf_lookup_by_id(vrf_id); @@ -445,10 +455,8 @@ static void vrf_autocomplete(vector comps, struct cmd_token *token) { struct vrf *vrf = NULL; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if (vrf->vrf_id != VRF_DEFAULT) - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); - } + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); } static const struct cmd_variable_handler vrf_var_handlers[] = { @@ -461,7 +469,8 @@ static const struct cmd_variable_handler vrf_var_handlers[] = { /* Initialize VRF module. */ void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), - int (*disable)(struct vrf *), int (*delete)(struct vrf *)) + int (*disable)(struct vrf *), int (*delete)(struct vrf *), + int ((*update)(struct vrf *))) { struct vrf *default_vrf; @@ -475,6 +484,7 @@ void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), vrf_master.vrf_enable_hook = enable; vrf_master.vrf_disable_hook = disable; vrf_master.vrf_delete_hook = delete; + vrf_master.vrf_update_name_hook = update; /* The default VRF always exists. */ default_vrf = vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME); @@ -483,6 +493,9 @@ void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), "vrf_init: failed to create the default VRF!"); exit(1); } + if (vrf_is_backend_netns()) + strlcpy(default_vrf->data.l.netns_name, + VRF_DEFAULT_NAME, NS_NAMSIZ); /* Enable the default VRF. */ if (!vrf_enable(default_vrf)) { @@ -876,12 +889,40 @@ void vrf_cmd_init(int (*writefunc)(struct vty *vty), } } -vrf_id_t vrf_get_default_id(void) +void vrf_set_default_name(const char *default_name) { - struct vrf *vrf = vrf_lookup_by_name(VRF_DEFAULT_NAME); + struct vrf *def_vrf; + struct vrf *vrf_with_default_name = NULL; - if (vrf) - return vrf->vrf_id; + def_vrf = vrf_lookup_by_id(VRF_DEFAULT); + assert(default_name); + vrf_with_default_name = vrf_lookup_by_name(default_name); + if (vrf_with_default_name && vrf_with_default_name != def_vrf) { + /* vrf name already used by an other VRF */ + zlog_debug("VRF: %s, avoid changing name to %s, same name exists (%u)", + vrf_with_default_name->name, default_name, + vrf_with_default_name->vrf_id); + return; + } + snprintf(vrf_default_name, VRF_NAMSIZ, "%s", default_name); + if (def_vrf) { + RB_REMOVE(vrf_name_head, &vrfs_by_name, def_vrf); + strlcpy(def_vrf->data.l.netns_name, + vrf_default_name, NS_NAMSIZ); + strlcpy(def_vrf->name, vrf_default_name, sizeof(def_vrf->name)); + RB_INSERT(vrf_name_head, &vrfs_by_name, def_vrf); + if (vrf_master.vrf_update_name_hook) + (*vrf_master.vrf_update_name_hook)(def_vrf); + } +} + +const char *vrf_get_default_name(void) +{ + return vrf_default_name; +} + +vrf_id_t vrf_get_default_id(void) +{ /* backend netns is only known by zebra * for other daemons, we return VRF_DEFAULT_INTERNAL */ diff --git a/lib/vrf.h b/lib/vrf.h index 56ba101ff0cf..c962ac4c6941 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -41,8 +41,6 @@ enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX }; #define VRF_NAMSIZ 36 #define NS_NAMSIZ 16 -#define VRF_DEFAULT_NAME "Default-IP-Routing-Table" - /* * The command strings */ @@ -201,8 +199,10 @@ extern int vrf_bitmap_check(vrf_bitmap_t, vrf_id_t); * delete -> Called back when a vrf is being deleted from * the system ( 2 and 3 ) above. */ -extern void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), - int (*disable)(struct vrf *), int (*delete)(struct vrf *)); +extern void vrf_init(int (*create)(struct vrf *vrf), int (*enable)(struct vrf *vrf), + int (*disable)(struct vrf *vrf), int (*delete)(struct vrf *vrf), + int ((*update)(struct vrf *vrf))); + /* * Call vrf_terminate when the protocol is being shutdown */ @@ -236,6 +236,10 @@ extern vrf_id_t vrf_get_default_id(void); /* The default VRF ID */ #define VRF_DEFAULT vrf_get_default_id() +extern void vrf_set_default_name(const char *default_name); +extern const char *vrf_get_default_name(void); +#define VRF_DEFAULT_NAME vrf_get_default_name() + /* VRF is mapped on netns or not ? */ int vrf_is_mapped_on_netns(struct vrf *vrf); diff --git a/lib/vty.c b/lib/vty.c index 748c14f675c3..480137a7a956 100644 --- 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: diff --git a/lib/zclient.c b/lib/zclient.c index b2bafcb7d8f8..c5a48c178afb 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1366,6 +1366,9 @@ static void zclient_vrf_add(struct zclient *zclient, vrf_id_t vrf_id) vrf = vrf_get(vrf_id, vrfname_tmp); vrf->data.l.table_id = data.l.table_id; memcpy(vrf->data.l.netns_name, data.l.netns_name, NS_NAMSIZ); + /* overwrite default vrf */ + if (vrf_id == VRF_DEFAULT) + vrf_set_default_name(vrfname_tmp); vrf_enable(vrf); } diff --git a/lib/zclient.h b/lib/zclient.h index b8ff85e80ff5..cab734ae5e0d 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -91,7 +91,6 @@ typedef enum { ZEBRA_IMPORT_ROUTE_REGISTER, ZEBRA_IMPORT_ROUTE_UNREGISTER, ZEBRA_IMPORT_CHECK_UPDATE, - ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD, ZEBRA_BFD_DEST_REGISTER, ZEBRA_BFD_DEST_DEREGISTER, ZEBRA_BFD_DEST_UPDATE, diff --git a/lib/zebra.h b/lib/zebra.h index b12f6616bae9..d80aa0693550 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -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 */ diff --git a/m4/.gitignore b/m4/.gitignore index 798188b0b93d..357e65588dce 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -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 diff --git a/m4/pkg.m4 b/m4/pkg.m4 index c5b26b52e6cd..a8dcd17c4187 100644 --- 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]) diff --git a/nhrpd/.gitignore b/nhrpd/.gitignore index 3f47381278fd..3d4d56d58937 100644 --- a/nhrpd/.gitignore +++ b/nhrpd/.gitignore @@ -1,2 +1 @@ -!Makefile nhrpd diff --git a/nhrpd/linux.c b/nhrpd/linux.c index 46a327b59f21..85e941e7bacd 100644 --- a/nhrpd/linux.c +++ b/nhrpd/linux.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index af78b3d9ee6a..4c6827cb3d63 100644 --- a/nhrpd/netlink_arp.c +++ b/nhrpd/netlink_arp.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/nhrpd/netlink_gre.c b/nhrpd/netlink_gre.c index 75ecaa70c124..3fdfa9c31307 100644 --- a/nhrpd/netlink_gre.c +++ b/nhrpd/netlink_gre.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/nhrpd/nhrp_event.c b/nhrpd/nhrp_event.c index 7ca9731765d2..9301c2d515eb 100644 --- a/nhrpd/nhrp_event.c +++ b/nhrpd/nhrp_event.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index 3a42712748cd..ccca100db579 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include "zebra.h" #include "linklist.h" diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c index e9f44e855862..f99e566399b5 100644 --- a/nhrpd/nhrp_main.c +++ b/nhrpd/nhrp_main.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include "zebra.h" @@ -130,7 +134,7 @@ int main(int argc, char **argv) /* Library inits. */ master = frr_init(); nhrp_error_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); nhrp_interface_init(); resolver_init(); diff --git a/nhrpd/nhrp_packet.c b/nhrpd/nhrp_packet.c index e62ee1ef7220..a983aa71bca9 100644 --- a/nhrpd/nhrp_packet.c +++ b/nhrpd/nhrp_packet.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include "nhrpd.h" #include "zbuf.h" diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 44271d68ac79..e051830f8524 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include "zebra.h" diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 044529a5cab4..e7b187f3b607 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -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" diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c index 9ed251706937..84053b4b5d68 100644 --- a/nhrpd/nhrp_shortcut.c +++ b/nhrpd/nhrp_shortcut.c @@ -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" diff --git a/nhrpd/resolver.c b/nhrpd/resolver.c index dfa5dc3df053..f017d974dfd5 100644 --- a/nhrpd/resolver.c +++ b/nhrpd/resolver.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include diff --git a/nhrpd/subdir.am b/nhrpd/subdir.am index d66e96822417..758c22e2be87 100644 --- a/nhrpd/subdir.am +++ b/nhrpd/subdir.am @@ -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@ diff --git a/nhrpd/vici.c b/nhrpd/vici.c index 7cd703414ac9..c1a99685f39d 100644 --- a/nhrpd/vici.c +++ b/nhrpd/vici.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/nhrpd/zbuf.c b/nhrpd/zbuf.c index 6e7cad8aec2c..c662295083e7 100644 --- a/nhrpd/zbuf.c +++ b/nhrpd/zbuf.c @@ -7,7 +7,10 @@ * (at your option) any later version. */ -#define _GNU_SOURCE +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/nhrpd/znl.c b/nhrpd/znl.c index 01b2f433af8b..6030987a1bdf 100644 --- a/nhrpd/znl.c +++ b/nhrpd/znl.c @@ -7,6 +7,10 @@ * (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/ospf6d/.gitignore b/ospf6d/.gitignore index 744af2d5ce70..e398b1ca5864 100644 --- a/ospf6d/.gitignore +++ b/ospf6d/.gitignore @@ -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 diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 5af88defeba6..dc7a3f6d4576 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -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)) { diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index 8b720b6d844a..40b3522c3d7c 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -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)); } diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index e88d10ad7e59..d871a8842ecb 100644 --- a/ospf6d/ospf6_lsa.h +++ b/ospf6d/ospf6_lsa.h @@ -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) \ diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 9580d87cf031..eadc856cac25 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -208,7 +208,7 @@ int main(int argc, char *argv[], char *envp[]) /* thread master */ master = frr_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); access_list_init(); prefix_list_init(); diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 0cc7294d6799..4c24f4713189 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -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); } } diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index a099eead49ba..021e825ae33d 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -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); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index fde47c74fef9..ca1a65ff0b29 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -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); diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am index 8a6c4a5ccfd3..d9c29f2651b9 100644 --- a/ospf6d/subdir.am +++ b/ospf6d/subdir.am @@ -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 = \ diff --git a/ospfclient/.gitignore b/ospfclient/.gitignore index 1740b04fbcbc..9be70451f001 100644 --- a/ospfclient/.gitignore +++ b/ospfclient/.gitignore @@ -1,16 +1 @@ -!Makefile -Makefile.in -*.o ospfclient -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.libs -.arch-inventory -.arch-ids -*~ -*.loT -refix diff --git a/ospfclient/subdir.am b/ospfclient/subdir.am index 834d4aaba77e..df7d85a1f5d8 100644 --- a/ospfclient/subdir.am +++ b/ospfclient/subdir.am @@ -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 diff --git a/ospfd/.gitignore b/ospfd/.gitignore index 752c875a6221..fc65db33ee53 100644 --- a/ospfd/.gitignore +++ b/ospfd/.gitignore @@ -1,17 +1,2 @@ -!Makefile -Makefile.in -*.o ospfd ospfd.conf -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.libs -.arch-inventory -.arch-ids -*~ -*.loT -*.a diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c index df41897660ac..594735a08f80 100644 --- a/ospfd/ospf_bfd.c +++ b/ospfd/ospf_bfd.c @@ -312,7 +312,7 @@ void ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params) * ospf_bfd_show_info - Show BFD info structure */ void ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, - uint8_t use_json, int param_only) + bool use_json, int param_only) { if (param_only) bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json, @@ -326,7 +326,7 @@ void ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, * ospf_bfd_interface_show - Show the interface BFD configuration. */ void ospf_bfd_interface_show(struct vty *vty, struct interface *ifp, - json_object *json_interface_sub, uint8_t use_json) + json_object *json_interface_sub, bool use_json) { struct ospf_if_params *params; diff --git a/ospfd/ospf_bfd.h b/ospfd/ospf_bfd.h index 6d7caf4217e5..74385d326852 100644 --- a/ospfd/ospf_bfd.h +++ b/ospfd/ospf_bfd.h @@ -35,13 +35,13 @@ extern void ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, extern void ospf_bfd_interface_show(struct vty *vty, struct interface *ifp, json_object *json_interface_sub, - uint8_t use_json); + bool use_json); extern void ospf_bfd_info_nbr_create(struct ospf_interface *oi, struct ospf_neighbor *nbr); extern void ospf_bfd_show_info(struct vty *vty, void *bfd_info, - json_object *json_obj, uint8_t use_json, + json_object *json_obj, bool use_json, int param_only); extern void ospf_bfd_info_free(void **bfd_info); diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index 19d2e6a95251..755634a2f166 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -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; } diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index 23dae6b08748..220de3234d20 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -24,6 +24,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -2311,7 +2315,7 @@ DEFUN (show_ip_opsf_srdb, int idx = 0; struct in_addr rid; struct sr_node *srn; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); json_object *json = NULL, *json_node_array = NULL; if (!OspfSR.enabled) { diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index fb9770d09ad9..aa877903fc07 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -145,6 +145,8 @@ static struct ospf *ospf_cmd_lookup_ospf(struct vty *vty, if (argv_find(argv, argc, "vrf", &idx_vrf)) { vrf_name = argv[idx_vrf + 1]->arg; + if (vrf_name == NULL || strmatch(vrf_name, VRF_DEFAULT_NAME)) + vrf_name = NULL; if (enable) { /* Allocate VRF aware instance */ ospf = ospf_get(*instance, vrf_name); @@ -2621,7 +2623,7 @@ const char *ospf_abr_type_descr_str[] = {"Unknown", "Standard (RFC2328)", const char *ospf_shortcut_mode_descr_str[] = {"Default", "Enabled", "Disabled"}; static void show_ip_ospf_area(struct vty *vty, struct ospf_area *area, - json_object *json_areas, uint8_t use_json) + json_object *json_areas, bool use_json) { json_object *json_area = NULL; @@ -3241,7 +3243,7 @@ DEFUN (show_ip_ospf, JSON_STR) { struct ospf *ospf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct listnode *node = NULL; char *vrf_name = NULL; bool all_vrf = FALSE; @@ -3261,11 +3263,15 @@ DEFUN (show_ip_ospf, /* vrf input is provided could be all or specific vrf*/ if (vrf_name) { + bool ospf_output = FALSE; + use_vrf = 1; + if (all_vrf) { for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { if (!ospf->oi_running) continue; + ospf_output = TRUE; ret = show_ip_ospf_common(vty, ospf, json, use_vrf); } @@ -3274,21 +3280,34 @@ DEFUN (show_ip_ospf, json_object_to_json_string_ext( json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); - } + } else if (!ospf_output) + vty_out(vty, "%% OSPF instance not found\n"); return ret; } ospf = ospf_lookup_by_inst_name(inst, vrf_name); if ((ospf == NULL) || !ospf->oi_running) { - if (uj) + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); + } else + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; } } else { ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); /* Display default ospf (instance 0) info */ if (ospf == NULL || !ospf->oi_running) { - if (uj) + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); + } else + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; } } @@ -3319,7 +3338,7 @@ DEFUN (show_ip_ospf_instance, int idx_number = 3; struct ospf *ospf; unsigned short instance = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); int ret = CMD_SUCCESS; json_object *json = NULL; @@ -3348,7 +3367,7 @@ DEFUN (show_ip_ospf_instance, static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf, struct interface *ifp, json_object *json_interface_sub, - uint8_t use_json) + bool use_json) { int is_up; struct ospf_neighbor *nbr; @@ -3665,7 +3684,7 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf, static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, char *intf_name, uint8_t use_vrf, - json_object *json, uint8_t use_json) + json_object *json, bool use_json) { struct interface *ifp; struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id); @@ -3758,7 +3777,7 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, static void show_ip_ospf_interface_traffic_sub(struct vty *vty, struct ospf_interface *oi, json_object *json_interface_sub, - uint8_t use_json) + bool use_json) { if (use_json) { json_object_int_add(json_interface_sub, "ifIndex", @@ -3796,7 +3815,7 @@ static void show_ip_ospf_interface_traffic_sub(struct vty *vty, /* OSPFv2 Packet Counters */ static int show_ip_ospf_interface_traffic_common( struct vty *vty, struct ospf *ospf, char *intf_name, json_object *json, - int display_once, uint8_t use_vrf, uint8_t use_json) + int display_once, uint8_t use_vrf, bool use_json) { struct vrf *vrf = NULL; struct interface *ifp = NULL; @@ -3914,7 +3933,7 @@ DEFUN (show_ip_ospf_interface, JSON_STR) { struct ospf *ospf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct listnode *node = NULL; char *vrf_name = NULL, *intf_name = NULL; bool all_vrf = FALSE; @@ -3949,14 +3968,21 @@ DEFUN (show_ip_ospf_interface, json_object_to_json_string_ext( json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); - } + } else if (!ospf) + vty_out(vty, "%% OSPF instance not found\n"); return ret; } ospf = ospf_lookup_by_inst_name(inst, vrf_name); if (ospf == NULL || !ospf->oi_running) { - if (uj) + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); + } else + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; } ret = show_ip_ospf_interface_common(vty, ospf, intf_name, @@ -3966,8 +3992,14 @@ DEFUN (show_ip_ospf_interface, /* Display default ospf (instance 0) info */ ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL || !ospf->oi_running) { - if (uj) + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); + } else + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; } ret = show_ip_ospf_interface_common(vty, ospf, intf_name, @@ -3998,7 +4030,7 @@ DEFUN (show_ip_ospf_instance_interface, int idx_intf = 0; struct ospf *ospf; unsigned short instance = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); char *intf_name = NULL; int ret = CMD_SUCCESS; json_object *json = NULL; @@ -4047,7 +4079,7 @@ DEFUN (show_ip_ospf_interface_traffic, bool all_vrf = FALSE; int inst = 0; int idx_vrf = 0, idx_intf = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); json_object *json = NULL; int ret = CMD_SUCCESS; int display_once = 0; @@ -4123,7 +4155,7 @@ static void show_ip_ospf_neighbour_header(struct vty *vty) static void show_ip_ospf_neighbor_sub(struct vty *vty, struct ospf_interface *oi, - json_object *json, uint8_t use_json) + json_object *json, bool use_json) { struct route_node *rn; struct ospf_neighbor *nbr, *prev_nbr = NULL; @@ -4234,7 +4266,7 @@ static void show_ip_ospf_neighbor_sub(struct vty *vty, } static int show_ip_ospf_neighbor_common(struct vty *vty, struct ospf *ospf, - json_object *json, uint8_t use_json, + json_object *json, bool use_json, uint8_t use_vrf) { struct ospf_interface *oi; @@ -4296,7 +4328,7 @@ DEFUN (show_ip_ospf_neighbor, JSON_STR) { struct ospf *ospf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct listnode *node = NULL; char *vrf_name = NULL; bool all_vrf = FALSE; @@ -4327,23 +4359,36 @@ DEFUN (show_ip_ospf_neighbor, json_object_to_json_string_ext( json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); - } + } else if (!ospf) + vty_out(vty, "OSPF instance not found\n"); return ret; } ospf = ospf_lookup_by_inst_name(inst, vrf_name); if (ospf == NULL || !ospf->oi_running) { - if (uj) + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); + } else + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; } } else { /* Display default ospf (instance 0) info */ ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL || !ospf->oi_running) { - if (uj) + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); + } else + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; } } @@ -4379,7 +4424,7 @@ DEFUN (show_ip_ospf_instance_neighbor, int idx_number = 3; struct ospf *ospf; unsigned short instance = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); json_object *json = NULL; int ret = CMD_SUCCESS; @@ -4406,7 +4451,7 @@ DEFUN (show_ip_ospf_instance_neighbor, } static int show_ip_ospf_neighbor_all_common(struct vty *vty, struct ospf *ospf, - json_object *json, uint8_t use_json, + json_object *json, bool use_json, uint8_t use_vrf) { struct listnode *node; @@ -4509,7 +4554,7 @@ DEFUN (show_ip_ospf_neighbor_all, JSON_STR) { struct ospf *ospf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct listnode *node = NULL; char *vrf_name = NULL; bool all_vrf = FALSE; @@ -4591,7 +4636,7 @@ DEFUN (show_ip_ospf_instance_neighbor_all, int idx_number = 3; struct ospf *ospf; unsigned short instance = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); json_object *json = NULL; int ret = CMD_SUCCESS; @@ -4619,7 +4664,7 @@ DEFUN (show_ip_ospf_instance_neighbor_all, static int show_ip_ospf_neighbor_int_common(struct vty *vty, struct ospf *ospf, int arg_base, struct cmd_token **argv, - uint8_t use_json, uint8_t use_vrf) + bool use_json, uint8_t use_vrf) { struct interface *ifp; struct route_node *rn; @@ -4678,7 +4723,7 @@ DEFUN (show_ip_ospf_neighbor_int, { struct ospf *ospf; int idx_ifname = 4; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct listnode *node = NULL; int ret = CMD_SUCCESS; struct interface *ifp = NULL; @@ -4714,7 +4759,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int, int idx_ifname = 5; struct ospf *ospf; unsigned short instance = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!uj) show_ip_ospf_neighbour_header(vty); @@ -4737,8 +4782,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int, static void show_ip_ospf_nbr_nbma_detail_sub(struct vty *vty, struct ospf_interface *oi, struct ospf_nbr_nbma *nbr_nbma, - uint8_t use_json, - json_object *json) + bool use_json, json_object *json) { char timebuf[OSPF_TIME_DUMP_SIZE]; json_object *json_sub = NULL; @@ -4818,8 +4862,7 @@ static void show_ip_ospf_nbr_nbma_detail_sub(struct vty *vty, static void show_ip_ospf_neighbor_detail_sub(struct vty *vty, struct ospf_interface *oi, struct ospf_neighbor *nbr, - json_object *json, - uint8_t use_json) + json_object *json, bool use_json) { char timebuf[OSPF_TIME_DUMP_SIZE]; json_object *json_sub = NULL; @@ -5035,7 +5078,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty, static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf, int arg_base, struct cmd_token **argv, - uint8_t use_json, uint8_t use_vrf) + bool use_json, uint8_t use_vrf) { struct listnode *node; struct ospf_neighbor *nbr; @@ -5096,7 +5139,7 @@ DEFUN (show_ip_ospf_neighbor_id, JSON_STR) { struct ospf *ospf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct listnode *node = NULL; int ret = CMD_SUCCESS; @@ -5125,7 +5168,7 @@ DEFUN (show_ip_ospf_instance_neighbor_id, int idx_router_id = 5; struct ospf *ospf; unsigned short instance = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); instance = strtoul(argv[idx_number]->arg, NULL, 10); ospf = ospf_lookup_instance(instance); @@ -5141,8 +5184,7 @@ DEFUN (show_ip_ospf_instance_neighbor_id, static int show_ip_ospf_neighbor_detail_common(struct vty *vty, struct ospf *ospf, - json_object *json, - uint8_t use_json, + json_object *json, bool use_json, uint8_t use_vrf) { struct ospf_interface *oi; @@ -5210,7 +5252,7 @@ DEFUN (show_ip_ospf_neighbor_detail, JSON_STR) { struct ospf *ospf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct listnode *node = NULL; char *vrf_name = NULL; bool all_vrf = FALSE; @@ -5290,7 +5332,7 @@ DEFUN (show_ip_ospf_instance_neighbor_detail, int idx_number = 3; struct ospf *ospf; unsigned short instance = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); json_object *json = NULL; int ret = CMD_SUCCESS; @@ -5319,7 +5361,7 @@ DEFUN (show_ip_ospf_instance_neighbor_detail, static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty, struct ospf *ospf, json_object *json, - uint8_t use_json, + bool use_json, uint8_t use_vrf) { struct listnode *node; @@ -5399,7 +5441,7 @@ DEFUN (show_ip_ospf_neighbor_detail_all, JSON_STR) { struct ospf *ospf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct listnode *node = NULL; char *vrf_name = NULL; bool all_vrf = FALSE; @@ -5481,7 +5523,7 @@ DEFUN (show_ip_ospf_instance_neighbor_detail_all, int idx_number = 3; struct ospf *ospf; unsigned short instance = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); json_object *json = NULL; int ret = CMD_SUCCESS; @@ -5511,7 +5553,7 @@ static int show_ip_ospf_neighbor_int_detail_common(struct vty *vty, struct ospf *ospf, int arg_base, struct cmd_token **argv, - uint8_t use_json) + bool use_json) { struct ospf_interface *oi; struct interface *ifp; @@ -5579,17 +5621,22 @@ DEFUN (show_ip_ospf_neighbor_int_detail, JSON_STR) { struct ospf *ospf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct listnode *node = NULL; int ret = CMD_SUCCESS; + bool ospf_output = FALSE; for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { if (!ospf->oi_running) continue; + ospf_output = TRUE; ret = show_ip_ospf_neighbor_int_detail_common(vty, ospf, 0, argv, uj); } + if (!ospf_output) + vty_out(vty, "%% OSPF instance not found\n"); + return ret; } @@ -5609,7 +5656,7 @@ DEFUN (show_ip_ospf_instance_neighbor_int_detail, int idx_ifname = 5; struct ospf *ospf; unsigned short instance = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); instance = strtoul(argv[idx_number]->arg, NULL, 10); ospf = ospf_lookup_instance(instance); @@ -6294,19 +6341,28 @@ DEFUN (show_ip_ospf_database_max, OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); if (vrf_name) { + bool ospf_output = FALSE; + use_vrf = 1; + if (all_vrf) { for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { if (!ospf->oi_running) continue; + ospf_output = TRUE; ret = show_ip_ospf_database_common( vty, ospf, idx_vrf ? 2 : 0, argc, argv, use_vrf); } + + if (!ospf_output) + vty_out(vty, "%% OSPF instance not found\n"); } else { ospf = ospf_lookup_by_inst_name(inst, vrf_name); - if (ospf == NULL || !ospf->oi_running) + if (ospf == NULL || !ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); return CMD_SUCCESS; + } ret = (show_ip_ospf_database_common( vty, ospf, idx_vrf ? 2 : 0, argc, argv, use_vrf)); @@ -6314,8 +6370,11 @@ DEFUN (show_ip_ospf_database_max, } else { /* Display default ospf (instance 0) info */ ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); - if (ospf == NULL || !ospf->oi_running) + if (ospf == NULL || !ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); return CMD_SUCCESS; + } + ret = show_ip_ospf_database_common(vty, ospf, 0, argc, argv, use_vrf); } @@ -6375,16 +6434,22 @@ DEFUN (show_ip_ospf_instance_database, } } else { ospf = ospf_lookup_by_inst_name(inst, vrf_name); - if ((ospf == NULL) || !ospf->oi_running) + if ((ospf == NULL) || !ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); return CMD_SUCCESS; + } + ret = (show_ip_ospf_database_common( vty, ospf, idx ? 2 : 0, argc, argv, use_vrf)); } } else { /* Display default ospf (instance 0) info */ ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); - if (ospf == NULL || !ospf->oi_running) + if (ospf == NULL || !ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); return CMD_SUCCESS; + } + ret = (show_ip_ospf_database_common(vty, ospf, 0, argc, argv, use_vrf)); } @@ -6413,8 +6478,10 @@ DEFUN (show_ip_ospf_instance_database_max, if (ospf == NULL) return CMD_NOT_MY_INSTANCE; - if (!ospf->oi_running) + if (!ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); return CMD_SUCCESS; + } return show_ip_ospf_database_common(vty, ospf, 1, argc, argv, 0); } @@ -6503,8 +6570,11 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router, ospf = ospf_lookup_instance(instance); if (ospf == NULL) return CMD_NOT_MY_INSTANCE; - if (!ospf->oi_running) + if (!ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); return CMD_SUCCESS; + } + return (show_ip_ospf_database_type_adv_router_common( vty, ospf, idx ? 1 : 0, argc, argv, use_vrf)); } @@ -6512,27 +6582,39 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router, OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); if (vrf_name) { + bool ospf_output = FALSE; + use_vrf = 1; + if (all_vrf) { for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { if (!ospf->oi_running) continue; + ospf_output = TRUE; ret = show_ip_ospf_database_type_adv_router_common( vty, ospf, idx ? 1 : 0, argc, argv, use_vrf); } + if (!ospf_output) + vty_out(vty, "%% OSPF instance not found\n"); } else { ospf = ospf_lookup_by_inst_name(inst, vrf_name); - if ((ospf == NULL) || !ospf->oi_running) + if ((ospf == NULL) || !ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); return CMD_SUCCESS; + } + ret = show_ip_ospf_database_type_adv_router_common( vty, ospf, idx ? 1 : 0, argc, argv, use_vrf); } } else { /* Display default ospf (instance 0) info */ ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); - if (ospf == NULL || !ospf->oi_running) + if (ospf == NULL || !ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); return CMD_SUCCESS; + } + ret = show_ip_ospf_database_type_adv_router_common( vty, ospf, idx ? 1 : 0, argc, argv, use_vrf); } @@ -9269,19 +9351,28 @@ DEFUN (show_ip_ospf_border_routers, OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); if (vrf_name) { + bool ospf_output = FALSE; + use_vrf = 1; + if (all_vrf) { for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { if (!ospf->oi_running) continue; + ospf_output = TRUE; ret = show_ip_ospf_border_routers_common( vty, ospf, use_vrf); } + + if (!ospf_output) + vty_out(vty, "%% OSPF instance not found\n"); } else { ospf = ospf_lookup_by_inst_name(inst, vrf_name); - if (ospf == NULL || !ospf->oi_running) + if (ospf == NULL || !ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); return CMD_SUCCESS; + } ret = show_ip_ospf_border_routers_common(vty, ospf, use_vrf); @@ -9289,8 +9380,11 @@ DEFUN (show_ip_ospf_border_routers, } else { /* Display default ospf (instance 0) info */ ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); - if (ospf == NULL || !ospf->oi_running) + if (ospf == NULL || !ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); return CMD_SUCCESS; + } + ret = show_ip_ospf_border_routers_common(vty, ospf, use_vrf); } @@ -9391,7 +9485,7 @@ DEFUN (show_ip_ospf_route, int inst = 0; int idx_vrf = 0; uint8_t use_vrf = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); json_object *json = NULL; if (uj) @@ -9401,11 +9495,15 @@ DEFUN (show_ip_ospf_route, /* vrf input is provided could be all or specific vrf*/ if (vrf_name) { + bool ospf_output = FALSE; + use_vrf = 1; + if (all_vrf) { for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { if (!ospf->oi_running) continue; + ospf_output = TRUE; ret = show_ip_ospf_route_common(vty, ospf, json, use_vrf); } @@ -9415,22 +9513,35 @@ DEFUN (show_ip_ospf_route, vty_out(vty, "%s\n", json_object_to_json_string(json)); json_object_free(json); - } + } else if (!ospf_output) + vty_out(vty, "%% OSPF instance not found\n"); return ret; } ospf = ospf_lookup_by_inst_name(inst, vrf_name); if (ospf == NULL || !ospf->oi_running) { - if (uj) + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); + } else + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; } } else { /* Display default ospf (instance 0) info */ ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL || !ospf->oi_running) { - if (uj) + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); + } else + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; } } @@ -9482,7 +9593,7 @@ DEFUN (show_ip_ospf_vrfs, "Show OSPF VRFs \n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); json_object *json = NULL; json_object *json_vrfs = NULL; struct ospf *ospf = NULL; diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index bfaedf2fe702..d311b4da6b75 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -234,12 +234,10 @@ static struct ospf *ospf_new(unsigned short instance, const char *name) new->instance = instance; new->router_id.s_addr = htonl(0); new->router_id_static.s_addr = htonl(0); - - if (name) { + if (name && !strmatch(name, VRF_DEFAULT_NAME)) { new->vrf_id = VRF_UNKNOWN; /* Freed in ospf_finish_final */ new->name = XSTRDUP(MTYPE_OSPF_TOP, name); - vrf = vrf_lookup_by_name(new->name); if (IS_DEBUG_OSPF_EVENT) zlog_debug( "%s: Create new ospf instance with vrf_name %s vrf_id %u", @@ -381,6 +379,9 @@ struct ospf *ospf_lookup_by_inst_name(unsigned short instance, const char *name) struct ospf *ospf = NULL; struct listnode *node, *nnode; + if (name == NULL || strmatch(name, VRF_DEFAULT_NAME)) + return ospf_lookup_by_vrf_id(VRF_DEFAULT); + for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) { if ((ospf->instance == instance) && ((ospf->name == NULL && name == NULL) @@ -2078,6 +2079,10 @@ static int ospf_vrf_enable(struct vrf *vrf) ospf = ospf_lookup_by_name(vrf->name); if (ospf) { + if (ospf->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) { + XFREE(MTYPE_OSPF_TOP, ospf->name); + ospf->name = NULL; + } old_vrf_id = ospf->vrf_id; /* We have instance configured, link to VRF and make it "up". */ ospf_vrf_link(ospf, vrf); @@ -2149,7 +2154,7 @@ static int ospf_vrf_disable(struct vrf *vrf) void ospf_vrf_init(void) { vrf_init(ospf_vrf_new, ospf_vrf_enable, ospf_vrf_disable, - ospf_vrf_delete); + ospf_vrf_delete, NULL); } void ospf_vrf_terminate(void) diff --git a/ospfd/subdir.am b/ospfd/subdir.am index cd659a9bc925..83074b5ac018 100644 --- a/ospfd/subdir.am +++ b/ospfd/subdir.am @@ -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 = \ diff --git a/pbrd/.gitignore b/pbrd/.gitignore index ff95d885276f..86622ea17416 100644 --- a/pbrd/.gitignore +++ b/pbrd/.gitignore @@ -1,15 +1 @@ -!Makefile -Makefile.in -libpbr.a pbrd -tags -TAGS -.deps -*.o -*.lo -*.la -*.libs -.arch-inventory -.arch-ids -*~ -*.loT diff --git a/pbrd/pbr_main.c b/pbrd/pbr_main.c index ba0962108375..f555ccc056bd 100644 --- a/pbrd/pbr_main.c +++ b/pbrd/pbr_main.c @@ -146,7 +146,7 @@ int main(int argc, char **argv, char **envp) pbr_debug_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); nexthop_group_init(pbr_nhgroup_add_cb, pbr_nhgroup_add_nexthop_cb, pbr_nhgroup_del_nexthop_cb, diff --git a/pbrd/subdir.am b/pbrd/subdir.am index 42ab393218ff..79475590345d 100644 --- a/pbrd/subdir.am +++ b/pbrd/subdir.am @@ -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 = \ diff --git a/pimd/.gitignore b/pimd/.gitignore index 1f56cfaecdab..b1780df75846 100644 --- a/pimd/.gitignore +++ b/pimd/.gitignore @@ -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 diff --git a/pimd/mtracebis.c b/pimd/mtracebis.c index c0d95aeed9e3..65c495eff045 100644 --- a/pimd/mtracebis.c +++ b/pimd/mtracebis.c @@ -17,6 +17,10 @@ * 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" diff --git a/pimd/mtracebis_netlink.c b/pimd/mtracebis_netlink.c index b4bf6bada34b..30ee8f24abd7 100644 --- a/pimd/mtracebis_netlink.c +++ b/pimd/mtracebis_netlink.c @@ -10,6 +10,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef __linux__ #include diff --git a/pimd/mtracebis_routeget.c b/pimd/mtracebis_routeget.c index 8c1cd8d96303..8d974403ac63 100644 --- a/pimd/mtracebis_routeget.c +++ b/pimd/mtracebis_routeget.c @@ -17,6 +17,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef __linux__ #include diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c index f7a217b514f4..466cc60643ac 100644 --- a/pimd/pim_bfd.c +++ b/pimd/pim_bfd.c @@ -64,7 +64,7 @@ void pim_bfd_write_config(struct vty *vty, struct interface *ifp) * pim_bfd_show_info - Show BFD info structure */ void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, - uint8_t use_json, int param_only) + bool use_json, int param_only) { if (param_only) bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json, diff --git a/pimd/pim_bfd.h b/pimd/pim_bfd.h index 83def93b6674..962b727f88f3 100644 --- a/pimd/pim_bfd.h +++ b/pimd/pim_bfd.h @@ -28,7 +28,7 @@ void pim_bfd_init(void); void pim_bfd_write_config(struct vty *vty, struct interface *ifp); void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, - uint8_t use_json, int param_only); + bool use_json, int param_only); void pim_bfd_if_param_set(struct interface *ifp, uint32_t min_rx, uint32_t min_tx, uint8_t detect_mult, int defaults); int pim_bfd_reg_dereg_all_nbr(struct interface *ifp, int command); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 611d8d36811a..5dc86417cfe2 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -432,7 +432,7 @@ static void pim_show_membership_helper(struct vty *vty, json_object_object_add(json_iface, ch_grp_str, json_row); } static void pim_show_membership(struct pim_instance *pim, struct vty *vty, - uint8_t uj) + bool uj) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; @@ -549,7 +549,7 @@ static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, } static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty, - uint8_t uj) + bool uj) { struct interface *ifp; time_t now; @@ -634,7 +634,7 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty, static void igmp_show_interfaces_single(struct pim_instance *pim, struct vty *vty, const char *ifname, - uint8_t uj) + bool uj) { struct igmp_sock *igmp; struct interface *ifp; @@ -894,7 +894,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty) static void pim_show_interfaces_single(struct pim_instance *pim, struct vty *vty, const char *ifname, - uint8_t uj) + bool uj) { struct in_addr ifaddr; struct interface *ifp; @@ -1295,7 +1295,7 @@ static void pim_show_interfaces_single(struct pim_instance *pim, } static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty, - const char *ifname, uint8_t uj) + const char *ifname, bool uj) { struct interface *ifp; struct igmp_stats rx_stats; @@ -1365,7 +1365,7 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty, } static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, - uint8_t uj) + bool uj) { struct interface *ifp; struct listnode *upnode; @@ -1458,7 +1458,7 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, } static void pim_show_interface_traffic(struct pim_instance *pim, - struct vty *vty, uint8_t uj) + struct vty *vty, bool uj) { struct interface *ifp = NULL; struct pim_interface *pim_ifp = NULL; @@ -1538,7 +1538,7 @@ static void pim_show_interface_traffic(struct pim_instance *pim, static void pim_show_interface_traffic_single(struct pim_instance *pim, struct vty *vty, - const char *ifname, uint8_t uj) + const char *ifname, bool uj) { struct interface *ifp = NULL; struct pim_interface *pim_ifp = NULL; @@ -1627,7 +1627,7 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim, static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, struct pim_ifchannel *ch, json_object *json, - time_t now, uint8_t uj) + time_t now, bool uj) { char ch_src_str[INET_ADDRSTRLEN]; char ch_grp_str[INET_ADDRSTRLEN]; @@ -1690,7 +1690,7 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, } } -static void pim_show_join(struct pim_instance *pim, struct vty *vty, uint8_t uj) +static void pim_show_join(struct pim_instance *pim, struct vty *vty, bool uj) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; @@ -1724,7 +1724,7 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, uint8_t uj) } static void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty, - const char *neighbor, uint8_t uj) + const char *neighbor, bool uj) { struct listnode *neighnode; struct interface *ifp; @@ -1933,8 +1933,7 @@ static void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty, } static void pim_show_state(struct pim_instance *pim, struct vty *vty, - const char *src_or_group, const char *group, - uint8_t uj) + const char *src_or_group, const char *group, bool uj) { struct channel_oil *c_oil; struct listnode *node; @@ -2135,7 +2134,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, } static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty, - uint8_t uj) + bool uj) { struct listnode *neighnode; struct interface *ifp; @@ -2331,7 +2330,7 @@ static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, } static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, - uint8_t uj) + bool uj) { struct listnode *upnode; struct pim_upstream *up; @@ -2476,7 +2475,7 @@ static void pim_show_join_desired_helper(struct pim_instance *pim, struct vty *vty, struct pim_interface *pim_ifp, struct pim_ifchannel *ch, - json_object *json, uint8_t uj) + json_object *json, bool uj) { struct pim_upstream *up = ch->upstream; json_object *json_group = NULL; @@ -2532,7 +2531,7 @@ static void pim_show_join_desired_helper(struct pim_instance *pim, } static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, - uint8_t uj) + bool uj) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; @@ -2568,7 +2567,7 @@ static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, } static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, - uint8_t uj) + bool uj) { struct listnode *upnode; struct pim_upstream *up; @@ -2701,7 +2700,7 @@ static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty, uptime_mroute_del, (long long)pim->mroute_del_events); } -static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, uint8_t uj) +static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) { struct listnode *up_node; struct pim_upstream *up; @@ -2821,8 +2820,7 @@ static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty) hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd); } -static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, - uint8_t uj) +static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj) { struct interface *ifp; time_t now; @@ -3373,7 +3371,7 @@ DEFUN (show_ip_igmp_interface, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -3400,7 +3398,7 @@ DEFUN (show_ip_igmp_interface_vrf_all, JSON_STR) { int idx = 2; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -3456,7 +3454,7 @@ DEFUN (show_ip_igmp_join_vrf_all, VRF_CMD_HELP_STR "IGMP static join information\n") { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -3490,7 +3488,7 @@ DEFUN (show_ip_igmp_groups, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -3510,7 +3508,7 @@ DEFUN (show_ip_igmp_groups_vrf_all, IGMP_GROUP_STR JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -3608,7 +3606,7 @@ DEFUN (show_ip_igmp_statistics, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -3715,7 +3713,7 @@ DEFUN (show_ip_pim_interface, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -3742,7 +3740,7 @@ DEFUN (show_ip_pim_interface_vrf_all, JSON_STR) { int idx = 6; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -3781,7 +3779,7 @@ DEFUN (show_ip_pim_join, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -3801,7 +3799,7 @@ DEFUN (show_ip_pim_join_vrf_all, "PIM interface join information\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -3835,7 +3833,7 @@ DEFUN (show_ip_pim_local_membership, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -3859,7 +3857,7 @@ DEFUN (show_ip_pim_neighbor, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -3886,7 +3884,7 @@ DEFUN (show_ip_pim_neighbor_vrf_all, JSON_STR) { int idx = 2; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -3949,7 +3947,7 @@ DEFUN (show_ip_pim_state, const char *group = NULL; int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -3983,7 +3981,7 @@ DEFUN (show_ip_pim_state_vrf_all, const char *src_or_group = NULL; const char *group = NULL; int idx = 2; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -4026,7 +4024,7 @@ DEFUN (show_ip_pim_upstream, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -4046,7 +4044,7 @@ DEFUN (show_ip_pim_upstream_vrf_all, "PIM upstream information\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -4078,7 +4076,7 @@ DEFUN (show_ip_pim_upstream_join_desired, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -4100,7 +4098,7 @@ DEFUN (show_ip_pim_upstream_rpf, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -4122,7 +4120,7 @@ DEFUN (show_ip_pim_rp, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -4142,7 +4140,7 @@ DEFUN (show_ip_pim_rp_vrf_all, "PIM RP information\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -4176,7 +4174,7 @@ DEFUN (show_ip_pim_rpf, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -4196,7 +4194,7 @@ DEFUN (show_ip_pim_rpf_vrf_all, "PIM cached source rpf information\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -4349,7 +4347,7 @@ DEFUN (show_ip_pim_interface_traffic, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -4473,7 +4471,7 @@ DEFUN (show_ip_multicast_vrf_all, VRF_CMD_HELP_STR "Multicast global information\n") { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -4496,7 +4494,7 @@ DEFUN (show_ip_multicast_vrf_all, } static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill, - uint8_t uj) + bool uj) { struct listnode *node; struct channel_oil *c_oil; @@ -4830,7 +4828,7 @@ DEFUN (show_ip_mroute, "Fill in Assumed data\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); bool fill = false; int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); @@ -4855,7 +4853,7 @@ DEFUN (show_ip_mroute_vrf_all, "Fill in Assumed data\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); int idx = 4; struct vrf *vrf; bool first = true; @@ -4963,7 +4961,7 @@ DEFUN (show_ip_mroute_count_vrf_all, VRF_CMD_HELP_STR "Route and packet count data\n") { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -5549,7 +5547,7 @@ DEFUN (no_ip_pim_ssm_prefix_list_name, } static void ip_pim_ssm_show_group_range(struct pim_instance *pim, - struct vty *vty, uint8_t uj) + struct vty *vty, bool uj) { struct pim_ssm *ssm = pim->ssm_info; const char *range_str = @@ -5578,7 +5576,7 @@ DEFUN (show_ip_pim_ssm_range, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -5589,7 +5587,7 @@ DEFUN (show_ip_pim_ssm_range, } static void ip_pim_ssm_show_group_type(struct pim_instance *pim, - struct vty *vty, uint8_t uj, + struct vty *vty, bool uj, const char *group) { struct in_addr group_addr; @@ -5631,7 +5629,7 @@ DEFUN (show_ip_pim_group_type, { int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!vrf) return CMD_WARNING; @@ -7908,7 +7906,7 @@ static void print_empty_json_obj(struct vty *vty) } static void ip_msdp_show_mesh_group(struct pim_instance *pim, struct vty *vty, - uint8_t uj) + bool uj) { struct listnode *mbrnode; struct pim_msdp_mg_mbr *mbr; @@ -7985,7 +7983,7 @@ DEFUN (show_ip_msdp_mesh_group, "MSDP mesh-group information\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); @@ -8007,7 +8005,7 @@ DEFUN (show_ip_msdp_mesh_group_vrf_all, "MSDP mesh-group information\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -8030,7 +8028,7 @@ DEFUN (show_ip_msdp_mesh_group_vrf_all, } static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty, - uint8_t uj) + bool uj) { struct listnode *mpnode; struct pim_msdp_peer *mp; @@ -8084,7 +8082,7 @@ static void ip_msdp_show_peers(struct pim_instance *pim, struct vty *vty, } static void ip_msdp_show_peers_detail(struct pim_instance *pim, struct vty *vty, - const char *peer, uint8_t uj) + const char *peer, bool uj) { struct listnode *mpnode; struct pim_msdp_peer *mp; @@ -8200,7 +8198,7 @@ DEFUN (show_ip_msdp_peer_detail, "peer ip address\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); @@ -8235,7 +8233,7 @@ DEFUN (show_ip_msdp_peer_detail_vrf_all, JSON_STR) { int idx = 2; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -8262,8 +8260,7 @@ DEFUN (show_ip_msdp_peer_detail_vrf_all, return CMD_SUCCESS; } -static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, - uint8_t uj) +static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj) { struct listnode *sanode; struct pim_msdp_sa *sa; @@ -8340,7 +8337,7 @@ static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, const char *grp_str, struct vty *vty, - uint8_t uj, json_object *json) + bool uj, json_object *json) { char rp_str[INET_ADDRSTRLEN]; char peer_str[INET_ADDRSTRLEN]; @@ -8404,7 +8401,7 @@ static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, } static void ip_msdp_show_sa_detail(struct pim_instance *pim, struct vty *vty, - uint8_t uj) + bool uj) { struct listnode *sanode; struct pim_msdp_sa *sa; @@ -8441,7 +8438,7 @@ DEFUN (show_ip_msdp_sa_detail, "Detailed output\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); int idx = 2; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); @@ -8464,7 +8461,7 @@ DEFUN (show_ip_msdp_sa_detail_vrf_all, "Detailed output\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; @@ -8487,7 +8484,7 @@ DEFUN (show_ip_msdp_sa_detail_vrf_all, } static void ip_msdp_show_sa_addr(struct pim_instance *pim, struct vty *vty, - const char *addr, uint8_t uj) + const char *addr, bool uj) { struct listnode *sanode; struct pim_msdp_sa *sa; @@ -8516,7 +8513,7 @@ static void ip_msdp_show_sa_addr(struct pim_instance *pim, struct vty *vty, } static void ip_msdp_show_sa_sg(struct pim_instance *pim, struct vty *vty, - const char *src, const char *grp, uint8_t uj) + const char *src, const char *grp, bool uj) { struct listnode *sanode; struct pim_msdp_sa *sa; @@ -8556,7 +8553,7 @@ DEFUN (show_ip_msdp_sa_sg, "group ip\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; int idx = 2; @@ -8593,7 +8590,7 @@ DEFUN (show_ip_msdp_sa_sg_vrf_all, "group ip\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); struct vrf *vrf; bool first = true; int idx = 2; diff --git a/pimd/pim_igmp_mtrace.c b/pimd/pim_igmp_mtrace.c index 95d0278a3431..1fb624a6a0bd 100644 --- a/pimd/pim_igmp_mtrace.c +++ b/pimd/pim_igmp_mtrace.c @@ -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; diff --git a/pimd/pim_igmp_stats.c b/pimd/pim_igmp_stats.c index 428816e1f095..40851a45299a 100644 --- a/pimd/pim_igmp_stats.c +++ b/pimd/pim_igmp_stats.c @@ -17,6 +17,10 @@ * 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) diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c index 8dc48cc00461..bf8d05d1e117 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -196,7 +196,8 @@ static int pim_vrf_config_write(struct vty *vty) void pim_vrf_init(void) { - vrf_init(pim_vrf_new, pim_vrf_enable, pim_vrf_disable, pim_vrf_delete); + vrf_init(pim_vrf_new, pim_vrf_enable, pim_vrf_disable, + pim_vrf_delete, NULL); vrf_cmd_init(pim_vrf_config_write, &pimd_privs); } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 3db5015e7381..031e527eb34f 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -951,8 +951,7 @@ int pim_rp_check_is_my_ip_address(struct pim_instance *pim, return 0; } -void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, - uint8_t uj) +void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj) { struct rp_info *rp_info; struct rp_info *prev_rp_info = NULL; diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index e0631b27bed0..672a69631907 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -68,7 +68,7 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group); #define RP(P, G) pim_rp_g ((P), (G)) void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, - uint8_t uj); + bool uj); void pim_resolve_rp_nh(struct pim_instance *pim); int pim_rp_list_cmp(void *v1, void *v2); #endif diff --git a/pimd/subdir.am b/pimd/subdir.am index 55d56ece9762..fef8e36577fe 100644 --- a/pimd/subdir.am +++ b/pimd/subdir.am @@ -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 = \ diff --git a/pkgsrc/.gitignore b/pkgsrc/.gitignore index 63e9a66d8f76..c97f963b3da6 100644 --- a/pkgsrc/.gitignore +++ b/pkgsrc/.gitignore @@ -1,8 +1 @@ -Makefile -Makefile.in *.sh -.arch-inventory -.arch-ids -*~ -*.loT - diff --git a/ports/.gitignore b/ports/.gitignore deleted file mode 100644 index dd5bf7c67c9b..000000000000 --- a/ports/.gitignore +++ /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 index dd5bf7c67c9b..000000000000 --- a/ports/files/.gitignore +++ /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 index dd5bf7c67c9b..000000000000 --- a/ports/pkg/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.arch-inventory -.arch-ids - -*~ -*.loT - diff --git a/python/clidef.py b/python/clidef.py index 2e5590964715..a140ce3d5454 100644 --- a/python/clidef.py +++ b/python/clidef.py @@ -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 *' @@ -277,4 +277,4 @@ def do_add(handler, varname, attr = ''): process_file(args.cfile, ofd, dumpfd, args.all_defun) if args.o is not None: - clippy.wrdiff(args.o, ofd, [args.cfile, os.path.realpath(__file__)]) + clippy.wrdiff(args.o, ofd, [args.cfile, os.path.realpath(__file__), sys.executable]) diff --git a/qpb/.gitignore b/qpb/.gitignore deleted file mode 100644 index 17e90443e977..000000000000 --- a/qpb/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -!Makefile -Makefile.in -*.o -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.a -*.libs -.arch-inventory -.arch-ids -*~ -*.loT diff --git a/qpb/qpb_allocator.c b/qpb/qpb_allocator.c index 7e5ba5b0ce40..aca611ba1952 100644 --- a/qpb/qpb_allocator.c +++ b/qpb/qpb_allocator.c @@ -22,6 +22,10 @@ * 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" diff --git a/qpb/subdir.am b/qpb/subdir.am index 3c006fd221b5..75a733f8fcfe 100644 --- a/qpb/subdir.am +++ b/qpb/subdir.am @@ -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 diff --git a/redhat/.gitignore b/redhat/.gitignore index a38f1c06e32a..15804cea0fa7 100644 --- a/redhat/.gitignore +++ b/redhat/.gitignore @@ -1,10 +1,2 @@ zebra.spec frr.spec -Makefile -Makefile.in -.nfs* -.arch-inventory -.arch-ids -*~ -*.loT - diff --git a/redhat/README.rpm_build.md b/redhat/README.rpm_build.md index c461e543d238..a3f095786d81 100644 --- a/redhat/README.rpm_build.md +++ b/redhat/README.rpm_build.md @@ -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 diff --git a/redhat/daemons b/redhat/daemons index de708cf4fd7e..c301a1c23a5d 100644 --- a/redhat/daemons +++ b/redhat/daemons @@ -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 diff --git a/redhat/frr.init b/redhat/frr.init index 2e33aee1730c..47a92eed32cc 100755 --- a/redhat/frr.init +++ b/redhat/frr.init @@ -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 diff --git a/redhat/frr.logrotate b/redhat/frr.logrotate index 654d355fd7ea..df7c5da54e58 100644 --- a/redhat/frr.logrotate +++ b/redhat/frr.logrotate @@ -93,3 +93,11 @@ /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 +} diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 25b48506a6ed..9c232c2bd552 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -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 @@ -594,6 +596,7 @@ fi %{_sbindir}/pbrd %endif %{_sbindir}/isisd +%{_sbindir}/fabricd %if %{with_ldpd} %{_sbindir}/ldpd %endif diff --git a/ripd/.gitignore b/ripd/.gitignore index 177250ca6108..f149501d61b4 100644 --- a/ripd/.gitignore +++ b/ripd/.gitignore @@ -1,17 +1,2 @@ -!Makefile -Makefile.in -*.o ripd ripd.conf -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.libs -.arch-inventory -.arch-ids -*~ -*.loT -*.a diff --git a/ripd/rip_main.c b/ripd/rip_main.c index e5a5c3e227ff..16087c2349ee 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -170,7 +170,7 @@ int main(int argc, char **argv) /* Library initialization. */ rip_error_init(); keychain_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); /* RIP related initialization. */ rip_init(); diff --git a/ripd/subdir.am b/ripd/subdir.am index 612db1a7abc5..0d06e7e653c0 100644 --- a/ripd/subdir.am +++ b/ripd/subdir.am @@ -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 = \ diff --git a/ripngd/.gitignore b/ripngd/.gitignore index 213384d13931..e6a8ee6be2d4 100644 --- a/ripngd/.gitignore +++ b/ripngd/.gitignore @@ -1,17 +1,2 @@ -!Makefile -Makefile.in -*.o ripngd ripngd.conf -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.libs -.arch-inventory -.arch-ids -*~ -*.loT -*.a diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index ef324b001a73..d7d3d245d6af 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -31,7 +31,7 @@ #include "stream.h" #include "zclient.h" #include "command.h" -#include "table.h" +#include "agg_table.h" #include "thread.h" #include "privs.h" #include "vrf.h" @@ -159,14 +159,15 @@ static int ripng_if_ipv6_lladdress_check(struct interface *ifp) static int ripng_if_down(struct interface *ifp) { - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo; struct ripng_interface *ri; struct list *list = NULL; struct listnode *listnode = NULL, *nextnode = NULL; if (ripng) - for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + for (rp = agg_route_top(ripng->table); rp; + rp = agg_route_next(rp)) if ((list = rp->info) != NULL) for (ALL_LIST_ELEMENTS(list, listnode, nextnode, rinfo)) @@ -479,7 +480,7 @@ int ripng_interface_address_delete(int command, struct zclient *zclient, vector ripng_enable_if; /* RIPng enable network table. */ -struct route_table *ripng_enable_network; +struct agg_table *ripng_enable_network; /* Lookup RIPng enable network. */ /* Check wether the interface has at least a connected prefix that @@ -492,7 +493,7 @@ static int ripng_enable_network_lookup_if(struct interface *ifp) for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { struct prefix *p; - struct route_node *n; + struct agg_node *n; p = connected->address; @@ -501,10 +502,10 @@ static int ripng_enable_network_lookup_if(struct interface *ifp) address.prefix = p->u.prefix6; address.prefixlen = IPV6_MAX_BITLEN; - n = route_node_match(ripng_enable_network, - (struct prefix *)&address); + n = agg_node_match(ripng_enable_network, + (struct prefix *)&address); if (n) { - route_unlock_node(n); + agg_unlock_node(n); return 1; } } @@ -521,7 +522,7 @@ static int ripng_enable_network_lookup2(struct connected *connected) p = connected->address; if (p->family == AF_INET6) { - struct route_node *node; + struct agg_node *node; address.family = p->family; address.prefix = p->u.prefix6; @@ -529,11 +530,11 @@ static int ripng_enable_network_lookup2(struct connected *connected) /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within * ripng_enable_network */ - node = route_node_match(ripng_enable_network, - (struct prefix *)&address); + node = agg_node_match(ripng_enable_network, + (struct prefix *)&address); if (node) { - route_unlock_node(node); + agg_unlock_node(node); return 1; } } @@ -544,12 +545,12 @@ static int ripng_enable_network_lookup2(struct connected *connected) /* Add RIPng enable network. */ static int ripng_enable_network_add(struct prefix *p) { - struct route_node *node; + struct agg_node *node; - node = route_node_get(ripng_enable_network, p); + node = agg_node_get(ripng_enable_network, p); if (node->info) { - route_unlock_node(node); + agg_unlock_node(node); return -1; } else node->info = (void *)1; @@ -563,17 +564,17 @@ static int ripng_enable_network_add(struct prefix *p) /* Delete RIPng enable network. */ static int ripng_enable_network_delete(struct prefix *p) { - struct route_node *node; + struct agg_node *node; - node = route_node_lookup(ripng_enable_network, p); + node = agg_node_lookup(ripng_enable_network, p); if (node) { node->info = NULL; /* Unlock info lock. */ - route_unlock_node(node); + agg_unlock_node(node); /* Unlock lookup lock. */ - route_unlock_node(node); + agg_unlock_node(node); return 1; } @@ -771,13 +772,14 @@ void ripng_clean_network() { unsigned int i; char *str; - struct route_node *rn; + struct agg_node *rn; /* ripng_enable_network */ - for (rn = route_top(ripng_enable_network); rn; rn = route_next(rn)) + for (rn = agg_route_top(ripng_enable_network); rn; + rn = agg_route_next(rn)) if (rn->info) { rn->info = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); } /* ripng_enable_if */ @@ -877,12 +879,12 @@ int ripng_network_write(struct vty *vty, int config_mode) { unsigned int i; const char *ifname; - struct route_node *node; + struct agg_node *node; char buf[BUFSIZ]; /* Write enable network. */ - for (node = route_top(ripng_enable_network); node; - node = route_next(node)) + for (node = agg_route_top(ripng_enable_network); node; + node = agg_route_next(node)) if (node->info) { struct prefix *p = &node->p; vty_out(vty, "%s%s/%d\n", @@ -1124,7 +1126,7 @@ void ripng_if_init() hook_register_prio(if_del, 0, ripng_if_delete_hook); /* RIPng enable network init. */ - ripng_enable_network = route_table_init(); + ripng_enable_network = agg_table_init(); /* RIPng enable interface init. */ ripng_enable_if = vector_init(1); diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index e4501d6f80aa..bc81a956d6cf 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -166,7 +166,7 @@ int main(int argc, char **argv) master = frr_init(); /* Library inits. */ - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); /* RIPngd inits. */ ripng_init(); diff --git a/ripngd/ripng_route.c b/ripngd/ripng_route.c index 83cb59c8b897..f66a0b95272b 100644 --- a/ripngd/ripng_route.c +++ b/ripngd/ripng_route.c @@ -22,7 +22,7 @@ #include #include "prefix.h" -#include "table.h" +#include "agg_table.h" #include "memory.h" #include "if.h" #include "vty.h" @@ -44,13 +44,12 @@ void ripng_aggregate_free(struct ripng_aggregate *aggregate) } /* Aggregate count increment check. */ -void ripng_aggregate_increment(struct route_node *child, - struct ripng_info *rinfo) +void ripng_aggregate_increment(struct agg_node *child, struct ripng_info *rinfo) { - struct route_node *np; + struct agg_node *np; struct ripng_aggregate *aggregate; - for (np = child; np; np = np->parent) + for (np = child; np; np = agg_node_parent(np)) if ((aggregate = np->aggregate) != NULL) { aggregate->count++; rinfo->suppress++; @@ -58,13 +57,12 @@ void ripng_aggregate_increment(struct route_node *child, } /* Aggregate count decrement check. */ -void ripng_aggregate_decrement(struct route_node *child, - struct ripng_info *rinfo) +void ripng_aggregate_decrement(struct agg_node *child, struct ripng_info *rinfo) { - struct route_node *np; + struct agg_node *np; struct ripng_aggregate *aggregate; - for (np = child; np; np = np->parent) + for (np = child; np; np = agg_node_parent(np)) if ((aggregate = np->aggregate) != NULL) { aggregate->count--; rinfo->suppress--; @@ -72,14 +70,14 @@ void ripng_aggregate_decrement(struct route_node *child, } /* Aggregate count decrement check for a list. */ -void ripng_aggregate_decrement_list(struct route_node *child, struct list *list) +void ripng_aggregate_decrement_list(struct agg_node *child, struct list *list) { - struct route_node *np; + struct agg_node *np; struct ripng_aggregate *aggregate; struct ripng_info *rinfo = NULL; struct listnode *node = NULL; - for (np = child; np; np = np->parent) + for (np = child; np; np = agg_node_parent(np)) if ((aggregate = np->aggregate) != NULL) aggregate->count -= listcount(list); @@ -90,8 +88,8 @@ void ripng_aggregate_decrement_list(struct route_node *child, struct list *list) /* RIPng routes treatment. */ int ripng_aggregate_add(struct prefix *p) { - struct route_node *top; - struct route_node *rp; + struct agg_node *top; + struct agg_node *rp; struct ripng_info *rinfo; struct ripng_aggregate *aggregate; struct ripng_aggregate *sub; @@ -99,7 +97,7 @@ int ripng_aggregate_add(struct prefix *p) struct listnode *node = NULL; /* Get top node for aggregation. */ - top = route_node_get(ripng->table, p); + top = agg_node_get(ripng->table, p); /* Allocate new aggregate. */ aggregate = ripng_aggregate_new(); @@ -108,7 +106,7 @@ int ripng_aggregate_add(struct prefix *p) top->aggregate = aggregate; /* Suppress routes match to the aggregate. */ - for (rp = route_lock_node(top); rp; rp = route_next_until(rp, top)) { + for (rp = agg_lock_node(top); rp; rp = agg_route_next_until(rp, top)) { /* Suppress normal route. */ if ((list = rp->info) != NULL) for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) { @@ -128,8 +126,8 @@ int ripng_aggregate_add(struct prefix *p) /* Delete RIPng static route. */ int ripng_aggregate_delete(struct prefix *p) { - struct route_node *top; - struct route_node *rp; + struct agg_node *top; + struct agg_node *rp; struct ripng_info *rinfo; struct ripng_aggregate *aggregate; struct ripng_aggregate *sub; @@ -137,13 +135,13 @@ int ripng_aggregate_delete(struct prefix *p) struct listnode *node = NULL; /* Get top node for aggregation. */ - top = route_node_get(ripng->table, p); + top = agg_node_get(ripng->table, p); /* Allocate new aggregate. */ aggregate = top->aggregate; /* Suppress routes match to the aggregate. */ - for (rp = route_lock_node(top); rp; rp = route_next_until(rp, top)) { + for (rp = agg_lock_node(top); rp; rp = agg_route_next_until(rp, top)) { /* Suppress normal route. */ if ((list = rp->info) != NULL) for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) { @@ -160,8 +158,8 @@ int ripng_aggregate_delete(struct prefix *p) top->aggregate = NULL; ripng_aggregate_free(aggregate); - route_unlock_node(top); - route_unlock_node(top); + agg_unlock_node(top); + agg_unlock_node(top); return 0; } diff --git a/ripngd/ripng_route.h b/ripngd/ripng_route.h index dc7d422d1e0f..e402f4a66c85 100644 --- a/ripngd/ripng_route.h +++ b/ripngd/ripng_route.h @@ -42,11 +42,11 @@ struct ripng_aggregate { uint16_t tag_out; }; -extern void ripng_aggregate_increment(struct route_node *rp, +extern void ripng_aggregate_increment(struct agg_node *rp, struct ripng_info *rinfo); -extern void ripng_aggregate_decrement(struct route_node *rp, +extern void ripng_aggregate_decrement(struct agg_node *rp, struct ripng_info *rinfo); -extern void ripng_aggregate_decrement_list(struct route_node *rp, +extern void ripng_aggregate_decrement_list(struct agg_node *rp, struct list *list); extern int ripng_aggregate_add(struct prefix *p); extern int ripng_aggregate_delete(struct prefix *p); diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index 6830e0e926a0..a8cc9ee128b4 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -23,7 +23,7 @@ #include "command.h" #include "prefix.h" -#include "table.h" +#include "agg_table.h" #include "stream.h" #include "memory.h" #include "routemap.h" @@ -37,7 +37,7 @@ struct zclient *zclient = NULL; /* Send ECMP routes to zebra. */ -static void ripng_zebra_ipv6_send(struct route_node *rp, uint8_t cmd) +static void ripng_zebra_ipv6_send(struct agg_node *rp, uint8_t cmd) { struct list *list = (struct list *)rp->info; struct zapi_route api; @@ -100,13 +100,13 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, uint8_t cmd) } /* Add/update ECMP routes to zebra. */ -void ripng_zebra_ipv6_add(struct route_node *rp) +void ripng_zebra_ipv6_add(struct agg_node *rp) { ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD); } /* Delete ECMP routes from zebra. */ -void ripng_zebra_ipv6_delete(struct route_node *rp) +void ripng_zebra_ipv6_delete(struct agg_node *rp) { ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE); } diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 934a87b0751f..d1341d67b749 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -27,7 +27,7 @@ #include "memory.h" #include "if.h" #include "stream.h" -#include "table.h" +#include "agg_table.h" #include "command.h" #include "sockopt.h" #include "distribute.h" @@ -394,7 +394,7 @@ static int ripng_lladdr_check(struct interface *ifp, struct in6_addr *addr) static int ripng_garbage_collect(struct thread *t) { struct ripng_info *rinfo; - struct route_node *rp; + struct agg_node *rp; rinfo = THREAD_ARG(t); rinfo->t_garbage_collect = NULL; @@ -409,7 +409,7 @@ static int ripng_garbage_collect(struct thread *t) listnode_delete(rp->info, rinfo); if (list_isempty((struct list *)rp->info)) { list_delete_and_null((struct list **)&rp->info); - route_unlock_node(rp); + agg_unlock_node(rp); } /* Free RIPng routing information. */ @@ -426,7 +426,7 @@ static void ripng_timeout_update(struct ripng_info *rinfo); */ struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new) { - struct route_node *rp = rinfo_new->rp; + struct agg_node *rp = rinfo_new->rp; struct ripng_info *rinfo = NULL; struct list *list = NULL; @@ -465,7 +465,7 @@ struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new) */ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new) { - struct route_node *rp = rinfo_new->rp; + struct agg_node *rp = rinfo_new->rp; struct list *list = (struct list *)rp->info; struct ripng_info *rinfo = NULL, *tmp_rinfo = NULL; struct listnode *node = NULL, *nextnode = NULL; @@ -522,7 +522,7 @@ struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new) */ struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo) { - struct route_node *rp = rinfo->rp; + struct agg_node *rp = rinfo->rp; struct list *list = (struct list *)rp->info; RIPNG_TIMER_OFF(rinfo->t_timeout); @@ -664,7 +664,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, { int ret; struct prefix_ipv6 p; - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo = NULL, newinfo; struct ripng_interface *ri; struct in6_addr *nexthop; @@ -773,7 +773,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, nexthop = &from->sin6_addr; /* Lookup RIPng routing table. */ - rp = route_node_get(ripng->table, (struct prefix *)&p); + rp = agg_node_get(ripng->table, (struct prefix *)&p); newinfo.rp = rp; newinfo.nexthop = *nexthop; @@ -798,7 +798,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, if (rte->metric > rinfo->metric) { /* New route has a greater metric. * Discard it. */ - route_unlock_node(rp); + agg_unlock_node(rp); return; } @@ -821,7 +821,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, /* Redistributed route check. */ if (rinfo->type != ZEBRA_ROUTE_RIPNG && rinfo->metric != RIPNG_METRIC_INFINITY) { - route_unlock_node(rp); + agg_unlock_node(rp); return; } @@ -830,7 +830,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) || (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) && rinfo->metric != RIPNG_METRIC_INFINITY) { - route_unlock_node(rp); + agg_unlock_node(rp); return; } } @@ -844,7 +844,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, if (rte->metric != RIPNG_METRIC_INFINITY) ripng_ecmp_add(&newinfo); else - route_unlock_node(rp); + agg_unlock_node(rp); } else { /* If there is an existing route, compare the next hop address to the address of the router from which the datagram came. @@ -890,7 +890,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, ripng_timeout_update(rinfo); /* Unlock tempolary lock of the route. */ - route_unlock_node(rp); + agg_unlock_node(rp); } } @@ -899,7 +899,7 @@ void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p, ifindex_t ifindex, struct in6_addr *nexthop, route_tag_t tag) { - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo = NULL, newinfo; struct list *list = NULL; @@ -909,7 +909,7 @@ void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p, if (IN6_IS_ADDR_LOOPBACK(&p->prefix)) return; - rp = route_node_get(ripng->table, (struct prefix *)p); + rp = agg_node_get(ripng->table, (struct prefix *)p); memset(&newinfo, 0, sizeof(struct ripng_info)); newinfo.type = type; @@ -928,7 +928,7 @@ void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p, if (rinfo->type == ZEBRA_ROUTE_CONNECT && rinfo->sub_type == RIPNG_ROUTE_INTERFACE && rinfo->metric != RIPNG_METRIC_INFINITY) { - route_unlock_node(rp); + agg_unlock_node(rp); return; } @@ -941,13 +941,13 @@ void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p, if (type != ZEBRA_ROUTE_RIPNG || ((sub_type != RIPNG_ROUTE_STATIC) && (sub_type != RIPNG_ROUTE_DEFAULT))) { - route_unlock_node(rp); + agg_unlock_node(rp); return; } } ripng_ecmp_replace(&newinfo); - route_unlock_node(rp); + agg_unlock_node(rp); } else ripng_ecmp_add(&newinfo); @@ -972,7 +972,7 @@ void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p, void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p, ifindex_t ifindex) { - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo; if (IN6_IS_ADDR_LINKLOCAL(&p->prefix)) @@ -980,7 +980,7 @@ void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p, if (IN6_IS_ADDR_LOOPBACK(&p->prefix)) return; - rp = route_node_lookup(ripng->table, (struct prefix *)p); + rp = agg_node_lookup(ripng->table, (struct prefix *)p); if (rp) { struct list *list = rp->info; @@ -1014,21 +1014,21 @@ void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p, ripng_event(RIPNG_TRIGGERED_UPDATE, 0); } } - route_unlock_node(rp); + agg_unlock_node(rp); } } /* Withdraw redistributed route. */ void ripng_redistribute_withdraw(int type) { - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo = NULL; struct list *list = NULL; if (!ripng) return; - for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) if ((list = rp->info) != NULL) { rinfo = listgetdata(listhead(list)); if ((rinfo->type == type) @@ -1199,7 +1199,7 @@ static void ripng_request_process(struct ripng_packet *packet, int size, caddr_t lim; struct rte *rte; struct prefix_ipv6 p; - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo; struct ripng_interface *ri; @@ -1255,14 +1255,13 @@ static void ripng_request_process(struct ripng_packet *packet, int size, p.prefixlen = rte->prefixlen; apply_mask_ipv6(&p); - rp = route_node_lookup(ripng->table, - (struct prefix *)&p); + rp = agg_node_lookup(ripng->table, (struct prefix *)&p); if (rp) { rinfo = listgetdata( listhead((struct list *)rp->info)); rte->metric = rinfo->metric; - route_unlock_node(rp); + agg_unlock_node(rp); } else rte->metric = RIPNG_METRIC_INFINITY; } @@ -1361,12 +1360,12 @@ static int ripng_read(struct thread *thread) /* Walk down the RIPng routing table then clear changed flag. */ static void ripng_clear_changed_flag(void) { - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo = NULL; struct list *list = NULL; struct listnode *listnode = NULL; - for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) if ((list = rp->info) != NULL) for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { UNSET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); @@ -1535,7 +1534,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, int route_type) { int ret; - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo; struct ripng_interface *ri; struct ripng_aggregate *aggregate; @@ -1558,7 +1557,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, ripng_rte_list = ripng_rte_new(); - for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { if ((list = rp->info) != NULL && (rinfo = listgetdata(listhead(list))) != NULL && rinfo->suppress == 0) { @@ -1807,9 +1806,9 @@ static int ripng_create(void) ripng->obuf = stream_new(RIPNG_MAX_PACKET_SIZE); /* Initialize RIPng routig table. */ - ripng->table = route_table_init(); - ripng->route = route_table_init(); - ripng->aggregate = route_table_init(); + ripng->table = agg_table_init(); + ripng->route = agg_table_init(); + ripng->aggregate = agg_table_init(); /* Make socket. */ ripng->sock = ripng_make_socket(); @@ -1952,7 +1951,7 @@ DEFUN (show_ipv6_ripng, IPV6_STR "Show RIPng routes\n") { - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo; struct ripng_aggregate *aggregate; struct prefix_ipv6 *p; @@ -1971,7 +1970,7 @@ DEFUN (show_ipv6_ripng, " (i) - interface, (a/S) - aggregated/Suppressed\n\n" " Network Next Hop Via Metric Tag Time\n"); - for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { if ((aggregate = rp->aggregate) != NULL) { p = (struct prefix_ipv6 *)&rp->p; @@ -2125,13 +2124,13 @@ DEFUN (clear_ipv6_rip, IPV6_STR "Clear IPv6 RIP database\n") { - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo; struct list *list; struct listnode *listnode; /* Clear received RIPng routes */ - for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { list = rp->info; if (list == NULL) continue; @@ -2155,7 +2154,7 @@ DEFUN (clear_ipv6_rip, if (list_isempty(list)) { list_delete_and_null(&list); rp->info = NULL; - route_unlock_node(rp); + agg_unlock_node(rp); } } @@ -2206,7 +2205,7 @@ DEFUN (ripng_route, int idx_ipv6addr = 1; int ret; struct prefix_ipv6 p; - struct route_node *rp; + struct agg_node *rp; ret = str2prefix_ipv6(argv[idx_ipv6addr]->arg, (struct prefix_ipv6 *)&p); @@ -2216,10 +2215,10 @@ DEFUN (ripng_route, } apply_mask_ipv6(&p); - rp = route_node_get(ripng->route, (struct prefix *)&p); + rp = agg_node_get(ripng->route, (struct prefix *)&p); if (rp->info) { vty_out(vty, "There is already same static route.\n"); - route_unlock_node(rp); + agg_unlock_node(rp); return CMD_WARNING; } rp->info = (void *)1; @@ -2240,7 +2239,7 @@ DEFUN (no_ripng_route, int idx_ipv6addr = 2; int ret; struct prefix_ipv6 p; - struct route_node *rp; + struct agg_node *rp; ret = str2prefix_ipv6(argv[idx_ipv6addr]->arg, (struct prefix_ipv6 *)&p); @@ -2250,17 +2249,17 @@ DEFUN (no_ripng_route, } apply_mask_ipv6(&p); - rp = route_node_lookup(ripng->route, (struct prefix *)&p); + rp = agg_node_lookup(ripng->route, (struct prefix *)&p); if (!rp) { vty_out(vty, "Can't find static route.\n"); return CMD_WARNING_CONFIG_FAILED; } ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0); - route_unlock_node(rp); + agg_unlock_node(rp); rp->info = NULL; - route_unlock_node(rp); + agg_unlock_node(rp); return CMD_SUCCESS; } @@ -2274,7 +2273,7 @@ DEFUN (ripng_aggregate_address, int idx_ipv6_prefixlen = 1; int ret; struct prefix p; - struct route_node *node; + struct agg_node *node; ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg, (struct prefix_ipv6 *)&p); @@ -2284,10 +2283,10 @@ DEFUN (ripng_aggregate_address, } /* Check aggregate alredy exist or not. */ - node = route_node_get(ripng->aggregate, &p); + node = agg_node_get(ripng->aggregate, &p); if (node->info) { vty_out(vty, "There is already same aggregate route.\n"); - route_unlock_node(node); + agg_unlock_node(node); return CMD_WARNING; } node->info = (void *)1; @@ -2307,7 +2306,7 @@ DEFUN (no_ripng_aggregate_address, int idx_ipv6_prefixlen = 2; int ret; struct prefix p; - struct route_node *rn; + struct agg_node *rn; ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg, (struct prefix_ipv6 *)&p); @@ -2316,14 +2315,14 @@ DEFUN (no_ripng_aggregate_address, return CMD_WARNING_CONFIG_FAILED; } - rn = route_node_lookup(ripng->aggregate, &p); + rn = agg_node_lookup(ripng->aggregate, &p); if (!rn) { vty_out(vty, "Can't find aggregate route.\n"); return CMD_WARNING_CONFIG_FAILED; } - route_unlock_node(rn); + agg_unlock_node(rn); rn->info = NULL; - route_unlock_node(rn); + agg_unlock_node(rn); ripng_aggregate_delete(&p); @@ -2582,7 +2581,7 @@ DEFUN (no_ripng_default_information_originate, /* Update ECMP routes to zebra when ECMP is disabled. */ static void ripng_ecmp_disable(void) { - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo, *tmp_rinfo; struct list *list; struct listnode *node, *nextnode; @@ -2590,7 +2589,7 @@ static void ripng_ecmp_disable(void) if (!ripng) return; - for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) if ((list = rp->info) != NULL && listcount(list) > 1) { rinfo = listgetdata(listhead(list)); if (!ripng_route_rte(rinfo)) @@ -2655,7 +2654,7 @@ static int ripng_config_write(struct vty *vty) int ripng_network_write(struct vty *, int); void ripng_redistribute_write(struct vty *, int); int write = 0; - struct route_node *rp; + struct agg_node *rp; if (ripng) { @@ -2678,7 +2677,8 @@ static int ripng_config_write(struct vty *vty) config_write_ripng_offset_list(vty); /* RIPng aggregate routes. */ - for (rp = route_top(ripng->aggregate); rp; rp = route_next(rp)) + for (rp = agg_route_top(ripng->aggregate); rp; + rp = agg_route_next(rp)) if (rp->info != NULL) vty_out(vty, " aggregate-address %s/%d\n", inet6_ntoa(rp->p.u.prefix6), @@ -2689,7 +2689,8 @@ static int ripng_config_write(struct vty *vty) vty_out(vty, " allow-ecmp\n"); /* RIPng static routes. */ - for (rp = route_top(ripng->route); rp; rp = route_next(rp)) + for (rp = agg_route_top(ripng->route); rp; + rp = agg_route_next(rp)) if (rp->info != NULL) vty_out(vty, " route %s/%d\n", inet6_ntoa(rp->p.u.prefix6), @@ -2811,7 +2812,7 @@ static void ripng_distribute_update_all_wrapper(struct access_list *notused) void ripng_clean() { int i; - struct route_node *rp; + struct agg_node *rp; struct ripng_info *rinfo; struct ripng_aggregate *aggregate; struct list *list = NULL; @@ -2819,7 +2820,8 @@ void ripng_clean() if (ripng) { /* Clear RIPng routes */ - for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + for (rp = agg_route_top(ripng->table); rp; + rp = agg_route_next(rp)) { if ((list = rp->info) != NULL) { rinfo = listgetdata(listhead(list)); if (ripng_route_rte(rinfo)) @@ -2834,13 +2836,13 @@ void ripng_clean() } list_delete_and_null(&list); rp->info = NULL; - route_unlock_node(rp); + agg_unlock_node(rp); } if ((aggregate = rp->aggregate) != NULL) { ripng_aggregate_free(aggregate); rp->aggregate = NULL; - route_unlock_node(rp); + agg_unlock_node(rp); } } @@ -2862,17 +2864,19 @@ void ripng_clean() } /* Static RIPng route configuration. */ - for (rp = route_top(ripng->route); rp; rp = route_next(rp)) + for (rp = agg_route_top(ripng->route); rp; + rp = agg_route_next(rp)) if (rp->info) { rp->info = NULL; - route_unlock_node(rp); + agg_unlock_node(rp); } /* RIPng aggregated prefixes */ - for (rp = route_top(ripng->aggregate); rp; rp = route_next(rp)) + for (rp = agg_route_top(ripng->aggregate); rp; + rp = agg_route_next(rp)) if (rp->info) { rp->info = NULL; - route_unlock_node(rp); + agg_unlock_node(rp); } for (i = 0; i < ZEBRA_ROUTE_MAX; i++) diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 534905d89597..1095a33494e7 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -109,13 +109,13 @@ struct ripng { struct stream *obuf; /* RIPng routing information base. */ - struct route_table *table; + struct agg_table *table; /* RIPng only static route information. */ - struct route_table *route; + struct agg_table *route; /* RIPng aggregate route information. */ - struct route_table *aggregate; + struct agg_table *aggregate; /* RIPng threads. */ struct thread *t_read; @@ -198,7 +198,7 @@ struct ripng_info { uint8_t metric_out; uint16_t tag_out; - struct route_node *rp; + struct agg_node *rp; }; #ifdef notyet @@ -377,8 +377,8 @@ extern void ripng_redistribute_withdraw(int type); extern void ripng_distribute_update_interface(struct interface *); extern void ripng_if_rmap_update_interface(struct interface *); -extern void ripng_zebra_ipv6_add(struct route_node *); -extern void ripng_zebra_ipv6_delete(struct route_node *); +extern void ripng_zebra_ipv6_add(struct agg_node *node); +extern void ripng_zebra_ipv6_delete(struct agg_node *node); extern void ripng_redistribute_clean(void); extern int ripng_redistribute_check(int); diff --git a/ripngd/subdir.am b/ripngd/subdir.am index 1f7ff09d6edc..8f834a1d297d 100644 --- a/ripngd/subdir.am +++ b/ripngd/subdir.am @@ -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 = \ diff --git a/sharpd/.gitignore b/sharpd/.gitignore index cc33cfc188ae..91b9f2e902f8 100644 --- a/sharpd/.gitignore +++ b/sharpd/.gitignore @@ -1,17 +1,2 @@ -Makefile -Makefile.in -*.o -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.a -*.libs -.arch-inventory -.arch-ids -*~ -*.loT sharpd sharpd.conf diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c index f0e6e3db4acf..65b1837f68f1 100644 --- a/sharpd/sharp_main.c +++ b/sharpd/sharp_main.c @@ -146,7 +146,7 @@ int main(int argc, char **argv, char **envp) master = frr_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); access_list_init(); route_map_init(); diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 956da9d4edd4..797e336c2d2d 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -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 (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; } diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index fcb555170b88..286f320874ca 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -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; diff --git a/sharpd/subdir.am b/sharpd/subdir.am index 490a2ba787eb..2a34aecfb3ef 100644 --- a/sharpd/subdir.am +++ b/sharpd/subdir.am @@ -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 = \ diff --git a/snapcraft/.gitignore b/snapcraft/.gitignore index ac7860290b9e..a4796fd730c0 100644 --- a/snapcraft/.gitignore +++ b/snapcraft/.gitignore @@ -3,4 +3,3 @@ parts prime stage frr*.snap -!*/Makefile diff --git a/solaris/.gitignore b/solaris/.gitignore index a2c7946e71ef..3f1a0385a426 100644 --- a/solaris/.gitignore +++ b/solaris/.gitignore @@ -1,5 +1,5 @@ Makefile -Makefile.in +!Makefile.in ?.manifest *.xml pkginfo.*.full @@ -17,6 +17,3 @@ depend.smf frr.init *.pkg *.pkg.gz -*~ -*.loT -*.a \ No newline at end of file diff --git a/solaris/Makefile.am b/solaris/Makefile.in similarity index 60% rename from solaris/Makefile.am rename to solaris/Makefile.in index 5633991d1a36..df9122a1db0d 100644 --- a/solaris/Makefile.am +++ b/solaris/Makefile.in @@ -2,13 +2,56 @@ # XXX This file uses GNU make extensions. -.PHONY: packages +.PHONY: packages all all-files + +all: all-files + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datarootdir = @datarootdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +includedir = @includedir@ +infodir = @infodir@ +mandir = @mandir@ +frr_statedir = @frr_statedir@ + +builddir = @builddir@ +srcdir = @srcdir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ + +enable_user = @enable_user@ +enable_group = @enable_group@ +enable_vty_group = @enable_vty_group@ + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +CONFDATE = @CONFDATE@ + +host_cpu = @host_cpu@ +host_os = @host_os@ + +SED = @SED@ +MAKE = @MAKE@ # the names of the various subpackages, and some convenient # derived variables. pkg_names = daemons dev doc libs smf pkg_frr_daemons = zebra bgpd ospfd ospf6d ripd ripngd -pkg_name_rev = @PACKAGE_VERSION@-@CONFDATE@-@target_os@-@target_cpu@ +pkg_name_rev = $(PACKAGE_VERSION)-$(CONFDATE)-$(host_os)-$(host_cpu) pkg_depends = $(pkg_names:%=depend.%) pkg_packages = $(pkg_names:%=@PACKAGE_TARNAME@-%-$(pkg_name_rev).pkg) pkg_pkginfos = $(pkg_names:%=pkginfo.%.full) @@ -36,29 +79,28 @@ edit = $(SED) \ -e 's,@enable_group\@,$(enable_group),g' \ -e 's,@enable_vty_group\@,$(enable_vty_group),g' \ -e 's,@frr_statedir\@,$(frr_statedir),g' \ - -e 's,[@]PACKAGE_NAME[@],@PACKAGE_NAME@,g' \ - -e 's,[@]PACKAGE_TARNAME[@],@PACKAGE_TARNAME@,g' \ - -e 's,[@]PACKAGE_VERSION[@],@PACKAGE_VERSION@,g' \ - -e 's,[@]PACKAGE_BUGREPORT[@],@PACKAGE_BUGREPORT@,g' \ - -e 's,[@]CONFDATE[@],@CONFDATE@,g' \ - -e 's,[@]target_cpu[@],$(target_cpu),g' \ - -e 's,[@]target_host[@],$(target_host),g' \ - -e 's,[@]target_os[@],$(target_os),g' + -e 's,[@]PACKAGE_NAME[@],$(PACKAGE_NAME),g' \ + -e 's,[@]PACKAGE_TARNAME[@],$(PACKAGE_TARNAME),g' \ + -e 's,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g' \ + -e 's,[@]PACKAGE_BUGREPORT[@],$(PACKAGE_BUGREPORT),g' \ + -e 's,[@]CONFDATE[@],$(CONFDATE),g' \ + -e 's,[@]host_cpu[@],$(host_cpu),g' \ + -e 's,[@]host_os[@],$(host_os),g' # common options for pkgmk -pkg_make_vars = exec_prefix=@exec_prefix@ prefix=@prefix@ \ - builddir=@builddir@ srcdir=@srcdir@ \ - top_builddir=@top_builddir@ top_srcdir=@top_srcdir@ \ - abs_builddir=@abs_builddir@ abs_srcdir=@abs_srcdir@ \ - abs_top_builddir=@abs_top_builddir@ abs_top_srcdir=@abs_top_srcdir@ +pkg_make_vars = exec_prefix=$(exec_prefix) prefix=$(prefix) \ + builddir=$(builddir) srcdir=$(srcdir) \ + top_builddir=$(top_builddir) top_srcdir=$(top_srcdir) \ + abs_builddir=$(abs_builddir) abs_srcdir=$(abs_srcdir) \ + abs_top_builddir=$(abs_top_builddir) abs_top_srcdir=$(abs_top_srcdir) # pkgmk: write the package to spool in build dir, to avoid root dependencies -pkg_make = pkgmk -o -d @abs_builddir@ \ +pkg_make = pkgmk -o -d $(abs_builddir) \ -f $< DESTDIR="$(DESTDIR)/" $(pkg_make_vars) # pkgtrans: write a pkg file stream, shame we cant pipe directly to it from # pkgmk.. -pkg_trans = pkgtrans -s @abs_builddir@ "@abs_builddir@/$@" +pkg_trans = pkgtrans -s $(abs_builddir) "$(abs_builddir)/$@" # pkgmk can only cope with a single pkginfo, cant 'stack' various # pkginfo template files and a package specific pkginfo file in the prototype @@ -95,7 +137,7 @@ frr.init: $(srcdir)/frr.init.in Makefile $(edit) $< > $@ # construct the pkg -@PACKAGE_TARNAME@-%-$(pkg_name_rev).pkg: prototype.% \ +$(PACKAGE_TARNAME)-%-$(pkg_name_rev).pkg: prototype.% \ depend.% frr.init pkginfo.%.full ($(pkg_make) && \ $(pkg_trans) "FRR$*") @@ -103,22 +145,11 @@ frr.init: $(srcdir)/frr.init.in Makefile %.pkg.gz : %.pkg (gzip -c $< > $@) -# pkginfo.package and prototype.package are all built sources -#BUILT_SOURCES = pkginfo.daemons pkginfo.dev pkginfo.doc pkginfo.libs \ -# prototype.daemons prototype.dev prototype.doc prototype.libs -BUILT_SOURCES = $(pkg_pkginfos) pkginfo.tmpl $(pkg_prototypes) \ - $(pkg_manifests) $(pkg_depends) frr.init - -CLEANFILES = $(BUILT_SOURCES) $(pkg_packages) - -EXTRA_DIST = $(pkg_manifests:%=%.in) $(pkg_prototypes:%=%.in) \ - $(pkg_names:%=pkginfo.%.tmpl.in) $(srcdir)/pkginfo.tmpl.in \ - $(pkg_depends:%=%.in) frr.init.in README.txt - pkg-root-install: (cd $(top_builddir) && \ $(MAKE) DESTDIR=$(abs_builddir)/frr-root install) packages: $(pkg_packages) -#nodist_pkgdata_DATA = $(pkg_packages) +all-files: $(pkg_pkginfos) pkginfo.tmpl $(pkg_prototypes) \ + $(pkg_manifests) $(pkg_depends) frr.init diff --git a/solaris/pkginfo.tmpl.in b/solaris/pkginfo.tmpl.in index 89a281ceb682..ffbf9b9cef65 100644 --- a/solaris/pkginfo.tmpl.in +++ b/solaris/pkginfo.tmpl.in @@ -1,4 +1,4 @@ -ARCH="@target_cpu@" +ARCH="@host_cpu@" CATEGORY="system" VERSION="@PACKAGE_VERSION@,REV=@CONFDATE@" VENDOR="http://www.frrouting.org/" diff --git a/solaris/subdir.am b/solaris/subdir.am new file mode 100644 index 000000000000..1d19d56a4d38 --- /dev/null +++ b/solaris/subdir.am @@ -0,0 +1,53 @@ +# +# solaris +# + +.PHONY: solaris/all +if SOLARIS +all: solaris/all +solaris/all: + @make -s -C solaris all +endif + +CLEANFILES += \ + solaris/frr.xml \ + solaris/frr.init \ + solaris/pkginfo.tmpl \ + solaris/prototype.daemons \ + solaris/prototype.dev \ + solaris/prototype.doc \ + solaris/prototype.libs \ + solaris/prototype.smf \ + solaris/pkginfo.daemons.tmpl \ + solaris/pkginfo.dev.tmpl \ + solaris/pkginfo.doc.tmpl \ + solaris/pkginfo.libs.tmpl \ + solaris/pkginfo.smf.tmpl \ + solaris/depend.daemons \ + solaris/depend.dev \ + solaris/depend.doc \ + solaris/depend.libs \ + solaris/depend.smf \ + # end + +EXTRA_DIST += \ + solaris/frr.xml.in \ + solaris/frr.init.in \ + solaris/pkginfo.tmpl.in \ + solaris/prototype.daemons.in \ + solaris/prototype.dev.in \ + solaris/prototype.doc.in \ + solaris/prototype.libs.in \ + solaris/prototype.smf.in \ + solaris/pkginfo.daemons.tmpl.in \ + solaris/pkginfo.dev.tmpl.in \ + solaris/pkginfo.doc.tmpl.in \ + solaris/pkginfo.libs.tmpl.in \ + solaris/pkginfo.smf.tmpl.in \ + solaris/depend.daemons.in \ + solaris/depend.dev.in \ + solaris/depend.doc.in \ + solaris/depend.libs.in \ + solaris/depend.smf.in \ + solaris/README.txt \ + # end diff --git a/staticd/static_nht.c b/staticd/static_nht.c index c6e4587b6aaf..44f7fb79da8d 100644 --- a/staticd/static_nht.c +++ b/staticd/static_nht.c @@ -29,8 +29,8 @@ #include "static_zebra.h" #include "static_nht.h" -void static_nht_update(struct prefix *p, uint32_t nh_num, - afi_t afi, vrf_id_t vrf_id) +void static_nht_update(struct prefix *p, uint32_t nh_num, afi_t afi, + vrf_id_t nh_vrf_id) { struct route_table *stable; struct static_route *si; @@ -40,41 +40,47 @@ void static_nht_update(struct prefix *p, uint32_t nh_num, bool orig; bool reinstall; - vrf = vrf_lookup_by_id(vrf_id); + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + svrf = vrf->info; + if (!svrf) + continue; - if (!vrf || !vrf->info) - return; + stable = static_vrf_static_table(afi, SAFI_UNICAST, svrf); + if (!stable) + continue; - svrf = vrf->info; - stable = static_vrf_static_table(afi, SAFI_UNICAST, svrf); - if (!stable) - return; + for (rn = route_top(stable); rn; rn = route_next(rn)) { + reinstall = false; + for (si = rn->info; si; si = si->next) { + if (si->nh_vrf_id != nh_vrf_id) + continue; - for (rn = route_top(stable); rn; rn = route_next(rn)) { - reinstall = false; - for (si = rn->info; si; si = si->next) { - if (si->type != STATIC_IPV4_GATEWAY && - si->type != STATIC_IPV4_GATEWAY_IFNAME && - si->type != STATIC_IPV6_GATEWAY && - si->type != STATIC_IPV6_GATEWAY_IFNAME) - continue; + if (si->type != STATIC_IPV4_GATEWAY + && si->type != STATIC_IPV4_GATEWAY_IFNAME + && si->type != STATIC_IPV6_GATEWAY + && si->type != STATIC_IPV6_GATEWAY_IFNAME) + continue; - orig = si->nh_valid; - if (p->family == AF_INET && - p->u.prefix4.s_addr == si->addr.ipv4.s_addr) - si->nh_valid = !!nh_num; + orig = si->nh_valid; + if (p->family == AF_INET + && p->u.prefix4.s_addr + == si->addr.ipv4.s_addr) + si->nh_valid = !!nh_num; - if (p->family == AF_INET6 && - memcmp(&p->u.prefix6, &si->addr.ipv6, 16) == 0) - si->nh_valid = !!nh_num; + if (p->family == AF_INET6 + && memcmp(&p->u.prefix6, &si->addr.ipv6, 16) + == 0) + si->nh_valid = !!nh_num; - if (orig != si->nh_valid) - reinstall = true; + if (orig != si->nh_valid) + reinstall = true; - if (reinstall) { - static_zebra_route_add(rn, si, vrf_id, - SAFI_UNICAST, true); - reinstall = false; + if (reinstall) { + static_zebra_route_add( + rn, si, vrf->vrf_id, + SAFI_UNICAST, true); + reinstall = false; + } } } } diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c index 6946f21271e4..ad143209ee0b 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -153,12 +153,18 @@ static int static_vrf_config_write(struct vty *vty) struct vrf *vrf; RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + if (vrf->vrf_id != VRF_DEFAULT) + vty_frame(vty, "vrf %s\n", vrf->name); + static_config(vty, vrf->info, AFI_IP, SAFI_UNICAST, "ip route"); static_config(vty, vrf->info, AFI_IP, SAFI_MULTICAST, "ip mroute"); static_config(vty, vrf->info, AFI_IP6, SAFI_UNICAST, "ipv6 route"); + + if (vrf->vrf_id != VRF_DEFAULT) + vty_endframe(vty, "!\n"); } return 0; @@ -190,7 +196,7 @@ int static_vrf_has_config(struct static_vrf *svrf) void static_vrf_init(void) { vrf_init(static_vrf_new, static_vrf_enable, - static_vrf_disable, static_vrf_delete); + static_vrf_disable, static_vrf_delete, NULL); vrf_cmd_init(static_vrf_config_write, &static_privs); } diff --git a/staticd/static_vty.c b/staticd/static_vty.c index 771d8d1de37a..f697969a7227 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -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; diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index a87dc074dfc0..4692dc00d714 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -35,6 +35,7 @@ #include "nexthop.h" #include "nexthop_group.h" #include "hash.h" +#include "jhash.h" #include "static_vrf.h" #include "static_routes.h" @@ -180,6 +181,9 @@ static void zebra_connected(struct zclient *zclient) struct static_nht_data { struct prefix *nh; + + vrf_id_t nh_vrf_id; + uint32_t refcount; uint8_t nh_num; }; @@ -201,13 +205,18 @@ static int static_zebra_nexthop_update(int command, struct zclient *zclient, memset(&lookup, 0, sizeof(lookup)); lookup.nh = &nhr.prefix; + lookup.nh_vrf_id = vrf_id; nhtd = hash_lookup(static_nht_hash, &lookup); - if (nhtd) + + if (nhtd) { nhtd->nh_num = nhr.nexthop_num; + static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, + nhtd->nh_vrf_id); + } else + zlog_err("No nhtd?"); - static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, vrf_id); return 1; } @@ -219,8 +228,10 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap) static unsigned int static_nht_hash_key(void *data) { struct static_nht_data *nhtd = data; + unsigned int key = 0; - return prefix_hash_key(nhtd->nh); + key = prefix_hash_key(nhtd->nh); + return jhash_1word(nhtd->nh_vrf_id, key); } static int static_nht_hash_cmp(const void *d1, const void *d2) @@ -228,6 +239,9 @@ static int static_nht_hash_cmp(const void *d1, const void *d2) const struct static_nht_data *nhtd1 = d1; const struct static_nht_data *nhtd2 = d2; + if (nhtd1->nh_vrf_id != nhtd2->nh_vrf_id) + return 0; + return prefix_same(nhtd1->nh, nhtd2->nh); } @@ -242,6 +256,7 @@ static void *static_nht_hash_alloc(void *data) prefix_copy(new->nh, copy->nh); new->refcount = 0; new->nh_num = 0; + new->nh_vrf_id = copy->nh_vrf_id; return new; } @@ -293,6 +308,7 @@ void static_zebra_nht_register(struct static_route *si, bool reg) memset(&lookup, 0, sizeof(lookup)); lookup.nh = &p; + lookup.nh_vrf_id = si->nh_vrf_id; si->nh_registered = reg; diff --git a/staticd/subdir.am b/staticd/subdir.am index 3b06a92e22a8..33cc0e20505e 100644 --- a/staticd/subdir.am +++ b/staticd/subdir.am @@ -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 = \ diff --git a/tests/.gitignore b/tests/.gitignore index c8368b39b613..37cd245de08c 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -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 index 000000000000..dd4594febe52 --- /dev/null +++ b/tests/Makefile @@ -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 index a7dec6734821..000000000000 --- a/tests/Makefile.am +++ /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 diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c index fef7d39ff590..83af5e9c6dff 100644 --- a/tests/bgpd/test_capability.c +++ b/tests/bgpd/test_capability.c @@ -913,7 +913,7 @@ int main(void) qobj_init(); master = thread_master_create(NULL); bgp_master_init(master); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_option_set(BGP_OPT_NO_LISTEN); bgp_pthreads_init(); diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c index 8db1cb2ca1d3..603b678cf176 100644 --- a/tests/bgpd/test_mp_attr.c +++ b/tests/bgpd/test_mp_attr.c @@ -1079,7 +1079,7 @@ int main(void) bgp_vty_init(); master = thread_master_create("test mp attr"); bgp_master_init(master); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_option_set(BGP_OPT_NO_LISTEN); bgp_attr_init(); diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c index d8d2286bf7c9..42f7d767597b 100644 --- a/tests/bgpd/test_mpath.c +++ b/tests/bgpd/test_mpath.c @@ -379,7 +379,7 @@ static int global_test_init(void) master = thread_master_create(NULL); zclient = zclient_new_notify(master, &zclient_options_default); bgp_master_init(master); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_option_set(BGP_OPT_NO_LISTEN); if (fileno(stdout) >= 0) diff --git a/tests/bgpd/test_packet.c b/tests/bgpd/test_packet.c index c58a85eed37a..9719aceec99b 100644 --- a/tests/bgpd/test_packet.c +++ b/tests/bgpd/test_packet.c @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) bgp_attr_init(); master = thread_master_create(NULL); bgp_master_init(master); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_option_set(BGP_OPT_NO_LISTEN); if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT)) diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c index 16bd5d96dab5..452245ec16fa 100644 --- a/tests/bgpd/test_peer_attr.c +++ b/tests/bgpd/test_peer_attr.c @@ -1387,7 +1387,7 @@ static void bgp_startup(void) master = thread_master_create(NULL); bgp_master_init(master); bgp_option_set(BGP_OPT_NO_LISTEN); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_init(); bgp_pthreads_run(); } diff --git a/tests/helpers/python/frrtest.py b/tests/helpers/python/frrtest.py index da9e447fc0a7..60bee5c88c71 100644 --- a/tests/helpers/python/frrtest.py +++ b/tests/helpers/python/frrtest.py @@ -176,8 +176,14 @@ def test_refout(self): 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): diff --git a/tests/isisd/test_fuzz_isis_tlv.c b/tests/isisd/test_fuzz_isis_tlv.c index 67a1593500b9..b75c1002d430 100644 --- a/tests/isisd/test_fuzz_isis_tlv.c +++ b/tests/isisd/test_fuzz_isis_tlv.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "test_fuzz_isis_tlv_tests.h" #include @@ -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); diff --git a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz index 4abbe81499be..4a89bda84eac 100644 Binary files a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz and b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz differ diff --git a/tests/isisd/test_isis_vertex_queue.c b/tests/isisd/test_isis_vertex_queue.c index 3e31b833511d..869dd732eb9d 100644 --- a/tests/isisd/test_isis_vertex_queue.c +++ b/tests/isisd/test_isis_vertex_queue.c @@ -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++; }; diff --git a/tests/lib/cli/test_cli.c b/tests/lib/cli/test_cli.c index 4cc15ba23fd8..8f062d8b5efd 100644 --- a/tests/lib/cli/test_cli.c +++ b/tests/lib/cli/test_cli.c @@ -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}", diff --git a/tests/lib/cli/test_cli.py b/tests/lib/cli/test_cli.py index e3c31c2d91fb..7371db283ac3 100644 --- a/tests/lib/cli/test_cli.py +++ b/tests/lib/cli/test_cli.py @@ -2,3 +2,4 @@ class TestCli(frrtest.TestRefOut): program = './test_cli' + built_refout = True diff --git a/tests/ospf6d/test_lsdb.c b/tests/ospf6d/test_lsdb.c index ec0835c71912..24821febe6be 100644 --- a/tests/ospf6d/test_lsdb.c +++ b/tests/ospf6d/test_lsdb.c @@ -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 index 000000000000..739a0e86feca --- /dev/null +++ b/tests/subdir.am @@ -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 diff --git a/tests/test_lblmgr.c b/tests/test_lblmgr.c index c751c0b12d03..652d7618a866 100644 --- a/tests/test_lblmgr.c +++ b/tests/test_lblmgr.c @@ -21,6 +21,10 @@ * 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" diff --git a/tools/.gitignore b/tools/.gitignore index 7bf3be9dbf6f..d400dfe8fa57 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1,10 +1,2 @@ -!Makefile -.arch-inventory -.arch-ids - -*~ -*.loT -.libs -*.o /permutations /ssd diff --git a/tools/etc/iproute2/rt_protos.d/frr.conf b/tools/etc/iproute2/rt_protos.d/frr.conf index 4c6968ac2765..bbb358fc6c5b 100644 --- a/tools/etc/iproute2/rt_protos.d/frr.conf +++ b/tools/etc/iproute2/rt_protos.d/frr.conf @@ -11,3 +11,4 @@ 194 sharp 195 pbr 196 static +197 openfabric diff --git a/tools/frr b/tools/frr index 0b170d33fd62..9c8a8e90433f 100755 --- 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 diff --git a/tools/permutations.c b/tools/permutations.c index 80441753e7a2..c5109dc3e882 100644 --- a/tools/permutations.c +++ b/tools/permutations.c @@ -20,6 +20,10 @@ * 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" diff --git a/tools/start-stop-daemon.c b/tools/start-stop-daemon.c index de58e0a20e2b..cc0315c1307d 100644 --- a/tools/start-stop-daemon.c +++ b/tools/start-stop-daemon.c @@ -25,12 +25,17 @@ * the whole automake/config.h dance. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef HAVE_LXC #define _GNU_SOURCE #include #endif /* HAVE_LXC */ #include +#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(); diff --git a/vtysh/.gitignore b/vtysh/.gitignore index 5856eac25352..c1a39b8a12a4 100644 --- a/vtysh/.gitignore +++ b/vtysh/.gitignore @@ -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 index 000000000000..07e093b0f51d --- /dev/null +++ b/vtysh/Makefile @@ -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 index 936640c83aac..000000000000 --- a/vtysh/Makefile.am +++ /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 diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index 92b5686a945a..0f68e58d62ea 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -29,16 +29,18 @@ print <; 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 index 000000000000..932429a87c8e --- /dev/null +++ b/vtysh/subdir.am @@ -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 diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index c249115fd372..6a92b9081377 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -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 ", "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 (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 ", + "show work-queues ", 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 []", + "write terminal []", "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 []", + "show running-config []", 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); diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index c8e4c025e035..ee980d5128d3 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -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,11 +50,11 @@ 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 +#define VTYSH_VRF VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_STATICD enum vtysh_write_integrated { WRITE_INTEGRATED_UNSPECIFIED, diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index 42f08342c0b2..9f6e20f2be65 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -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) diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 86fa62f474a4..7e979f2c8f39 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -30,6 +30,16 @@ #include #include +/* + * 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 #include "getopt.h" #include "command.h" diff --git a/watchfrr/.gitignore b/watchfrr/.gitignore index b8c020c04cbe..b3f5a6cd9141 100644 --- a/watchfrr/.gitignore +++ b/watchfrr/.gitignore @@ -1,16 +1 @@ -!Makefile -Makefile.in -*.o watchfrr -tags -TAGS -.deps -.nfs* -*.lo -*.la -*.libs -.arch-inventory -.arch-ids -*~ -*.loT - diff --git a/watchfrr/subdir.am b/watchfrr/subdir.am index 931f11ef63a5..f0b49c9a8482 100644 --- a/watchfrr/subdir.am +++ b/watchfrr/subdir.am @@ -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 += \ diff --git a/zebra/.gitignore b/zebra/.gitignore index 4a06756a2d56..41a86e7d753a 100644 --- a/zebra/.gitignore +++ b/zebra/.gitignore @@ -1,15 +1,3 @@ -!Makefile -Makefile.in -*.o zebra zebra.conf client -tags -TAGS -.deps -.nfs* -.libs -.arch-inventory -.arch-ids -*~ -*.loT diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c index 5a58fe1751cb..7ec73ea111cd 100644 --- a/zebra/if_ioctl_solaris.c +++ b/zebra/if_ioctl_solaris.c @@ -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 @@ static int interface_list_ioctl(int af) 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; } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index a15d914243df..0dcf5082a2c9 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -259,6 +259,8 @@ static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type) *zif_type = ZEBRA_IF_VXLAN; else if (strcmp(kind, "macvlan") == 0) *zif_type = ZEBRA_IF_MACVLAN; + else if (strcmp(kind, "veth") == 0) + *zif_type = ZEBRA_IF_VETH; } #define parse_rtattr_nested(tb, max, rta) \ @@ -675,7 +677,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); /* Update link. */ - zebra_if_update_link(ifp, link_ifindex); + zebra_if_update_link(ifp, link_ifindex, ns_id); /* Hardware type and address. */ ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type); @@ -1262,7 +1264,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) ZEBRA_INTERFACE_VRF_LOOPBACK); /* Update link. */ - zebra_if_update_link(ifp, link_ifindex); + zebra_if_update_link(ifp, link_ifindex, ns_id); netlink_interface_update_hw_addr(tb, ifp); diff --git a/zebra/interface.c b/zebra/interface.c index 763931d3503c..32ee1a566aea 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1002,13 +1002,16 @@ void if_refresh(struct interface *ifp) if_get_flags(ifp); } -void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex) +void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex, + ns_id_t ns_id) { struct zebra_if *zif; + if (IS_ZEBRA_IF_VETH(ifp)) + return; zif = (struct zebra_if *)ifp->info; zif->link_ifindex = link_ifindex; - zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), link_ifindex); } @@ -1093,6 +1096,10 @@ static const char *zebra_ziftype_2str(zebra_iftype_t zif_type) return "VRF"; break; + case ZEBRA_IF_VETH: + return "VETH"; + break; + default: return "Unknown"; break; diff --git a/zebra/interface.h b/zebra/interface.h index 9634bfdb3fb8..956d430cf9e9 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -191,6 +191,7 @@ typedef enum { ZEBRA_IF_BRIDGE, /* bridge device */ ZEBRA_IF_VLAN, /* VLAN sub-interface */ ZEBRA_IF_MACVLAN, /* MAC VLAN interface*/ + ZEBRA_IF_VETH, /* VETH interface*/ } zebra_iftype_t; /* Zebra "slave" interface type */ @@ -312,7 +313,10 @@ static inline void zebra_if_set_ziftype(struct interface *ifp, #define IS_ZEBRA_IF_MACVLAN(ifp) \ (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_MACVLAN) -#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \ +#define IS_ZEBRA_IF_VETH(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VETH) + +#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \ (((struct zebra_if *)(ifp->info))->zif_slave_type \ == ZEBRA_IF_SLAVE_BRIDGE) @@ -344,7 +348,8 @@ extern int if_subnet_add(struct interface *, struct connected *); extern int if_subnet_delete(struct interface *, struct connected *); extern int ipv6_address_configured(struct interface *ifp); extern void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id); -extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex); +extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex, + ns_id_t ns_id); extern void vrf_add_update(struct vrf *vrfp); diff --git a/zebra/main.c b/zebra/main.c index 5e7c69382fe9..8db1c48f223b 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -99,6 +99,7 @@ struct option longopts[] = { {"ecmp", required_argument, NULL, 'e'}, {"label_socket", no_argument, NULL, 'l'}, {"retain", no_argument, NULL, 'r'}, + {"vrfdefaultname", required_argument, NULL, 'o'}, #ifdef HAVE_NETLINK {"vrfwnetns", no_argument, NULL, 'n'}, {"nl-bufsize", required_argument, NULL, 's'}, @@ -235,7 +236,7 @@ int main(int argc, char **argv) frr_preinit(&zebra_di, argc, argv); frr_opt_add( - "bakz:e:l:r" + "bakz:e:l:o:r" #ifdef HAVE_NETLINK "s:n" #endif @@ -254,6 +255,7 @@ int main(int argc, char **argv) " -l, --label_socket Socket to external label manager\n" " -k, --keep_kernel Don't delete old routes which were installed by zebra.\n" " -r, --retain When program terminates, retain added route by zebra.\n" + " -o, --vrfdefaultname Set default VRF name.\n" #ifdef HAVE_NETLINK " -n, --vrfwnetns Use NetNS as VRF backend\n" " -s, --nl-bufsize Set netlink receive buffer size\n" @@ -296,6 +298,9 @@ int main(int argc, char **argv) return 1; } break; + case 'o': + vrf_set_default_name(optarg); + break; case 'z': zserv_path = optarg; if (!frr_zclient_addr(&dummy, &dummylen, optarg)) { diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 3683596b4139..8e2cd2e418c3 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -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 diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index c4f21d1504eb..cefd1996a96a 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -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); diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index b3aeaf2f76c1..8e5d7fbdbee5 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -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 diff --git a/zebra/subdir.am b/zebra/subdir.am index 5dc3750315b1..a87fcec41f0e 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -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 diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c index ebd632270c7d..be0f6a23be74 100644 --- a/zebra/zebra_fpm_protobuf.c +++ b/zebra/zebra_fpm_protobuf.c @@ -129,6 +129,7 @@ static inline int add_nexthop(qpb_allocator_t *allocator, Fpm__AddRoute *msg, } // TODO: Use src. + (void)src; return 1; } diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index f7283aed36af..8f48cc5191f6 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -2698,7 +2698,7 @@ void zebra_mpls_lsp_schedule(struct zebra_vrf *zvrf) * (VTY command handler). */ void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf, - mpls_label_t label, uint8_t use_json) + mpls_label_t label, bool use_json) { struct hash *lsp_table; zebra_lsp_t *lsp; @@ -2729,7 +2729,7 @@ void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf, * Display MPLS label forwarding table (VTY command handler). */ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, - uint8_t use_json) + bool use_json) { char buf[BUFSIZ]; json_object *json = NULL; diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 65204a67dc8c..86bee129cfe5 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -349,13 +349,13 @@ void zebra_mpls_lsp_schedule(struct zebra_vrf *zvrf); * (VTY command handler). */ void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf, - mpls_label_t label, uint8_t use_json); + mpls_label_t label, bool use_json); /* * Display MPLS label forwarding table (VTY command handler). */ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, - uint8_t use_json); + bool use_json); /* * Display MPLS LSP configuration of all static LSPs (VTY command handler). diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c index 2e02b12311e6..796aa3f66610 100644 --- a/zebra/zebra_mpls_vty.c +++ b/zebra/zebra_mpls_vty.c @@ -339,7 +339,7 @@ DEFUN (show_mpls_table, JSON_STR) { struct zebra_vrf *zvrf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); zvrf = vrf_info_lookup(VRF_DEFAULT); zebra_mpls_print_lsp_table(vty, zvrf, uj); @@ -357,7 +357,7 @@ DEFUN (show_mpls_table_lsp, { uint32_t label; struct zebra_vrf *zvrf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); zvrf = vrf_info_lookup(VRF_DEFAULT); label = atoi(argv[3]->arg); diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 2b7bf04ec389..12207805d952 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -149,6 +149,41 @@ static int zebra_ns_delete(char *name) return 0; } +static int zebra_ns_notify_self_identify(struct stat *netst) +{ + char net_path[64]; + int netns; + + sprintf(net_path, "/proc/self/ns/net"); + netns = open(net_path, O_RDONLY); + if (netns < 0) + return -1; + if (fstat(netns, netst) < 0) { + close(netns); + return -1; + } + close(netns); + return 0; +} + +static bool zebra_ns_notify_is_default_netns(const char *name) +{ + struct stat default_netns_stat; + struct stat st; + char netnspath[64]; + + if (zebra_ns_notify_self_identify(&default_netns_stat)) + return false; + + memset(&st, 0, sizeof(struct stat)); + snprintf(netnspath, 64, "%s/%s", NS_RUN_DIR, name); + /* compare with local stat */ + if (stat(netnspath, &st) == 0 && + (st.st_dev == default_netns_stat.st_dev) && + (st.st_ino == default_netns_stat.st_ino)) + return true; + return false; +} static int zebra_ns_ready_read(struct thread *t) { @@ -178,6 +213,14 @@ static int zebra_ns_ready_read(struct thread *t) if (err < 0) return zebra_ns_continue_read(zns_info, stop_retry); + if (zebra_ns_notify_is_default_netns(basename(netnspath))) { + zlog_warn( + "NS notify : NS %s is default VRF." + " Updating VRF Name", basename(netnspath)); + vrf_set_default_name(basename(netnspath)); + return zebra_ns_continue_read(zns_info, 1); + } + /* success : close fd and create zns context */ zebra_ns_notify_create_context_from_entry_name(basename(netnspath)); return zebra_ns_continue_read(zns_info, 1); @@ -259,6 +302,13 @@ void zebra_ns_notify_parse(void) dent->d_name); continue; } + if (zebra_ns_notify_is_default_netns(dent->d_name)) { + zlog_warn( + "NS notify : NS %s is default VRF." + " Updating VRF Name", dent->d_name); + vrf_set_default_name(dent->d_name); + continue; + } zebra_ns_notify_create_context_from_entry_name(dent->d_name); } closedir(srcdir); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index ab07549ec26d..2c8fa77c32d9 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -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 " : ""), diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 05ae418b57f0..be8f879246b8 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -282,6 +282,19 @@ static int zebra_vrf_delete(struct vrf *vrf) return 0; } +static int zebra_vrf_update(struct vrf *vrf) +{ + struct zebra_vrf *zvrf = vrf->info; + + assert(zvrf); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("VRF %s id %u, name updated", vrf->name, + zvrf_id(zvrf)); + zebra_vrf_add_update(zvrf); + return 0; +} + + /* Return if this VRF has any FRR configuration or not. * IMPORTANT: This function needs to be updated when additional configuration * is added for a VRF. @@ -491,7 +504,7 @@ static int vrf_config_write(struct vty *vty) void zebra_vrf_init(void) { vrf_init(zebra_vrf_new, zebra_vrf_enable, zebra_vrf_disable, - zebra_vrf_delete); + zebra_vrf_delete, zebra_vrf_update); vrf_cmd_init(vrf_config_write, &zserv_privs); } diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 4f1d5cf6d584..de08e323af11 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -55,7 +55,7 @@ extern int allow_delete; static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, - safi_t safi, bool use_fib, uint8_t use_json, + safi_t safi, bool use_fib, bool use_json, route_tag_t tag, const struct prefix *longer_prefix_p, bool supernets_only, int type, @@ -135,7 +135,7 @@ DEFUN (show_ip_rpf, "Display RPF information for multicast source\n" JSON_STR) { - int uj = use_json(argc, argv); + bool uj = use_json(argc, argv); return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST, false, uj, 0, NULL, false, 0, 0); } @@ -760,8 +760,7 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf, bool use_fib, route_tag_t tag, const struct prefix *longer_prefix_p, bool supernets_only, int type, - unsigned short ospf_instance_id, - uint8_t use_json) + unsigned short ospf_instance_id, bool use_json) { struct route_node *rn; struct route_entry *re; @@ -850,7 +849,7 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf, } static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, - safi_t safi, bool use_fib, uint8_t use_json, + safi_t safi, bool use_fib, bool use_json, route_tag_t tag, const struct prefix *longer_prefix_p, bool supernets_only, int type, @@ -1723,7 +1722,7 @@ DEFUN (show_vrf_vni, struct zebra_vrf *zvrf; json_object *json = NULL; json_object *json_vrfs = NULL; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (uj) { json = json_object_new_object(); @@ -1759,7 +1758,7 @@ DEFUN (show_evpn_global, "EVPN\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); zebra_vxlan_print_evpn(vty, uj); return CMD_SUCCESS; @@ -1774,7 +1773,7 @@ DEFUN (show_evpn_vni, JSON_STR) { struct zebra_vrf *zvrf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); zvrf = vrf_info_lookup(VRF_DEFAULT); zebra_vxlan_print_vnis(vty, zvrf, uj); @@ -1792,7 +1791,7 @@ DEFUN (show_evpn_vni_vni, { struct zebra_vrf *zvrf; vni_t vni; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); vni = strtoul(argv[3]->arg, NULL, 10); zvrf = vrf_info_lookup(VRF_DEFAULT); @@ -1814,7 +1813,7 @@ DEFUN (show_evpn_rmac_vni_mac, { vni_t l3vni = 0; struct ethaddr mac; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); l3vni = strtoul(argv[4]->arg, NULL, 10); if (!prefix_str2mac(argv[6]->arg, &mac)) { @@ -1836,7 +1835,7 @@ DEFUN (show_evpn_rmac_vni, JSON_STR) { vni_t l3vni = 0; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); l3vni = strtoul(argv[4]->arg, NULL, 10); zebra_vxlan_print_rmacs_l3vni(vty, l3vni, uj); @@ -1854,7 +1853,7 @@ DEFUN (show_evpn_rmac_vni_all, "All VNIs\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); zebra_vxlan_print_rmacs_all_l3vni(vty, uj); @@ -1875,7 +1874,7 @@ DEFUN (show_evpn_nh_vni_ip, { vni_t l3vni; struct ipaddr ip; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); l3vni = strtoul(argv[4]->arg, NULL, 10); if (str2ipaddr(argv[6]->arg, &ip) != 0) { @@ -1899,7 +1898,7 @@ DEFUN (show_evpn_nh_vni, JSON_STR) { vni_t l3vni; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); l3vni = strtoul(argv[4]->arg, NULL, 10); zebra_vxlan_print_nh_l3vni(vty, l3vni, uj); @@ -1917,7 +1916,7 @@ DEFUN (show_evpn_nh_vni_all, "All VNIs\n" JSON_STR) { - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); zebra_vxlan_print_nh_all_l3vni(vty, uj); @@ -1936,7 +1935,7 @@ DEFUN (show_evpn_mac_vni, { struct zebra_vrf *zvrf; vni_t vni; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); vni = strtoul(argv[4]->arg, NULL, 10); zvrf = vrf_info_lookup(VRF_DEFAULT); @@ -1955,7 +1954,7 @@ DEFUN (show_evpn_mac_vni_all, JSON_STR) { struct zebra_vrf *zvrf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); zvrf = vrf_info_lookup(VRF_DEFAULT); zebra_vxlan_print_macs_all_vni(vty, zvrf, uj); @@ -1976,7 +1975,7 @@ DEFUN (show_evpn_mac_vni_all_vtep, { struct zebra_vrf *zvrf; struct in_addr vtep_ip; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); if (!inet_aton(argv[6]->arg, &vtep_ip)) { if (!uj) @@ -2030,7 +2029,7 @@ DEFUN (show_evpn_mac_vni_vtep, struct zebra_vrf *zvrf; vni_t vni; struct in_addr vtep_ip; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); vni = strtoul(argv[4]->arg, NULL, 10); if (!inet_aton(argv[6]->arg, &vtep_ip)) { @@ -2056,7 +2055,7 @@ DEFUN (show_evpn_neigh_vni, { struct zebra_vrf *zvrf; vni_t vni; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); vni = strtoul(argv[4]->arg, NULL, 10); zvrf = vrf_info_lookup(VRF_DEFAULT); @@ -2075,7 +2074,7 @@ DEFUN (show_evpn_neigh_vni_all, JSON_STR) { struct zebra_vrf *zvrf; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); zvrf = vrf_info_lookup(VRF_DEFAULT); zebra_vxlan_print_neigh_all_vni(vty, zvrf, uj); @@ -2097,7 +2096,7 @@ DEFUN (show_evpn_neigh_vni_neigh, struct zebra_vrf *zvrf; vni_t vni; struct ipaddr ip; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); vni = strtoul(argv[4]->arg, NULL, 10); if (str2ipaddr(argv[6]->arg, &ip) != 0) { @@ -2125,7 +2124,7 @@ DEFUN (show_evpn_neigh_vni_vtep, struct zebra_vrf *zvrf; vni_t vni; struct in_addr vtep_ip; - uint8_t uj = use_json(argc, argv); + bool uj = use_json(argc, argv); vni = strtoul(argv[4]->arg, NULL, 10); if (!inet_aton(argv[6]->arg, &vtep_ip)) { diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index b0fc0a39bd85..eb1b07170129 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -79,7 +79,7 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt[]); static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, struct ipaddr *ip, uint8_t flags, - uint16_t cmd); + uint32_t seq, uint16_t cmd); static unsigned int neigh_hash_keymake(void *p); static int neigh_cmp(const void *p1, const void *p2); static void *zvni_neigh_alloc(void *p); @@ -93,7 +93,7 @@ static void zvni_neigh_del_all(zebra_vni_t *zvni, int uninstall, int upd_client, static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip); static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip, struct ethaddr *macaddr, - uint8_t flags); + uint8_t flags, uint32_t seq); static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip, struct ethaddr *macaddr, uint8_t flags); @@ -147,7 +147,7 @@ static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client, uint32_t flags); static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr); static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr, - uint8_t flags); + uint8_t flags, uint32_t seq); static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr, uint8_t flags); static zebra_vni_t *zvni_map_vlan(struct interface *ifp, @@ -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); @@ -296,47 +299,60 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json) struct vty *vty; char buf1[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; + const char *type_str; + const char *state_str; + bool flags_present = false; ipaddr2str(&n->ip, buf2, sizeof(buf2)); prefix_mac2str(&n->emac, buf1, sizeof(buf1)); + type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ? + "local" : "remote"; + state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive"; vty = (struct vty *)ctxt; if (json == NULL) { vty_out(vty, "IP: %s\n", ipaddr2str(&n->ip, buf2, sizeof(buf2))); - vty_out(vty, " MAC: %s", + vty_out(vty, " Type: %s\n", type_str); + vty_out(vty, " State: %s\n", state_str); + vty_out(vty, " MAC: %s\n", prefix_mac2str(&n->emac, buf1, sizeof(buf1))); } else { json_object_string_add(json, "ip", buf2); + json_object_string_add(json, "type", type_str); + json_object_string_add(json, "state", state_str); json_object_string_add(json, "mac", buf1); } if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { if (json == NULL) { - vty_out(vty, " Remote VTEP: %s", + vty_out(vty, " Remote VTEP: %s\n", inet_ntoa(n->r_vtep_ip)); } else json_object_string_add(json, "remoteVtep", inet_ntoa(n->r_vtep_ip)); } - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - if (!json) { - vty_out(vty, "\n"); - vty_out(vty, " State: %s", - IS_ZEBRA_NEIGH_ACTIVE(n) ? "Active" - : "Inactive"); - } - } if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) { - if (!json) - vty_out(vty, " Default-gateway"); - else + if (!json) { + vty_out(vty, " Flags: Default-gateway"); + flags_present = true; + } else json_object_boolean_true_add(json, "defaultGateway"); } if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) { - if (!json) - vty_out(vty, " Router"); + if (!json) { + vty_out(vty, + flags_present ? " ,Router" : " Flags: Router"); + flags_present = true; + } + } + if (json == NULL) { + if (flags_present) + vty_out(vty, "\n"); + vty_out(vty, " Local Seq: %u Remote Seq: %u\n", + n->loc_seq, n->rem_seq); + } else { + json_object_int_add(json, "localSequence", n->loc_seq); + json_object_int_add(json, "remoteSequence", n->rem_seq); } - if (json == NULL) - vty_out(vty, "\n"); } /* @@ -350,6 +366,7 @@ static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt) char buf1[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; struct neigh_walk_ctx *wctx = ctxt; + const char *state_str; vty = wctx->vty; json_vni = wctx->json; @@ -360,55 +377,58 @@ static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt) prefix_mac2str(&n->emac, buf1, sizeof(buf1)); ipaddr2str(&n->ip, buf2, sizeof(buf2)); - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) - && !(wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)) { + state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive"; + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) + return; + if (json_vni == NULL) { - vty_out(vty, "%*s %-6s %-17s\n", -wctx->addr_width, - buf2, "local", buf1); + vty_out(vty, "%*s %-6s %-8s %-17s\n", + -wctx->addr_width, buf2, "local", + state_str, buf1); } else { json_object_string_add(json_row, "type", "local"); + json_object_string_add(json_row, "state", state_str); json_object_string_add(json_row, "mac", buf1); + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) + json_object_boolean_true_add( + json_row, "defaultGateway"); + json_object_int_add(json_row, "localSequence", + n->loc_seq); + json_object_int_add(json_row, "remoteSequence", + n->rem_seq); } wctx->count++; - } else { - if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) { - if (IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip)) { - if (json_vni == NULL) { - if (wctx->count == 0) - vty_out(vty, - "%*s %-6s %-17s %-21s\n", - -wctx->addr_width, - "Neighbor", "Type", - "MAC", "Remote VTEP"); - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx->addr_width, buf2, - "remote", buf1, - inet_ntoa(n->r_vtep_ip)); - } else { - json_object_string_add(json_row, "type", - "remote"); - json_object_string_add(json_row, "mac", - buf1); - json_object_string_add( - json_row, "remoteVtep", - inet_ntoa(n->r_vtep_ip)); - } - wctx->count++; - } + } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { + if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) && + !IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip)) + return; + + if (json_vni == NULL) { + if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) && + (wctx->count == 0)) + vty_out(vty, + "%*s %-6s %-8s %-17s %-21s\n", + -wctx->addr_width, "Neighbor", "Type", + "State", "MAC", "Remote VTEP"); + vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n", + -wctx->addr_width, buf2, "remote", state_str, + buf1, inet_ntoa(n->r_vtep_ip)); } else { - if (json_vni == NULL) { - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx->addr_width, buf2, "remote", buf1, - inet_ntoa(n->r_vtep_ip)); - } else { - json_object_string_add(json_row, "type", - "remote"); - json_object_string_add(json_row, "mac", buf1); - json_object_string_add(json_row, "remoteVtep", - inet_ntoa(n->r_vtep_ip)); - } - wctx->count++; + json_object_string_add(json_row, "type", "remote"); + json_object_string_add(json_row, "state", state_str); + json_object_string_add(json_row, "mac", buf1); + json_object_string_add(json_row, "remoteVtep", + inet_ntoa(n->r_vtep_ip)); + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) + json_object_boolean_true_add(json_row, + "defaultGateway"); + json_object_int_add(json_row, "localSequence", + n->loc_seq); + json_object_int_add(json_row, "remoteSequence", + n->rem_seq); } + wctx->count++; } if (json_vni) @@ -461,8 +481,9 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); if (json == NULL) { - vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP", - "Type", "MAC", "Remote VTEP"); + vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n", + -wctx.addr_width, "IP", "Type", + "State", "MAC", "Remote VTEP"); } hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); @@ -535,6 +556,8 @@ static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty, inet_ntoa(zrmac->fwd_info.r_vtep_ip)); json_object_int_add(json, "refCount", rb_host_count(&zrmac->host_rb)); + json_object_int_add(json, "localSequence", zrmac->loc_seq); + json_object_int_add(json, "remoteSequence", zrmac->rem_seq); RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb) json_object_array_add( json_hosts, @@ -588,6 +611,10 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt) vty_out(vty, " Remote-gateway Mac "); vty_out(vty, "\n"); + vty_out(vty, " Local Seq: %u Remote Seq: %u", + mac->loc_seq, mac->rem_seq); + vty_out(vty, "\n"); + /* print all the associated neigh */ vty_out(vty, " Neighbors:\n"); if (!listcount(mac->neigh_list)) @@ -596,11 +623,8 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt) for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) { vty_out(vty, " %s %s\n", ipaddr2str(&n->ip, buf2, sizeof(buf2)), - CHECK_FLAG(n->flags, ZEBRA_MAC_LOCAL) - ? (IS_ZEBRA_NEIGH_ACTIVE(n) - ? "Active" - : "Inactive") - : ""); + (IS_ZEBRA_NEIGH_ACTIVE(n) + ? "Active" : "Inactive")); } } @@ -627,13 +651,15 @@ static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt) if (json_mac_hdr) json_mac = json_object_new_object(); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) - && !(wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)) { + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { struct zebra_ns *zns; ifindex_t ifindex; struct interface *ifp; vlanid_t vid; + if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) + return; + zns = zebra_ns_lookup(NS_DEFAULT); ifindex = mac->fwd_info.local.ifindex; ifp = if_lookup_by_index_per_ns(zns, ifindex); @@ -653,59 +679,46 @@ static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt) else json_object_int_add(json_mac, "vlan", vid); } - if (json_mac_hdr == NULL) + if (json_mac_hdr == NULL) { vty_out(vty, "\n"); - else + } else { + json_object_int_add(json_mac, "localSequence", + mac->loc_seq); + json_object_int_add(json_mac, "remoteSequence", + mac->rem_seq); json_object_object_add(json_mac_hdr, buf1, json_mac); + } + wctx->count++; + } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) { - if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, - &wctx->r_vtep_ip)) { - if (wctx->count == 0) { - if (json_mac_hdr == NULL) { - vty_out(vty, "\nVNI %u\n\n", - wctx->zvni->vni); - vty_out(vty, - "%-17s %-6s %-21s %-5s\n", - "MAC", "Type", - "Intf/Remote VTEP", - "VLAN"); - } - } - if (json_mac_hdr == NULL) - vty_out(vty, "%-17s %-6s %-21s\n", buf1, - "remote", - inet_ntoa(mac->fwd_info - .r_vtep_ip)); - else { - json_object_string_add(json_mac, "type", - "remote"); - json_object_string_add( - json_mac, "remoteVtep", - inet_ntoa(mac->fwd_info - .r_vtep_ip)); - json_object_object_add(json_mac_hdr, - buf1, json_mac); - } - wctx->count++; + + if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) && + !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, + &wctx->r_vtep_ip)) + return; + + if (json_mac_hdr == NULL) { + if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) && + (wctx->count == 0)) { + vty_out(vty, "\nVNI %u\n\n", wctx->zvni->vni); + vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", + "Type", "Intf/Remote VTEP", "VLAN"); } + vty_out(vty, "%-17s %-6s %-21s\n", buf1, "remote", + inet_ntoa(mac->fwd_info.r_vtep_ip)); } else { - if (json_mac_hdr == NULL) - vty_out(vty, "%-17s %-6s %-21s\n", buf1, - "remote", - inet_ntoa(mac->fwd_info.r_vtep_ip)); - else { - json_object_string_add(json_mac, "type", - "remote"); - json_object_string_add( - json_mac, "remoteVtep", + json_object_string_add(json_mac, "type", "remote"); + json_object_string_add(json_mac, "remoteVtep", inet_ntoa(mac->fwd_info.r_vtep_ip)); - json_object_object_add(json_mac_hdr, buf1, - json_mac); - } - wctx->count++; + json_object_object_add(json_mac_hdr, buf1, json_mac); + json_object_int_add(json_mac, "localSequence", + mac->loc_seq); + json_object_int_add(json_mac, "remoteSequence", + mac->rem_seq); } + + wctx->count++; } } @@ -1166,7 +1179,7 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt[]) */ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, struct ipaddr *ip, uint8_t flags, - uint16_t cmd) + uint32_t seq, uint16_t cmd) { char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; @@ -1197,7 +1210,10 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, } else stream_putl(s, 0); /* Just MAC. */ - stream_putc(s, flags); /* sticky mac/gateway mac */ + if (cmd == ZEBRA_MACIP_ADD) { + stream_putc(s, flags); /* sticky mac/gateway mac */ + stream_putl(s, seq); /* sequence number */ + } /* Write packet size. */ @@ -1205,10 +1221,10 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Send MACIP %s flags 0x%x MAC %s IP %s L2-VNI %u to %s", + "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s", (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags, prefix_mac2str(macaddr, buf, sizeof(buf)), - ipaddr2str(ip, buf2, sizeof(buf2)), vni, + ipaddr2str(ip, buf2, sizeof(buf2)), seq, vni, zebra_route_string(client->proto)); if (cmd == ZEBRA_MACIP_ADD) @@ -1393,106 +1409,100 @@ static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip) return n; } -/* Process all neigh associated to a mac upon local mac add event */ -static void zvni_process_neigh_on_local_mac_add(zebra_vni_t *zvni, - zebra_mac_t *zmac) +/* + * Process all neighbors associated with a MAC upon the MAC being learnt + * locally or undergoing any other change (such as sequence number). + */ +static void zvni_process_neigh_on_local_mac_change(zebra_vni_t *zvni, + zebra_mac_t *zmac, + bool seq_change) { zebra_neigh_t *n = NULL; struct listnode *node = NULL; char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("Processing neighbors on local MAC %s %s, VNI %u", + prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)), + seq_change ? "CHANGE" : "ADD", zvni->vni); + + /* Walk all neighbors and mark any inactive local neighbors as + * active and/or update sequence number upon a move, and inform BGP. + * The action for remote neighbors is TBD. + * NOTE: We can't simply uninstall remote neighbors as the kernel may + * accidentally end up deleting a just-learnt local neighbor. + */ for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - /* MAC is learnt locally, program all inactive neigh - * pointing to this mac */ - if (IS_ZEBRA_NEIGH_INACTIVE(n)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "neigh %s (MAC %s) on L2-VNI %u is now ACTIVE", - ipaddr2str(&n->ip, buf2, - sizeof(buf2)), - prefix_mac2str(&n->emac, buf, - sizeof(buf)), - zvni->vni); - + if (IS_ZEBRA_NEIGH_INACTIVE(n) || seq_change) { ZEBRA_NEIGH_SET_ACTIVE(n); + n->loc_seq = zmac->loc_seq; zvni_neigh_send_add_to_client( - zvni->vni, &n->ip, &n->emac, n->flags); - } else { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "neigh %s (MAC %s) on VNI %u should NOT be ACTIVE", - ipaddr2str(&n->ip, buf2, - sizeof(buf2)), - prefix_mac2str(&n->emac, buf, - sizeof(buf)), - zvni->vni); + zvni->vni, &n->ip, &n->emac, + n->flags, n->loc_seq); } - } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { - /* TODO: assume the neigh has moved too ?? */ } } } -/* Process all neigh associated to a mac upon local mac del event */ +/* + * Process all neighbors associated with a local MAC upon the MAC being + * deleted. + */ static void zvni_process_neigh_on_local_mac_del(zebra_vni_t *zvni, zebra_mac_t *zmac) { zebra_neigh_t *n = NULL; struct listnode *node = NULL; char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u", + prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)), + zvni->vni); + + /* Walk all local neighbors and mark as inactive and inform + * BGP, if needed. + * TBD: There is currently no handling for remote neighbors. We + * don't expect them to exist, if they do, do we install the MAC + * as a remote MAC and the neighbor as remote? + */ for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { if (IS_ZEBRA_NEIGH_ACTIVE(n)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE", - ipaddr2str(&n->ip, buf2, - sizeof(buf2)), - prefix_mac2str(&n->emac, buf, - sizeof(buf)), - zvni->vni); - ZEBRA_NEIGH_SET_INACTIVE(n); + n->loc_seq = 0; zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0); } - } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) - && IS_ZEBRA_DEBUG_VXLAN) { - zlog_debug( - "local MAC %s getting deleted on VNI %u has remote neigh %s", - prefix_mac2str(&n->emac, buf, sizeof(buf)), - zvni->vni, - ipaddr2str(&n->ip, buf2, sizeof(buf2))); } } } -/* process all neigh associated to a mac entry upon remote mac add */ +/* + * Process all neighbors associated with a MAC upon the MAC being remotely + * learnt. + */ static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t *zvni, zebra_mac_t *zmac) { zebra_neigh_t *n = NULL; struct listnode *node = NULL; char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u", + prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)), + zvni->vni); + + /* Walk all local neighbors and mark as inactive and inform + * BGP, if needed. + */ for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { if (IS_ZEBRA_NEIGH_ACTIVE(n)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE", - ipaddr2str(&n->ip, buf2, - sizeof(buf2)), - prefix_mac2str(&n->emac, buf, - sizeof(buf)), - zvni->vni); - ZEBRA_NEIGH_SET_INACTIVE(n); + n->loc_seq = 0; zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0); } @@ -1500,25 +1510,14 @@ static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t *zvni, } } -/* process all neigh associated to mac entry upon remote mac del */ +/* + * Process all neighbors associated with a remote MAC upon the MAC being + * deleted. + */ static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t *zvni, zebra_mac_t *zmac) { - zebra_neigh_t *n = NULL; - struct listnode *node = NULL; - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - - for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) - && IS_ZEBRA_DEBUG_VXLAN) { - zlog_debug( - "remote MAC %s getting deleted on VNI %u has local neigh %s", - prefix_mac2str(&n->emac, buf, sizeof(buf)), - zvni->vni, - ipaddr2str(&n->ip, buf2, sizeof(buf2))); - } - } + /* NOTE: Currently a NO-OP. */ } /* @@ -1526,7 +1525,8 @@ static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t *zvni, */ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip, struct ethaddr *macaddr, - uint8_t neigh_flags) + uint8_t neigh_flags, + uint32_t seq) { uint8_t flags = 0; @@ -1537,7 +1537,7 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip, SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags, - ZEBRA_MACIP_ADD); + seq, ZEBRA_MACIP_ADD); } /* @@ -1547,7 +1547,7 @@ static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip, struct ethaddr *macaddr, uint8_t flags) { return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags, - ZEBRA_MACIP_DEL); + 0, ZEBRA_MACIP_DEL); } /* @@ -1578,6 +1578,7 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n) flags = NTF_EXT_LEARNED; if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG) flags |= NTF_ROUTER; + ZEBRA_NEIGH_SET_ACTIVE(n); ret = kernel_add_neigh(vlan_if, &n->ip, &n->emac, flags); #endif return ret; @@ -1609,6 +1610,8 @@ static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n) if (!vlan_if) return -1; + ZEBRA_NEIGH_SET_INACTIVE(n); + n->loc_seq = 0; return kernel_del_neigh(vlan_if, &n->ip); } @@ -1802,6 +1805,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni, /* Set "local" forwarding info. */ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW); + ZEBRA_NEIGH_SET_ACTIVE(n); /* Set Router flag (R-bit) */ if (ip->ipa_type == IPADDR_V6) SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); @@ -1819,7 +1823,8 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni, prefix_mac2str(macaddr, buf, sizeof(buf)), ipaddr2str(ip, buf2, sizeof(buf2)), n->flags); - zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags); + zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, + n->flags, n->loc_seq); return 0; } @@ -1963,11 +1968,15 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, char buf2[INET6_ADDRSTRLEN]; zebra_neigh_t *n = NULL; zebra_mac_t *zmac = NULL, *old_zmac = NULL; + uint32_t old_mac_seq = 0, mac_new_seq = 0; + bool upd_mac_seq = false; + bool neigh_mac_change = false; bool check_rbit = false; - /* create a dummy MAC if the MAC is not already present */ + /* Check if the MAC exists. */ zmac = zvni_mac_lookup(zvni, macaddr); if (!zmac) { + /* create a dummy MAC if the MAC is not already present */ if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( "AUTO MAC %s created for neigh %s on VNI %u", @@ -1985,15 +1994,40 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info)); memset(&zmac->flags, 0, sizeof(uint32_t)); SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO); + } else { + if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) { + /* + * We don't change the MAC to local upon a neighbor + * learn event, we wait for the explicit local MAC + * learn. However, we have to compute its sequence + * number in preparation for when it actually turns + * local. + */ + upd_mac_seq = true; + } } - /* If same entry already exists, it might be a change or it might be a - * move from remote to local. - */ + /* Check if the neighbor exists. */ n = zvni_neigh_lookup(zvni, ip); - if (n) { + if (!n) { + /* New neighbor - create */ + n = zvni_neigh_add(zvni, ip, macaddr); + if (!n) { + flog_err( + ZEBRA_ERR_MAC_ADD_FAILED, + "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u", + ipaddr2str(ip, buf2, sizeof(buf2)), + prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, zvni->vni); + return -1; + } + /* Set "local" forwarding info. */ + SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); + n->ifindex = ifp->ifindex; + check_rbit = true; + } else { if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - + /* If there is no MAC change, BGP isn't interested. */ if (router_flag != (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) ? 1 : 0)) @@ -2007,16 +2041,26 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, n->ifindex = ifp->ifindex; } else { - /* If the MAC has changed, - * need to issue a delete first - * as this means a different MACIP route. - * Also, need to do some unlinking/relinking. + /* If the MAC has changed, need to issue a + * delete first as this means a different + * MACIP route. Also, need to do some + * unlinking/relinking. We also need to + * update the MAC's sequence number + * in different situations. */ - zvni_neigh_send_del_to_client(zvni->vni, &n->ip, - &n->emac, 0); + if (IS_ZEBRA_NEIGH_ACTIVE(n)) + zvni_neigh_send_del_to_client( + zvni->vni, &n->ip, &n->emac, 0); old_zmac = zvni_mac_lookup(zvni, &n->emac); if (old_zmac) { - listnode_delete(old_zmac->neigh_list, n); + old_mac_seq = + CHECK_FLAG(old_zmac->flags, + ZEBRA_MAC_REMOTE) ? + old_zmac->rem_seq : + old_zmac->loc_seq; + neigh_mac_change = upd_mac_seq = true; + listnode_delete( + old_zmac->neigh_list, n); zvni_deref_ip2mac(zvni, old_zmac, 0); } @@ -2028,14 +2072,21 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, listnode_add_sort(zmac->neigh_list, n); } - } else - /* Neighbor has moved from remote to local. */ - { - /* If MAC has changed, do the unlink/link */ + } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { + /* + * Neighbor has moved from remote to local. Its + * MAC could have also changed as part of the move. + */ if (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) != 0) { old_zmac = zvni_mac_lookup(zvni, &n->emac); if (old_zmac) { + old_mac_seq = CHECK_FLAG( + old_zmac->flags, + ZEBRA_MAC_REMOTE) ? + old_zmac->rem_seq : + old_zmac->loc_seq; + neigh_mac_change = upd_mac_seq = true; listnode_delete(old_zmac->neigh_list, n); zvni_deref_ip2mac(zvni, old_zmac, 0); @@ -2053,22 +2104,19 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, n->ifindex = ifp->ifindex; check_rbit = true; } - } else { - /* New neighbor - create */ - n = zvni_neigh_add(zvni, ip, macaddr); - if (!n) { - flog_err( - ZEBRA_ERR_MAC_ADD_FAILED, - "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u", - ipaddr2str(ip, buf2, sizeof(buf2)), - prefix_mac2str(macaddr, buf, sizeof(buf)), - ifp->name, ifp->ifindex, zvni->vni); - return -1; - } - /* Set "local" forwarding info. */ - SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); - n->ifindex = ifp->ifindex; - check_rbit = true; + } + + /* If MAC was previously remote, or the neighbor had a different + * MAC earlier, recompute the sequence number. + */ + if (upd_mac_seq) { + uint32_t seq1, seq2; + + seq1 = CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE) ? + zmac->rem_seq + 1 : zmac->loc_seq; + seq2 = neigh_mac_change ? old_mac_seq + 1 : 0; + mac_new_seq = zmac->loc_seq < MAX(seq1, seq2) ? + MAX(seq1, seq2) : zmac->loc_seq; } /*Mark Router flag (R-bit) */ @@ -2078,38 +2126,40 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); /* Before we program this in BGP, we need to check if MAC is locally - * learnt as well + * learnt. If not, force neighbor to be inactive and reset its seq. */ if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "Skipping neigh %s add to client as MAC %s is not local on VNI %u with flags 0x%x", - ipaddr2str(ip, buf2, sizeof(buf2)), - prefix_mac2str(macaddr, buf, sizeof(buf)), - zvni->vni, n->flags); - + ZEBRA_NEIGH_SET_INACTIVE(n); + n->loc_seq = 0; + zmac->loc_seq = mac_new_seq; return 0; } - if (!check_rbit) { + if (!check_rbit) + return 0; + + /* If the MAC's sequence number has changed, inform the MAC and all + * neighbors associated with the MAC to BGP, else just inform this + * neighbor. + */ + if (upd_mac_seq && zmac->loc_seq != mac_new_seq) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "Skipping neigh %s with MAC %s on VNI %u add to client as router flag is not set.", - ipaddr2str(ip, buf2, sizeof(buf2)), - prefix_mac2str(macaddr, buf, sizeof(buf)), - zvni->vni); + zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u", + prefix_mac2str(macaddr, buf, sizeof(buf)), + zvni->vni, zmac->loc_seq, mac_new_seq); + zmac->loc_seq = mac_new_seq; + if (zvni_mac_send_add_to_client(zvni->vni, macaddr, + zmac->flags, zmac->loc_seq)) + return -1; + zvni_process_neigh_on_local_mac_change(zvni, zmac, 1); return 0; } - /* Inform BGP. */ - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x", - ipaddr2str(ip, buf2, sizeof(buf2)), - prefix_mac2str(macaddr, buf, sizeof(buf)), - zvni->vni, n->flags); ZEBRA_NEIGH_SET_ACTIVE(n); + n->loc_seq = zmac->loc_seq; - return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags); + return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, + n->flags, n->loc_seq); } static int zvni_remote_neigh_update(zebra_vni_t *zvni, @@ -2325,7 +2375,7 @@ static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac) * Inform BGP about local MAC addition. */ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr, - uint8_t mac_flags) + uint8_t mac_flags, uint32_t seq) { uint8_t flags = 0; @@ -2335,7 +2385,7 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr, SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags, - ZEBRA_MACIP_ADD); + seq, ZEBRA_MACIP_ADD); } /* @@ -2352,7 +2402,7 @@ static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr, SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags, - ZEBRA_MACIP_DEL); + 0, ZEBRA_MACIP_DEL); } /* @@ -3976,69 +4026,442 @@ static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni, return 0; } -/* Public functions */ - -int is_l3vni_for_prefix_routes_only(vni_t vni) +/* Process a remote MACIP add from BGP. */ +static void process_remote_macip_add(vni_t vni, + struct ethaddr *macaddr, + uint16_t ipa_len, + struct ipaddr *ipaddr, + uint8_t flags, + uint32_t seq, + struct in_addr vtep_ip) { - zebra_l3vni_t *zl3vni = NULL; - - zl3vni = zl3vni_lookup(vni); - if (!zl3vni) - return 0; - - return CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? 1 : 0; -} + zebra_vni_t *zvni; + zebra_vtep_t *zvtep; + zebra_mac_t *mac, *old_mac; + zebra_neigh_t *n = NULL; + int update_mac = 0, update_neigh = 0; + char buf[ETHER_ADDR_STRLEN]; + char buf1[INET6_ADDRSTRLEN]; + struct interface *ifp = NULL; + struct zebra_if *zif = NULL; + uint32_t tmp_seq; + uint8_t sticky = 0; + uint8_t remote_gw = 0; + uint8_t router_flag = 0; -/* handle evpn route in vrf table */ -void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, struct ethaddr *rmac, - struct ipaddr *vtep_ip, - struct prefix *host_prefix) -{ - zebra_l3vni_t *zl3vni = NULL; - struct ipaddr ipv4_vtep; + /* Locate VNI hash entry - expected to exist. */ + zvni = zvni_lookup(vni); + if (!zvni) { + zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni); + return; + } - zl3vni = zl3vni_from_vrf(vrf_id); - if (!zl3vni || !is_l3vni_oper_up(zl3vni)) + ifp = zvni->vxlan_if; + if (ifp) + zif = ifp->info; + if (!ifp || + !if_is_operative(ifp) || + !zif || + !zif->brslave_info.br_if) { + zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info", + vni); return; + } - /* - * add the next hop neighbor - - * neigh to be installed is the ipv6 nexthop neigh + /* The remote VTEP specified should normally exist, but it is + * possible that when peering comes up, peer may advertise MACIP + * routes before advertising type-3 routes. */ - zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix); + zvtep = zvni_vtep_find(zvni, &vtep_ip); + if (!zvtep) { + if (zvni_vtep_add(zvni, &vtep_ip) == NULL) { + flog_err( + ZEBRA_ERR_VTEP_ADD_FAILED, + "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD", + vni, zvni); + return; + } - /* - * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4 - * address. Rmac is programmed against the ipv4 vtep because we only - * support ipv4 tunnels in the h/w right now - */ - memset(&ipv4_vtep, 0, sizeof(struct ipaddr)); - ipv4_vtep.ipa_type = IPADDR_V4; - if (vtep_ip->ipa_type == IPADDR_V6) - ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6, - &(ipv4_vtep.ipaddr_v4)); - else - memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4, - sizeof(struct in_addr)); + zvni_vtep_install(zvni, &vtep_ip); + } - /* - * add the rmac - remote rmac to be installed is against the ipv4 - * nexthop address - */ - zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep, host_prefix); -} + sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); + remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + router_flag = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); -/* handle evpn vrf route delete */ -void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id, - struct ipaddr *vtep_ip, - struct prefix *host_prefix) -{ - zebra_l3vni_t *zl3vni = NULL; - zebra_neigh_t *nh = NULL; - zebra_mac_t *zrmac = NULL; + mac = zvni_mac_lookup(zvni, macaddr); - zl3vni = zl3vni_from_vrf(vrf_id); - if (!zl3vni) + /* Ignore if the mac is already present as a gateway mac */ + if (mac && + CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) && + CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC", + vni, + prefix_mac2str(macaddr, buf, sizeof(buf)), + ipa_len ? " IP " : "", + ipa_len ? + ipaddr2str(ipaddr, buf1, sizeof(buf1)) : ""); + return; + } + + /* check if the remote MAC is unknown or has a change. + * If so, that needs to be updated first. Note that client could + * install MAC and MACIP separately or just install the latter. + */ + if (!mac + || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) + || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0) != sticky + || (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? 1 : 0) + != remote_gw + || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip) + || seq != mac->rem_seq) + update_mac = 1; + + if (update_mac) { + if (!mac) { + mac = zvni_mac_add(zvni, macaddr); + if (!mac) { + zlog_warn( + "Failed to add MAC %s VNI %u Remote VTEP %s", + prefix_mac2str(macaddr, buf, + sizeof(buf)), + vni, inet_ntoa(vtep_ip)); + return; + } + + /* Is this MAC created for a MACIP? */ + if (ipa_len) + SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + } else { + const char *mac_type; + + /* When host moves but changes its (MAC,IP) + * binding, BGP may install a MACIP entry that + * corresponds to "older" location of the host + * in transient situations (because {IP1,M1} + * is a different route from {IP1,M2}). Check + * the sequence number and ignore this update + * if appropriate. + */ + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { + tmp_seq = mac->loc_seq; + mac_type = "local"; + } else { + tmp_seq = mac->rem_seq; + mac_type = "remote"; + } + if (seq < tmp_seq) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u", + vni, + prefix_mac2str(macaddr, + buf, sizeof(buf)), + ipa_len ? " IP " : "", + ipa_len ? + ipaddr2str(ipaddr, + buf1, sizeof(buf1)) : "", + mac_type, + tmp_seq); + return; + } + } + + /* Set "auto" and "remote" forwarding info. */ + UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); + memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); + SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); + mac->fwd_info.r_vtep_ip = vtep_ip; + + if (sticky) + SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + else + UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + + if (remote_gw) + SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); + else + UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); + + zvni_process_neigh_on_remote_mac_add(zvni, mac); + + /* Install the entry. */ + zvni_mac_install(zvni, mac); + } + + /* Update seq number. */ + mac->rem_seq = seq; + + /* If there is no IP, return after clearing AUTO flag of MAC. */ + if (!ipa_len) { + UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + return; + } + + /* Check if the remote neighbor itself is unknown or has a + * change. If so, create or update and then install the entry. + */ + n = zvni_neigh_lookup(zvni, ipaddr); + if (!n + || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + || (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0) + || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip) + || ((CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) ? 1 : 0) + != router_flag) + || seq != n->rem_seq) + update_neigh = 1; + + if (update_neigh) { + if (!n) { + n = zvni_neigh_add(zvni, ipaddr, macaddr); + if (!n) { + zlog_warn( + "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s", + ipaddr2str(ipaddr, buf1, + sizeof(buf1)), + prefix_mac2str(macaddr, buf, + sizeof(buf)), + vni, inet_ntoa(vtep_ip)); + return; + } + + } else { + const char *n_type; + + /* When host moves but changes its (MAC,IP) + * binding, BGP may install a MACIP entry that + * corresponds to "older" location of the host + * in transient situations (because {IP1,M1} + * is a different route from {IP1,M2}). Check + * the sequence number and ignore this update + * if appropriate. + */ + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + tmp_seq = n->loc_seq; + n_type = "local"; + } else { + tmp_seq = n->rem_seq; + n_type = "remote"; + } + if (seq < tmp_seq) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u", + vni, + prefix_mac2str(macaddr, + buf, sizeof(buf)), + ipa_len ? " IP " : "", + ipa_len ? + ipaddr2str(ipaddr, + buf1, sizeof(buf1)) : "", + n_type, + tmp_seq); + return; + } + if (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0) { + /* MAC change, send a delete for old + * neigh if learnt locally. + */ + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) && + IS_ZEBRA_NEIGH_ACTIVE(n)) + zvni_neigh_send_del_to_client( + zvni->vni, &n->ip, + &n->emac, 0); + + /* update neigh list for macs */ + old_mac = zvni_mac_lookup(zvni, &n->emac); + if (old_mac) { + listnode_delete(old_mac->neigh_list, n); + zvni_deref_ip2mac(zvni, old_mac, 1); + } + listnode_add_sort(mac->neigh_list, n); + memcpy(&n->emac, macaddr, ETH_ALEN); + } + } + + /* Set "remote" forwarding info. */ + UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); + n->r_vtep_ip = vtep_ip; + SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); + + /* Set router flag (R-bit) to this Neighbor entry */ + if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG)) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + else + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + + /* Install the entry. */ + zvni_neigh_install(zvni, n); + } + + /* Update seq number. */ + n->rem_seq = seq; +} + +/* Process a remote MACIP delete from BGP. */ +static void process_remote_macip_del(vni_t vni, + struct ethaddr *macaddr, + uint16_t ipa_len, + struct ipaddr *ipaddr, + struct in_addr vtep_ip) +{ + zebra_vni_t *zvni; + zebra_mac_t *mac = NULL; + zebra_neigh_t *n = NULL; + struct interface *ifp = NULL; + struct zebra_if *zif = NULL; + char buf[ETHER_ADDR_STRLEN]; + char buf1[INET6_ADDRSTRLEN]; + + /* Locate VNI hash entry - expected to exist. */ + zvni = zvni_lookup(vni); + if (!zvni) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni); + return; + } + + ifp = zvni->vxlan_if; + if (ifp) + zif = ifp->info; + if (!ifp || + !if_is_operative(ifp) || + !zif || + !zif->brslave_info.br_if) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info", + vni); + return; + } + + /* The remote VTEP specified is normally expected to exist, but + * it is possible that the peer may delete the VTEP before deleting + * any MACs referring to the VTEP, in which case the handler (see + * remote_vtep_del) would have already deleted the MACs. + */ + if (!zvni_vtep_find(zvni, &vtep_ip)) + return; + + mac = zvni_mac_lookup(zvni, macaddr); + if (ipa_len) + n = zvni_neigh_lookup(zvni, ipaddr); + + if (n && !mac) { + zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL", + prefix_mac2str(macaddr, buf, sizeof(buf)), + ipaddr2str(ipaddr, buf1, sizeof(buf1)), vni); + return; + } + + /* If the remote mac or neighbor doesn't exist there is nothing + * more to do. Otherwise, uninstall the entry and then remove it. + */ + if (!mac && !n) + return; + + /* Ignore the delete if this mac is a gateway mac-ip */ + if (mac + && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) + && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) { + zlog_warn( + "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC", + vni, + prefix_mac2str(macaddr, buf, sizeof(buf)), + ipa_len ? " IP " : "", + ipa_len ? + ipaddr2str(ipaddr, buf1, sizeof(buf1)) : ""); + return; + } + + /* Uninstall remote neighbor or MAC. */ + if (n) { + /* When the MAC changes for an IP, it is possible the + * client may update the new MAC before trying to delete the + * "old" neighbor (as these are two different MACIP routes). + * Do the delete only if the MAC matches. + */ + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + && (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) { + zvni_neigh_uninstall(zvni, n); + zvni_neigh_del(zvni, n); + zvni_deref_ip2mac(zvni, mac, 1); + } + } else { + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { + zvni_process_neigh_on_remote_mac_del(zvni, mac); + + if (list_isempty(mac->neigh_list)) { + zvni_mac_uninstall(zvni, mac, 0); + zvni_mac_del(zvni, mac); + } else + SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + } + } +} + + +/* Public functions */ + +int is_l3vni_for_prefix_routes_only(vni_t vni) +{ + zebra_l3vni_t *zl3vni = NULL; + + zl3vni = zl3vni_lookup(vni); + if (!zl3vni) + return 0; + + return CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? 1 : 0; +} + +/* handle evpn route in vrf table */ +void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, struct ethaddr *rmac, + struct ipaddr *vtep_ip, + struct prefix *host_prefix) +{ + zebra_l3vni_t *zl3vni = NULL; + struct ipaddr ipv4_vtep; + + zl3vni = zl3vni_from_vrf(vrf_id); + if (!zl3vni || !is_l3vni_oper_up(zl3vni)) + return; + + /* + * add the next hop neighbor - + * neigh to be installed is the ipv6 nexthop neigh + */ + zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix); + + /* + * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4 + * address. Rmac is programmed against the ipv4 vtep because we only + * support ipv4 tunnels in the h/w right now + */ + memset(&ipv4_vtep, 0, sizeof(struct ipaddr)); + ipv4_vtep.ipa_type = IPADDR_V4; + if (vtep_ip->ipa_type == IPADDR_V6) + ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6, + &(ipv4_vtep.ipaddr_v4)); + else + memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4, + sizeof(struct in_addr)); + + /* + * add the rmac - remote rmac to be installed is against the ipv4 + * nexthop address + */ + zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep, host_prefix); +} + +/* handle evpn vrf route delete */ +void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id, + struct ipaddr *vtep_ip, + struct prefix *host_prefix) +{ + zebra_l3vni_t *zl3vni = NULL; + zebra_neigh_t *nh = NULL; + zebra_mac_t *zrmac = NULL; + + zl3vni = zl3vni_from_vrf(vrf_id); + if (!zl3vni) return; /* find the next hop entry and rmac entry */ @@ -4057,8 +4480,7 @@ void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id, } void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni, - struct ethaddr *rmac, - uint8_t use_json) + struct ethaddr *rmac, bool use_json) { zebra_l3vni_t *zl3vni = NULL; zebra_mac_t *zrmac = NULL; @@ -4102,8 +4524,7 @@ void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni, } } -void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, - uint8_t use_json) +void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json) { zebra_l3vni_t *zl3vni; uint32_t num_rmacs; @@ -4147,7 +4568,7 @@ void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, } } -void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, uint8_t use_json) +void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json) { struct zebra_ns *zns = NULL; json_object *json = NULL; @@ -4184,7 +4605,7 @@ void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, uint8_t use_json) } void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni, - struct ipaddr *ip, uint8_t use_json) + struct ipaddr *ip, bool use_json) { zebra_l3vni_t *zl3vni = NULL; zebra_neigh_t *n = NULL; @@ -4228,7 +4649,7 @@ void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni, } } -void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, uint8_t use_json) +void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json) { uint32_t num_nh; struct nh_walk_ctx wctx; @@ -4272,7 +4693,7 @@ void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, uint8_t use_json) } } -void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, uint8_t use_json) +void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json) { struct zebra_ns *zns = NULL; json_object *json = NULL; @@ -4303,13 +4724,12 @@ void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, uint8_t use_json) json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); } - return; } /* * Display L3 VNI information (VTY command handler). */ -void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, uint8_t use_json) +void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json) { void *args[2]; json_object *json = NULL; @@ -4362,6 +4782,7 @@ void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf, zl3vni_rmac2str(zl3vni, buf, sizeof(buf))); } else { json_object *json_vrf = NULL; + json_vrf = json_object_new_object(); json_object_string_add(json_vrf, "vrf", zvrf_name(zvrf)); json_object_int_add(json_vrf, "vni", zl3vni->vni); @@ -4382,7 +4803,7 @@ void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf, * Display Neighbors for a VNI (VTY command handler). */ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, uint8_t use_json) + vni_t vni, bool use_json) { zebra_vni_t *zvni; uint32_t num_neigh; @@ -4421,8 +4842,9 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, vty_out(vty, "Number of ARPs (local and remote) known for this VNI: %u\n", num_neigh); - vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP", - "Type", "MAC", "Remote VTEP"); + vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n", + -wctx.addr_width, "IP", "Type", + "State", "MAC", "Remote VTEP"); } else json_object_int_add(json, "numArpNd", num_neigh); @@ -4438,7 +4860,7 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, * Display neighbors across all VNIs (VTY command handler). */ void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf, - uint8_t use_json) + bool use_json) { json_object *json = NULL; void *args[2]; @@ -4467,7 +4889,7 @@ void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf, */ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, - struct ipaddr *ip, uint8_t use_json) + struct ipaddr *ip, bool use_json) { zebra_vni_t *zvni; zebra_neigh_t *n; @@ -4509,7 +4931,7 @@ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, */ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip, - uint8_t use_json) + bool use_json) { zebra_vni_t *zvni; uint32_t num_neigh; @@ -4551,7 +4973,7 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, * Display MACs for a VNI (VTY command handler). */ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, uint8_t use_json) + vni_t vni, bool use_json) { zebra_vni_t *zvni; uint32_t num_macs; @@ -4606,7 +5028,7 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, * Display MACs for all VNIs (VTY command handler). */ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf, - uint8_t use_json) + bool use_json) { struct mac_walk_ctx wctx; json_object *json = NULL; @@ -4636,8 +5058,7 @@ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf, */ void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, - struct in_addr vtep_ip, - uint8_t use_json) + struct in_addr vtep_ip, bool use_json) { struct mac_walk_ctx wctx; json_object *json = NULL; @@ -4693,7 +5114,7 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, */ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip, - uint8_t use_json) + bool use_json) { zebra_vni_t *zvni; uint32_t num_macs; @@ -4743,7 +5164,7 @@ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, * Display VNI information (VTY command handler). */ void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, - uint8_t use_json) + bool use_json) { json_object *json = NULL; void *args[2]; @@ -4782,7 +5203,7 @@ void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, } /* Display all global details for EVPN */ -void zebra_vxlan_print_evpn(struct vty *vty, uint8_t uj) +void zebra_vxlan_print_evpn(struct vty *vty, bool uj) { int num_l2vnis = 0; int num_l3vnis = 0; @@ -4831,7 +5252,7 @@ void zebra_vxlan_print_evpn(struct vty *vty, uint8_t uj) * Display VNI hash table (VTY command handler). */ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf, - uint8_t use_json) + bool use_json) { json_object *json = NULL; struct zebra_ns *zns = NULL; @@ -5016,14 +5437,9 @@ void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS) struct ethaddr macaddr; struct ipaddr ip; struct in_addr vtep_ip; - zebra_vni_t *zvni; - zebra_mac_t *mac; - zebra_neigh_t *n; - unsigned short l = 0, ipa_len; + uint16_t l = 0, ipa_len; char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; - struct interface *ifp = NULL; - struct zebra_if *zif = NULL; memset(&macaddr, 0, sizeof(struct ethaddr)); memset(&ip, 0, sizeof(struct ipaddr)); @@ -5036,8 +5452,6 @@ void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS) /* Message contains VNI, followed by MAC followed by IP (if any) * followed by remote VTEP IP. */ - mac = NULL; - n = NULL; memset(&ip, 0, sizeof(ip)); STREAM_GETL(s, vni); STREAM_GET(&macaddr.octet, s, ETH_ALEN); @@ -5053,103 +5467,17 @@ void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS) if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s", + "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s", + vni, prefix_mac2str(&macaddr, buf, sizeof(buf)), - ipaddr2str(&ip, buf1, sizeof(buf1)), vni, + ipa_len ? " IP " : "", + ipa_len ? + ipaddr2str(&ip, buf1, sizeof(buf1)) : "", inet_ntoa(vtep_ip), zebra_route_string(client->proto)); - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "Failed to locate VNI hash upon remote MACIP DEL, " - "VNI %u", - vni); - continue; - } - ifp = zvni->vxlan_if; - if (!ifp) { - zlog_warn( - "VNI %u hash %p doesn't have intf upon remote MACIP DEL", - vni, zvni); - continue; - } - zif = ifp->info; - - /* If down or not mapped to a bridge, we're done. */ - if (!if_is_operative(ifp) || !zif->brslave_info.br_if) - continue; - - /* The remote VTEP specified is normally expected to exist, but - * it is - * possible that the peer may delete the VTEP before deleting - * any MACs - * referring to the VTEP, in which case the handler (see - * remote_vtep_del) - * would have already deleted the MACs. - */ - if (!zvni_vtep_find(zvni, &vtep_ip)) - continue; + process_remote_macip_del(vni, &macaddr, ipa_len, &ip, vtep_ip); - mac = zvni_mac_lookup(zvni, &macaddr); - if (ipa_len) - n = zvni_neigh_lookup(zvni, &ip); - - if (n && !mac) { - zlog_warn("Failed to locate MAC %s for neigh %s VNI %u", - prefix_mac2str(&macaddr, buf, sizeof(buf)), - ipaddr2str(&ip, buf1, sizeof(buf1)), vni); - continue; - } - - /* If the remote mac or neighbor doesn't exist there is nothing - * more - * to do. Otherwise, uninstall the entry and then remove it. - */ - if (!mac && !n) - continue; - - /* Ignore the delete if this mac is a gateway mac-ip */ - if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) - && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) { - zlog_warn( - "%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway", - zvrf_id(zvrf), - prefix_mac2str(&macaddr, buf, sizeof(buf)), - ipaddr2str(&ip, buf1, sizeof(buf1)), vni); - continue; - } - - /* Uninstall remote neighbor or MAC. */ - if (n) { - /* When the MAC changes for an IP, it is possible the - * client may - * update the new MAC before trying to delete the "old" - * neighbor - * (as these are two different MACIP routes). Do the - * delete only - * if the MAC matches. - */ - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) - && (memcmp(n->emac.octet, macaddr.octet, ETH_ALEN) - == 0)) { - zvni_neigh_uninstall(zvni, n); - zvni_neigh_del(zvni, n); - zvni_deref_ip2mac(zvni, mac, 1); - } - } else { - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - zvni_process_neigh_on_remote_mac_del(zvni, mac); - - if (list_isempty(mac->neigh_list)) { - zvni_mac_uninstall(zvni, mac, 0); - zvni_mac_del(zvni, mac); - } else - SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); - } - } } stream_failure: @@ -5168,29 +5496,18 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) struct ethaddr macaddr; struct ipaddr ip; struct in_addr vtep_ip; - zebra_vni_t *zvni; - zebra_vtep_t *zvtep; - zebra_mac_t *mac, *old_mac; - zebra_neigh_t *n; - unsigned short l = 0, ipa_len; - int update_mac = 0, update_neigh = 0; + uint16_t l = 0, ipa_len; + uint8_t flags = 0; + uint32_t seq; char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; - uint8_t sticky = 0; - uint8_t remote_gw = 0; - uint8_t router_flag = 0; - uint8_t flags = 0; - struct interface *ifp = NULL; - struct zebra_if *zif = NULL; memset(&macaddr, 0, sizeof(struct ethaddr)); memset(&ip, 0, sizeof(struct ipaddr)); memset(&vtep_ip, 0, sizeof(struct in_addr)); if (!EVPN_ENABLED(zvrf)) { - zlog_warn( - "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback", - __PRETTY_FUNCTION__); + zlog_warn("EVPN not enabled, ignoring remote MACIP ADD"); return; } @@ -5201,9 +5518,6 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) /* Message contains VNI, followed by MAC followed by IP (if any) * followed by remote VTEP IP. */ - update_mac = update_neigh = 0; - mac = NULL; - n = NULL; memset(&ip, 0, sizeof(ip)); STREAM_GETL(s, vni); STREAM_GET(&macaddr.octet, s, ETH_ALEN); @@ -5219,188 +5533,23 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) /* Get flags - sticky mac and/or gateway mac */ STREAM_GETC(s, flags); - sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); - remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); - router_flag = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); l++; + STREAM_GETL(s, seq); + l += 4; if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s", + "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s", + vni, prefix_mac2str(&macaddr, buf, sizeof(buf)), - ipaddr2str(&ip, buf1, sizeof(buf1)), vni, - inet_ntoa(vtep_ip), flags, + ipa_len ? " IP " : "", + ipa_len ? + ipaddr2str(&ip, buf1, sizeof(buf1)) : "", + flags, seq, inet_ntoa(vtep_ip), zebra_route_string(client->proto)); - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) { - zlog_warn( - "Failed to locate VNI hash upon remote MACIP ADD, VNI %u", - vni); - continue; - } - ifp = zvni->vxlan_if; - if (!ifp) { - zlog_warn( - "VNI %u hash %p doesn't have intf upon remote MACIP add", - vni, zvni); - continue; - } - zif = ifp->info; - - /* If down or not mapped to a bridge, we're done. */ - if (!if_is_operative(ifp) || !zif->brslave_info.br_if) - continue; - - /* The remote VTEP specified should normally exist, but it is - * possible - * that when peering comes up, peer may advertise MACIP routes - * before - * advertising type-3 routes. - */ - zvtep = zvni_vtep_find(zvni, &vtep_ip); - if (!zvtep) { - if (zvni_vtep_add(zvni, &vtep_ip) == NULL) { - flog_err( - ZEBRA_ERR_VTEP_ADD_FAILED, - "Failed to add remote VTEP, VNI %u zvni %p", - vni, zvni); - continue; - } - - zvni_vtep_install(zvni, &vtep_ip); - } - - mac = zvni_mac_lookup(zvni, &macaddr); - - /* Ignore the update if the mac is already present - as a gateway mac */ - if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) - && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac", - zvrf_id(zvrf), - prefix_mac2str(&macaddr, buf, - sizeof(buf)), - ipaddr2str(&ip, buf1, sizeof(buf1)), - vni); - continue; - } - - /* check if the remote MAC is unknown or has a change. - * If so, that needs to be updated first. Note that client could - * install MAC and MACIP separately or just install the latter. - */ - if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) - || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0) - != sticky - || (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? 1 : 0) - != remote_gw - || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)) - update_mac = 1; - - if (update_mac) { - if (!mac) { - mac = zvni_mac_add(zvni, &macaddr); - if (!mac) { - zlog_warn( - "Failed to add MAC %s VNI %u Remote VTEP %s", - prefix_mac2str(&macaddr, buf, - sizeof(buf)), - vni, inet_ntoa(vtep_ip)); - return; - } - - /* Is this MAC created for a MACIP? */ - if (ipa_len) - SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); - } - - /* Set "auto" and "remote" forwarding info. */ - UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); - memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); - SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); - mac->fwd_info.r_vtep_ip = vtep_ip; - - if (sticky) - SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); - else - UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); - - if (remote_gw) - SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); - else - UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); - - zvni_process_neigh_on_remote_mac_add(zvni, mac); - - /* Install the entry. */ - zvni_mac_install(zvni, mac); - } - - /* If there is no IP, continue - after clearing AUTO flag of - * MAC. */ - if (!ipa_len) { - UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO); - continue; - } - - /* Check if the remote neighbor itself is unknown or has a - * change. - * If so, create or update and then install the entry. - */ - n = zvni_neigh_lookup(zvni, &ip); - if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) - || ((CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) ? 1 : 0) - != router_flag) - || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0) - || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)) - update_neigh = 1; - - if (update_neigh) { - if (!n) { - n = zvni_neigh_add(zvni, &ip, &macaddr); - if (!n) { - zlog_warn( - "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s", - ipaddr2str(&ip, buf1, - sizeof(buf1)), - prefix_mac2str(&macaddr, buf, - sizeof(buf)), - vni, inet_ntoa(vtep_ip)); - return; - } - - } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr)) - != 0) { - /* MAC change, update neigh list for old and new - * mac */ - old_mac = zvni_mac_lookup(zvni, &n->emac); - if (old_mac) { - listnode_delete(old_mac->neigh_list, n); - zvni_deref_ip2mac(zvni, old_mac, 1); - } - listnode_add_sort(mac->neigh_list, n); - memcpy(&n->emac, &macaddr, ETH_ALEN); - } - - /* Set "remote" forwarding info. */ - UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); - /* TODO: Handle MAC change. */ - n->r_vtep_ip = vtep_ip; - SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); - - /* Set router flag (R-bit) to this Neighbor entry */ - if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG)) - SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - else - UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - - /* Install the entry. */ - zvni_neigh_install(zvni, n); - } + process_remote_macip_add(vni, &macaddr, ipa_len, &ip, + flags, seq, vtep_ip); } stream_failure: @@ -5546,7 +5695,7 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, } if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u", + zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u", prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, ifp->ifindex, vid, zvni->vni); @@ -5559,12 +5708,12 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) return 0; - /* Remove MAC from BGP. */ - zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags); - /* Update all the neigh entries associated with this mac */ zvni_process_neigh_on_local_mac_del(zvni, mac); + /* Remove MAC from BGP. */ + zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags); + /* * If there are no neigh associated with the mac delete the mac * else mark it as AUTO for forward reference @@ -5590,8 +5739,9 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, zebra_vni_t *zvni; zebra_mac_t *mac; char buf[ETHER_ADDR_STRLEN]; - int add = 1; - uint8_t mac_sticky; + bool mac_sticky = false; + bool inform_client = false; + bool upd_neigh = false; /* We are interested in MACs only on ports or (port, VLAN) that * map to a VNI. @@ -5613,26 +5763,48 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, return -1; } - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u", - sticky ? "sticky " : "", - prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, - ifp->ifindex, vid, zvni->vni); - - /* If same entry already exists, nothing to do. */ + /* Check if we need to create or update or it is a NO-OP. */ mac = zvni_mac_lookup(zvni, macaddr); - if (mac) { - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { - mac_sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) - ? 1 - : 0; + if (!mac) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u", + sticky ? "sticky " : "", + prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, vid, zvni->vni); + mac = zvni_mac_add(zvni, macaddr); + if (!mac) { + flog_err( + ZEBRA_ERR_MAC_ADD_FAILED, + "Failed to add MAC %s intf %s(%u) VID %u VNI %u", + prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, vid, zvni->vni); + return -1; + } + SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); + mac->fwd_info.local.ifindex = ifp->ifindex; + mac->fwd_info.local.vid = vid; + if (sticky) + SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + inform_client = true; + + } else { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x", + sticky ? "sticky " : "", + prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, vid, zvni->vni, + mac->flags); + + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) + mac_sticky = true; /* - * return if nothing has changed. - * inform bgp if sticky flag has changed - * update locally and do not inform bgp if local - * parameters like interface has changed + * Update any changes and if changes are relevant to + * BGP, note it. */ if (mac_sticky == sticky && mac->fwd_info.local.ifindex == ifp->ifindex @@ -5647,61 +5819,74 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, ifp->name, ifp->ifindex, vid, zvni->vni); return 0; - } else if (mac_sticky != sticky) { - add = 1; - } else { - add = 0; /* This is an update of local - interface. */ } - } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { + if (mac_sticky != sticky) { + if (sticky) + SET_FLAG(mac->flags, + ZEBRA_MAC_STICKY); + else + UNSET_FLAG(mac->flags, + ZEBRA_MAC_STICKY); + inform_client = true; + } + + memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); + mac->fwd_info.local.ifindex = ifp->ifindex; + mac->fwd_info.local.vid = vid; + + } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) || + CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) { + /* - * If we have already learned the MAC as a remote sticky - * MAC, - * this is a operator error and we must log a warning + * MAC has either moved or was "internally" created due + * to a neighbor learn and is now actually learnt. If + * it was learnt as a remote sticky MAC, this is an + * operator error. */ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) { zlog_warn( - "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d", + "MAC %s already learnt as remote sticky behind VTEP %s VNI %u", prefix_mac2str(macaddr, buf, sizeof(buf)), inet_ntoa(mac->fwd_info.r_vtep_ip), zvni->vni); return 0; } - } - } - if (!mac) { - mac = zvni_mac_add(zvni, macaddr); - if (!mac) { - flog_err(ZEBRA_ERR_MAC_ADD_FAILED, - "Failed to add MAC %s intf %s(%u) VID %u", - prefix_mac2str(macaddr, buf, sizeof(buf)), - ifp->name, ifp->ifindex, vid); - return -1; + /* If an actual move, compute MAC's seq number */ + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) + mac->loc_seq = MAX(mac->rem_seq + 1, + mac->loc_seq); + UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); + UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); + memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); + mac->fwd_info.local.ifindex = ifp->ifindex; + mac->fwd_info.local.vid = vid; + if (sticky) + SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + else + UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + /* + * We have to inform BGP of this MAC as well as process + * all neighbors. + */ + inform_client = true; + upd_neigh = true; } } - /* Set "local" forwarding info. */ - UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); - UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO); - SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); - memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); - mac->fwd_info.local.ifindex = ifp->ifindex; - mac->fwd_info.local.vid = vid; - - if (sticky) - SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); - else - UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); - /* Inform BGP if required. */ - if (add) { - zvni_process_neigh_on_local_mac_add(zvni, mac); - return zvni_mac_send_add_to_client(zvni->vni, macaddr, - mac->flags); + if (inform_client) { + if (zvni_mac_send_add_to_client(zvni->vni, macaddr, + mac->flags, mac->loc_seq)) + return -1; } + /* Process all neighbors associated with this MAC, if required. */ + if (upd_neigh) + zvni_process_neigh_on_local_mac_change(zvni, mac, 0); + return 0; } diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index 2732ef72edfd..5097757b1dd8 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -68,53 +68,51 @@ extern int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf); extern int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf); extern int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf); extern void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni, - struct ipaddr *ip, uint8_t uj); -extern void zebra_vxlan_print_evpn(struct vty *vty, uint8_t uj); + struct ipaddr *ip, bool uj); +extern void zebra_vxlan_print_evpn(struct vty *vty, bool uj); extern void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni, struct ethaddr *rmac, - uint8_t use_json); + bool use_json); extern void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, uint8_t use_json); + vni_t vni, bool use_json); extern void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf, - uint8_t use_json); + bool use_json); extern void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, struct in_addr vtep_ip, - uint8_t use_json); + bool use_json); extern void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct ethaddr *mac); extern void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip, - uint8_t use_json); + bool use_json); extern void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, uint8_t use_json); + vni_t vni, bool use_json); extern void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf, - uint8_t use_json); + bool use_json); extern void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct ipaddr *ip, - uint8_t use_json); + bool use_json); extern void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip, - uint8_t use_json); + bool use_json); extern void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, uint8_t use_json); + vni_t vni, bool use_json); extern void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf, - uint8_t use_json); + bool use_json); extern void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t vni, - uint8_t use_json); -extern void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, - uint8_t use_json); + bool use_json); +extern void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json); extern void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t vni, - uint8_t use_json); -extern void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, uint8_t use_json); -extern void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, - uint8_t use_json); + bool use_json); +extern void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json); +extern void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json); extern void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf, json_object *json_vrfs); extern int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p, diff --git a/zebra/zebra_vxlan_null.c b/zebra/zebra_vxlan_null.c index afc59774c91d..00c849a3d01b 100644 --- a/zebra/zebra_vxlan_null.c +++ b/zebra/zebra_vxlan_null.c @@ -83,7 +83,7 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf) { } -void zebra_vxlan_print_evpn(struct vty *vty, uint8_t uj) +void zebra_vxlan_print_evpn(struct vty *vty, bool uj) { } diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index e86967041b2e..44163eb331b6 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -260,6 +260,10 @@ struct zebra_mac_t_ { struct in_addr r_vtep_ip; } fwd_info; + /* Mobility sequence numbers associated with this entry. */ + uint32_t rem_seq; + uint32_t loc_seq; + /* List of neigh associated with this mac */ struct list *neigh_list; @@ -338,6 +342,16 @@ struct zebra_neigh_t_ { /* Remote VTEP IP - applicable only for remote neighbors. */ struct in_addr r_vtep_ip; + /* + * Mobility sequence numbers associated with this entry. The rem_seq + * represents the sequence number from the client (BGP) for the most + * recent add or update of this entry while the loc_seq represents + * the sequence number informed (or to be informed) by zebra to BGP + * for this entry. + */ + uint32_t rem_seq; + uint32_t loc_seq; + /* list of hosts pointing to this remote NH entry */ struct host_rb_tree_entry host_rb; }; diff --git a/zebra/zserv.c b/zebra/zserv.c index 174e0107439b..4a341bfe1be9 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -705,7 +705,8 @@ static struct zserv *zserv_client_create(int sock) .stop = frr_pthread_attr_default.stop }; client->pthread = - frr_pthread_new(&zclient_pthr_attrs, "Zebra API client thread"); + frr_pthread_new(&zclient_pthr_attrs, "Zebra API client thread", + "zebra_apic"); zebra_vrf_update_all(client);