diff options
197 files changed, 2953 insertions, 5134 deletions
diff --git a/Makefile.am b/Makefile.am index a959fd9e5a..425d7bb311 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,7 +135,6 @@ include qpb/subdir.am include fpm/subdir.am include grpc/subdir.am include tools/subdir.am -include solaris/subdir.am include bgpd/subdir.am include bgpd/rfp-example/librfp/subdir.am @@ -6,8 +6,8 @@ FRRouting ========= FRR is free software that implements and manages various IPv4 and IPv6 routing -protocols. It runs on nearly all distributions of Linux and BSD as well as -Solaris and supports all modern CPU architectures. +protocols. It runs on nearly all distributions of Linux and BSD and +supports all modern CPU architectures. FRR currently supports the following protocols: diff --git a/bfdd/bfd.c b/bfdd/bfd.c index c16912060c..57e5909f57 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -2158,6 +2158,7 @@ void bfd_session_update_vrf_name(struct bfd_session *bs, struct vrf *vrf) if (yang_module_find("frr-bfdd") && bs->key.vrfname[0]) { struct lyd_node *bfd_dnode; char xpath[XPATH_MAXLEN], xpath_srcaddr[XPATH_MAXLEN + 32]; + char oldpath[XPATH_MAXLEN], newpath[XPATH_MAXLEN]; char addr_buf[INET6_ADDRSTRLEN]; int slen; @@ -2178,14 +2179,19 @@ void bfd_session_update_vrf_name(struct bfd_session *bs, struct vrf *vrf) "[interface='%s']", bs->key.ifname); else slen += snprintf(xpath + slen, sizeof(xpath) - slen, - "[interface='']"); + "[interface='*']"); snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']/vrf", bs->key.vrfname); bfd_dnode = yang_dnode_get(running_config->dnode, xpath, bs->key.vrfname); if (bfd_dnode) { + yang_dnode_get_path(bfd_dnode->parent, oldpath, + sizeof(oldpath)); yang_dnode_change_leaf(bfd_dnode, vrf->name); + yang_dnode_get_path(bfd_dnode->parent, newpath, + sizeof(newpath)); + nb_running_move_tree(oldpath, newpath); running_config->version++; } } diff --git a/bfdd/bfdd.c b/bfdd/bfdd.c index 6b8f2c5d46..098e7a289e 100644 --- a/bfdd/bfdd.c +++ b/bfdd/bfdd.c @@ -21,6 +21,8 @@ #include <zebra.h> #include "filter.h" +#include "if.h" +#include "vrf.h" #include "bfd.h" #include "bfdd_nb.h" diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index d115684b1c..ddec83397d 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -127,7 +127,7 @@ DEFPY_YANG_NOSH( "[interface='%s']", ifname); else slen += snprintf(xpath + slen, sizeof(xpath) - slen, - "[interface='']"); + "[interface='*']"); if (vrf) snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']", vrf); else @@ -185,7 +185,7 @@ DEFPY_YANG( "[interface='%s']", ifname); else slen += snprintf(xpath + slen, sizeof(xpath) - slen, - "[interface='']"); + "[interface='*']"); if (vrf) snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']", vrf); else @@ -218,7 +218,7 @@ static void _bfd_cli_show_peer(struct vty *vty, struct lyd_node *dnode, if (strcmp(vrf, VRF_DEFAULT_NAME)) vty_out(vty, " vrf %s", vrf); - if (ifname[0]) + if (strcmp(ifname, "*")) vty_out(vty, " interface %s", ifname); vty_out(vty, "\n"); diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c index 0046bc625b..fe6a0b7905 100644 --- a/bfdd/bfdd_nb_config.c +++ b/bfdd/bfdd_nb_config.c @@ -45,11 +45,11 @@ static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, if (yang_dnode_exists(dnode, "./source-addr")) strtosa(yang_dnode_get_string(dnode, "./source-addr"), &lsa); - /* Get optional interface and vrf names. */ - if (yang_dnode_exists(dnode, "./interface")) - ifname = yang_dnode_get_string(dnode, "./interface"); - if (yang_dnode_exists(dnode, "./vrf")) - vrfname = yang_dnode_get_string(dnode, "./vrf"); + ifname = yang_dnode_get_string(dnode, "./interface"); + vrfname = yang_dnode_get_string(dnode, "./vrf"); + + if (strcmp(ifname, "*") == 0) + ifname = NULL; /* Generate the corresponding key. */ gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname); @@ -72,18 +72,10 @@ static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, */ yang_dnode_get_prefix(&p, dnode, "./dest-addr"); - /* - * To support old FRR versions we must allow empty - * interface to be specified, however that should - * change in the future. - */ - if (yang_dnode_exists(dnode, "./interface")) - ifname = yang_dnode_get_string(dnode, "./interface"); - else - ifname = ""; + ifname = yang_dnode_get_string(dnode, "./interface"); if (p.family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6) - && strlen(ifname) == 0) { + && strcmp(ifname, "*") == 0) { zlog_warn( "%s: when using link-local you must specify an interface.", __func__); diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 79fb7e55e9..3a0400a4b3 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -265,7 +265,8 @@ struct ecommunity *ecommunity_dup(struct ecommunity *ecom) if (new->size) { new->val = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ecom->unit_size); - memcpy(new->val, ecom->val, ecom->size * ecom->unit_size); + memcpy(new->val, ecom->val, + (size_t)ecom->size * (size_t)ecom->unit_size); } else new->val = NULL; return new; @@ -285,18 +286,16 @@ struct ecommunity *ecommunity_merge(struct ecommunity *ecom1, struct ecommunity *ecom2) { if (ecom1->val) - ecom1->val = - XREALLOC(MTYPE_ECOMMUNITY_VAL, ecom1->val, - (ecom1->size + ecom2->size) * - ecom1->unit_size); + ecom1->val = XREALLOC(MTYPE_ECOMMUNITY_VAL, ecom1->val, + (size_t)(ecom1->size + ecom2->size) + * (size_t)ecom1->unit_size); else - ecom1->val = - XMALLOC(MTYPE_ECOMMUNITY_VAL, - (ecom1->size + ecom2->size) * - ecom1->unit_size); + ecom1->val = XMALLOC(MTYPE_ECOMMUNITY_VAL, + (size_t)(ecom1->size + ecom2->size) + * (size_t)ecom1->unit_size); memcpy(ecom1->val + (ecom1->size * ecom1->unit_size), ecom2->val, - ecom2->size * ecom1->unit_size); + (size_t)ecom2->size * (size_t)ecom1->unit_size); ecom1->size += ecom2->size; return ecom1; diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index 798bce8219..3b7fb649a9 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -268,12 +268,7 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, json_object *json_ecom_path = NULL; json_object *json_time_path = NULL; char timebuf[BGP_UPTIME_LEN]; - struct bgp_dest *dest = NULL; - if (path) - dest = path->net; - if (dest) - bgp_dest_get_bgp_table_info(dest); if (p == NULL || p->family != AF_FLOWSPEC) return; if (json_paths) { diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index ee3580edf1..6c077878b5 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1319,11 +1319,18 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) else peer->v_holdtime = send_holdtime; - if ((CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) - && (peer->keepalive < peer->v_holdtime / 3)) - peer->v_keepalive = peer->keepalive; - else - peer->v_keepalive = peer->v_holdtime / 3; + /* Set effective keepalive to 1/3 the effective holdtime. + * Use configured keeplive when < effective keepalive. + */ + peer->v_keepalive = peer->v_holdtime / 3; + if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) { + if (peer->keepalive && peer->keepalive < peer->v_keepalive) + peer->v_keepalive = peer->keepalive; + } else { + if (peer->bgp->default_keepalive + && peer->bgp->default_keepalive < peer->v_keepalive) + peer->v_keepalive = peer->bgp->default_keepalive; + } /* Open option part parse. */ if (optlen != 0) { diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 174c11fd34..15c1df8473 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3340,14 +3340,20 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true : false; - /* Only validated for unicast and multicast currently. */ - /* Also valid for EVPN where the nexthop is an IP address. */ - if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN) + /* + * Only validated for unicast and multicast currently. + * Also valid for EVPN where the nexthop is an IP address. + * If we are a bgp static route being checked then there is + * no need to check to see if the nexthop is martian as + * that it should be ok. + */ + if (is_bgp_static_route || + (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)) return false; /* If NEXT_HOP is present, validate it. */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) { - if ((attr->nexthop.s_addr == INADDR_ANY && !is_bgp_static_route) + if (attr->nexthop.s_addr == INADDR_ANY || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr)) || bgp_nexthop_self(bgp, afi, type, stype, attr, dest)) return true; @@ -3366,8 +3372,7 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, switch (attr->mp_nexthop_len) { case BGP_ATTR_NHLEN_IPV4: case BGP_ATTR_NHLEN_VPNV4: - ret = ((attr->mp_nexthop_global_in.s_addr == INADDR_ANY - && !is_bgp_static_route) + ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY || IPV4_CLASS_DE( ntohl(attr->mp_nexthop_global_in.s_addr)) || bgp_nexthop_self(bgp, afi, type, stype, attr, @@ -3376,9 +3381,8 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, case BGP_ATTR_NHLEN_IPV6_GLOBAL: case BGP_ATTR_NHLEN_VPNV6_GLOBAL: - ret = ((IN6_IS_ADDR_UNSPECIFIED( + ret = (IN6_IS_ADDR_UNSPECIFIED( &attr->mp_nexthop_global) - && !is_bgp_static_route) || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global) || IN6_IS_ADDR_MULTICAST( &attr->mp_nexthop_global) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 11e872f6b4..b203238520 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2367,7 +2367,7 @@ static void bgp_encode_pbr_rule_action(struct stream *s, struct prefix pfx; uint8_t fam = AF_INET; - if (pbra && pbra->nh.type == NEXTHOP_TYPE_IPV6) + if (pbra->nh.type == NEXTHOP_TYPE_IPV6) fam = AF_INET6; stream_putl(s, 0); /* seqno unused */ if (pbr) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index b654e85206..3c707b41ca 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -290,7 +290,15 @@ void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id) bgp->name_pretty, bgp->vrf_id, inet_ntoa(*addr)); - bgp_router_id_set(bgp, addr, false); + /* + * if old router-id was 0x0, set flag + * to use this new value + */ + bgp_router_id_set(bgp, addr, + (bgp->router_id.s_addr + == INADDR_ANY) + ? true + : false); } } } @@ -313,7 +321,15 @@ void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id) bgp->name_pretty, bgp->vrf_id, inet_ntoa(*addr)); - bgp_router_id_set(bgp, addr, false); + /* + * if old router-id was 0x0, set flag + * to use this new value + */ + bgp_router_id_set(bgp, addr, + (bgp->router_id.s_addr + == INADDR_ANY) + ? true + : false); } } diff --git a/bgpd/rfapi/rfapi.h b/bgpd/rfapi/rfapi.h index beb44aa780..b2079fb13e 100644 --- a/bgpd/rfapi/rfapi.h +++ b/bgpd/rfapi/rfapi.h @@ -33,12 +33,8 @@ /* probably ought to have a field-specific define in config.h */ #ifndef s6_addr32 /* for solaris/bsd */ -#ifdef SOLARIS_IPV6 -# define s6_addr32 _S6_un._S6_u32 -#else # define s6_addr32 __u6_addr.__u6_addr32 #endif -#endif #define RFAPI_V4_ADDR 0x04 #define RFAPI_V6_ADDR 0x06 diff --git a/configure.ac b/configure.ac index a952cf7063..3cc74c4110 100755 --- a/configure.ac +++ b/configure.ac @@ -542,7 +542,7 @@ AC_ARG_ENABLE([fabricd], AC_ARG_ENABLE([vrrpd], AS_HELP_STRING([--disable-vrrpd], [do not build vrrpd])) AC_ARG_ENABLE([bgp-announce], - AS_HELP_STRING([--disable-bgp-announce,], [turn off BGP route announcement])) + 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_ENABLE([bgp-bmp], @@ -593,7 +593,7 @@ AC_ARG_ENABLE([rusage], AC_ARG_ENABLE([gcc_ultra_verbose], AS_HELP_STRING([--enable-gcc-ultra-verbose], [enable ultra verbose GCC warnings])) AC_ARG_ENABLE([backtrace], - AS_HELP_STRING([--disable-backtrace,], [disable crash backtraces (default autodetect)])) + AS_HELP_STRING([--disable-backtrace], [disable crash backtraces (default autodetect)])) AC_ARG_ENABLE([time-check], AS_HELP_STRING([--disable-time-check], [disable slow thread warning messages])) AC_ARG_ENABLE([cpu-time], @@ -1124,17 +1124,7 @@ is_linux=false AC_MSG_CHECKING([which operating system interface to use]) case "$host_os" in sunos* | solaris2*) - AC_MSG_RESULT([Solaris]) - - 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]) - AC_CHECK_LIB([umem], [main]) - SOLARIS="solaris" - AC_MSG_WARN([--Solaris support is being considered for deprecation, please let us know if you are still using this--]) + AC_MSG_FAILURE([Solaris support has been removed please see versions prior or equal to 7.5]) ;; linux*) AC_MSG_RESULT([Linux]) @@ -1167,7 +1157,6 @@ case "$host_os" in AC_DEFINE([BSD_V6_SYSCTL], [1], [BSD v6 sysctl to turn on and off forwarding]) ;; esac -AM_CONDITIONAL([SOLARIS], [test "$SOLARIS" = "solaris"]) AM_CONDITIONAL([LINUX], [${is_linux}]) AC_SYS_LARGEFILE @@ -1391,10 +1380,6 @@ case "$host_os" in AC_MSG_RESULT([pfpacket]) ISIS_METHOD_MACRO="ISIS_METHOD_PFPACKET" ;; - solaris* | sunos*) - AC_MSG_RESULT([DLPI]) - ISIS_METHOD_MACRO="ISIS_METHOD_DLPI" - ;; *) if test "$ac_cv_header_net_bpf_h" = "no"; then if test "$ac_cv_header_sys_dlpi_h" = "no"; then @@ -1512,7 +1497,6 @@ if test "$ac_cv_have_decl_TCP_MD5SIG" = "no"; then AC_CHECK_DECLS([TCP_MD5SIG], [], [], MD5_INCLUDES)]) fi -AC_SUBST([SOLARIS]) AC_CHECK_LIB([crypt], [crypt], [], [AC_CHECK_LIB([crypto], [DES_crypt])]) AC_CHECK_LIB([resolv], [res_init]) @@ -1577,10 +1561,70 @@ dnl -------------------- dnl Daemon disable check dnl -------------------- +AS_IF([test "$enable_bgpd" != "no"], [ + AC_DEFINE([HAVE_BGPD], [1], [bgpd]) +]) + +AS_IF([test "$enable_ripd" != "no"], [ + AC_DEFINE([HAVE_RIPD], [1], [ripd]) +]) + +AS_IF([test "$enable_ripngd" != "no"], [ + AC_DEFINE([HAVE_RIPNGD], [1], [ripngd]) +]) + +AS_IF([test "$enable_ospfd" != "no"], [ + AC_DEFINE([HAVE_OSPFD], [1], [ospfd]) +]) + +AS_IF([test "$enable_ospf6d" != "no"], [ + AC_DEFINE([HAVE_OSPF6D], [1], [ospf6d]) +]) + AS_IF([test "$enable_ldpd" != "no"], [ AC_DEFINE([HAVE_LDPD], [1], [ldpd]) ]) +AS_IF([test "$enable_nhrpd" != "no"], [ + AC_DEFINE([HAVE_NHRPD], [1], [nhrpd]) +]) + +AS_IF([test "$enable_eigrpd" != "no"], [ + AC_DEFINE([HAVE_EIGRPD], [1], [eigrpd]) +]) + +AS_IF([test "$enable_babeld" != "no"], [ + AC_DEFINE([HAVE_BABELD], [1], [babeld]) +]) + +AS_IF([test "$enable_isisd" != "no"], [ + AC_DEFINE([HAVE_ISISD], [1], [isisd]) +]) + +AS_IF([test "$enable_pimd" != "no"], [ + AC_DEFINE([HAVE_PIMD], [1], [pimd]) +]) + +AS_IF([test "$enable_pbrd" != "no"], [ + AC_DEFINE([HAVE_PBRD], [1], [pbrd]) +]) + +AS_IF([test "$enable_sharpd" = "yes"], [ + AC_DEFINE([HAVE_SHARPD], [1], [sharpd]) +]) + +AS_IF([test "$enable_staticd" != "no"], [ + AC_DEFINE([HAVE_STATICD], [1], [staticd]) +]) + +AS_IF([test "$enable_fabricd" != "no"], [ + AC_DEFINE([HAVE_FABRICD], [1], [fabricd]) +]) + +AS_IF([test "$enable_vrrpd" != "no"], [ + AC_DEFINE([HAVE_VRRPD], [1], [vrrpd]) +]) + if test "$enable_bfdd" = "no"; then AC_DEFINE([HAVE_BFDD], [0], [bfdd]) BFDD="" @@ -2143,17 +2187,6 @@ if test "$enable_capabilities" != "no"; then LIBCAP="-lcap" frr_ac_lcaps="yes"] ) - else - AC_CHECK_HEADERS([priv.h], - [AC_MSG_CHECKING([Solaris style privileges are available]) - AC_TRY_COMPILE([#include <priv.h>], [getpflags(PRIV_AWARE);], - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_SOLARIS_CAPABILITIES], [1], [getpflags]) - frr_ac_scaps="yes"], - AC_MSG_RESULT(no) - ) - ] - ) fi if test "$frr_ac_scaps" = "yes" \ -o "$frr_ac_lcaps" = "yes"; then @@ -2219,7 +2252,7 @@ dnl check for malloc mallinfo struct and call dnl this must try and link using LIBS, in 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 mallinfo dnl ----------------------------------------- AC_CHECK_HEADERS([malloc.h malloc_np.h malloc/malloc.h],,, [FRR_INCLUDES]) @@ -2413,7 +2446,6 @@ AC_CONFIG_FILES([ config.version changelog-auto redhat/frr.spec - solaris/Makefile alpine/APKBUILD snapcraft/snapcraft.yaml lib/version.h diff --git a/debian/README.Debian b/debian/README.Debian index 01b9213ae4..a23a0efcac 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -31,10 +31,6 @@ The following Build Profiles have been added: controls whether the RPKI module is built. Will be enabled by default at some point, adds some extra dependencies. -- pkg.frr.nosnmp (pkg.frr.snmp) - controls whether the SNMP module is built, see below for license issues. - Will remain default-off as long as the license issue persists. - - pkg.frr.nosystemd Disables both systemd unit file installation as well as watchfrr sd_notify support at startup. Removes libsystemd dependency. @@ -108,3 +104,5 @@ See message #4525 from 2005-05-09 in the quagga-users mailing list. Check /etc/pam.d/frr, it probably denies access to your user. The passwords configured in /etc/frr/frr.conf are only for telnet access. + + -- OndÅ™ej Surý <OndÅ™ej Surý <ondrej@debian.org>>, Fri, 3 Jul 2020 12:39:42 +0200 diff --git a/debian/compat b/debian/compat index ec635144f6..f599e28b8a 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -9 +10 diff --git a/debian/control b/debian/control index fca6956760..4aaa9f21bf 100644 --- a/debian/control +++ b/debian/control @@ -2,64 +2,63 @@ Source: frr Section: net Priority: optional Maintainer: David Lamparter <equinox-debian@diac24.net> -Uploaders: FRRouting-dev <dev@lists.frrouting.org> -Build-Depends: - autotools-dev, - bison, - chrpath, - debhelper (>= 9), - debhelper (>= 9.20160709) <!pkg.frr.nosystemd> | dh-systemd <!pkg.frr.nosystemd>, - dh-autoreconf, - flex, - gawk, - install-info, - libc-ares-dev, - libcap-dev, - libjson-c-dev | libjson0-dev, - libpam0g-dev | libpam-dev, - libpcre3-dev, - libpython3-dev, - libreadline-dev, - librtr-dev <!pkg.frr.nortrlib>, - libsnmp-dev, - libssh-dev <!pkg.frr.nortrlib>, - libsystemd-dev <!pkg.frr.nosystemd>, - libyang-dev (>= 1.0.184), - pkg-config, - python3, - python3-dev, - python3-sphinx, - python3-pytest <!nocheck>, - texinfo (>= 4.7) -Standards-Version: 4.4.1 +Uploaders: FRRouting-dev <dev@lists.frrouting.org>, + OndÅ™ej Surý <ondrej@debian.org> +Build-Depends: bison, + chrpath, + debhelper (>= 10~) | dh-systemd, + debhelper (>= 9.20150101~), + flex, + gawk, + install-info, + libc-ares-dev, + libcap-dev, + libjson-c-dev | libjson0-dev, + libpam0g-dev | libpam-dev, + libpcre3-dev, + libpython3-dev, + libreadline-dev, + librtr-dev <!pkg.frr.nortrlib>, + libsnmp-dev, + libssh-dev <!pkg.frr.nortrlib>, + libsystemd-dev <!pkg.frr.nosystemd>, + libyang-dev (>= 1.0.184), + lsb-base, + pkg-config, + python3, + python3-dev, + python3-pytest <!nocheck>, + python3-sphinx, + texinfo (>= 4.7) +Standards-Version: 4.5.0.3 Homepage: https://www.frrouting.org/ Vcs-Browser: https://github.com/FRRouting/frr/tree/debian/master Vcs-Git: https://github.com/FRRouting/frr.git -b debian/master Package: frr Architecture: linux-any -Depends: - ${misc:Depends}, - ${shlibs:Depends}, - iproute2 | iproute, - logrotate (>= 3.2-11) +Depends: iproute2 | iproute, + logrotate (>= 3.2-11), + lsof, + ${misc:Depends}, + ${shlibs:Depends} Pre-Depends: adduser Recommends: frr-pythontools Suggests: frr-doc -Conflicts: - zebra, - zebra-pj, - pimd, - quagga, - quagga-bgpd, - quagga-core, - quagga-isisd, - quagga-ospf6d, - quagga-ospfd, - quagga-pimd, - quagga-ripd, - quagga-ripngd -Replaces: zebra, zebra-pj +Conflicts: pimd, + quagga, + quagga-bgpd, + quagga-core, + quagga-isisd, + quagga-ospf6d, + quagga-ospfd, + quagga-pimd, + quagga-ripd, + quagga-ripngd, + zebra, + zebra-pj +Replaces: zebra, + zebra-pj Description: FRRouting suite of internet protocols (BGP, OSPF, IS-IS, ...) FRRouting implements the routing protocols commonly used in the internet and private networks to exchange information between routers. @@ -77,10 +76,9 @@ Description: FRRouting suite of internet protocols (BGP, OSPF, IS-IS, ...) Package: frr-snmp Architecture: linux-any -Depends: - ${misc:Depends}, - ${shlibs:Depends}, - frr (= ${binary:Version}) +Depends: frr (= ${binary:Version}), + ${misc:Depends}, + ${shlibs:Depends} Recommends: snmpd Description: FRRouting suite - SNMP support Adds SNMP support to FRR's daemons by attaching to net-snmp's snmpd @@ -89,10 +87,9 @@ Description: FRRouting suite - SNMP support Package: frr-rpki-rtrlib Architecture: linux-any -Depends: - ${misc:Depends}, - ${shlibs:Depends}, - frr (= ${binary:Version}) +Depends: frr (= ${binary:Version}), + ${misc:Depends}, + ${shlibs:Depends} Description: FRRouting suite - BGP RPKI support (rtrlib) Adds RPKI support to FRR's bgpd, allowing validation of BGP routes against cryptographic information stored in WHOIS databases. This is @@ -105,10 +102,9 @@ Package: frr-doc Section: doc Architecture: all Multi-Arch: foreign -Depends: - ${misc:Depends}, - libjs-jquery, - libjs-underscore +Depends: libjs-jquery, + libjs-underscore, + ${misc:Depends} Suggests: frr Conflicts: quagga-doc Description: FRRouting suite - user manual @@ -118,11 +114,10 @@ Description: FRRouting suite - user manual Package: frr-pythontools Architecture: all -Depends: - ${misc:Depends}, - frr (<< ${source:Upstream-Version}.0-~), - frr (>= ${source:Version}~), - python3:any +Depends: frr (<< ${source:Upstream-Version}.0-~), + frr (>= ${source:Version}~), + python3:any, + ${misc:Depends} Description: FRRouting suite - Python tools The FRRouting suite uses a small Python tool to provide configuration reload functionality, particularly useful when the interactive configuration diff --git a/debian/frr-doc.install b/debian/frr-doc.install index c48dc5a8db..a666162122 100644 --- a/debian/frr-doc.install +++ b/debian/frr-doc.install @@ -1,10 +1,16 @@ # html docs include RST sources -usr/share/doc/frr/html - # info + images referenced by it -usr/share/info/ -doc/user/_build/texinfo/*.png usr/share/info - # other README.md usr/share/doc/frr doc/figures/*.png usr/share/doc/frr +doc/figures/fig-normal-processing.png usr/share/info +doc/figures/fig-rs-processing.png usr/share/info +doc/figures/fig-vnc-commercial-route-reflector.png usr/share/info +doc/figures/fig-vnc-frr-route-reflector.png usr/share/info +doc/figures/fig-vnc-gw.png usr/share/info +doc/figures/fig-vnc-mesh.png usr/share/info +doc/figures/fig-vnc-redundant-route-reflectors.png usr/share/info +doc/figures/fig_topologies_full.png usr/share/info +doc/figures/fig_topologies_rs.png usr/share/info +usr/share/doc/frr/html +usr/share/info/ diff --git a/debian/frr.dirs b/debian/frr.dirs index 4b05c8c907..9e592e370c 100644 --- a/debian/frr.dirs +++ b/debian/frr.dirs @@ -1,6 +1,6 @@ -etc/logrotate.d/ etc/frr/ etc/iproute2/rt_protos.d/ +etc/logrotate.d/ usr/share/doc/frr/ usr/share/doc/frr/examples/ usr/share/lintian/overrides/ diff --git a/debian/frr.docs b/debian/frr.docs index 34dbbd7bc7..220127caa1 100644 --- a/debian/frr.docs +++ b/debian/frr.docs @@ -1,2 +1,2 @@ -tools/zebra.el debian/README.Debian +tools/zebra.el diff --git a/debian/frr.install b/debian/frr.install index e2485fe8b8..cefc3135b2 100644 --- a/debian/frr.install +++ b/debian/frr.install @@ -1,20 +1,20 @@ +debian/frr.conf usr/lib/tmpfiles.d etc/ -usr/bin/vtysh +tools/frr-reload usr/lib/frr/ usr/bin/mtracebis +usr/bin/vtysh usr/lib/*/frr/libfrr.* usr/lib/*/frr/libfrrcares.* usr/lib/*/frr/libfrrospfapiclient.* +usr/lib/*/frr/modules/bgpd_bmp.so +usr/lib/*/frr/modules/dplane_fpm_nl.so +usr/lib/*/frr/modules/zebra_cumulus_mlag.so +usr/lib/*/frr/modules/zebra_fpm.so +usr/lib/*/frr/modules/zebra_irdp.so usr/lib/frr/*.sh usr/lib/frr/*d usr/lib/frr/watchfrr usr/lib/frr/zebra -usr/lib/*/frr/modules/zebra_cumulus_mlag.so -usr/lib/*/frr/modules/dplane_fpm_nl.so -usr/lib/*/frr/modules/zebra_irdp.so -usr/lib/*/frr/modules/zebra_fpm.so -usr/lib/*/frr/modules/bgpd_bmp.so usr/share/doc/frr/examples usr/share/man/ usr/share/yang/ -tools/frr-reload usr/lib/frr/ -debian/frr.conf usr/lib/tmpfiles.d diff --git a/debian/frr.tmpfile b/debian/frr.tmpfile new file mode 100644 index 0000000000..dee3cd849a --- /dev/null +++ b/debian/frr.tmpfile @@ -0,0 +1,2 @@ +# Create the /run/frr directory at boot or from systemd-tmpfiles on install +d /run/frr 0755 frr frr diff --git a/debian/gbp.conf b/debian/gbp.conf new file mode 100644 index 0000000000..990c4d226e --- /dev/null +++ b/debian/gbp.conf @@ -0,0 +1,4 @@ +[DEFAULT] +pristine-tar = False +debian-branch = master +upstream-tree=SLOPPY diff --git a/debian/rules b/debian/rules index c8550ecb52..6cc03c378a 100755 --- a/debian/rules +++ b/debian/rules @@ -22,17 +22,17 @@ else endif ifeq ($(filter pkg.frr.nosystemd,$(DEB_BUILD_PROFILES)),) - DH_WITH_SYSTEMD=systemd, + DH_WITHOUT_SYSTEMD= CONF_SYSTEMD=--enable-systemd=yes else - DH_WITH_SYSTEMD= + DH_WITHOUT_SYSTEMD=--without=systemd CONF_SYSTEMD=--enable-systemd=no endif export PYTHON=python3 %: - dh $@ --with=$(DH_WITH_SYSTEMD)autoreconf --parallel + dh $@ $(DH_WITHOUT_SYSTEMD) override_dh_auto_configure: $(shell dpkg-buildflags --export=sh); \ diff --git a/debian/source/format b/debian/source/format index af745b310b..163aaf8d82 100644 --- a/debian/source/format +++ b/debian/source/format @@ -1 +1 @@ -3.0 (git) +3.0 (quilt) diff --git a/debian/tests/control b/debian/tests/control index 5990a69370..6cb5b02dc1 100644 --- a/debian/tests/control +++ b/debian/tests/control @@ -3,9 +3,12 @@ Depends: frr Restrictions: needs-root, isolation-container Tests: bgpd-snmp-rpki -Depends: frr, frr-snmp, frr-rpki-rtrlib +Depends: frr, + frr-rpki-rtrlib, + frr-snmp Restrictions: needs-root, isolation-container Tests: py-frr-reload -Depends: frr, frr-pythontools +Depends: frr, + frr-pythontools Restrictions: needs-root, isolation-container diff --git a/debian/watch b/debian/watch index c286392d7e..f17eba4130 100644 --- a/debian/watch +++ b/debian/watch @@ -1,4 +1,5 @@ version=4 +opts=uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\d*)$/$1~$2/ \ https://github.com/FRRouting/frr/releases/ \ - download/frr-(?:\d[\d.]*)/frr-(\d[\d.]*)\.tar\.xz debian uupdate + .*/frr-(\d\S+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) diff --git a/doc/developer/building-frr-for-omnios.rst b/doc/developer/building-frr-for-omnios.rst deleted file mode 100644 index 3a69279b0c..0000000000 --- a/doc/developer/building-frr-for-omnios.rst +++ /dev/null @@ -1,143 +0,0 @@ -OmniOS (OpenSolaris) -==================================================== - -OmniOS restrictions: --------------------- - -- MPLS is not supported on ``OmniOS`` or ``Solaris``. MPLS requires a - Linux Kernel (4.5 or higher). LDP can be built, but may have limited - use without MPLS - -Enable IP & IPv6 forwarding -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -:: - - routeadm -e ipv4-forwarding - routeadm -e ipv6-forwarding - -Install required packages -------------------------- - -Add packages: - -:: - - pkg install \ - developer/build/autoconf \ - developer/build/automake \ - developer/lexer/flex \ - developer/parser/bison \ - developer/object-file \ - developer/linker \ - developer/library/lint \ - developer/build/gnu-make \ - developer/gcc51 \ - library/idnkit \ - library/idnkit/header-idnkit \ - system/header \ - system/library/math/header-math \ - git libtool pkg-config - -Add additional Solaris packages: - -:: - - pkgadd -d http://get.opencsw.org/now - /opt/csw/bin/pkgutil -U - /opt/csw/bin/pkgutil -y -i texinfo - /opt/csw/bin/pkgutil -y -i perl - /opt/csw/bin/pkgutil -y -i libjson_c_dev - /opt/csw/bin/pkgutil -y -i python27 py_pip python27_dev - -Add libjson to Solaris equivalent of ld.so.conf - -:: - - crle -l /opt/csw/lib -u - -Add pytest: - -:: - - pip install "pytest<5" - -Install Sphinx::: - - pip install sphinx - -Select Python 2.7 as default (required for pytest) - -:: - - rm -f /usr/bin/python - ln -s /opt/csw/bin/python2.7 /usr/bin/python - -Fix PATH for all users and non-interactive sessions. Edit -``/etc/default/login`` and add the following default PATH: - -:: - - PATH=/usr/gnu/bin:/usr/bin:/usr/sbin:/sbin:/opt/csw/bin - -Edit ``~/.profile`` and add the following default PATH: - -:: - - PATH=/usr/gnu/bin:/usr/bin:/usr/sbin:/sbin:/opt/csw/bin - -.. include:: building-libyang.rst - -Get FRR, compile it and install it (from Git) ---------------------------------------------- - -**This assumes you want to build and install FRR from source and not -using any packages** - -Add frr group and user -^^^^^^^^^^^^^^^^^^^^^^ - -:: - - sudo groupadd -g 93 frr - sudo groupadd -g 94 frrvty - sudo useradd -g 93 -u 93 -G frrvty -c "FRR suite" \ - -d /nonexistent -s /bin/false frr - -(You may prefer different options on configure statement. These are just -an example) - -:: - - git clone https://github.com/frrouting/frr.git frr - cd frr - ./bootstrap.sh - export MAKE=gmake - export LDFLAGS="-L/opt/csw/lib" - export CPPFLAGS="-I/opt/csw/include" - export PKG_CONFIG_PATH=/opt/csw/lib/pkgconfig - ./configure \ - --sysconfdir=/etc/frr \ - --enable-exampledir=/usr/share/doc/frr/examples/ \ - --localstatedir=/var/run/frr \ - --sbindir=/usr/lib/frr \ - --enable-multipath=64 \ - --enable-user=frr \ - --enable-group=frr \ - --enable-vty-group=frrvty \ - --enable-configfile-mask=0640 \ - --enable-logfile-mask=0640 \ - --enable-fpm \ - --with-pkg-git-version \ - --with-pkg-extra-version=-MyOwnFRRVersion - gmake - gmake check - sudo gmake install - -Enable IP & IPv6 forwarding -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -:: - - routeadm -e ipv4-forwarding - routeadm -e ipv6-forwarding diff --git a/doc/developer/building.rst b/doc/developer/building.rst index fbe1f24d35..730741a8ef 100644 --- a/doc/developer/building.rst +++ b/doc/developer/building.rst @@ -20,7 +20,6 @@ Building FRR 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-ubuntu1404 diff --git a/doc/developer/subdir.am b/doc/developer/subdir.am index 03b4b5a3e2..57f885ecc1 100644 --- a/doc/developer/subdir.am +++ b/doc/developer/subdir.am @@ -16,7 +16,6 @@ dev_RSTFILES = \ 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-openwrt.rst \ doc/developer/building-frr-for-ubuntu1404.rst \ diff --git a/doc/user/basic.rst b/doc/user/basic.rst index 5b7786de18..e85e1842b3 100644 --- a/doc/user/basic.rst +++ b/doc/user/basic.rst @@ -159,8 +159,8 @@ Basic Config Commands use the ``log record-priority`` global configuration command. To disable this option, use the ``no`` form of the command. By default, the severity level is not included in logged messages. Note: some - versions of syslogd (including Solaris) can be configured to include - the facility and level in the messages emitted. + versions of syslogd can be configured to include the facility and + level in the messages emitted. .. index:: single: log timestamp precision (0-6) diff --git a/doc/user/overview.rst b/doc/user/overview.rst index 724d1d0b9c..07702cbdd1 100644 --- a/doc/user/overview.rst +++ b/doc/user/overview.rst @@ -139,7 +139,6 @@ of their original release (in case of GNU/Linux, this is since the kernel's release on https://kernel.org/) may need some work. Similarly, the following platforms may work with some effort: -- Solaris - MacOS Recent versions of the following compilers are well tested: @@ -148,6 +147,17 @@ Recent versions of the following compilers are well tested: - LLVM's Clang - Intel's ICC +.. _unsupported-platforms: + +UnSupported Platforms +--------------------- + +.. index:: UnSupported platforms + +In General if the platform you are attempting to use is not listed above then +FRR does not support being run on that platform. The only caveat here is that +version 7.5 and before Solaris was supported in a limited fashion. + .. _feature-matrix: Feature Matrix @@ -167,73 +177,73 @@ feature you're interested in, it should be supported on your platform. 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** | | | | | | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| `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` | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| `pbrd` (Policy Routing) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| **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` | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| `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` | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| `nhrpd` (NHRP) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| **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` | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| `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** | | | | | | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| `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** | | | | | | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| `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` | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| EVPN BUM Forwarding | :mark:`≥5.0` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | -+-----------------------------------+----------------+--------------+------------+------------+------------+ -| `vrrpd` (VRRP) | :mark:`≥5.1` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | -+-----------------------------------+----------------+--------------+------------+------------+------------+ ++-----------------------------------+----------------+--------------+------------+------------+ +| Daemon / Feature | Linux | OpenBSD | FreeBSD | NetBSD | ++===================================+================+==============+============+============+ +| **FRR Core** | | | | | ++-----------------------------------+----------------+--------------+------------+------------+ +| `zebra` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| VRF | :mark:`≥4.8` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ +| MPLS | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ +| `pbrd` (Policy Routing) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ +| **WAN / Carrier protocols** | | | | | ++-----------------------------------+----------------+--------------+------------+------------+ +| `bgpd` (BGP) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| VRF / L3VPN | :mark:`≥4.8` | :mark:`CP` | :mark:`CP` | :mark:`CP` | +| | :mark:`†4.3` | | | | ++-----------------------------------+----------------+--------------+------------+------------+ +| EVPN | :mark:`≥4.18` | :mark:`CP` | :mark:`CP` | :mark:`CP` | +| | :mark:`†4.9` | | | | ++-----------------------------------+----------------+--------------+------------+------------+ +| VNC (Virtual Network Control) | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | ++-----------------------------------+----------------+--------------+------------+------------+ +| Flowspec | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | ++-----------------------------------+----------------+--------------+------------+------------+ +| `ldpd` (LDP) | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ +| VPWS / PW | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ +| VPLS | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ +| `nhrpd` (NHRP) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ +| **Link-State Routing** | | | | | ++-----------------------------------+----------------+--------------+------------+------------+ +| `ospfd` (OSPFv2) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| Segment Routing | :mark:`≥4.12` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ +| `ospf6d` (OSPFv3) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| `isisd` (IS-IS) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| **Distance-Vector Routing** | | | | | ++-----------------------------------+----------------+--------------+------------+------------+ +| `ripd` (RIPv2) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| `ripngd` (RIPng) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| `babeld` (BABEL) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| `eigrpd` (EIGRP) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| **Multicast Routing** | | | | | ++-----------------------------------+----------------+--------------+------------+------------+ +| `pimd` (PIM) | :mark:`≥4.18` | :mark:`N` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| SSM (Source Specific) | :mark:`Y` | :mark:`N` | :mark:`Y` | :mark:`Y` | ++-----------------------------------+----------------+--------------+------------+------------+ +| ASM (Any Source) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ +| EVPN BUM Forwarding | :mark:`≥5.0` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ +| `vrrpd` (VRRP) | :mark:`≥5.1` | :mark:`N` | :mark:`N` | :mark:`N` | ++-----------------------------------+----------------+--------------+------------+------------+ The indicators have the following semantics: diff --git a/doc/user/pbr.rst b/doc/user/pbr.rst index 99ef258cb2..c869c6bc45 100644 --- a/doc/user/pbr.rst +++ b/doc/user/pbr.rst @@ -39,7 +39,7 @@ listing of ECMP nexthops used to forward packets for when a pbr-map is matched. sub-mode where you can specify individual nexthops. To exit this mode type exit or end as per normal conventions for leaving a sub-mode. -.. clicmd:: nexthop [A.B.C.D|X:X::X:XX] [interface] [nexthop-vrf NAME] [label LABELS] +.. clicmd:: nexthop [A.B.C.D|X:X::X:XX] [interface [onlink]] [nexthop-vrf NAME] [label LABELS] Create a v4 or v6 nexthop. All normal rules for creating nexthops that you are used to are allowed here. The syntax was intentionally kept the same as diff --git a/doc/user/pim.rst b/doc/user/pim.rst index d30a5ed647..d5899ab455 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -15,7 +15,7 @@ network for optimizing forwarding of overlay BUM traffic. On Linux for PIM-SM operation you *must* have kernel version 4.18 or greater. To use PIM for EVPN BUM forwarding, kernels 5.0 or greater are required. - OpenBSD has no multicast support and FreeBSD, NetBSD and Solaris only + OpenBSD has no multicast support and FreeBSD, and NetBSD only have support for SSM. .. _starting-and-stopping-pimd: diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index a9ab162b40..98655e6cba 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -183,8 +183,8 @@ Standard Commands .. clicmd:: no link-detect Enable/disable link-detect on platforms which support this. Currently only - Linux and Solaris, and only where network interface drivers support - reporting link-state via the ``IFF_RUNNING`` flag. + Linux, and only where network interface drivers support reporting + link-state via the ``IFF_RUNNING`` flag. In FRR, link-detect is on by default. diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h index 33c17af1cc..c06fe708f7 100644 --- a/include/linux/neighbour.h +++ b/include/linux/neighbour.h @@ -31,6 +31,7 @@ enum { NDA_PROTOCOL, /* Originator of entry */ NDA_NH_ID, NDA_NOTIFY, + NDA_EXT_FLAGS, __NDA_MAX }; @@ -49,6 +50,10 @@ enum { #define NTF_STICKY 0x40 #define NTF_ROUTER 0x80 +/* Neighbor Cache Entry extended flags, part of NDA_EXT_FLAGS attribute */ +#define NTF_E_WEAK_OVERRIDE_STATE 0x01 +#define NTF_E_MH_PEER_SYNC 0x02 + /* * Neighbor Cache Entry States. */ diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index eddbc04504..9b814c92de 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -164,6 +164,20 @@ enum { RTM_GETNEXTHOP, #define RTM_GETNEXTHOP RTM_GETNEXTHOP + RTM_NEWLINKPROP = 108, +#define RTM_NEWLINKPROP RTM_NEWLINKPROP + RTM_DELLINKPROP, +#define RTM_DELLINKPROP RTM_DELLINKPROP + RTM_GETLINKPROP, +#define RTM_GETLINKPROP RTM_GETLINKPROP + + RTM_NEWVLAN = 112, +#define RTM_NEWNVLAN RTM_NEWVLAN + RTM_DELVLAN, +#define RTM_DELVLAN RTM_DELVLAN + RTM_GETVLAN, +#define RTM_GETVLAN RTM_GETVLAN + __RTM_MAX, #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) }; @@ -172,7 +186,7 @@ enum { #define RTM_NR_FAMILIES (RTM_NR_MSGTYPES >> 2) #define RTM_FAM(cmd) (((cmd) - RTM_BASE) >> 2) -/* +/* Generic structure for encapsulation of optional route information. It is reminiscent of sockaddr, but with sa_family replaced with attribute type. @@ -212,7 +226,7 @@ struct rtmsg { unsigned char rtm_table; /* Routing table id */ unsigned char rtm_protocol; /* Routing protocol; see below */ - unsigned char rtm_scope; /* See below */ + unsigned char rtm_scope; /* See below */ unsigned char rtm_type; /* See below */ unsigned rtm_flags; @@ -243,12 +257,12 @@ enum { /* rtm_protocol */ -#define RTPROT_UNSPEC 0 -#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirects; - not used by current IPv4 */ -#define RTPROT_KERNEL 2 /* Route installed by kernel */ -#define RTPROT_BOOT 3 /* Route installed during boot */ -#define RTPROT_STATIC 4 /* Route installed by administrator */ +#define RTPROT_UNSPEC 0 +#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirects; + not used by current IPv4 */ +#define RTPROT_KERNEL 2 /* Route installed by kernel */ +#define RTPROT_BOOT 3 /* Route installed during boot */ +#define RTPROT_STATIC 4 /* Route installed by administrator */ /* Values of protocol >= RTPROT_STATIC are not interpreted by kernel; they are just passed from user and back as is. @@ -257,22 +271,23 @@ enum { avoid conflicts. */ -#define RTPROT_GATED 8 /* Apparently, GateD */ -#define RTPROT_RA 9 /* RDISC/ND router advertisements */ -#define RTPROT_MRT 10 /* Merit MRT */ -#define RTPROT_ZEBRA 11 /* Zebra */ -#define RTPROT_BIRD 12 /* BIRD */ -#define RTPROT_DNROUTED 13 /* DECnet routing daemon */ -#define RTPROT_XORP 14 /* XORP */ -#define RTPROT_NTK 15 /* Netsukuku */ -#define RTPROT_DHCP 16 /* DHCP client */ -#define RTPROT_MROUTED 17 /* Multicast daemon */ -#define RTPROT_BABEL 42 /* Babel daemon */ -#define RTPROT_BGP 186 /* BGP Routes */ -#define RTPROT_ISIS 187 /* ISIS Routes */ -#define RTPROT_OSPF 188 /* OSPF Routes */ -#define RTPROT_RIP 189 /* RIP Routes */ -#define RTPROT_EIGRP 192 /* EIGRP Routes */ +#define RTPROT_GATED 8 /* Apparently, GateD */ +#define RTPROT_RA 9 /* RDISC/ND router advertisements */ +#define RTPROT_MRT 10 /* Merit MRT */ +#define RTPROT_ZEBRA 11 /* Zebra */ +#define RTPROT_BIRD 12 /* BIRD */ +#define RTPROT_DNROUTED 13 /* DECnet routing daemon */ +#define RTPROT_XORP 14 /* XORP */ +#define RTPROT_NTK 15 /* Netsukuku */ +#define RTPROT_DHCP 16 /* DHCP client */ +#define RTPROT_MROUTED 17 /* Multicast daemon */ +#define RTPROT_KEEPALIVED 18 /* Keepalived daemon */ +#define RTPROT_BABEL 42 /* Babel daemon */ +#define RTPROT_BGP 186 /* BGP Routes */ +#define RTPROT_ISIS 187 /* ISIS Routes */ +#define RTPROT_OSPF 188 /* OSPF Routes */ +#define RTPROT_RIP 189 /* RIP Routes */ +#define RTPROT_EIGRP 192 /* EIGRP Routes */ /* rtm_scope @@ -302,6 +317,8 @@ enum rt_scope_t { #define RTM_F_PREFIX 0x800 /* Prefix addresses */ #define RTM_F_LOOKUP_TABLE 0x1000 /* set rtm_table to FIB lookup result */ #define RTM_F_FIB_MATCH 0x2000 /* return full fib lookup match */ +#define RTM_F_OFFLOAD 0x4000 /* route is offloaded */ +#define RTM_F_TRAP 0x8000 /* route is trapping packets */ /* Reserved table identifiers */ @@ -523,7 +540,7 @@ struct ifinfomsg { }; /******************************************************************** - * prefix information + * prefix information ****/ struct prefixmsg { @@ -537,7 +554,7 @@ struct prefixmsg { unsigned char prefix_pad3; }; -enum +enum { PREFIX_UNSPEC, PREFIX_ADDRESS, @@ -593,11 +610,17 @@ enum { TCA_HW_OFFLOAD, TCA_INGRESS_BLOCK, TCA_EGRESS_BLOCK, + TCA_DUMP_FLAGS, __TCA_MAX }; #define TCA_MAX (__TCA_MAX - 1) +#define TCA_DUMP_FLAGS_TERSE (1 << 0) /* Means that in dump user gets only basic + * data necessary to identify the objects + * (handle, cookie, etc.) and stats. + */ + #define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg)))) #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg)) @@ -714,6 +737,8 @@ enum rtnetlink_groups { #define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R RTNLGRP_NEXTHOP, #define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP + RTNLGRP_BRVLAN, +#define RTNLGRP_BRVLAN RTNLGRP_BRVLAN __RTNLGRP_MAX }; #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) @@ -753,6 +778,7 @@ enum { #define RTEXT_FILTER_BRVLAN (1 << 1) #define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2) #define RTEXT_FILTER_SKIP_STATS (1 << 3) +#define RTEXT_FILTER_MRP (1 << 4) /* End of information exported to user level */ diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index f7cdd58f72..5bfbb2cf7e 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -304,7 +304,6 @@ void isis_adj_state_change(struct isis_adjacency **padj, continue; if (new_state == ISIS_ADJ_UP) { circuit->upadjcount[level - 1]++; - hook_call(isis_adj_state_change_hook, adj); /* update counter & timers for debugging * purposes */ adj->last_flap = time(NULL); @@ -317,7 +316,6 @@ void isis_adj_state_change(struct isis_adjacency **padj, if (circuit->upadjcount[level - 1] == 0) isis_tx_queue_clean(circuit->tx_queue); - hook_call(isis_adj_state_change_hook, adj); if (new_state == ISIS_ADJ_DOWN) del = true; } @@ -342,7 +340,6 @@ void isis_adj_state_change(struct isis_adjacency **padj, continue; if (new_state == ISIS_ADJ_UP) { circuit->upadjcount[level - 1]++; - hook_call(isis_adj_state_change_hook, adj); /* update counter & timers for debugging * purposes */ @@ -365,13 +362,14 @@ void isis_adj_state_change(struct isis_adjacency **padj, if (circuit->upadjcount[level - 1] == 0) isis_tx_queue_clean(circuit->tx_queue); - hook_call(isis_adj_state_change_hook, adj); if (new_state == ISIS_ADJ_DOWN) del = true; } } } + hook_call(isis_adj_state_change_hook, adj); + if (del) { isis_delete_adj(adj); *padj = NULL; @@ -467,11 +465,15 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, vty_out(vty, "%-3u", adj->level); /* level */ vty_out(vty, "%-13s", adj_state2string(adj->adj_state)); now = time(NULL); - if (adj->last_upd) - vty_out(vty, "%-9llu", - (unsigned long long)adj->last_upd - + adj->hold_time - now); - else + if (adj->last_upd) { + if (adj->last_upd + adj->hold_time + < (unsigned long long)now) + vty_out(vty, " Expiring"); + else + vty_out(vty, " %-9llu", + (unsigned long long)adj->last_upd + + adj->hold_time - now); + } else vty_out(vty, "- "); vty_out(vty, "%-10s", snpa_print(adj->snpa)); vty_out(vty, "\n"); @@ -491,11 +493,15 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, vty_out(vty, ", Level: %u", adj->level); /* level */ vty_out(vty, ", State: %s", adj_state2string(adj->adj_state)); now = time(NULL); - if (adj->last_upd) - vty_out(vty, ", Expires in %s", - time2string(adj->last_upd + adj->hold_time - - now)); - else + if (adj->last_upd) { + if (adj->last_upd + adj->hold_time + < (unsigned long long)now) + vty_out(vty, " Expiring"); + else + vty_out(vty, ", Expires in %s", + time2string(adj->last_upd + + adj->hold_time - now)); + } else vty_out(vty, ", Expires in %s", time2string(adj->hold_time)); vty_out(vty, "\n"); diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index 0988fe8578..6edbc2956a 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -80,14 +80,18 @@ int isis_instance_create(struct nb_cb_create_args *args) int isis_instance_destroy(struct nb_cb_destroy_args *args) { struct isis_area *area; + vrf_id_t vrf_id; if (args->event != NB_EV_APPLY) return NB_OK; area = nb_running_unset_entry(args->dnode); + + vrf_id = area->isis->vrf_id; + isis_area_destroy(area); /* remove ldp-sync config */ - if (area->isis->vrf_id == VRF_DEFAULT) + if (vrf_id == VRF_DEFAULT) isis_ldp_sync_gbl_exit(true); return NB_OK; diff --git a/lib/hash.h b/lib/hash.h index e7ba3187f5..00953ff3b3 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -236,7 +236,8 @@ extern void *hash_release(struct hash *hash, void *data); * Iterate over the elements in a hash table. * * It is safe to delete items passed to the iteration function from the hash - * table during iteration. Please note that adding entries to the hash + * table during iteration. More than one item cannot be deleted during each + * iteration. Please note that adding entries to the hash * during the walk will cause undefined behavior in that some new entries * will be walked and some will not. So do not do this. * @@ -802,44 +802,6 @@ void if_dump_all(void) if_dump(ifp); } -#ifdef SUNOS_5 -/* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created - * a seperate struct interface for each logical interface, so config - * file may be full of 'interface fooX:Y'. Solaris however does not - * expose logical interfaces via PF_ROUTE, so trying to track logical - * interfaces can be fruitless, for that reason Quagga only tracks - * the primary IP interface. - * - * We try accomodate SUNWzebra by: - * - looking up the interface name, to see whether it exists, if so - * its useable - * - for protocol daemons, this could only because zebra told us of - * the interface - * - for zebra, only because it learnt from kernel - * - if not: - * - search the name to see if it contains a sub-ipif / logical interface - * seperator, the ':' char. If it does: - * - text up to that char must be the primary name - get that name. - * if not: - * - no idea, just get the name in its entirety. - */ -static struct interface *if_sunwzebra_get(const char *name, vrf_id_t vrf_id) -{ - struct interface *ifp; - char *cp; - - if ((ifp = if_lookup_by_name(name, vrf_id)) != NULL) - return ifp; - - /* hunt the primary interface name... */ - cp = strchr(name, ':'); - if (cp) - *cp = '\0'; - - return if_get_by_name(name, vrf_id); -} -#endif /* SUNOS_5 */ - #if 0 /* For debug purpose. */ DEFUN (show_address, @@ -1554,11 +1516,7 @@ static int lib_interface_create(struct nb_cb_create_args *args) case NB_EV_APPLY: vrf = vrf_lookup_by_name(vrfname); assert(vrf); -#ifdef SUNOS_5 - ifp = if_sunwzebra_get(ifname, vrf->vrf_id); -#else ifp = if_get_by_name(ifname, vrf->vrf_id); -#endif /* SUNOS_5 */ ifp->configured = true; nb_running_set_entry(args->dnode, ifp); @@ -452,7 +452,10 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_OPAQUE_MESSAGE), DESC_ENTRY(ZEBRA_OPAQUE_REGISTER), DESC_ENTRY(ZEBRA_OPAQUE_UNREGISTER), - DESC_ENTRY(ZEBRA_NEIGH_DISCOVER)}; + DESC_ENTRY(ZEBRA_NEIGH_DISCOVER), + DESC_ENTRY(ZEBRA_NHG_ADD), + DESC_ENTRY(ZEBRA_NHG_DEL), + DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER)}; #undef DESC_ENTRY static const struct zebra_desc_table unknown = {0, "unknown", '?'}; diff --git a/lib/netns_linux.c b/lib/netns_linux.c index e8d549b4e0..c688433983 100644 --- a/lib/netns_linux.c +++ b/lib/netns_linux.c @@ -43,9 +43,6 @@ DEFINE_MTYPE_STATIC(LIB, NS, "NetNS Context") DEFINE_MTYPE_STATIC(LIB, NS_NAME, "NetNS Name") -/* default NS ID value used when VRF backend is not NETNS */ -#define NS_DEFAULT_INTERNAL 0 - static inline int ns_compare(const struct ns *ns, const struct ns *ns2); static struct ns *ns_lookup_name_internal(const char *name); @@ -101,9 +98,6 @@ static inline int setns(int fd, int nstype) static int have_netns_enabled = -1; #endif /* HAVE_NETNS */ -/* default NS ID value used when VRF backend is not NETNS */ -#define NS_DEFAULT_INTERNAL 0 - static int have_netns(void) { #ifdef HAVE_NETNS @@ -612,15 +606,7 @@ ns_id_t ns_id_get_absolute(ns_id_t ns_id_reference, ns_id_t link_nsid) return ns->ns_id; } -ns_id_t ns_get_default_id(void) -{ - if (default_ns) - return default_ns->ns_id; - return NS_DEFAULT_INTERNAL; -} - struct ns *ns_get_default(void) { return default_ns; } - diff --git a/lib/netns_other.c b/lib/netns_other.c index 740d2b621e..3fc4b8df4b 100644 --- a/lib/netns_other.c +++ b/lib/netns_other.c @@ -18,8 +18,8 @@ */ -#if !defined(GNU_LINUX) && (defined(SUNOS_5) || defined(OPEN_BSD)) -/* SUNOS_5 or OPEN_BSD */ +#if !defined(GNU_LINUX) && defined(OPEN_BSD) +/* OPEN_BSD */ #include <zebra.h> #include "ns.h" @@ -110,13 +110,6 @@ void ns_init(void) { } -/* API to retrieve default NS */ -ns_id_t ns_get_default_id(void) -{ - return NS_UNKNOWN; -} - - /* API that can be used to change from NS */ int ns_switchback_to_initial(void) { diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 687cac4062..83905abe43 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -41,6 +41,7 @@ struct nexthop_hold { char *nhvrf_name; union sockunion *addr; char *intf; + bool onlink; char *labels; uint32_t weight; char *backup_str; @@ -560,6 +561,10 @@ static int nhgl_cmp(struct nexthop_hold *nh1, struct nexthop_hold *nh2) if (ret) return ret; + ret = ((int)nh2->onlink) - ((int)nh1->onlink); + if (ret) + return ret; + return nhgc_cmp_helper(nh1->labels, nh2->labels); } @@ -673,8 +678,8 @@ DEFPY(no_nexthop_group_backup, no_nexthop_group_backup_cmd, static void nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc, const char *nhvrf_name, const union sockunion *addr, - const char *intf, const char *labels, - const uint32_t weight, + const char *intf, bool onlink, + const char *labels, const uint32_t weight, const char *backup_str) { struct nexthop_hold *nh; @@ -690,6 +695,8 @@ static void nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc, if (labels) nh->labels = XSTRDUP(MTYPE_TMP, labels); + nh->onlink = onlink; + nh->weight = weight; if (backup_str) @@ -738,9 +745,10 @@ static void nexthop_group_unsave_nhop(struct nexthop_group_cmd *nhgc, */ static bool nexthop_group_parse_nexthop(struct nexthop *nhop, const union sockunion *addr, - const char *intf, const char *name, - const char *labels, int *lbl_ret, - uint32_t weight, const char *backup_str) + const char *intf, bool onlink, + const char *name, const char *labels, + int *lbl_ret, uint32_t weight, + const char *backup_str) { int ret = 0; struct vrf *vrf; @@ -764,6 +772,9 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop, return false; } + if (onlink) + SET_FLAG(nhop->flags, NEXTHOP_FLAG_ONLINK); + if (addr) { if (addr->sa.sa_family == AF_INET) { nhop->gate.ipv4.s_addr = addr->sin.sin_addr.s_addr; @@ -820,15 +831,15 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop, static bool nexthop_group_parse_nhh(struct nexthop *nhop, const struct nexthop_hold *nhh) { - return (nexthop_group_parse_nexthop(nhop, nhh->addr, nhh->intf, - nhh->nhvrf_name, nhh->labels, NULL, - nhh->weight, nhh->backup_str)); + return (nexthop_group_parse_nexthop( + nhop, nhh->addr, nhh->intf, nhh->onlink, nhh->nhvrf_name, + nhh->labels, NULL, nhh->weight, nhh->backup_str)); } DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, "[no] nexthop\ <\ - <A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\ + <A.B.C.D|X:X::X:X>$addr [INTERFACE$intf [onlink$onlink]]\ |INTERFACE$intf\ >\ [{ \ @@ -842,6 +853,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, "v4 Address\n" "v6 Address\n" "Interface to use\n" + "Treat nexthop as directly attached to the interface\n" "Interface to use\n" "If the nexthop is in a different vrf tell us\n" "The nexthop-vrf Name\n" @@ -870,8 +882,9 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, } } - legal = nexthop_group_parse_nexthop(&nhop, addr, intf, vrf_name, label, - &lbl_ret, weight, backup_idx); + legal = nexthop_group_parse_nexthop(&nhop, addr, intf, !!onlink, + vrf_name, label, &lbl_ret, weight, + backup_idx); if (nhop.type == NEXTHOP_TYPE_IPV6 && IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6)) { @@ -933,8 +946,8 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, } /* Save config always */ - nexthop_group_save_nhop(nhgc, vrf_name, addr, intf, label, - weight, backup_idx); + nexthop_group_save_nhop(nhgc, vrf_name, addr, intf, !!onlink, + label, weight, backup_idx); if (legal && nhg_hooks.add_nexthop) nhg_hooks.add_nexthop(nhgc, nh); @@ -1106,6 +1119,9 @@ static void nexthop_group_write_nexthop_internal(struct vty *vty, if (nh->intf) vty_out(vty, " %s", nh->intf); + if (nh->onlink) + vty_out(vty, " onlink"); + if (nh->nhvrf_name) vty_out(vty, " nexthop-vrf %s", nh->nhvrf_name); diff --git a/lib/northbound.c b/lib/northbound.c index 99c6ab57ec..5816c162d8 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -122,9 +122,9 @@ static int nb_node_new_cb(const struct lys_node *snode, void *arg) if (CHECK_FLAG(snode->nodetype, LYS_CONTAINER | LYS_LIST)) { bool config_only = true; - yang_snodes_iterate_subtree(snode, NULL, - nb_node_check_config_only, 0, - &config_only); + (void)yang_snodes_iterate_subtree(snode, NULL, + nb_node_check_config_only, 0, + &config_only); if (config_only) SET_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY); } @@ -161,10 +161,7 @@ extern ns_id_t ns_map_nsid_with_external(ns_id_t ns_id, bool map); */ extern void ns_init(void); -/* API to retrieve default NS */ -extern ns_id_t ns_get_default_id(void); - -#define NS_DEFAULT ns_get_default_id() +#define NS_DEFAULT 0 /* API that can be used to change from NS */ extern int ns_switchback_to_initial(void); diff --git a/lib/prefix.h b/lib/prefix.h index 2a33d532c8..471978ed28 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -22,15 +22,11 @@ #ifndef _ZEBRA_PREFIX_H #define _ZEBRA_PREFIX_H -#ifdef SUNOS_5 -#include <sys/ethernet.h> -#else #ifdef GNU_LINUX #include <net/ethernet.h> #else #include <netinet/if_ether.h> #endif -#endif #include "sockunion.h" #include "ipaddr.h" #include "compiler.h" @@ -411,12 +407,7 @@ static inline void ipv4_addr_copy(struct in_addr *dst, /* glibc defines s6_addr32 to __in6_u.__u6_addr32 if __USE_{MISC || GNU} */ #ifndef s6_addr32 -#if defined(SUNOS_5) -/* Some SunOS define s6_addr32 only to kernel */ -#define s6_addr32 _S6_un._S6_u32 -#else #define s6_addr32 __u6_addr.__u6_addr32 -#endif /* SUNOS_5 */ #endif /*s6_addr32*/ /* Prototypes. */ diff --git a/lib/privs.c b/lib/privs.c index dc43b7279d..1bb5d059c8 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -37,12 +37,12 @@ DEFINE_MTYPE_STATIC(LIB, PRIVS, "Privilege information") #ifdef HAVE_CAPABILITIES #ifdef HAVE_LCAPS static const bool privs_per_process; /* = false */ -#elif defined(HAVE_SOLARIS_CAPABILITIES) -static const bool privs_per_process = true; -#endif #else static const bool privs_per_process = true; -#endif /* HAVE_CAPABILITIES */ +#endif /* HAVE_LCAPS */ +#else /* HAVE_CAPABILITIES */ +static const bool privs_per_process = true; +#endif #ifdef HAVE_CAPABILITIES @@ -67,11 +67,7 @@ typedef cap_value_t pvalue_t; typedef struct _pset pset_t; typedef cap_t pstorage_t; -#elif defined(HAVE_SOLARIS_CAPABILITIES) -typedef priv_t pvalue_t; -typedef priv_set_t pset_t; -typedef priv_set_t *pstorage_t; -#else /* neither LCAPS nor SOLARIS_CAPABILITIES */ +#else /* no LCAPS */ #error "HAVE_CAPABILITIES defined, but neither LCAPS nor Solaris Capabilties!" #endif /* HAVE_LCAPS */ #endif /* HAVE_CAPABILITIES */ @@ -163,67 +159,7 @@ static struct { { 1, (pvalue_t[]){CAP_FOWNER}, }, -#elif defined(HAVE_SOLARIS_CAPABILITIES) /* HAVE_LCAPS */ - /* Quagga -> Solaris privilege mappings */ - [ZCAP_SETID] = - { - 1, (pvalue_t[]){PRIV_PROC_SETID}, - }, - [ZCAP_BIND] = - { - 1, (pvalue_t[]){PRIV_NET_PRIVADDR}, - }, -/* IP_CONFIG is a subset of NET_CONFIG and is allowed in zones */ -#ifdef PRIV_SYS_IP_CONFIG - [ZCAP_NET_ADMIN] = - { - 1, (pvalue_t[]){PRIV_SYS_IP_CONFIG}, - }, -#else - [ZCAP_NET_ADMIN] = - { - 1, (pvalue_t[]){PRIV_SYS_NET_CONFIG}, - }, -#endif - [ZCAP_NET_RAW] = - { - 2, (pvalue_t[]){PRIV_NET_RAWACCESS, - PRIV_NET_ICMPACCESS}, - }, - [ZCAP_CHROOT] = - { - 1, (pvalue_t[]){PRIV_PROC_CHROOT}, - }, - [ZCAP_NICE] = - { - 1, (pvalue_t[]){PRIV_PROC_PRIOCNTL}, - }, - [ZCAP_PTRACE] = - { - 1, (pvalue_t[]){PRIV_PROC_SESSION}, - }, - [ZCAP_DAC_OVERRIDE] = - { - 5, (pvalue_t[]){PRIV_FILE_DAC_EXECUTE, - PRIV_FILE_DAC_READ, - PRIV_FILE_DAC_SEARCH, - PRIV_FILE_DAC_WRITE, - PRIV_FILE_DAC_SEARCH}, - }, - [ZCAP_READ_SEARCH] = - { - 2, (pvalue_t[]){PRIV_FILE_DAC_SEARCH, - PRIV_FILE_DAC_READ}, - }, - [ZCAP_SYS_ADMIN] = - { - 1, (pvalue_t[]){PRIV_SYS_ADMIN}, - }, - [ZCAP_FOWNER] = - { - 1, (pvalue_t[]){PRIV_FILE_OWNER}, - }, -#endif /* HAVE_SOLARIS_CAPABILITIES */ +#endif /* HAVE_LCAPS */ }; #ifdef HAVE_LCAPS @@ -432,225 +368,8 @@ static void zprivs_caps_terminate(void) cap_free(zprivs_state.caps); } -#elif defined(HAVE_SOLARIS_CAPABILITIES) /* !HAVE_LCAPS */ - -/* Solaris specific capability/privilege methods - * - * Resources: - * - the 'privileges' man page - * - http://cvs.opensolaris.org - * - - * http://blogs.sun.com/roller/page/gbrunett?entry=privilege_enabling_set_id_programs1 - */ - -static pset_t *zprivs_caps_minimal() -{ - pset_t *minimal; - - if ((minimal = priv_str_to_set("basic", ",", NULL)) == NULL) { - fprintf(stderr, "%s: couldn't get basic set!\n", __func__); - exit(1); - } - - /* create a minimal privilege set from the basic set */ - (void)priv_delset(minimal, PRIV_PROC_EXEC); - (void)priv_delset(minimal, PRIV_PROC_INFO); - (void)priv_delset(minimal, PRIV_PROC_SESSION); - (void)priv_delset(minimal, PRIV_FILE_LINK_ANY); - - return minimal; -} - -/* convert zebras privileges to system capabilities */ -static pset_t *zcaps2sys(zebra_capabilities_t *zcaps, int num) -{ - pset_t *syscaps; - int i, j = 0; - - if ((syscaps = priv_allocset()) == NULL) { - fprintf(stderr, "%s: could not allocate syscaps!\n", __func__); - exit(1); - } - - priv_emptyset(syscaps); - - for (i = 0; i < num; i++) - for (j = 0; j < cap_map[zcaps[i]].num; j++) - priv_addset(syscaps, cap_map[zcaps[i]].system_caps[j]); - - return syscaps; -} - -/* callback exported to users to RAISE and LOWER effective privileges - * from nothing to the given permitted set and back down - */ -int zprivs_change_caps(zebra_privs_ops_t op) -{ - pset_t *privset; - - /* should be no possibility of being called without valid caps */ - assert(zprivs_state.syscaps_p); - if (!zprivs_state.syscaps_p) { - fprintf(stderr, "%s: Eek, missing privileged caps!", __func__); - exit(1); - } - - assert(zprivs_state.caps); - if (!zprivs_state.caps) { - fprintf(stderr, "%s: Eek, missing caps!", __func__); - exit(1); - } - - /* to raise: copy original permitted as our working effective set - * to lower: copy regular effective set stored in zprivs_state.caps - */ - if (op == ZPRIVS_RAISE) - privset = zprivs_state.syscaps_p; - else if (op == ZPRIVS_LOWER) - privset = zprivs_state.caps; - else - return -1; - - if (setppriv(PRIV_SET, PRIV_EFFECTIVE, privset) != 0) - return -1; - - return 0; -} - -/* Retrieve current privilege state, is it RAISED or LOWERED? */ -zebra_privs_current_t zprivs_state_caps(void) -{ - zebra_privs_current_t result; - pset_t *effective; - - if ((effective = priv_allocset()) == NULL) { - fprintf(stderr, "%s: failed to get priv_allocset! %s\n", - __func__, safe_strerror(errno)); - return ZPRIVS_UNKNOWN; - } - - if (getppriv(PRIV_EFFECTIVE, effective)) { - fprintf(stderr, "%s: failed to get state! %s\n", __func__, - safe_strerror(errno)); - result = ZPRIVS_UNKNOWN; - } else { - if (priv_isequalset(effective, zprivs_state.syscaps_p)) - result = ZPRIVS_RAISED; - else if (priv_isequalset(effective, zprivs_state.caps)) - result = ZPRIVS_LOWERED; - else - result = ZPRIVS_UNKNOWN; - } - - priv_freeset(effective); - return result; -} - -static void zprivs_caps_init(struct zebra_privs_t *zprivs) -{ - pset_t *basic; - pset_t *minimal; - - /* the specified sets */ - zprivs_state.syscaps_p = zcaps2sys(zprivs->caps_p, zprivs->cap_num_p); - zprivs_state.syscaps_i = zcaps2sys(zprivs->caps_i, zprivs->cap_num_i); - - /* nonsensical to have gotten here but not have capabilities */ - if (!zprivs_state.syscaps_p) { - fprintf(stderr, - "%s: capabilities enabled, but no valid capabilities supplied\n", - __func__); - } - - /* We retain the basic set in our permitted set, as Linux has no - * equivalent. The basic set on Linux hence is implicit, always - * there. - */ - if ((basic = priv_str_to_set("basic", ",", NULL)) == NULL) { - fprintf(stderr, "%s: couldn't get basic set!\n", __func__); - exit(1); - } - - /* Add the basic set to the permitted set */ - priv_union(basic, zprivs_state.syscaps_p); - priv_freeset(basic); - - /* Hey kernel, we know about privileges! - * this isn't strictly required, use of setppriv should have same effect - */ - if (setpflags(PRIV_AWARE, 1)) { - fprintf(stderr, "%s: error setting PRIV_AWARE!, %s\n", __func__, - safe_strerror(errno)); - exit(1); - } - - /* need either valid or empty sets for both p and i.. */ - assert(zprivs_state.syscaps_i && zprivs_state.syscaps_p); - - /* we have caps, we have no need to ever change back the original user - * change real, effective and saved to the specified user. - */ - /* only change uid if we don't have the correct one */ - if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) { - if (setreuid(zprivs_state.zuid, zprivs_state.zuid)) { - fprintf(stderr, "%s: could not setreuid, %s\n", - __func__, safe_strerror(errno)); - exit(1); - } - } - - /* set the permitted set */ - if (setppriv(PRIV_SET, PRIV_PERMITTED, zprivs_state.syscaps_p)) { - fprintf(stderr, "%s: error setting permitted set!, %s\n", - __func__, safe_strerror(errno)); - exit(1); - } - - /* set the inheritable set */ - if (setppriv(PRIV_SET, PRIV_INHERITABLE, zprivs_state.syscaps_i)) { - fprintf(stderr, "%s: error setting inheritable set!, %s\n", - __func__, safe_strerror(errno)); - exit(1); - } - - /* we need a minimal basic set for 'effective', potentially for - * inheritable too */ - minimal = zprivs_caps_minimal(); - - /* now set the effective set with a subset of basic privileges */ - if (setppriv(PRIV_SET, PRIV_EFFECTIVE, minimal)) { - fprintf(stderr, "%s: error setting effective set!, %s\n", - __func__, safe_strerror(errno)); - exit(1); - } - - /* we'll use the minimal set as our working-storage privset */ - zprivs_state.caps = minimal; - - /* set methods for the caller to use */ - zprivs->change = zprivs_change_caps; - zprivs->current_state = zprivs_state_caps; -} - -static void zprivs_caps_terminate(void) -{ - assert(zprivs_state.caps); - - /* clear all capabilities by using working-storage privset */ - setppriv(PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps); - setppriv(PRIV_SET, PRIV_PERMITTED, zprivs_state.caps); - setppriv(PRIV_SET, PRIV_INHERITABLE, zprivs_state.caps); - - /* free up private state */ - if (zprivs_state.syscaps_p) - priv_freeset(zprivs_state.syscaps_p); - if (zprivs_state.syscaps_i) - priv_freeset(zprivs_state.syscaps_i); - - priv_freeset(zprivs_state.caps); -} -#else /* !HAVE_LCAPS && ! HAVE_SOLARIS_CAPABILITIES */ -#error "Neither Solaris nor Linux capabilities, dazed and confused..." +#else /* !HAVE_LCAPS */ +#error "no Linux capabilities, dazed and confused..." #endif /* HAVE_LCAPS */ #endif /* HAVE_CAPABILITIES */ diff --git a/lib/route_types.pl b/lib/route_types.pl index e007de4d69..39af8d0d56 100755 --- a/lib/route_types.pl +++ b/lib/route_types.pl @@ -121,7 +121,10 @@ sub codelist { } $str =~ s/ $//; push @lines, $str . "\\n\" \\\n"; - push @lines, " \" > - selected route, * - FIB route, q - queued, r - rejected, b - backup\\n\\n\""; + push @lines, " \" > - selected route, * - FIB route, q - queued, r - rejected, b - backup\\n\""; + push @lines, " \" t - trapped, o - offload failure\\n\""; + + return join("", @lines); } diff --git a/lib/route_types.txt b/lib/route_types.txt index b549c11cfc..37cc2fb590 100644 --- a/lib/route_types.txt +++ b/lib/route_types.txt @@ -84,7 +84,7 @@ 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_VRRP, vrrp, vrrpd, '-', 0, 0, 0, "VRRP" -ZEBRA_ROUTE_NHG, nhg, none, '-', 0, 0, 0, "Nexthop Group" +ZEBRA_ROUTE_NHG, zebra, none, '-', 0, 0, 0, "Nexthop Group" ZEBRA_ROUTE_SRTE, srte, none, '-', 0, 0, 0, "SR-TE" ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, 0, "-" diff --git a/lib/sigevent.c b/lib/sigevent.c index fcd85d0d43..04fcc814ef 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -170,8 +170,6 @@ static void *program_counter(void *context) #elif defined(__powerpc__) # define REG_INDEX 32 #endif -#elif defined(SUNOS_5) /* !GNU_LINUX */ -# define REG_INDEX REG_PC #endif /* GNU_LINUX */ #ifdef REG_INDEX diff --git a/lib/sockopt.c b/lib/sockopt.c index 21fddcd01d..ed21b72df7 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -20,10 +20,6 @@ #include <zebra.h> -#ifdef SUNOS_5 -#include <ifaddrs.h> -#endif - #include "log.h" #include "sockopt.h" #include "sockunion.h" @@ -351,35 +347,6 @@ int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, return setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m)); -#elif defined(SUNOS_5) - char ifname[IF_NAMESIZE]; - struct ifaddrs *ifa, *ifap; - struct in_addr ifaddr; - - if (if_indextoname(ifindex, ifname) == NULL) - return -1; - - if (getifaddrs(&ifa) != 0) - return -1; - - for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) { - struct sockaddr_in *sa; - - if (strcmp(ifap->ifa_name, ifname) != 0) - continue; - if (ifap->ifa_addr->sa_family != AF_INET) - continue; - sa = (struct sockaddr_in *)ifap->ifa_addr; - memcpy(&ifaddr, &sa->sin_addr, sizeof(ifaddr)); - break; - } - - freeifaddrs(ifa); - if (!ifap) /* This means we did not find an IP */ - return -1; - - return setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&ifaddr, - sizeof(ifaddr)); #else #error "Unsupported multicast API" #endif @@ -483,15 +450,9 @@ static ifindex_t getsockopt_ipv4_ifindex(struct msghdr *msgh) /* retrieval based on IP_RECVIF */ -#ifndef SUNOS_5 /* BSD systems use a sockaddr_dl as the control message payload. */ struct sockaddr_dl *sdl; -#else - /* SUNOS_5 uses an integer with the index. */ - ifindex_t *ifindex_p; -#endif /* SUNOS_5 */ -#ifndef SUNOS_5 /* BSD */ sdl = (struct sockaddr_dl *)getsockopt_cmsg_data(msgh, IPPROTO_IP, IP_RECVIF); @@ -499,18 +460,6 @@ static ifindex_t getsockopt_ipv4_ifindex(struct msghdr *msgh) ifindex = sdl->sdl_index; else ifindex = 0; -#else - /* - * Solaris. On Solaris 8, IP_RECVIF is defined, but the call to - * enable it fails with errno=99, and the struct msghdr has - * controllen 0. - */ - ifindex_p = (uint_t *)getsockopt_cmsg_data(msgh, IPPROTO_IP, IP_RECVIF); - if (ifindex_p != NULL) - ifindex = *ifindex_p; - else - ifindex = 0; -#endif /* SUNOS_5 */ #else /* diff --git a/lib/sockopt.h b/lib/sockopt.h index 4081e6a45b..545abe631f 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -59,11 +59,7 @@ extern int setsockopt_ipv6_tclass(int, int); #if defined(IP_RECVIF) /* BSD/Solaris */ -#if defined(SUNOS_5) -#define SOPT_SIZE_CMSG_RECVIF_IPV4() (sizeof(uint_t)) -#else #define SOPT_SIZE_CMSG_RECVIF_IPV4() (sizeof(struct sockaddr_dl)) -#endif /* SUNOS_5 */ #endif /* IP_RECVIF */ /* SOPT_SIZE_CMSG_IFINDEX_IPV4 - portable type */ @@ -39,8 +39,7 @@ #include "northbound.h" #include "northbound_cli.h" -/* default VRF ID value used when VRF backend is not NETNS */ -#define VRF_DEFAULT_INTERNAL 0 +/* default VRF name value used when VRF backend is not NETNS */ #define VRF_DEFAULT_NAME_INTERNAL "default" DEFINE_MTYPE_STATIC(LIB, VRF, "VRF") @@ -331,6 +330,9 @@ const char *vrf_id_to_name(vrf_id_t vrf_id) { struct vrf *vrf; + if (vrf_id == VRF_DEFAULT) + return VRF_DEFAULT_NAME; + vrf = vrf_lookup_by_id(vrf_id); return VRF_LOGNAME(vrf); } @@ -518,7 +520,7 @@ void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), strlcpy(default_vrf->data.l.netns_name, VRF_DEFAULT_NAME, NS_NAMSIZ); - ns = ns_lookup(ns_get_default_id()); + ns = ns_lookup(NS_DEFAULT); ns->vrf_ctxt = default_vrf; default_vrf->ns_ctxt = ns; } @@ -946,17 +948,6 @@ 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 - */ - if (vrf_is_backend_netns()) - return ns_get_default_id(); - else - return VRF_DEFAULT_INTERNAL; -} - int vrf_bind(vrf_id_t vrf_id, int fd, const char *name) { int ret = 0; @@ -262,12 +262,8 @@ extern int vrf_getaddrinfo(const char *node, const char *service, extern int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *args); -/* function called by macro VRF_DEFAULT - * to get the default VRF_ID - */ -extern vrf_id_t vrf_get_default_id(void); /* The default VRF ID */ -#define VRF_DEFAULT vrf_get_default_id() +#define VRF_DEFAULT 0 extern void vrf_set_default_name(const char *default_name, bool force); extern const char *vrf_get_default_name(void); @@ -358,15 +358,6 @@ void vty_hello(struct vty *vty) vty_out(vty, "MOTD file not found\n"); } else if (host.motd) vty_out(vty, "%s", host.motd); - -#if CONFDATE > 20200901 - CPP_NOTICE("Please remove solaris code from system as it is deprecated"); -#endif -#ifdef SUNOS_5 - zlog_warn("If you are using FRR on Solaris, the FRR developers would love to hear from you\n"); - zlog_warn("Please send email to dev@lists.frrouting.org about this message\n"); - zlog_warn("We are considering deprecating Solaris and want to find users of Solaris systems\n"); -#endif } /* Put out prompt and wait input from user. */ diff --git a/lib/zclient.c b/lib/zclient.c index c5016d22e2..b7d240b4e8 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1017,6 +1017,57 @@ done: return ret; } +int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg) +{ + int i; + + if (cmd != ZEBRA_NHG_DEL && cmd != ZEBRA_NHG_ADD) { + flog_err(EC_LIB_ZAPI_ENCODE, + "%s: Specified zapi NHG command (%d) doesn't exist\n", + __func__, cmd); + return -1; + } + + stream_reset(s); + zclient_create_header(s, cmd, VRF_DEFAULT); + + stream_putw(s, api_nhg->proto); + stream_putl(s, api_nhg->id); + + if (cmd == ZEBRA_NHG_ADD) { + /* Nexthops */ + zapi_nexthop_group_sort(api_nhg->nexthops, + api_nhg->nexthop_num); + + stream_putw(s, api_nhg->nexthop_num); + + for (i = 0; i < api_nhg->nexthop_num; i++) + zapi_nexthop_encode(s, &api_nhg->nexthops[i], 0, 0); + + /* Backup nexthops */ + + stream_putw(s, api_nhg->backup_nexthop_num); + + for (i = 0; i < api_nhg->backup_nexthop_num; i++) + zapi_nexthop_encode(s, &api_nhg->backup_nexthops[i], 0, + 0); + } + + stream_putw_at(s, 0, stream_get_endp(s)); + + return 0; +} + +int zclient_nhg_send(struct zclient *zclient, int cmd, struct zapi_nhg *api_nhg) +{ + api_nhg->proto = zclient->redist_default; + + if (zapi_nhg_encode(zclient->obuf, cmd, api_nhg)) + return -1; + + return zclient_send_message(zclient); +} + int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api) { struct zapi_nexthop *api_nh; @@ -1058,6 +1109,9 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api) stream_write(s, (uint8_t *)&api->src_prefix.prefix, psize); } + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NHG)) + stream_putl(s, api->nhgid); + /* Nexthops. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { /* limit the number of nexthops if necessary */ @@ -1171,8 +1225,8 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api) /* * Decode a single zapi nexthop object */ -static int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh, - uint32_t api_flags, uint32_t api_message) +int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh, + uint32_t api_flags, uint32_t api_message) { int i, ret = -1; @@ -1328,6 +1382,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) } } + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NHG)) + STREAM_GETL(s, api->nhgid); + /* Nexthops. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { STREAM_GETW(s, api->nexthop_num); @@ -1432,6 +1489,22 @@ int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, struct pbr_rule *zrule) return 0; } +bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id, + enum zapi_nhg_notify_owner *note) +{ + uint32_t read_id; + + STREAM_GET(note, s, sizeof(*note)); + STREAM_GETL(s, read_id); + + *id = read_id; + + return true; + +stream_failure: + return false; +} + bool zapi_route_notify_decode(struct stream *s, struct prefix *p, uint32_t *tableid, enum zapi_route_notify_owner *note) @@ -1582,6 +1655,9 @@ int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh, znh->ifindex = nh->ifindex; znh->gate = nh->gate; + if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK)) + SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_ONLINK); + if (nh->nh_label && (nh->nh_label->num_labels > 0)) { /* Validate */ @@ -3733,6 +3809,11 @@ static int zclient_read(struct thread *thread) (*zclient->rule_notify_owner)(command, zclient, length, vrf_id); break; + case ZEBRA_NHG_NOTIFY_OWNER: + if (zclient->nhg_notify_owner) + (*zclient->nhg_notify_owner)(command, zclient, length, + vrf_id); + break; case ZEBRA_GET_LABEL_CHUNK: if (zclient->label_chunk) (*zclient->label_chunk)(command, zclient, length, @@ -4001,3 +4082,13 @@ int zclient_send_neigh_discovery_req(struct zclient *zclient, stream_putw_at(s, 0, stream_get_endp(s)); return zclient_send_message(zclient); } + +/* + * Get a starting nhg point for a routing protocol + */ +uint32_t zclient_get_nhg_start(uint32_t proto) +{ + assert(proto < ZEBRA_ROUTE_MAX); + + return ZEBRA_NHG_PROTO_SPACING * proto; +} diff --git a/lib/zclient.h b/lib/zclient.h index f99b3ad743..959a101395 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -209,6 +209,9 @@ typedef enum { ZEBRA_MLAG_CLIENT_REGISTER, ZEBRA_MLAG_CLIENT_UNREGISTER, ZEBRA_MLAG_FORWARD_MSG, + ZEBRA_NHG_ADD, + ZEBRA_NHG_DEL, + ZEBRA_NHG_NOTIFY_OWNER, ZEBRA_ERROR, ZEBRA_CLIENT_CAPABILITIES, ZEBRA_OPAQUE_MESSAGE, @@ -354,6 +357,7 @@ struct zclient { int (*mlag_process_up)(void); int (*mlag_process_down)(void); int (*mlag_handle_msg)(struct stream *msg, int len); + int (*nhg_notify_owner)(ZAPI_CALLBACK_ARGS); int (*handle_error)(enum zebra_error_types error); int (*opaque_msg_handler)(ZAPI_CALLBACK_ARGS); int (*opaque_register_handler)(ZAPI_CALLBACK_ARGS); @@ -370,6 +374,7 @@ struct zclient { #define ZAPI_MESSAGE_SRCPFX 0x20 /* Backup nexthops are present */ #define ZAPI_MESSAGE_BACKUP_NEXTHOPS 0x40 +#define ZAPI_MESSAGE_NHG 0x80 /* * This should only be used by a DAEMON that needs to communicate @@ -434,6 +439,20 @@ struct zapi_nexthop { #define ZAPI_NEXTHOP_FLAG_HAS_BACKUP 0x08 /* Nexthop has a backup */ /* + * ZAPI Nexthop Group. For use with protocol creation of nexthop groups. + */ +struct zapi_nhg { + uint16_t proto; + uint32_t id; + + uint16_t nexthop_num; + struct zapi_nexthop nexthops[MULTIPATH_NUM]; + + uint16_t backup_nexthop_num; + struct zapi_nexthop backup_nexthops[MULTIPATH_NUM]; +}; + +/* * Some of these data structures do not map easily to * a actual data structure size giving different compilers * and systems. For those data structures we need @@ -480,6 +499,20 @@ struct zapi_route { * route entry. This mainly is used for backup static routes. */ #define ZEBRA_FLAG_RR_USE_DISTANCE 0x40 +/* + * This flag tells everyone that the route was intentionally + * not offloaded and the route will be sent to the cpu for + * forwarding. This flag makes no sense unless you are in + * an asic offload situation + */ +#define ZEBRA_FLAG_TRAPPED 0x80 +/* + * This flag tells everyone that the route has been + * successfully offloaded to an asic for forwarding. + * This flag makes no sense unless you are in an asic + * offload situation. + */ +#define ZEBRA_FLAG_OFFLOADED 0x100 /* The older XXX_MESSAGE flags live here */ uint32_t message; @@ -500,6 +533,8 @@ struct zapi_route { uint16_t backup_nexthop_num; struct zapi_nexthop backup_nexthops[MULTIPATH_NUM]; + uint32_t nhgid; + uint8_t distance; uint32_t metric; @@ -578,6 +613,13 @@ enum zapi_route_notify_owner { ZAPI_ROUTE_REMOVE_FAIL, }; +enum zapi_nhg_notify_owner { + ZAPI_NHG_FAIL_INSTALL, + ZAPI_NHG_INSTALLED, + ZAPI_NHG_REMOVED, + ZAPI_NHG_REMOVE_FAIL, +}; + enum zapi_rule_notify_owner { ZAPI_RULE_FAIL_INSTALL, ZAPI_RULE_INSTALLED, @@ -657,6 +699,22 @@ struct zclient_options { extern struct zclient_options zclient_options_default; +/* + * We reserve the top 4 bits for l2-NHG, everything else + * is for zebra/proto l3-NHG. + * + * Each client is going to get it's own nexthop group space + * and we'll separate them, we'll figure out where to start based upon + * the route_types.h + */ +#define ZEBRA_NHG_PROTO_UPPER \ + ((uint32_t)250000000) /* Bottom 28 bits then rounded down */ +#define ZEBRA_NHG_PROTO_SPACING (ZEBRA_NHG_PROTO_UPPER / ZEBRA_ROUTE_MAX) +#define ZEBRA_NHG_PROTO_LOWER \ + (ZEBRA_NHG_PROTO_SPACING * (ZEBRA_ROUTE_CONNECT + 1)) + +extern uint32_t zclient_get_nhg_start(uint32_t proto); + extern struct zclient *zclient_new(struct thread_master *m, struct zclient_options *opt); @@ -839,7 +897,11 @@ extern int zclient_send_rnh(struct zclient *zclient, int command, int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, uint32_t api_flags, uint32_t api_message); extern int zapi_route_encode(uint8_t, struct stream *, struct zapi_route *); -extern int zapi_route_decode(struct stream *, struct zapi_route *); +extern int zapi_route_decode(struct stream *s, struct zapi_route *api); +extern int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh, + uint32_t api_flags, uint32_t api_message); +bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id, + enum zapi_nhg_notify_owner *note); bool zapi_route_notify_decode(struct stream *s, struct prefix *p, uint32_t *tableid, enum zapi_route_notify_owner *note); @@ -850,6 +912,12 @@ bool zapi_ipset_notify_decode(struct stream *s, uint32_t *unique, enum zapi_ipset_notify_owner *note); + +extern int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg); +extern int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg); +extern int zclient_nhg_send(struct zclient *zclient, int cmd, + struct zapi_nhg *api_nhg); + #define ZEBRA_IPSET_NAME_SIZE 32 bool zapi_ipset_entry_notify_decode(struct stream *s, diff --git a/lib/zebra.h b/lib/zebra.h index b2f0202c53..14d66d6627 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -27,12 +27,6 @@ #include "compiler.h" -#ifdef SUNOS_5 -typedef unsigned int uint32_t; -typedef unsigned short uint16_t; -typedef unsigned char uint8_t; -#endif /* SUNOS_5 */ - #include <unistd.h> #include <stdio.h> #include <stdlib.h> @@ -76,11 +70,6 @@ typedef unsigned char uint8_t; #include <stdbool.h> /* machine dependent includes */ -#ifdef SUNOS_5 -#include <strings.h> -#endif /* SUNOS_5 */ - -/* machine dependent includes */ #ifdef HAVE_LINUX_VERSION_H #include <linux/version.h> #endif /* HAVE_LINUX_VERSION_H */ @@ -112,10 +101,6 @@ typedef unsigned char uint8_t; #include <sys/prctl.h> #endif /* HAVE_LCAPS */ -#ifdef HAVE_SOLARIS_CAPABILITIES -#include <priv.h> -#endif /* HAVE_SOLARIS_CAPABILITIES */ - /* network include group */ #include <sys/socket.h> @@ -306,8 +291,7 @@ struct in_pktinfo { #if defined(__NetBSD__) \ || (defined(__FreeBSD__) && (__FreeBSD_version < 1100030)) \ || (defined(__OpenBSD__) && (OpenBSD < 200311)) \ - || (defined(__APPLE__)) \ - || (defined(SUNOS_5) && defined(WORDS_BIGENDIAN)) + || (defined(__APPLE__)) #define HAVE_IP_HDRINCL_BSD_ORDER #endif diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 20f339d43f..04ece6dbb0 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -138,7 +138,7 @@ struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list, if (ifaddr.s_addr == igmp->ifaddr.s_addr) return igmp; - return 0; + return NULL; } struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd) @@ -150,7 +150,7 @@ struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd) if (fd == igmp->fd) return igmp; - return 0; + return NULL; } static int pim_igmp_other_querier_expire(struct thread *t) @@ -1004,7 +1004,7 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, if (fd < 0) { zlog_warn("Could not open IGMP socket for %s on %s", inet_ntoa(ifaddr), ifp->name); - return 0; + return NULL; } sin.sin_family = AF_INET; @@ -1013,7 +1013,9 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) != 0) { zlog_warn("Could not bind IGMP socket for %s on %s", inet_ntoa(ifaddr), ifp->name); - return 0; + close(fd); + + return NULL; } igmp = igmp_sock_new(fd, ifaddr, ifp, mtrace_only); diff --git a/ripd/ripd.c b/ripd/ripd.c index ecadf8fb71..bcf73e8f89 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -3667,13 +3667,20 @@ static int rip_vrf_enable(struct vrf *vrf) */ if (yang_module_find("frr-ripd") && old_vrf_name) { struct lyd_node *rip_dnode; + char oldpath[XPATH_MAXLEN]; + char newpath[XPATH_MAXLEN]; rip_dnode = yang_dnode_get( running_config->dnode, "/frr-ripd:ripd/instance[vrf='%s']/vrf", old_vrf_name); if (rip_dnode) { + yang_dnode_get_path(rip_dnode->parent, oldpath, + sizeof(oldpath)); yang_dnode_change_leaf(rip_dnode, vrf->name); + yang_dnode_get_path(rip_dnode->parent, newpath, + sizeof(newpath)); + nb_running_move_tree(oldpath, newpath); running_config->version++; } } diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index bf6c6ff27b..8a7950daf4 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -2791,13 +2791,20 @@ static int ripng_vrf_enable(struct vrf *vrf) */ if (yang_module_find("frr-ripngd") && old_vrf_name) { struct lyd_node *ripng_dnode; + char oldpath[XPATH_MAXLEN]; + char newpath[XPATH_MAXLEN]; ripng_dnode = yang_dnode_get( running_config->dnode, "/frr-ripngd:ripngd/instance[vrf='%s']/vrf", old_vrf_name); if (ripng_dnode) { + yang_dnode_get_path(ripng_dnode->parent, oldpath, + sizeof(oldpath)); yang_dnode_change_leaf(ripng_dnode, vrf->name); + yang_dnode_get_path(ripng_dnode->parent, newpath, + sizeof(newpath)); + nb_running_move_tree(oldpath, newpath); running_config->version++; } } diff --git a/sharpd/sharp_globals.h b/sharpd/sharp_globals.h index 8eba57f4dd..0bd47454a9 100644 --- a/sharpd/sharp_globals.h +++ b/sharpd/sharp_globals.h @@ -31,6 +31,7 @@ struct sharp_routes { /* The nexthop info we are using for installation */ struct nexthop nhop; struct nexthop backup_nhop; + uint32_t nhgid; struct nexthop_group nhop_group; struct nexthop_group backup_nhop_group; diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c index ccf34b10dd..4cd92c7f3d 100644 --- a/sharpd/sharp_main.c +++ b/sharpd/sharp_main.c @@ -47,6 +47,7 @@ #include "sharp_zebra.h" #include "sharp_vty.h" #include "sharp_globals.h" +#include "sharp_nht.h" DEFINE_MGROUP(SHARPD, "sharpd") @@ -164,7 +165,7 @@ int main(int argc, char **argv, char **envp) sharp_global_init(); - nexthop_group_init(NULL, NULL, NULL, NULL); + sharp_nhgroup_init(); vrf_init(NULL, NULL, NULL, NULL, NULL); sharp_zebra_init(); diff --git a/sharpd/sharp_nht.c b/sharpd/sharp_nht.c index 174f186863..7484dd3b06 100644 --- a/sharpd/sharp_nht.c +++ b/sharpd/sharp_nht.c @@ -25,11 +25,15 @@ #include "nexthop.h" #include "nexthop_group.h" #include "vty.h" +#include "typesafe.h" +#include "zclient.h" #include "sharp_nht.h" #include "sharp_globals.h" +#include "sharp_zebra.h" DEFINE_MTYPE_STATIC(SHARPD, NH_TRACKER, "Nexthop Tracker") +DEFINE_MTYPE_STATIC(SHARPD, NHG, "Nexthop Group") struct sharp_nh_tracker *sharp_nh_tracker_get(struct prefix *p) { @@ -65,3 +69,157 @@ void sharp_nh_tracker_dump(struct vty *vty) nht->updates); } } + +PREDECL_RBTREE_UNIQ(sharp_nhg_rb); + +struct sharp_nhg { + struct sharp_nhg_rb_item mylistitem; + + uint32_t id; + + char name[256]; + + bool installed; +}; + +static uint32_t nhg_id; + +static uint32_t sharp_get_next_nhid(void) +{ + zlog_debug("NHG ID assigned: %u", nhg_id); + return nhg_id++; +} + +struct sharp_nhg_rb_head nhg_head; + +static int sharp_nhg_compare_func(const struct sharp_nhg *a, + const struct sharp_nhg *b) +{ + return strncmp(a->name, b->name, strlen(a->name)); +} + +DECLARE_RBTREE_UNIQ(sharp_nhg_rb, struct sharp_nhg, mylistitem, + sharp_nhg_compare_func); + +static struct sharp_nhg *sharp_nhgroup_find_id(uint32_t id) +{ + struct sharp_nhg *lookup; + + /* Yea its just a for loop, I don't want add complexity + * to sharpd with another RB tree for just IDs + */ + + frr_each (sharp_nhg_rb, &nhg_head, lookup) { + if (lookup->id == id) + return lookup; + } + + return NULL; +} + +static void sharp_nhgroup_add_cb(const char *name) +{ + struct sharp_nhg *snhg; + + snhg = XCALLOC(MTYPE_NHG, sizeof(*snhg)); + snhg->id = sharp_get_next_nhid(); + strlcpy(snhg->name, name, sizeof(snhg->name)); + + sharp_nhg_rb_add(&nhg_head, snhg); +} + +static void sharp_nhgroup_add_nexthop_cb(const struct nexthop_group_cmd *nhgc, + const struct nexthop *nhop) +{ + struct sharp_nhg lookup; + struct sharp_nhg *snhg; + struct nexthop_group_cmd *bnhgc = NULL; + + strlcpy(lookup.name, nhgc->name, sizeof(lookup.name)); + snhg = sharp_nhg_rb_find(&nhg_head, &lookup); + + if (nhgc->backup_list_name[0]) + bnhgc = nhgc_find(nhgc->backup_list_name); + + nhg_add(snhg->id, &nhgc->nhg, (bnhgc ? &bnhgc->nhg : NULL)); +} + +static void sharp_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhgc, + const struct nexthop *nhop) +{ + struct sharp_nhg lookup; + struct sharp_nhg *snhg; + struct nexthop_group_cmd *bnhgc = NULL; + + strlcpy(lookup.name, nhgc->name, sizeof(lookup.name)); + snhg = sharp_nhg_rb_find(&nhg_head, &lookup); + + if (nhgc->backup_list_name[0]) + bnhgc = nhgc_find(nhgc->backup_list_name); + + nhg_add(snhg->id, &nhgc->nhg, (bnhgc ? &bnhgc->nhg : NULL)); +} + +static void sharp_nhgroup_delete_cb(const char *name) +{ + struct sharp_nhg lookup; + struct sharp_nhg *snhg; + + strlcpy(lookup.name, name, sizeof(lookup.name)); + snhg = sharp_nhg_rb_find(&nhg_head, &lookup); + if (!snhg) + return; + + nhg_del(snhg->id); + sharp_nhg_rb_del(&nhg_head, snhg); + XFREE(MTYPE_NHG, snhg); +} + +uint32_t sharp_nhgroup_get_id(const char *name) +{ + struct sharp_nhg lookup; + struct sharp_nhg *snhg; + + strlcpy(lookup.name, name, sizeof(lookup.name)); + snhg = sharp_nhg_rb_find(&nhg_head, &lookup); + if (!snhg) + return 0; + + return snhg->id; +} + +void sharp_nhgroup_id_set_installed(uint32_t id, bool installed) +{ + struct sharp_nhg *snhg; + + snhg = sharp_nhgroup_find_id(id); + if (!snhg) { + zlog_debug("%s: nhg %u not found", __func__, id); + return; + } + + snhg->installed = installed; +} + +bool sharp_nhgroup_id_is_installed(uint32_t id) +{ + struct sharp_nhg *snhg; + + snhg = sharp_nhgroup_find_id(id); + if (!snhg) { + zlog_debug("%s: nhg %u not found", __func__, id); + return false; + } + + return snhg->installed; +} + +void sharp_nhgroup_init(void) +{ + sharp_nhg_rb_init(&nhg_head); + nhg_id = zclient_get_nhg_start(ZEBRA_ROUTE_SHARP); + + nexthop_group_init(sharp_nhgroup_add_cb, sharp_nhgroup_add_nexthop_cb, + sharp_nhgroup_del_nexthop_cb, + sharp_nhgroup_delete_cb); +} diff --git a/sharpd/sharp_nht.h b/sharpd/sharp_nht.h index 0b00774a81..da33502878 100644 --- a/sharpd/sharp_nht.h +++ b/sharpd/sharp_nht.h @@ -35,4 +35,10 @@ struct sharp_nh_tracker { extern struct sharp_nh_tracker *sharp_nh_tracker_get(struct prefix *p); extern void sharp_nh_tracker_dump(struct vty *vty); + +extern uint32_t sharp_nhgroup_get_id(const char *name); +extern void sharp_nhgroup_id_set_installed(uint32_t id, bool installed); +extern bool sharp_nhgroup_id_is_installed(uint32_t id); + +extern void sharp_nhgroup_init(void); #endif diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index d390ea8192..d062f027ab 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -192,6 +192,7 @@ DEFPY (install_routes, struct vrf *vrf; struct prefix prefix; uint32_t rts; + uint32_t nhgid = 0; sg.r.total_routes = routes; sg.r.installed_routes = 0; @@ -244,6 +245,8 @@ DEFPY (install_routes, return CMD_WARNING; } + nhgid = sharp_nhgroup_get_id(nexthop_group); + sg.r.nhgid = nhgid; sg.r.nhop_group.nexthop = nhgc->nhg.nexthop; /* Use group's backup nexthop info if present */ @@ -296,7 +299,7 @@ DEFPY (install_routes, sg.r.inst = instance; sg.r.vrf_id = vrf->vrf_id; rts = routes; - sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, + sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, nhgid, &sg.r.nhop_group, &sg.r.backup_nhop_group, rts); diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 08f5a07b7e..d167e8e277 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -217,7 +217,7 @@ int sharp_install_lsps_helper(bool install_p, bool update_p, } void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, - uint8_t instance, + uint8_t instance, uint32_t nhgid, const struct nexthop_group *nhg, const struct nexthop_group *backup_nhg, uint32_t routes) @@ -239,7 +239,7 @@ void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, monotime(&sg.r.t_start); for (i = 0; i < routes; i++) { - route_add(p, vrf_id, (uint8_t)instance, nhg, backup_nhg); + route_add(p, vrf_id, (uint8_t)instance, nhgid, nhg, backup_nhg); if (v4) p->u.prefix4.s_addr = htonl(++temp); else @@ -288,7 +288,7 @@ static void handle_repeated(bool installed) if (!installed) { sg.r.installed_routes = 0; sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst, - &sg.r.nhop_group, + sg.r.nhgid, &sg.r.nhop_group, &sg.r.backup_nhop_group, sg.r.total_routes); } @@ -357,8 +357,58 @@ void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label) zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP); } -void route_add(const struct prefix *p, vrf_id_t vrf_id, - uint8_t instance, const struct nexthop_group *nhg, +void nhg_add(uint32_t id, const struct nexthop_group *nhg, + const struct nexthop_group *backup_nhg) +{ + struct zapi_nhg api_nhg = {}; + struct zapi_nexthop *api_nh; + struct nexthop *nh; + + api_nhg.id = id; + for (ALL_NEXTHOPS_PTR(nhg, nh)) { + if (api_nhg.nexthop_num >= MULTIPATH_NUM) { + zlog_warn( + "%s: number of nexthops greater than max multipath size, truncating", + __func__); + break; + } + + api_nh = &api_nhg.nexthops[api_nhg.nexthop_num]; + + zapi_nexthop_from_nexthop(api_nh, nh); + api_nhg.nexthop_num++; + } + + if (backup_nhg) { + for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) { + if (api_nhg.backup_nexthop_num >= MULTIPATH_NUM) { + zlog_warn( + "%s: number of backup nexthops greater than max multipath size, truncating", + __func__); + break; + } + api_nh = &api_nhg.backup_nexthops + [api_nhg.backup_nexthop_num]; + + zapi_backup_nexthop_from_nexthop(api_nh, nh); + api_nhg.backup_nexthop_num++; + } + } + + zclient_nhg_send(zclient, ZEBRA_NHG_ADD, &api_nhg); +} + +void nhg_del(uint32_t id) +{ + struct zapi_nhg api_nhg = {}; + + api_nhg.id = id; + + zclient_nhg_send(zclient, ZEBRA_NHG_DEL, &api_nhg); +} + +void route_add(const struct prefix *p, vrf_id_t vrf_id, uint8_t instance, + uint32_t nhgid, const struct nexthop_group *nhg, const struct nexthop_group *backup_nhg) { struct zapi_route api; @@ -376,14 +426,20 @@ void route_add(const struct prefix *p, vrf_id_t vrf_id, SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - for (ALL_NEXTHOPS_PTR(nhg, nh)) { - api_nh = &api.nexthops[i]; + /* Only send via ID if nhgroup has been successfully installed */ + if (nhgid && sharp_nhgroup_id_is_installed(nhgid)) { + SET_FLAG(api.message, ZAPI_MESSAGE_NHG); + api.nhgid = nhgid; + } else { + for (ALL_NEXTHOPS_PTR(nhg, nh)) { + api_nh = &api.nexthops[i]; - zapi_nexthop_from_nexthop(api_nh, nh); + zapi_nexthop_from_nexthop(api_nh, nh); - i++; + i++; + } + api.nexthop_num = i; } - api.nexthop_num = i; /* Include backup nexthops, if present */ if (backup_nhg && backup_nhg->nexthop) { @@ -668,6 +724,33 @@ void sharp_zebra_send_arp(const struct interface *ifp, const struct prefix *p) zclient_send_neigh_discovery_req(zclient, ifp, p); } +static int nhg_notify_owner(ZAPI_CALLBACK_ARGS) +{ + enum zapi_nhg_notify_owner note; + uint32_t id; + + if (!zapi_nhg_notify_decode(zclient->ibuf, &id, ¬e)) + return -1; + + switch (note) { + case ZAPI_NHG_INSTALLED: + sharp_nhgroup_id_set_installed(id, true); + zlog_debug("Installed nhg %u", id); + break; + case ZAPI_NHG_FAIL_INSTALL: + zlog_debug("Failed install of nhg %u", id); + break; + case ZAPI_NHG_REMOVED: + zlog_debug("Removed nhg %u", id); + break; + case ZAPI_NHG_REMOVE_FAIL: + zlog_debug("Failed removal of nhg %u", id); + break; + } + + return 0; +} + void sharp_zebra_init(void) { struct zclient_options opt = {.receive_notify = true}; @@ -684,6 +767,7 @@ void sharp_zebra_init(void) zclient->route_notify_owner = route_notify_owner; zclient->nexthop_update = sharp_nexthop_update; zclient->import_check_update = sharp_nexthop_update; + zclient->nhg_notify_owner = nhg_notify_owner; zclient->redistribute_route_add = sharp_redistribute_route; zclient->redistribute_route_del = sharp_redistribute_route; diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h index 0a44fa694f..4a767ababf 100644 --- a/sharpd/sharp_zebra.h +++ b/sharpd/sharp_zebra.h @@ -29,15 +29,18 @@ int sharp_zclient_create(uint32_t session_id); int sharp_zclient_delete(uint32_t session_id); extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label); +extern void nhg_add(uint32_t id, const struct nexthop_group *nhg, + const struct nexthop_group *backup_nhg); +extern void nhg_del(uint32_t id); extern void route_add(const struct prefix *p, vrf_id_t, uint8_t instance, - const struct nexthop_group *nhg, + uint32_t nhgid, const struct nexthop_group *nhg, const struct nexthop_group *backup_nhg); extern void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance); extern void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import, bool watch, bool connected); extern void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, - uint8_t instance, + uint8_t instance, uint32_t nhgid, const struct nexthop_group *nhg, const struct nexthop_group *backup_nhg, uint32_t routes); diff --git a/solaris/.gitignore b/solaris/.gitignore deleted file mode 100644 index 3f1a0385a4..0000000000 --- a/solaris/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -Makefile -!Makefile.in -?.manifest -*.xml -pkginfo.*.full -pkginfo.tmpl -prototype.daemons -prototype.dev -prototype.doc -prototype.libs -prototype.smf -depend.daemons -depend.dev -depend.doc -depend.libs -depend.smf -frr.init -*.pkg -*.pkg.gz diff --git a/solaris/Makefile.in b/solaris/Makefile.in deleted file mode 100644 index df9122a1db..0000000000 --- a/solaris/Makefile.in +++ /dev/null @@ -1,155 +0,0 @@ -# Solaris packages automake file - -# XXX This file uses GNU make extensions. - -.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)-$(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) -pkg_prototypes = $(pkg_names:%=prototype.%) -pkg_manifests = frr.xml - -# pkgmk variable substitutions wont grok ${variable} in prototype -# file, so we cant let autoconf generate the file sadly -# wish automake would just provide a template for this -edit = $(SED) \ - -e 's,@prefix\@,$(prefix),g' \ - -e 's,@exec_prefix,$(exec_prefix),g' \ - -e 's,@bindir\@,$(bindir),g' \ - -e 's,@sbindir\@,$(sbindir),g' \ - -e 's,@libexecdir\@,$(libexecdir),g' \ - -e 's,@datadir\@,$(datadir),g' \ - -e 's,@sysconfdir\@,$(sysconfdir),g' \ - -e 's,@sharedstatedir\@,$(sharedstatedir),g' \ - -e 's,@localstatedir\@,$(localstatedir),g' \ - -e 's,@libdir\@,$(libdir),g' \ - -e 's,@includedir\@,$(includedir),g' \ - -e 's,@infodir\@,$(infodir),g' \ - -e 's,@mandir\@,$(mandir),g' \ - -e 's,@enable_user\@,$(enable_user),g' \ - -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,[@]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) - -# pkgmk: write the package to spool in build dir, to avoid root dependencies -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)/$@" - -# pkgmk can only cope with a single pkginfo, cant 'stack' various -# pkginfo template files and a package specific pkginfo file in the prototype -# Create the package specific template here, and create the full pkginfo -# by cating this and the common pkginfo.tmpl together. -pkginfo.tmpl: $(srcdir)/pkginfo.tmpl.in Makefile - rm -f $@ - $(edit) $< > $@ - -pkginfo.%.tmpl: $(srcdir)/pkginfo.%.tmpl.in Makefile - rm -f $@ - $(edit) $< > $@ - -pkginfo.%.full: pkginfo.%.tmpl pkginfo.tmpl Makefile - cat pkginfo.tmpl pkginfo.$*.tmpl > $@ - -# use 'edit' above to transform prototype.in to pkgmk acceptable prototype -prototype.%: $(srcdir)/prototype.%.in Makefile - rm -f $@ - $(edit) $< > $@ - -# use edit to construct the SMF manifest files -%.xml: $(srcdir)/%.xml.in Makefile - rm -f $@ - $(edit) $< > $@ -# use edit to construct the depend files -depend.%: $(srcdir)/depend.%.in Makefile - rm -f $@ - $(edit) $< > $@ - -# method file (bit like init script) -frr.init: $(srcdir)/frr.init.in Makefile - rm -f $@ - $(edit) $< > $@ - -# construct the pkg -$(PACKAGE_TARNAME)-%-$(pkg_name_rev).pkg: prototype.% \ - depend.% frr.init pkginfo.%.full - ($(pkg_make) && \ - $(pkg_trans) "FRR$*") - -%.pkg.gz : %.pkg - (gzip -c $< > $@) - -pkg-root-install: - (cd $(top_builddir) && \ - $(MAKE) DESTDIR=$(abs_builddir)/frr-root install) - -packages: $(pkg_packages) - -all-files: $(pkg_pkginfos) pkginfo.tmpl $(pkg_prototypes) \ - $(pkg_manifests) $(pkg_depends) frr.init diff --git a/solaris/README.txt b/solaris/README.txt deleted file mode 100644 index 589570d881..0000000000 --- a/solaris/README.txt +++ /dev/null @@ -1,186 +0,0 @@ -To build packages for Solaris 10: - -Requirements: -------------- - -- Development environment including gcc (eg as shipped with Solaris 10) - -- The Package tools from Solaris 10 or Solaris Nevada/Express. - -- i.manifest and r.manifest scripts as supplied with Solaris Express - in /usr/sadm/install/scripts/ or from OpenSolaris.org: - - http://cvs.opensolaris.org/source/xref/usr/src/pkgdefs/common_files/i.manifest - http://cvs.opensolaris.org/source/xref/usr/src/pkgdefs/common_files/r.manifest - - i.manifest must be at least version 1.5. Place these scripts in - this directory if you are using Solaris 10 GA (which does not ship with - these scripts), or in the solaris/ directory in the FRRouting source. - - -Package creation instructions: ------------------------------- - -1. Configure and build FRRouting (frr) in the top level build directory as per normal, eg: - - ./configure --prefix=/usr/local/frr \ - --localstatedir=/var/run/frr \ - --enable-gcc-rdynamic --enable-opaque-lsa --enable-ospf-te \ - --enable-multipath=64 --enable-user=frr \ - --enable-ospfclient=yes --enable-ospfapi=yes \ - --enable-group=frr --enable-nssa --enable-opaque-lsa - -You will need /usr/sfw/bin and /usr/ccs/bin in your path. - -2. make install in the top-level build directory, it's a good idea to make -use of DESTDIR to install to an alternate root, eg: - - gmake DESTDIR=/var/tmp/qroot install - -3. In this directory (solaris/), run make packages, specifying DESTDIR if -appropriate, eg: - - gmake DESTDIR=/var/tmp/qroot packages - -This should result in 4 packages being created: - - frr-libs-...-$ARCH.pkg - FRRlibs - frr-daemons-...-$ARCH.pkg - FRRdaemons - frr-doc-...-$ARCH.pkg - FRRdoc - frr-dev-...-$ARCH.pkg - FRRdev - frr-smf-...-$ARCH.pkg - FRRsmf - -FRRlibs and FRRdaemons are needed for daemon runtime. FRRsmf -provides the required bits for Solaris 10+ SMF support. - - -Install and post-install configuration notes: ---------------------------------------------- - -- If you specified a user/group which does not exist per default on Solaris - (eg frr/frr) you *must* create these before installing these on a - system. The packages do *not* create the users. - -- The configuration files are not created. You must create the configuration - file yourself, either with your complete desired configuration, or else if - you wish to use the telnet interface for further configuration you must - create them containing at least: - - password whatever - - The user which frr runs as must have write permissions on this file, no - other user should have read permissions, and you would also have to enable - the telnet interface (see below). - -- SMF notes: - - - FRRsmf installs a svc:/network/routing/frr service, with an - instance for each daemon - - - The state of all instances of frr service can be inspected with: - - svcs -l svc:/network/routing/frr - - or typically just with a shortcut of 'frr': - - svcs -l frr - - - A specific instance of the frr service can be inspected by specifying - the daemon name as the instance, ie frr:<daemon>: - - svcs -l svc:/network/routing/frr:zebra - svcs -l svc:/network/routing/frr:ospfd - <etc> - - or typically just with the shortcut of 'frr:<daemon>' or even - <daemon>: - - svcs -l frr:zebra - svcs -l ospfd - - Eg: - - # # svcs -l ripd - fmri svc:/network/routing/frr:ripd - name FRRouting: ripd, RIPv1/2 IPv4 routing protocol daemon. - enabled true - state online - next_state none - state_time Wed Jun 15 16:21:02 2005 - logfile /var/svc/log/network-routing-frr:ripd.log - restarter svc:/system/svc/restarter:default - contract_id 93 - dependency require_all/restart svc:/network/routing/frr:zebra (online) - dependency require_all/restart file://localhost//usr/local/frr/etc/ripd.conf (online) - dependency require_all/none svc:/system/filesystem/usr:default (online) - dependency require_all/none svc:/network/loopback (online) - - - Configuration of startup options is by way of SMF properties in a - property group named 'frr'. The defaults should automatically be - inline with how you configured FRRouting in Step 1 above. - - - By default the VTY interface is disabled. To change this, see below for - how to set the 'frr/vty_port' property as appropriate for - /each/ service. Also, the VTY is set to listen only to localhost by - default, you may change the 'frr/vty_addr' property as appropriate - for both of the 'frr' service and specific individual instances of - the 'frr' service (ie frr:zebra, frr:ospfd, etc..). - - - Properties belonging to the 'frr' service are inherited by all - instances. Eg: - - # svcprop -p frr svc:/network/routing/frr - frr/group astring root - frr/retain boolean false - frr/user astring root - frr/vty_addr astring 127.1 - frr/vty_port integer 0 - - # svcprop -p frr svc:/network/routing/frr:ospfd - frr/retain_routes boolean false - frr/group astring root - frr/retain boolean false - frr/user astring root - frr/vty_addr astring 127.1 - frr/vty_port integer 0 - - All instances will inherit these properties, unless the instance itself - overrides these defaults. This also implies one can modify properties of - the 'frr' service and have them apply to all daemons. - - # svccfg -s svc:/network/routing/frr \ - setprop frr/vty_addr = astring: ::1 - - # svcprop -p frr svc:/network/routing/frr - frr/group astring root - frr/retain boolean false - frr/user astring root - frr/vty_port integer 0 - frr/vty_addr astring ::1 - - # # You *must* refresh instances to have the property change - # # take affect for the 'running snapshot' of service state. - # svcadm refresh frr:ospfd - - # svcprop -p frr svc:/network/routing/frr:ospfd - frr/retain_routes boolean false - frr/group astring root - frr/retain boolean false - frr/user astring root - frr/vty_port integer 0 - frr/vty_addr astring ::1 - - Other daemon-specific options/properties may be available, however they - are not yet honoured/used (eg ospfd/apiserver on svc:/network/ospf). - - - As SMF is dependency aware, restarting network/zebra will restart all the - other daemons. - - - To upgrade from one set of FRRouting packages to a newer release, - one must first pkgrm the installed packages. When one pkgrm's FRRsmf all - property configuration will be lost, and any customisations will have to - redone after installing the updated FRRsmf package. - -- These packages are not supported by Sun Microsystems, report bugs via the - usual FRRouting channels, ie Issue Tracker. Improvements/contributions of course would be greatly appreciated. - diff --git a/solaris/depend.daemons.in b/solaris/depend.daemons.in deleted file mode 100644 index a8ce943e31..0000000000 --- a/solaris/depend.daemons.in +++ /dev/null @@ -1,8 +0,0 @@ -P FRRlibs FRRouting common runtime libraries - @PACKAGE_VERSION@,REV=@CONFDATE@ -P SUNWcsu Core Solaris, (Usr) -P SUNWcsr Core Solaris Libraries (Root) -P SUNWcnetr Core Solaris Network Infrastructure (Root) -I SUNWzebrar -I SUNWzebrau -I CSWzebra diff --git a/solaris/depend.dev.in b/solaris/depend.dev.in deleted file mode 100644 index 1b65724a04..0000000000 --- a/solaris/depend.dev.in +++ /dev/null @@ -1,2 +0,0 @@ -P FRRlibs FRRouting common runtime libraries - @PACKAGE_VERSION@,REV=@CONFDATE@ diff --git a/solaris/depend.doc.in b/solaris/depend.doc.in deleted file mode 100644 index b33792911d..0000000000 --- a/solaris/depend.doc.in +++ /dev/null @@ -1 +0,0 @@ -P SUNWdoc Documentation Tools diff --git a/solaris/depend.libs.in b/solaris/depend.libs.in deleted file mode 100644 index 04f04efd01..0000000000 --- a/solaris/depend.libs.in +++ /dev/null @@ -1,5 +0,0 @@ -P SUNWcslr Core Solaris Libraries (Root) -P SUNWcsl Core Solaris, (Shared Libs) -P SUNWlibmsr Math & Microtasking Libraries (Root) -R FRRdaemons FRRouting daemons -R FRRdev diff --git a/solaris/depend.smf.in b/solaris/depend.smf.in deleted file mode 100644 index b3b1bd778c..0000000000 --- a/solaris/depend.smf.in +++ /dev/null @@ -1,8 +0,0 @@ -P FRRaemons FRRouting daemons - @PACKAGE_VERSION@,REV=@CONFDATE@ -P SUNWcsu Core Solaris, (Usr) -P SUNWcsr Core Solaris Libraries (Root) -P SUNWroute Network Routing daemons/commands (Usr) -I SUNWzebrar -I SUNWzebrau -I CSWzebra diff --git a/solaris/frr.init.in b/solaris/frr.init.in deleted file mode 100755 index bd9ab85e69..0000000000 --- a/solaris/frr.init.in +++ /dev/null @@ -1,276 +0,0 @@ -#!/sbin/sh -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This file is part of FRRouting. -# -# FRRouting 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. -# -# FRRouting 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 FRRouting; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. -# -# Starts/stops the given daemon - -SMFINCLUDE=/lib/svc/share/smf_include.sh -ROUTEADMINCLUDE=/lib/svc/share/routing_include.sh -GLOBAL_OPTIONS="PAfiug" -DAEMON_PATH=@sbindir@ -USER=@enable_user@ -GROUP=@enable_group@ - -# handle upgrade of daemon-args SMF property to new routeadm properties -# used during upgrade too by routeadm. -# relevant to S10U4+ only. -handle_routeadm_upgrade () { - GLOBAL_OPTIONS="PAfiug" - - daemon_args=`get_daemon_args $SMF_FMRI` - - if [ -n "$daemon_args" ]; then - set_daemon_value_property "$SMF_FMRI" "$daemon_args" \ - "$GLOBAL_OPTIONS" "P" vty_port 0 - set_daemon_value_property "$SMF_FMRI" "$daemon_args" \ - "$GLOBAL_OPTIONS" "A" vty_address - set_daemon_value_property "$SMF_FMRI" "$daemon_args" \ - "$GLOBAL_OPTIONS" "f" config_file - set_daemon_value_property "$SMF_FMRI" "$daemon_args" \ - "$GLOBAL_OPTIONS" "i" pid_file - set_daemon_value_property "$SMF_FMRI" "$daemon_args" \ - "$GLOBAL_OPTIONS" "u" user - set_daemon_value_property "$SMF_FMRI" "$daemon_args" \ - "$GLOBAL_OPTIONS" "g" group - - case "$1" in - zebra) - set_daemon_boolean_property "$SMF_FMRI" "$daemon_args" \ - "${GLOBAL_OPTIONS}b" "b" batch true false - ;; - ripd|ripngd) - set_daemon_boolean_property "$SMF_FMRI" "$daemon_args" \ - "${GLOBAL_OPTIONS}r" "r" retain true false - ;; - bgpd) - set_daemon_boolean_property "$SMF_FMRI" "$daemon_args" \ - "${GLOBAL_OPTIONS}rnp" "r" retain true false - set_daemon_boolean_property "$SMF_FMRI" "$daemon_args" \ - "${GLOBAL_OPTIONS}rnp" "n" no_kernel true false - set_daemon_value_property "$SMF_FMRI" "$daemon_args" \ - "${GLOBAL_OPTIONS}rnp" "p" bgp_port - esac - clear_daemon_args $SMF_FMRI - fi -} - -upgrade_config () { - DAEMON=$1 - # handle upgrade of SUNWzebra to FRRouting - if [ -d "/etc/frr" -a ! -f "/etc/frr/${DAEMON}.conf" ] ; then - if [ -f "/etc/sfw/zebra/${DAEMON}.conf" ] ; then - cp "/etc/sfw/zebra/${DAEMON}.conf" \ - "/etc/frr/${DAEMON}.conf.upgrade" \ - || exit $SMF_EXIT_ERR_FATAL - chown "${USER}:${GROUP}" "/etc/frr/${DAEMON}.conf.upgrade" \ - || exit $SMF_EXIT_ERR_FATAL - chmod 0600 "/etc/frr/${DAEMON}.conf.upgrade" \ - || exit $SMF_EXIT_ERR_FATAL - mv "/etc/frr/${DAEMON}.conf.upgrade" "/etc/frr/${DAEMON}.conf" \ - || exit $SMF_EXIT_ERR_FATAL - fi - fi - - if [ ! -f "/etc/frr/${DAEMON}.conf" ] ; then - touch "/etc/frr/${DAEMON}.conf.new" \ - || exit $SMF_EXIT_ERR_FATAL - chown "${USER}:${GROUP}" "/etc/frr/${DAEMON}.conf.new" \ - || exit $SMF_EXIT_ERR_FATAL - chmod 0600 "/etc/frr/${DAEMON}.conf.new" \ - || exit $SMF_EXIT_ERR_FATAL - mv "/etc/frr/${DAEMON}.conf.new" "/etc/frr/${DAEMON}.conf" \ - || exit $SMF_EXIT_ERR_FATAL - fi -} - -# Relevant to S10+ -frr_is_globalzone () { - if [ "${FRR_INIT_ZONENAME:=`/sbin/zonename`}" = "global" \ - -o `/sbin/zonename -t` = "exclusive" ]; then - return 0 - else - return 1 - fi -} - -routeadm_daemon_args () { - # globals - args="`get_daemon_option_from_property $SMF_FMRI config_file f`" - args="${args} `get_daemon_option_from_property $SMF_FMRI vty_port P`" - args="${args} `get_daemon_option_from_property $SMF_FMRI vty_address A`" - args="${args} `get_daemon_option_from_property $SMF_FMRI pid_file i`" - - # user and group we need for config file upgrade.. - SMF_USER=`get_routeadm_property $SMF_FMRI user` - SMF_GROUP=`get_routeadm_property()$SMF_FMRI group` - if [ "${SMF_USER}" ] ; then - USER="${SMF_USER}" - args="${args} -u ${SMF_USER}" - fi - if [ "${SMF_GROUP}" ] ; then - GROUP="${SMF_GROUP}" - args="${args} -g ${SMF_GROUP}" - fi - - case $1 in - zebra) - args="${args} `get_daemon_option_from_boolean_property $SMF_FMRI batch -b true`" - ;; - ripd|ripngd) - args="${args} `get_daemon_option_from_boolean_property $SMF_FMRI retain -r true`" - ;; - bgpd) - args="${args} `get_daemon_option_from_boolean_property $SMF_FMRI retain -r true`" - args="${args} `get_daemon_option_from_boolean_property $SMF_FMRI no_kernel -n true`" - args="${args} `get_daemon_option_from_property $SMF_FMRI bgp_port p 179`" - ;; - esac - echo ${args} -} - -# Include smf functions, if available. If not, define smf_present to indicate -# there is no SMF. Should allow this script to work pre-S10. -if [ -f "$SMFINCLUDE" ] ; then - . "$SMFINCLUDE"; - - # source the SMF-routeadm include if present.. - if [ -f "$ROUTEADMINCLUDE" ] ; then - . "$ROUTEADMINCLUDE" - fi -else - # pre-SMF system, fake up any functions and exit codes - # which SMFINCLUDE usually provides. - smf_present () { - return 1 - } - SMF_EXIT_OK=0; - SMF_EXIT_ERR_CONFIG=96; - SMF_EXIT_ERR_FATAL=95; -fi - -# if there's no SMF, set some default DAEMON_ARGS -smf_present || DAEMON_ARGS="" - -usage () { - if smf_present ; then - echo "Usage: $0 <daemon>"; - else - echo "Usage: $0 <stop|start> <daemon> <daemon arguments>"; - fi - echo "The --pid_file argument is implied"; - echo "This help message: $0 <help|usage>"; -} - -# parse arguments, different according to SMF or not. -case $1 in - 'help' | 'usage') - usage - exit $SMF_EXIT_OK - ;; -esac - -if smf_present ; then - FRR_METHOD="start" -else - FRR_METHOD="$1" - shift; -fi - -DAEMON="$1" - -# daemon path must be given -if [ -z "$DAEMON_PATH/$DAEMON" ]; then - usage - exit $SMF_EXIT_ERR_FATAL -fi - -# only bgpd is suitable for running in a non-global zone, at this -# time. -case "${DAEMON}" in - bgpd) - ;; - zebra | ospfd | ospf6d | ripd | ripngd ) - frr_is_globalzone || exit $SMF_EXIT_OK - ;; - *) - usage - exit $SMF_EXIT_ERR_CONFIG; - ;; -esac - -# Older FRRouting SMF packages pass daemon args on the commandline -# Newer SMF routeadm model uses properties for each argument -# so we must handle that. -if [ smf_present -a -f "$ROUTEADMINCLUDE" ]; then - handle_routeadm_upgrade $DAEMON; - DAEMON_ARGS=`routeadm_daemon_args`; -else - if [ $# -gt 0 ] ; then - shift - DAEMON_ARGS="$@" - fi -fi - -upgrade_config "$DAEMON" - -if [ ! -f "@sysconfdir@/${DAEMON}.conf" ] ; then - echo "Could not find config file, @sysconfdir@/${DAEMON}.conf" - exit $SMF_EXIT_ERR_CONFIG -fi - -# we need @frr_statedir@ to exist, it probably is on tmpfs. -if [ ! -d @frr_statedir@ ] ; then - mkdir -p @frr_statedir@ - chown @enable_user@:@enable_group@ @frr_statedir@ - chmod 751 @frr_statedir@ -fi - -PIDFILE="@frr_statedir@/${DAEMON}.pid" - -start () { - if [ ! -x "$DAEMON_PATH/$DAEMON" ] ; then - echo "Error, could not find daemon, $DAEMON_PATH/$DAEMON" - exit $SMF_EXIT_ERR_FATAL - fi - eval exec $DAEMON_PATH/$DAEMON $DAEMON_ARGS --pid_file ${PIDFILE} & -} - -stop_by_pidfile () { - if [ -f "${PIDFILE}" ]; then - /usr/bin/kill -TERM `/usr/bin/cat "${PIDFILE}"` - fi -} - -case "$FRR_METHOD" in -'start') - start - ;; -'stop') - stop_by_pidfile - ;; - -*) - usage - exit $SMF_EXIT_ERR_FATAL - ;; -esac - -exit $SMF_EXIT_OK; diff --git a/solaris/frr.xml.in b/solaris/frr.xml.in deleted file mode 100644 index 08a9a11c0f..0000000000 --- a/solaris/frr.xml.in +++ /dev/null @@ -1,828 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> -<!-- - This file is part of FRRouting (FRR) - - FRRouting 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) anylater version. - - FRRouting 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 FRRouting; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Copyright 2007 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. - - Copyright 2015 Joyent, Inc. - - ident "@(#)frr.xml 1.0 19/01/17 SMI" ---> - -<service_bundle type='manifest' name='SUNWfrr-daemons:frr'> - -<service - name='network/routing/zebra' - type='service' - version='1'> - - <single_instance /> - <instance name='frr' enabled='false'> - - <dependency name='fs' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri - value='svc:/system/filesystem/usr:default' /> - </dependency> - - <dependency name='net' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri value='svc:/network/initial' /> - </dependency> - - <!-- do not not run unless routing-setup has run --> - <dependency - name='network_routing_setup' - grouping='require_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/routing-setup' /> - </dependency> - - <exec_method - type='method' - name='start' - exec='/lib/svc/method/frr zebra' - timeout_seconds='60'> - <method_context> - <method_credential - user='root' group='root'/> - </method_context> - </exec_method> - - <exec_method - type='method' - name='stop' - exec=':kill' - timeout_seconds='60'> - </exec_method> - - <!-- if we define these properties at the service level, each - instance inherits them, and it can override with - desired values. - --> - <property_group name='startd' - type='framework'> - <!-- sub-process core dumps shouldn't restart session --> - <propval name='ignore_error' - type='astring' value='core,signal' /> - </property_group> - - <!-- Properties in this group are used by routeadm (1M) --> - <property_group name='routeadm' type='application'> - <stability value='Unstable' /> - <!-- Identifies service as a routing service --> - <propval name='daemon' type='astring' - value='@sbindir@/zebra' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - <!-- zebra should not contribute to ipv4/ipv6 routing state --> - <propval name='protocol' type='astring' value='zebra' /> - </property_group> - - <!-- Properties in this group are modifiable via routeadm (1M) --> - <property_group name='routing' type='application'> - <stability value='Evolving' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - - <!-- Options common to FRRouting daemons - Property names are equivalent to the long - option name, consult FRRouting documentation --> - <!-- The config file to use, if not the default --> - <propval name='config_file' type='astring' value=''/> - <!-- The vty_port to listen on if not the default. - 0 to disable --> - <propval name='vty_port' type='integer' value='0' /> - <!-- The address to bind the VTY interface to, if not any. --> - <propval name='vty_address' type='astring' value='' /> - <!-- The user to switch to after startup, if not the default --> - <propval name='user' type='astring' value='' /> - <!-- The group to switch to, if not the default. - If user is specified, this defaults to a group with - same name as user --> - <propval name='group' type='astring' value='' /> - <!-- The pidfile to use, if not the default of - @frr_statedir@ --> - <propval name='pid_file' type='astring' value='' /> - - <!-- Options specific to zebra --> - <propval name='batch' type='boolean' value='false' /> - </property_group> - - <property_group name='general' type='framework'> - <!-- to start stop routing services --> - <propval name='action_authorization' type='astring' - value='solaris.smf.manage.routing' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.manage.routing' /> - </property_group> - - <template> - <common_name> - <loctext xml:lang='C'> - FRRouting: zebra, RIB, kernel intermediary and misc daemon - </loctext> - </common_name> - <documentation> - <manpage title='zebra' section='1M' - manpath='@mandir@' /> - <doc_link name='frrouting.org' - uri='http://www.frrouting.org/' /> - </documentation> - </template> - </instance> - <stability value='Unstable' /> -</service> - -<service - name='network/routing/rip' - type='service' - version='1'> - - <instance name='frr' enabled='false'> - - <dependency name='fs' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri - value='svc:/system/filesystem/usr:default' /> - </dependency> - - <dependency - name='ipv4-forwarding' - grouping='optional_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/ipv4-forwarding' /> - </dependency> - - <!-- do not not run unless routing-setup has run --> - <dependency - name='network_routing_setup' - grouping='require_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/routing-setup' /> - </dependency> - - <!-- ensure that restart of zebra is propogated to daemon --> - <dependency - name='zebra' - grouping='require_all' - restart_on='restart' - type='service'> - <service_fmri value='svc:/network/routing/zebra:frr' /> - </dependency> - - <exec_method - type='method' - name='start' - exec='/lib/svc/method/frr ripd' - timeout_seconds='60'> - <method_context> - <method_credential - user='root' group='root'/> - </method_context> - </exec_method> - - <exec_method - type='method' - name='stop' - exec=':kill' - timeout_seconds='60'> - </exec_method> - - <property_group name='startd' - type='framework'> - <!-- sub-process core dumps shouldn't restart session --> - <propval name='ignore_error' - type='astring' value='core,signal' /> - </property_group> - - <!-- Properties in this group are used by routeadm (1M) --> - <property_group name='routeadm' type='application'> - <stability value='Unstable' /> - <!-- Identifies service as a routing service --> - <propval name='daemon' type='astring' - value='@sbindir@/ripd' /> - <propval name='legacy-daemon' type='astring' - value='/usr/sfw/sbin/ripdstart' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - <propval name='protocol' type='astring' value='ipv4' /> - </property_group> - - <!-- Properties in this group are modifiable via routeadm (1M) --> - <property_group name='routing' type='application'> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - - <!-- Options common to FRRouting daemons --> - <!-- The config file to use, if not the default --> - <propval name='config_file' type='astring' value=''/> - <!-- The vty_port to listen on if not the default. - 0 to disable --> - <propval name='vty_port' type='integer' value='0' /> - <!-- The address to bind the VTY interface to, if not any. --> - <propval name='vty_address' type='astring' value='' /> - <!-- The user to switch to after startup, if not the default --> - <propval name='user' type='astring' value='' /> - <!-- The group to switch to, if not the default. - If user is specified, this defaults to a group with - same name as user --> - <propval name='group' type='astring' value='' /> - <!-- The pidfile to use, if not the default of - @frr_statedir@ --> - <propval name='pid_file' type='astring' value='' /> - - <!-- Options specific to ripd --> - <propval name='retain' type='boolean' value='false' /> - </property_group> - - <property_group name='general' type='framework'> - <!-- to start stop routing services --> - <propval name='action_authorization' type='astring' - value='solaris.smf.manage.routing' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.manage.routing' /> - </property_group> - - <template> - <common_name> - <loctext xml:lang='C'> - FRRouting: ripd, RIPv1/2 IPv4 routing protocol daemon. - </loctext> - </common_name> - <documentation> - <manpage title='ripd' section='1M' - manpath='@mandir@' /> - <doc_link name='frrouting.org' - uri='http://www.frrouting.org/' /> - </documentation> - </template> - </instance> - <stability value='Unstable' /> -</service> - -<service - name='network/routing/ripng' - type='service' - version='1'> - - <instance name='frr' enabled='false'> - - <dependency name='fs' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri - value='svc:/system/filesystem/usr:default' /> - </dependency> - - <dependency - name='ipv6-forwarding' - grouping='optional_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/ipv6-forwarding' /> - </dependency> - - <!-- do not not run unless routing-setup has run --> - <dependency - name='network_routing_setup' - grouping='require_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/routing-setup' /> - </dependency> - - <!-- ensure that restart of zebra is propogated to daemon --> - <dependency - name='zebra' - grouping='require_all' - restart_on='restart' - type='service'> - <service_fmri value='svc:/network/routing/zebra:frr' /> - </dependency> - - <exec_method - type='method' - name='start' - exec='/lib/svc/method/frr ripngd' - timeout_seconds='60'> - <method_context> - <method_credential - user='root' group='root'/> - </method_context> - </exec_method> - - <exec_method - type='method' - name='stop' - exec=':kill' - timeout_seconds='60' > - </exec_method> - - <property_group name='startd' - type='framework'> - <!-- sub-process core dumps shouldn't restart session --> - <propval name='ignore_error' - type='astring' value='core,signal' /> - </property_group> - - <!-- Properties in this group are used by routeadm (1M) --> - <property_group name='routeadm' type='application'> - <stability value='Unstable' /> - <!-- Identifies service as a routing service --> - <propval name='daemon' type='astring' - value='@sbindir@/ripngd' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - <propval name='protocol' type='astring' value='ipv6'/> - </property_group> - - <!-- Properties in this group are modifiable via routeadm (1M) --> - <property_group name='routing' type='application'> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - - <!-- Options common to frr daemons --> - <!-- The config file to use, if not the default --> - <propval name='config_file' type='astring' value=''/> - <!-- The vty_port to listen on if not the default. - 0 to disable --> - <propval name='vty_port' type='integer' value='0' /> - <!-- The address to bind the VTY interface to, if not any. --> - <propval name='vty_address' type='astring' value='' /> - <!-- The user to switch to after startup, if not the default --> - <propval name='user' type='astring' value='' /> - <!-- The group to switch to, if not the default. - If user is specified, this defaults to a group with - same name as user --> - <propval name='group' type='astring' value='' /> - <!-- The pidfile to use, if not the default of - @frr_statedir@ --> - <propval name='pid_file' type='astring' value='' /> - - <!-- Options specific to ripngd --> - <propval name='retain' type='boolean' value='false' /> - </property_group> - - <property_group name='general' type='framework'> - <!-- to start stop routing services --> - <propval name='action_authorization' type='astring' - value='solaris.smf.manage.routing' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.manage.routing' /> - </property_group> - - <template> - <common_name> - <loctext xml:lang='C'> - frr: ripngd, RIPng IPv6 routing protocol daemon. - </loctext> - </common_name> - <documentation> - <manpage title='ripngd' section='1M' - manpath='@mandir@' /> - <doc_link name='frrouting.org' - uri='http://www.frrouting.org/' /> - </documentation> - </template> - </instance> - <stability value='Unstable' /> -</service> - -<service - name='network/routing/ospf' - type='service' - version='1'> - - <instance name='frr' enabled='false'> - - <dependency name='fs' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri - value='svc:/system/filesystem/usr:default' /> - </dependency> - - <dependency - name='ipv4-forwarding' - grouping='optional_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/ipv4-forwarding' /> - </dependency> - - <!-- do not not run unless routing-setup has run --> - <dependency - name='network_routing_setup' - grouping='require_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/routing-setup' /> - </dependency> - - <!-- ensure that restart of zebra is propogated to daemon --> - <dependency - name='zebra' - grouping='require_all' - restart_on='restart' - type='service'> - <service_fmri value='svc:/network/routing/zebra:frr' /> - </dependency> - - <exec_method - type='method' - name='start' - exec='/lib/svc/method/frr ospfd' - timeout_seconds='60'> - <method_context> - <method_credential - user='root' group='root'/> - </method_context> - </exec_method> - - <!-- ospfd can take a long time to shutdown, due to graceful - shutdown - --> - <exec_method - type='method' - name='stop' - exec=':kill' - timeout_seconds='600'> - </exec_method> - - <property_group name='startd' - type='framework'> - <!-- sub-process core dumps shouldn't restart session --> - <propval name='ignore_error' - type='astring' value='core,signal' /> - </property_group> - - <!-- Properties in this group are used by routeadm (1M) --> - <property_group name='routeadm' type='application'> - <stability value='Unstable' /> - <!-- Identifies service as a routing service --> - <propval name='daemon' type='astring' - value='@sbindir@/ospfd' /> - <propval name='legacy-daemon' type='astring' - value='/usr/sfw/sbin/ospfdstart' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - <propval name='protocol' type='astring' value='ipv4'/> - </property_group> - - <!-- Properties in this group are modifiable via routeadm (1M) --> - <property_group name='routing' type='application'> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - - <!-- Options common to frr daemons --> - <!-- The config file to use, if not the default --> - <propval name='config_file' type='astring' value=''/> - <!-- The vty_port to listen on if not the default. - 0 to disable --> - <propval name='vty_port' type='integer' value='0' /> - <!-- The address to bind the VTY interface to, if not any. --> - <propval name='vty_address' type='astring' value='' /> - <!-- The user to switch to after startup, if not the default --> - <propval name='user' type='astring' value='' /> - <!-- The group to switch to, if not the default. - If user is specified, this defaults to a group with - same name as user --> - <propval name='group' type='astring' value='' /> - <!-- The pidfile to use, if not the default of - @frr_statedir@ --> - <propval name='pid_file' type='astring' value='' /> - </property_group> - - <property_group name='general' type='framework'> - <!-- to start stop routing services --> - <propval name='action_authorization' type='astring' - value='solaris.smf.manage.routing' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.manage.routing' /> - </property_group> - - <template> - <common_name> - <loctext xml:lang='C'> - frr: ospfd, OSPFv2 IPv4 routing protocol daemon. - </loctext> - </common_name> - <documentation> - <manpage title='ospfd' section='1M' - manpath='@mandir@' /> - <doc_link name='frrouting.org' - uri='http://www.frrouting.org/' /> - </documentation> - </template> - </instance> - <stability value='Unstable' /> -</service> - -<service - name='network/routing/ospf6' - type='service' - version='1'> - - <instance name='frr' enabled='false'> - - <dependency name='fs' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri - value='svc:/system/filesystem/usr:default' /> - </dependency> - - <dependency - name='ipv6-forwarding' - grouping='optional_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/ipv6-forwarding' /> - </dependency> - - <!-- do not not run unless routing-setup has run --> - <dependency - name='network_routing_setup' - grouping='require_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/routing-setup' /> - </dependency> - - <!-- ensure that restart of zebra is propogated to daemon --> - <dependency - name='zebra' - grouping='require_all' - restart_on='restart' - type='service'> - <service_fmri value='svc:/network/routing/zebra:frr' /> - </dependency> - - <exec_method - type='method' - name='start' - exec='/lib/svc/method/frr ospf6d' - timeout_seconds='60'> - <method_context> - <method_credential - user='root' group='root'/> - </method_context> - </exec_method> - - <exec_method - type='method' - name='stop' - exec=':kill' - timeout_seconds='60'> - </exec_method> - - <property_group name='startd' - type='framework'> - <!-- sub-process core dumps shouldn't restart session --> - <propval name='ignore_error' - type='astring' value='core,signal' /> - </property_group> - - <!-- Properties in this group are used by routeadm (1M) --> - <property_group name='routeadm' type='application'> - <stability value='Unstable' /> - <!-- Identifies service as a routing service --> - <propval name='daemon' type='astring' - value='@sbindir@/ospf6d' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - <propval name='protocol' type='astring' value='ipv6'/> - </property_group> - - <!-- Properties in this group are modifiable via routeadm (1M) --> - <property_group name='routing' type='application'> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - - <!-- Options common to frr daemons --> - <!-- The config file to use, if not the default --> - <propval name='config_file' type='astring' value=''/> - <!-- The vty_port to listen on if not the default. - 0 to disable --> - <propval name='vty_port' type='integer' value='0' /> - <!-- The address to bind the VTY interface to, if not any. --> - <propval name='vty_address' type='astring' value='' /> - <!-- The user to switch to after startup, if not the default --> - <propval name='user' type='astring' value='' /> - <!-- The group to switch to, if not the default. - If user is specified, this defaults to a group with - same name as user --> - <propval name='group' type='astring' value='' /> - <!-- The pidfile to use, if not the default of - @frr_statedir@ --> - <propval name='pid_file' type='astring' value='' /> - </property_group> - - <property_group name='general' type='framework'> - <!-- to start stop routing services --> - <propval name='action_authorization' type='astring' - value='solaris.smf.manage.routing' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.manage.routing' /> - </property_group> - - <template> - <common_name> - <loctext xml:lang='C'> - frr: ospf6d, OSPFv3 IPv6 routing protocol daemon. - </loctext> - </common_name> - <documentation> - <manpage title='ospf6d' section='1M' - manpath='@mandir@' /> - <doc_link name='frrouting.org' - uri='http://www.frrouting.org/' /> - </documentation> - </template> - </instance> - <stability value='Unstable' /> -</service> - - -<service - name='network/routing/bgp' - type='service' - version='1'> - - <instance name='frr' enabled='false'> - - <dependency name='fs' - grouping='require_all' - restart_on='none' - type='service'> - <service_fmri - value='svc:/system/filesystem/usr:default' /> - </dependency> - - <dependency - name='ipv6-forwarding' - grouping='optional_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/ipv6-forwarding' /> - </dependency> - - <dependency - name='ipv4-forwarding' - grouping='optional_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/ipv4-forwarding' /> - </dependency> - - <!-- do not not run unless routing-setup has run --> - <dependency - name='network_routing_setup' - grouping='require_all' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/network/routing-setup' /> - </dependency> - - <!-- ensure that restart of zebra is propogated to daemon --> - <dependency - name='zebra' - grouping='require_all' - restart_on='restart' - type='service'> - <service_fmri value='svc:/network/routing/zebra:frr' /> - </dependency> - - <exec_method - type='method' - name='start' - exec='/lib/svc/method/frr bgpd' - timeout_seconds='60'> - <method_context> - <method_credential - user='root' group='root'/> - </method_context> - </exec_method> - - <exec_method - type='method' - name='stop' - exec=':kill' - timeout_seconds='60' > - </exec_method> - - <property_group name='startd' - type='framework'> - <!-- sub-process core dumps shouldn't restart session --> - <propval name='ignore_error' - type='astring' value='core,signal' /> - </property_group> - - <!-- Properties in this group are used by routeadm (1M) --> - <property_group name='routeadm' type='application'> - <stability value='Unstable' /> - <!-- Identifies service as a routing service --> - <propval name='daemon' type='astring' - value='@sbindir@/bgpd' /> - <propval name='legacy-daemon' type='astring' - value='/usr/sfw/sbin/bgpdstart' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - <property name='protocol' type='astring'> - <astring_list> - <value_node value='ipv4'/> - <value_node value='ipv6'/> - </astring_list> - </property> - </property_group> - - <!-- Properties in this group are modifiable via routeadm (1M) --> - <property_group name='routing' type='application'> - <propval name='value_authorization' type='astring' - value='solaris.smf.value.routing' /> - - <!-- Options common to frr daemons. --> - <!-- The config file to use, if not the default --> - <propval name='config_file' type='astring' value=''/> - <!-- The vty_port to listen on if not the default. - 0 to disable --> - <propval name='vty_port' type='integer' value='0' /> - <!-- The address to bind the VTY interface to, if not any. --> - <propval name='vty_address' type='astring' value='' /> - <!-- The user to switch to after startup, if not the default --> - <propval name='user' type='astring' value='' /> - <!-- The group to switch to, if not the default. - If user is specified, this defaults to a group with - same name as user --> - <propval name='group' type='astring' value='' /> - <!-- The pidfile to use, if not the default of - @frr_statedir@ --> - <propval name='pid_file' type='astring' value='' /> - - <!-- Options specific to bgpd --> - <propval name='retain' type='boolean' value='false' /> - <propval name='no_kernel' type='boolean' value='false' /> - <propval name='bgp_port' type='astring' value='' /> - - <!-- - If enable_zebra is false, it will not be switched - on by the start method. - --> - <propval name='enable_zebra' type='boolean' value='true' /> - </property_group> - - <property_group name='general' type='framework'> - <!-- to start stop routing services --> - <propval name='action_authorization' type='astring' - value='solaris.smf.manage.routing' /> - <propval name='value_authorization' type='astring' - value='solaris.smf.manage.routing' /> - </property_group> - - <template> - <common_name> - <loctext xml:lang='C'> - frr: bgpd, BGP routing protocol daemon. - </loctext> - </common_name> - <documentation> - <manpage title='bgpd' section='1M' - manpath='@mandir@' /> - <doc_link name='frrouting.org' - uri='http://www.frrouting.org/' /> - </documentation> - </template> - </instance> - <stability value='Unstable' /> -</service> -</service_bundle> diff --git a/solaris/pkginfo.daemons.tmpl.in b/solaris/pkginfo.daemons.tmpl.in deleted file mode 100644 index 7070d6dc97..0000000000 --- a/solaris/pkginfo.daemons.tmpl.in +++ /dev/null @@ -1,2 +0,0 @@ -PKG="FRRdaemons" -NAME="@PACKAGE_NAME@ - @PACKAGE_NAME@ daemons" diff --git a/solaris/pkginfo.dev.tmpl.in b/solaris/pkginfo.dev.tmpl.in deleted file mode 100644 index 23796ba226..0000000000 --- a/solaris/pkginfo.dev.tmpl.in +++ /dev/null @@ -1,3 +0,0 @@ -PKG=FRRdev -NAME="@PACKAGE_NAME@ - @PACKAGE_NAME@ development files" - diff --git a/solaris/pkginfo.doc.tmpl.in b/solaris/pkginfo.doc.tmpl.in deleted file mode 100644 index 727fbb526f..0000000000 --- a/solaris/pkginfo.doc.tmpl.in +++ /dev/null @@ -1,2 +0,0 @@ -PKG=FRRdoc -NAME="@PACKAGE_NAME@ - @PACKAGE_NAME@ documentation" diff --git a/solaris/pkginfo.libs.tmpl.in b/solaris/pkginfo.libs.tmpl.in deleted file mode 100644 index adf945862c..0000000000 --- a/solaris/pkginfo.libs.tmpl.in +++ /dev/null @@ -1,2 +0,0 @@ -PKG=FRRlibs -NAME="@PACKAGE_NAME@ - @PACKAGE_NAME@ common runtime libraries" diff --git a/solaris/pkginfo.smf.tmpl.in b/solaris/pkginfo.smf.tmpl.in deleted file mode 100644 index a90cb1bdee..0000000000 --- a/solaris/pkginfo.smf.tmpl.in +++ /dev/null @@ -1,2 +0,0 @@ -PKG="FRRsmf" -NAME="@PACKAGE_NAME@ - @PACKAGE_NAME@ SMF support" diff --git a/solaris/pkginfo.tmpl.in b/solaris/pkginfo.tmpl.in deleted file mode 100644 index ffbf9b9cef..0000000000 --- a/solaris/pkginfo.tmpl.in +++ /dev/null @@ -1,10 +0,0 @@ -ARCH="@host_cpu@" -CATEGORY="system" -VERSION="@PACKAGE_VERSION@,REV=@CONFDATE@" -VENDOR="http://www.frrouting.org/" -HOTLINE="@PACKAGE_BUGREPORT@" -EMAIL=maintainers@frrouting.org -DESC="@PACKAGE_NAME@ Routing Protocols" -MAXINST=1 -CLASSES="none preserve renamenew manifest" -BASEDIR=/ diff --git a/solaris/prototype.daemons.in b/solaris/prototype.daemons.in deleted file mode 100644 index 9af275a17f..0000000000 --- a/solaris/prototype.daemons.in +++ /dev/null @@ -1,20 +0,0 @@ -i pkginfo=$abs_builddir/pkginfo.daemons.full -i depend=$abs_builddir/depend.daemons -i copying=$abs_top_srcdir/COPYING -d none @sbindir@=$DESTDIR/@sbindir@ 0755 root bin -f none @sbindir@/zebra=$DESTDIR/@sbindir@/zebra 0755 root bin -f none @sbindir@/bgpd=$DESTDIR/@sbindir@/bgpd 0755 root bin -f none @sbindir@/ripd=$DESTDIR/@sbindir@/ripd 0755 root bin -f none @sbindir@/ripngd=$DESTDIR/@sbindir@/ripngd 0755 root bin -f none @sbindir@/ospfd=$DESTDIR/@sbindir@/ospfd 0755 root bin -f none @sbindir@/ospf6d=$DESTDIR/@sbindir@/ospf6d 0755 root bin -f none @sbindir@/watchfrr=$DESTDIR/@sbindir@/watchfrr 0755 root bin -d none @sysconfdir@=$DESTDIR/@sysconfdir@ 0711 @enable_user@ @enable_group@ -f none @sysconfdir@/zebra.conf.sample=$DESTDIR/@sysconfdir@/zebra.conf.sample 0644 root bin -f none @sysconfdir@/bgpd.conf.sample=$DESTDIR/@sysconfdir@/bgpd.conf.sample 0644 root bin -f none @sysconfdir@/bgpd.conf.sample2=$DESTDIR/@sysconfdir@/bgpd.conf.sample2 0644 root bin -f none @sysconfdir@/ripd.conf.sample=$DESTDIR/@sysconfdir@/ripd.conf.sample 0644 root bin -f none @sysconfdir@/ripngd.conf.sample=$DESTDIR/@sysconfdir@/ripngd.conf.sample 0644 root bin -f none @sysconfdir@/ospfd.conf.sample=$DESTDIR/@sysconfdir@/ospfd.conf.sample 0644 root bin -f none @sysconfdir@/ospf6d.conf.sample=$DESTDIR/@sysconfdir@/ospf6d.conf.sample 0644 root bin -d none @frr_statedir@=$DESTDIR/@frr_statedir@ 0711 @enable_user@ @enable_group@ diff --git a/solaris/prototype.dev.in b/solaris/prototype.dev.in deleted file mode 100644 index 40d20515c3..0000000000 --- a/solaris/prototype.dev.in +++ /dev/null @@ -1,55 +0,0 @@ -i pkginfo=$abs_builddir/pkginfo.dev.full -i depend=$abs_builddir/depend.dev -i copying=$abs_top_srcdir/COPYING -f none @libdir@/libfrr.la=$DESTDIR/@libdir@/libfrr.la 0755 root bin -f none @libdir@/libfrr.a=$DESTDIR/@libdir@/libfrr.a 0644 root bin -f none @libdir@/libfrrospfapiclient.la=$DESTDIR/@libdir@/libfrrospfapiclient.la 0755 root bin -f none @libdir@/libfrrospfapiclient.a=$DESTDIR/@libdir@/libfrrospfapiclient.a 0644 root bin -d none @includedir@=$DESTDIR/@includedir@ 0755 root bin -d none @includedir@/frr=$DESTDIR/@includedir@/frr 0755 root bin -d none @includedir@/frr/ospfd=$DESTDIR/@includedir@/frr/ospfd 0755 root bin -f none @includedir@/frr/ospfd/ospf_api.h=$DESTDIR/@includedir@/frr/ospfd/ospf_api.h 0644 root bin -f none @includedir@/frr/ospfd/ospf_asbr.h=$DESTDIR/@includedir@/frr/ospfd/ospf_asbr.h 0644 root bin -f none @includedir@/frr/ospfd/ospf_dump.h=$DESTDIR/@includedir@/frr/ospfd/ospf_dump.h 0644 root bin -f none @includedir@/frr/ospfd/ospf_lsa.h=$DESTDIR/@includedir@/frr/ospfd/ospf_lsa.h 0644 root bin -f none @includedir@/frr/ospfd/ospf_lsdb.h=$DESTDIR/@includedir@/frr/ospfd/ospf_lsdb.h 0644 root bin -f none @includedir@/frr/ospfd/ospf_nsm.h=$DESTDIR/@includedir@/frr/ospfd/ospf_nsm.h 0644 root bin -f none @includedir@/frr/ospfd/ospf_ism.h=$DESTDIR/@includedir@/frr/ospfd/ospf_ism.h 0644 root bin -f none @includedir@/frr/ospfd/ospf_opaque.h=$DESTDIR/@includedir@/frr/ospfd/ospf_opaque.h 0644 root bin -f none @includedir@/frr/ospfd/ospfd.h=$DESTDIR/@includedir@/frr/ospfd/ospfd.h 0644 root bin -f none @includedir@/frr/buffer.h=$DESTDIR/@includedir@/frr/buffer.h 0644 root bin -f none @includedir@/frr/command.h=$DESTDIR/@includedir@/frr/command.h 0644 root bin -f none @includedir@/frr/filter.h=$DESTDIR/@includedir@/frr/filter.h 0644 root bin -f none @includedir@/frr/getopt.h=$DESTDIR/@includedir@/frr/getopt.h 0644 root bin -f none @includedir@/frr/hash.h=$DESTDIR/@includedir@/frr/hash.h 0644 root bin -f none @includedir@/frr/if.h=$DESTDIR/@includedir@/frr/if.h 0644 root bin -f none @includedir@/frr/linklist.h=$DESTDIR/@includedir@/frr/linklist.h 0644 root bin -f none @includedir@/frr/log.h=$DESTDIR/@includedir@/frr/log.h 0644 root bin -f none @includedir@/frr/memory.h=$DESTDIR/@includedir@/frr/memory.h 0644 root bin -f none @includedir@/frr/network.h=$DESTDIR/@includedir@/frr/network.h 0644 root bin -f none @includedir@/frr/prefix.h=$DESTDIR/@includedir@/frr/prefix.h 0644 root bin -f none @includedir@/frr/routemap.h=$DESTDIR/@includedir@/frr/routemap.h 0644 root bin -f none @includedir@/frr/distribute.h=$DESTDIR/@includedir@/frr/distribute.h 0644 root bin -f none @includedir@/frr/sockunion.h=$DESTDIR/@includedir@/frr/sockunion.h 0644 root bin -f none @includedir@/frr/str.h=$DESTDIR/@includedir@/frr/str.h 0644 root bin -f none @includedir@/frr/stream.h=$DESTDIR/@includedir@/frr/stream.h 0644 root bin -f none @includedir@/frr/table.h=$DESTDIR/@includedir@/frr/table.h 0644 root bin -f none @includedir@/frr/thread.h=$DESTDIR/@includedir@/frr/thread.h 0644 root bin -f none @includedir@/frr/vector.h=$DESTDIR/@includedir@/frr/vector.h 0644 root bin -f none @includedir@/frr/version.h=$DESTDIR/@includedir@/frr/version.h 0644 root bin -f none @includedir@/frr/vty.h=$DESTDIR/@includedir@/frr/vty.h 0644 root bin -f none @includedir@/frr/zebra.h=$DESTDIR/@includedir@/frr/zebra.h 0644 root bin -f none @includedir@/frr/plist.h=$DESTDIR/@includedir@/frr/plist.h 0644 root bin -f none @includedir@/frr/zclient.h=$DESTDIR/@includedir@/frr/zclient.h 0644 root bin -f none @includedir@/frr/sockopt.h=$DESTDIR/@includedir@/frr/sockopt.h 0644 root bin -f none @includedir@/frr/smux.h=$DESTDIR/@includedir@/frr/smux.h 0644 root bin -f none @includedir@/frr/md5.h=$DESTDIR/@includedir@/frr/md5.h 0644 root bin -f none @includedir@/frr/if_rmap.h=$DESTDIR/@includedir@/frr/if_rmap.h 0644 root bin -f none @includedir@/frr/keychain.h=$DESTDIR/@includedir@/frr/keychain.h 0644 root bin -f none @includedir@/frr/privs.h=$DESTDIR/@includedir@/frr/privs.h 0644 root bin -f none @includedir@/frr/sigevent.h=$DESTDIR/@includedir@/frr/sigevent.h 0644 root bin -f none @includedir@/frr/pqueue.h=$DESTDIR/@includedir@/frr/pqueue.h 0644 root bin -f none @includedir@/frr/jhash.h=$DESTDIR/@includedir@/frr/jhash.h 0644 root bin -f none @includedir@/frr/zassert.h=$DESTDIR/@includedir@/frr/zassert.h 0644 root bin -d none @includedir@/frr/ospfapi=$DESTDIR/@includedir@/frr/ospfapi 0755 root bin -f none @includedir@/frr/ospfapi/ospf_apiclient.h=$DESTDIR/@includedir@/frr/ospfapi/ospf_apiclient.h 0644 root bin diff --git a/solaris/prototype.doc.in b/solaris/prototype.doc.in deleted file mode 100644 index 9f7995350a..0000000000 --- a/solaris/prototype.doc.in +++ /dev/null @@ -1,17 +0,0 @@ -i pkginfo=$abs_builddir/pkginfo.doc.full -i depend=$abs_builddir/depend.doc -i copying=$abs_top_srcdir/COPYING -d none @infodir@=$DESTDIR/@infodir@ 0755 root bin -#f none @infodir@/dir=$DESTDIR/@infodir@/dir 0644 root bin -f none @infodir@/frr.info=$DESTDIR/@infodir@/frr.info 0644 root bin -d none @mandir@=$DESTDIR/@mandir@ 0755 root bin -d none @mandir@/man1=$DESTDIR/@mandir@/man1 0755 root bin -f none @mandir@/man1/vtysh.1=$DESTDIR/@mandir@/man1/vtysh.1 0644 root bin -d none @mandir@/man8=$DESTDIR/@mandir@/man8 0755 root bin -f none @mandir@/man8/frr-bgpd.8=$DESTDIR/@mandir@/man8/bgpd.8 0644 root bin -f none @mandir@/man8/frr-ospf6d.8=$DESTDIR/@mandir@/man8/frr-ospf6d.8 0644 root bin -f none @mandir@/man8/frr-ospfd.8=$DESTDIR/@mandir@/man8/frr-ospfd.8 0644 root bin -f none @mandir@/man8/frr-ripd.8=$DESTDIR/@mandir@/man8/frr-ripd.8 0644 root bin -f none @mandir@/man8/frr-ripngd.8=$DESTDIR/@mandir@/man8/frr-ripngd.8 0644 root bin -f none @mandir@/man8/frr-zebra.8=$DESTDIR/@mandir@/man8/frr-zebra.8 0644 root bin -f none @mandir@/man8/frr-isisd.8=$DESTDIR/@mandir@/man8/frr-isisd.8 0644 root bin diff --git a/solaris/prototype.libs.in b/solaris/prototype.libs.in deleted file mode 100644 index bd8e3e4fe7..0000000000 --- a/solaris/prototype.libs.in +++ /dev/null @@ -1,10 +0,0 @@ -i pkginfo=$abs_builddir/pkginfo.libs.full -i depend=$abs_builddir/depend.libs -i copying=$abs_top_srcdir/COPYING -d none @libdir@=$DESTDIR/@libdir@ 0755 root bin -s none @libdir@/libfrr.so.0=libfrr.so.0.0.0 -f none @libdir@/libfrr.so.0.0.0=$DESTDIR/@libdir@/libfrr.so.0.0.0 0755 root bin -s none @libdir@/libfrr.so=libfrr.so.0.0.0 -f none @libdir@/libfrrospfapiclient.so.0.0.0=$DESTDIR/@libdir@/libfrrospfapiclient.so.0.0.0 0755 root bin -s none @libdir@/libfrrospfapiclient.so.0=libfrrospfapiclient.so.0.0.0 -s none @libdir@/libfrrospfapiclient.so=libfrrospfapiclient.so.0.0.0 diff --git a/solaris/prototype.smf.in b/solaris/prototype.smf.in deleted file mode 100644 index 5755a8827d..0000000000 --- a/solaris/prototype.smf.in +++ /dev/null @@ -1,8 +0,0 @@ -i pkginfo=$abs_builddir/pkginfo.smf.full -i depend=$abs_builddir/depend.smf -i copying=$abs_top_srcdir/COPYING -i i.manifest -i r.manifest -f manifest var/svc/manifest/network/frr.xml 0444 root bin -#f none var/svc/profile/@PACKAGE_TARNAME@_options.xml=$abs_builddir/options.xml 0755 root sys -f none lib/svc/method/frr=$abs_builddir/frr.init 0755 root bin diff --git a/solaris/subdir.am b/solaris/subdir.am deleted file mode 100644 index 1d19d56a4d..0000000000 --- a/solaris/subdir.am +++ /dev/null @@ -1,53 +0,0 @@ -# -# 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/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c index 9d395bee89..dbfe853365 100644 --- a/tests/lib/test_srcdest_table.c +++ b/tests/lib/test_srcdest_table.c @@ -34,12 +34,7 @@ * should be added by autoconf if not present? */ #ifndef s6_addr32 -#if defined(SUNOS_5) -/* Some SunOS define s6_addr32 only to kernel */ -#define s6_addr32 _S6_un._S6_u32 -#else #define s6_addr32 __u6_addr.__u6_addr32 -#endif /* SUNOS_5 */ #endif /*s6_addr32*/ struct thread_master *master; diff --git a/tests/subdir.am b/tests/subdir.am index e54bfc4a35..d7318efc72 100644 --- a/tests/subdir.am +++ b/tests/subdir.am @@ -12,31 +12,33 @@ TESTS_BGPD = \ tests/bgpd/test_mp_attr \ tests/bgpd/test_mpath \ tests/bgpd/test_bgp_table +IGNORE_BGPD = else TESTS_BGPD = +IGNORE_BGPD = --ignore=bgpd/ endif if ISISD -if SOLARIS -TESTS_ISISD = -else TESTS_ISISD = \ tests/isisd/test_fuzz_isis_tlv \ tests/isisd/test_isis_lspdb \ tests/isisd/test_isis_spf \ tests/isisd/test_isis_vertex_queue \ # end -endif +IGNORE_ISISD = else TESTS_ISISD = +IGNORE_ISISD = --ignore=isisd/ endif if OSPF6D TESTS_OSPF6D = \ tests/ospf6d/test_lsdb \ # end +IGNORE_OSPF6D = else TESTS_OSPF6D = +IGNORE_OSPF6D = --ignore=ospf6d/ endif clippy_scan += \ @@ -372,7 +374,7 @@ EXTRA_DIST += \ .PHONY: tests/tests.xml tests/tests.xml: $(check_PROGRAMS) - ( cd tests; $(PYTHON) ../$(srcdir)/tests/runtests.py --junitxml=tests.xml -v ../$(srcdir)/tests; ) + ( cd tests; $(PYTHON) ../$(srcdir)/tests/runtests.py --junitxml=tests.xml -v ../$(srcdir)/tests $(IGNORE_BGPD) $(IGNORE_ISISD) $(IGNORE_OSPF6D); ) check: tests/tests.xml clean-local: clean-tests diff --git a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py index 8525838d96..32b219283b 100755..100644 --- a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py +++ b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py @@ -113,8 +113,8 @@ def setup_module(module): net['r%s' % i].loadConf('ospfd', '%s/r%s/ospfd.conf' % (thisDir, i)) if net['r1'].checkRouterVersion('<', '4.0'): net['r%s' % i].loadConf('ospf6d', '%s/r%s/ospf6d.conf-pre-v4' % (thisDir, i)) - else: - net['r%s' % i].loadConf('ospf6d', '%s/r%s/ospf6d.conf' % (thisDir, i)) + else: + net['r%s' % i].loadConf('ospf6d', '%s/r%s/ospf6d.conf' % (thisDir, i)) net['r%s' % i].loadConf('isisd', '%s/r%s/isisd.conf' % (thisDir, i)) net['r%s' % i].loadConf('bgpd', '%s/r%s/bgpd.conf' % (thisDir, i)) if net['r%s' % i].daemon_available('ldpd'): @@ -126,7 +126,7 @@ def setup_module(module): net['r%s' % i].loadConf('pbrd', '%s/r%s/pbrd.conf' % (thisDir, i)) net['r%s' % i].startRouter() - # For debugging after starting Quagga/FRR daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -148,7 +148,7 @@ def test_router_running(): if (fatal_error != ""): pytest.skip(fatal_error) - print("\n\n** Check if FRR/Quagga is running on each Router node") + print("\n\n** Check if FRR is running on each Router node") print("******************************************\n") sleep(5) @@ -157,7 +157,7 @@ def test_router_running(): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -213,7 +213,7 @@ def test_error_messages_vtysh(): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -295,7 +295,7 @@ def test_error_messages_daemons(): assert error_logs == "", "Daemons report errors to StdErr" - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -363,7 +363,7 @@ def test_converge_protocols(): assert failures == 0, "IPv6 Routing table failed for r%s\n%s" % (i, diff) - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line ## CLI(net) def route_get_nhg_id(route_str): @@ -374,26 +374,36 @@ def route_get_nhg_id(route_str): nhg_id = int(match.group(1)) return nhg_id -def verify_nexthop_group(nhg_id, recursive=False): +def verify_nexthop_group(nhg_id, recursive=False, ecmp=0): # Verify NHG is valid/installed output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id) match = re.search(r"Valid", output) assert match is not None, "Nexthop Group ID=%d not marked Valid" % nhg_id - # If recursive, we need to look at its resolved group - if recursive: - match = re.search(r"Depends: \((\d+)\)", output) - resolved_id = int(match.group(1)) - verify_nexthop_group(resolved_id, False) + if ecmp or recursive: + match = re.search(r"Depends:.*\n", output) + assert match is not None, "Nexthop Group ID=%d has no depends" % nhg_id + + # list of IDs in group + depends = re.findall(r"\((\d+)\)", match.group(0)) + + if ecmp: + assert (len(depends) == ecmp), "Nexthop Group ID=%d doesn't match ecmp size" % nhg_id + else: + # If recursive, we need to look at its resolved group + assert (len(depends) == 1), "Nexthop Group ID=%d should only have one recursive depend" % nhg_id + resolved_id = int(depends[0]) + verify_nexthop_group(resolved_id, False) + else: match = re.search(r"Installed", output) assert match is not None, "Nexthop Group ID=%d not marked Installed" % nhg_id -def verify_route_nexthop_group(route_str, recursive=False): +def verify_route_nexthop_group(route_str, recursive=False, ecmp=0): # Verify route and that zebra created NHGs for and they are valid/installed nhg_id = route_get_nhg_id(route_str) - verify_nexthop_group(nhg_id, recursive) + verify_nexthop_group(nhg_id, recursive, ecmp) def test_nexthop_groups(): global fatal_error @@ -527,7 +537,7 @@ def test_rip_status(): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -582,7 +592,7 @@ def test_ripng_status(): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -611,7 +621,7 @@ def test_ospfv2_interfaces(): actual = net['r%s' % i].cmd('vtysh -c "show ip ospf interface" 2> /dev/null').rstrip() # Mask out Bandwidth portion. They may change.. actual = re.sub(r"BW [0-9]+ Mbit", "BW XX Mbit", actual) - actual = re.sub(r"ifindex [0-9]", "ifindex X", actual) + actual = re.sub(r"ifindex [0-9]", "ifindex X", actual) # Drop time in next due actual = re.sub(r"Hello due in [0-9\.]+s", "Hello due in XX.XXXs", actual) @@ -646,7 +656,7 @@ def test_ospfv2_interfaces(): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -701,7 +711,7 @@ def test_isis_interfaces(): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -782,7 +792,7 @@ def test_bgp_summary(): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -864,7 +874,7 @@ def test_bgp_ipv6_summary(): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -882,52 +892,52 @@ def test_bgp_ipv4(): print("******************************************\n") diffresult = {} for i in range(1, 2): - success = 0 - for refTableFile in (glob.glob( - '%s/r%s/show_bgp_ipv4*.ref' % (thisDir, i))): - if os.path.isfile(refTableFile): - # Read expected result from file - expected = open(refTableFile).read().rstrip() - # Fix newlines (make them all the same) - expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) - - # Actual output from router - actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv4" 2> /dev/null').rstrip() - # Remove summary line (changed recently) - actual = re.sub(r'Total number.*', '', actual) - actual = re.sub(r'Displayed.*', '', actual) - actual = actual.rstrip() - # Fix newlines (make them all the same) - actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) - - # Generate Diff - diff = topotest.get_textdiff(actual, expected, - title1="actual SHOW BGP IPv4", - title2="expected SHOW BGP IPv4") - - # Empty string if it matches, otherwise diff contains unified diff - if diff: - diffresult[refTableFile] = diff - else: - success = 1 - print("template %s matched: r%s ok" % (refTableFile, i)) - break - - if not success: - resultstr = 'No template matched.\n' - for f in diffresult.iterkeys(): - resultstr += ( - 'template %s: r%s failed SHOW BGP IPv4 check:\n%s\n' - % (f, i, diffresult[f])) - raise AssertionError( - "SHOW BGP IPv4 failed for router r%s:\n%s" % (i, resultstr)) + success = 0 + for refTableFile in (glob.glob( + '%s/r%s/show_bgp_ipv4*.ref' % (thisDir, i))): + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv4" 2> /dev/null').rstrip() + # Remove summary line (changed recently) + actual = re.sub(r'Total number.*', '', actual) + actual = re.sub(r'Displayed.*', '', actual) + actual = actual.rstrip() + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = topotest.get_textdiff(actual, expected, + title1="actual SHOW BGP IPv4", + title2="expected SHOW BGP IPv4") + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + diffresult[refTableFile] = diff + else: + success = 1 + print("template %s matched: r%s ok" % (refTableFile, i)) + break + + if not success: + resultstr = 'No template matched.\n' + for f in diffresult.iterkeys(): + resultstr += ( + 'template %s: r%s failed SHOW BGP IPv4 check:\n%s\n' + % (f, i, diffresult[f])) + raise AssertionError( + "SHOW BGP IPv4 failed for router r%s:\n%s" % (i, resultstr)) # Make sure that all daemons are running for i in range(1, 2): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -945,51 +955,51 @@ def test_bgp_ipv6(): print("******************************************\n") diffresult = {} for i in range(1, 2): - success = 0 - for refTableFile in (glob.glob( - '%s/r%s/show_bgp_ipv6*.ref' % (thisDir, i))): - if os.path.isfile(refTableFile): - # Read expected result from file - expected = open(refTableFile).read().rstrip() - # Fix newlines (make them all the same) - expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) - - # Actual output from router - actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv6" 2> /dev/null').rstrip() - # Remove summary line (changed recently) - actual = re.sub(r'Total number.*', '', actual) - actual = re.sub(r'Displayed.*', '', actual) - actual = actual.rstrip() - # Fix newlines (make them all the same) - actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) - - # Generate Diff - diff = topotest.get_textdiff(actual, expected, - title1="actual SHOW BGP IPv6", - title2="expected SHOW BGP IPv6") - - # Empty string if it matches, otherwise diff contains unified diff - if diff: - diffresult[refTableFile] = diff - else: - success = 1 - print("template %s matched: r%s ok" % (refTableFile, i)) - - if not success: - resultstr = 'No template matched.\n' - for f in diffresult.iterkeys(): - resultstr += ( - 'template %s: r%s failed SHOW BGP IPv6 check:\n%s\n' - % (f, i, diffresult[f])) - raise AssertionError( - "SHOW BGP IPv6 failed for router r%s:\n%s" % (i, resultstr)) + success = 0 + for refTableFile in (glob.glob( + '%s/r%s/show_bgp_ipv6*.ref' % (thisDir, i))): + if os.path.isfile(refTableFile): + # Read expected result from file + expected = open(refTableFile).read().rstrip() + # Fix newlines (make them all the same) + expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) + + # Actual output from router + actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv6" 2> /dev/null').rstrip() + # Remove summary line (changed recently) + actual = re.sub(r'Total number.*', '', actual) + actual = re.sub(r'Displayed.*', '', actual) + actual = actual.rstrip() + # Fix newlines (make them all the same) + actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) + + # Generate Diff + diff = topotest.get_textdiff(actual, expected, + title1="actual SHOW BGP IPv6", + title2="expected SHOW BGP IPv6") + + # Empty string if it matches, otherwise diff contains unified diff + if diff: + diffresult[refTableFile] = diff + else: + success = 1 + print("template %s matched: r%s ok" % (refTableFile, i)) + + if not success: + resultstr = 'No template matched.\n' + for f in diffresult.iterkeys(): + resultstr += ( + 'template %s: r%s failed SHOW BGP IPv6 check:\n%s\n' + % (f, i, diffresult[f])) + raise AssertionError( + "SHOW BGP IPv6 failed for router r%s:\n%s" % (i, resultstr)) # Make sure that all daemons are running for i in range(1, 2): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) def test_route_map(): @@ -1101,6 +1111,34 @@ def test_nexthop_groups_with_route_maps(): net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE"') net["r1"].cmd('vtysh -c "c t" -c "no ip prefix-list NOPE seq 5 permit %s/32"' % permit_route_str) +def test_nexthop_group_replace(): + global fatal_error + global net + + # Skip if previous fatal error condition is raised + if (fatal_error != ""): + pytest.skip(fatal_error) + + print("\n\n** Verifying Nexthop Groups") + print("******************************************\n") + + ### Nexthop Group Tests + + ## 2-Way ECMP Directly Connected + + net["r1"].cmd('vtysh -c "c t" -c "nexthop-group replace" -c "nexthop 1.1.1.1 r1-eth1 onlink" -c "nexthop 1.1.1.2 r1-eth2 onlink"') + + # Create with sharpd using nexthop-group + net["r1"].cmd('vtysh -c "sharp install routes 3.3.3.1 nexthop-group replace 1"') + + verify_route_nexthop_group("3.3.3.1/32") + + # Change the nexthop group + net["r1"].cmd('vtysh -c "c t" -c "nexthop-group replace" -c "no nexthop 1.1.1.1 r1-eth1 onlink" -c "nexthop 1.1.1.3 r1-eth1 onlink" -c "nexthop 1.1.1.4 r1-eth4 onlink"') + + # Verify it updated. We can just check install and ecmp count here. + verify_route_nexthop_group("3.3.3.1/32", False, 3) + def test_mpls_interfaces(): global fatal_error global net @@ -1155,7 +1193,7 @@ def test_mpls_interfaces(): fatal_error = net['r%s' % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) diff --git a/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py index 7d1521c8b2..595132214b 100644 --- a/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py +++ b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py @@ -21,7 +21,7 @@ # """ -test_bfd_bgp_cbit_topo3.py: Test the FRR/Quagga BFD daemon with multihop and BGP +test_bfd_bgp_cbit_topo3.py: Test the FRR BFD daemon with multihop and BGP unnumbered. """ diff --git a/tests/topotests/bfd-topo1/test_bfd_topo1.py b/tests/topotests/bfd-topo1/test_bfd_topo1.py index 5306fdf353..6e589d55eb 100644 --- a/tests/topotests/bfd-topo1/test_bfd_topo1.py +++ b/tests/topotests/bfd-topo1/test_bfd_topo1.py @@ -23,7 +23,7 @@ # """ -test_bfd_topo1.py: Test the FRR/Quagga BFD daemon. +test_bfd_topo1.py: Test the FRR BFD daemon. """ import os diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.py b/tests/topotests/bfd-topo2/test_bfd_topo2.py index 2c5ce3e4c3..feb4576bd3 100644 --- a/tests/topotests/bfd-topo2/test_bfd_topo2.py +++ b/tests/topotests/bfd-topo2/test_bfd_topo2.py @@ -23,7 +23,7 @@ # """ -test_bfd_topo2.py: Test the FRR/Quagga BFD daemon with multihop and BGP +test_bfd_topo2.py: Test the FRR BFD daemon with multihop and BGP unnumbered. """ diff --git a/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py b/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py index 95595ecba4..5fed135f8d 100644 --- a/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py +++ b/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py @@ -24,7 +24,7 @@ # """ -test_bfd_vrf_topo1.py: Test the FRR/Quagga BFD daemon. +test_bfd_vrf_topo1.py: Test the FRR BFD daemon. """ import os diff --git a/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py b/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py index 41fa7c0a09..41fa7c0a09 100755..100644 --- a/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py +++ b/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py diff --git a/tests/topotests/bgp-evpn-mh/test_evpn_mh.py b/tests/topotests/bgp-evpn-mh/test_evpn_mh.py index ee50a422a7..9af22c06bd 100644 --- a/tests/topotests/bgp-evpn-mh/test_evpn_mh.py +++ b/tests/topotests/bgp-evpn-mh/test_evpn_mh.py @@ -477,9 +477,9 @@ def check_es(dut): vtep_ips.append(vtep["vtep_ip"]) if "local" in types: - result = check_local_es(esi, vtep_ips, dut.name, []) + result = check_local_es(esi, vtep_ips, dut.name, []) else: - result = check_remote_es(esi, vtep_ips, dut.name, []) + result = check_remote_es(esi, vtep_ips, dut.name, []) if result: return result diff --git a/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py b/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py index 607b036c6a..607b036c6a 100755..100644 --- a/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py +++ b/tests/topotests/bgp-path-attributes-topo1/test_bgp_path_attributes.py diff --git a/tests/topotests/bgp-prefix-list-topo1/test_prefix_lists.py b/tests/topotests/bgp-prefix-list-topo1/test_prefix_lists.py index 22952f645c..22952f645c 100755..100644 --- a/tests/topotests/bgp-prefix-list-topo1/test_prefix_lists.py +++ b/tests/topotests/bgp-prefix-list-topo1/test_prefix_lists.py diff --git a/tests/topotests/bgp-route-map/test_route_map_topo1.py b/tests/topotests/bgp-route-map/test_route_map_topo1.py index 1aa951edaa..1aa951edaa 100755..100644 --- a/tests/topotests/bgp-route-map/test_route_map_topo1.py +++ b/tests/topotests/bgp-route-map/test_route_map_topo1.py diff --git a/tests/topotests/bgp-route-map/test_route_map_topo2.py b/tests/topotests/bgp-route-map/test_route_map_topo2.py index 3056aa29f3..3056aa29f3 100755..100644 --- a/tests/topotests/bgp-route-map/test_route_map_topo2.py +++ b/tests/topotests/bgp-route-map/test_route_map_topo2.py diff --git a/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py b/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py index f9d22a3a36..f9d22a3a36 100755..100644 --- a/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py +++ b/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py diff --git a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py index 69ef7e9fae..0d99f23ad9 100755..100644 --- a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py +++ b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py @@ -22,7 +22,7 @@ # """ - test_bgp_evpn.py: Test the FRR/Quagga BGP daemon with BGP IPv6 interface + test_bgp_evpn.py: Test the FRR BGP daemon with BGP IPv6 interface with route advertisements on a separate netns. """ @@ -143,7 +143,7 @@ def setup_module(mod): logger.info('result: '+output); router = tgen.gears['r1'] - for rname, router in router_list.iteritems(): + for rname, router in router_list.items(): if rname == 'r1': router.load_config( TopoRouter.RD_ZEBRA, diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py index fdbd317093..fdbd317093 100755..100644 --- a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py +++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py index e1ec0ea81b..e1ec0ea81b 100755..100644 --- a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py +++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py diff --git a/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py b/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py index 0acf8d2dbc..783e746418 100644 --- a/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py +++ b/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py @@ -22,7 +22,7 @@ # """ - test_bgp_ipv6_rtadv.py: Test the FRR/Quagga BGP daemon with BGP IPv6 interface + test_bgp_ipv6_rtadv.py: Test the FRR BGP daemon with BGP IPv6 interface with route advertisements on a separate netns. """ diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py index 05db9ab14b..752e37f5f8 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py @@ -22,7 +22,7 @@ # """ -customize.py: Simple FRR/Quagga MPLS L3VPN test topology +customize.py: Simple FRR MPLS L3VPN test topology | +----+----+ diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py index fb919f02d0..1c3c51f68e 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py @@ -22,7 +22,7 @@ # """ -customize.py: Simple FRR/Quagga MPLS L3VPN test topology +customize.py: Simple FRR MPLS L3VPN test topology | +----+----+ diff --git a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_1.py b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_1.py index dc06b7131a..dc06b7131a 100755..100644 --- a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_1.py +++ b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_1.py diff --git a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py index bb88e47415..bb88e47415 100755..100644 --- a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py +++ b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py diff --git a/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py b/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py index c15b88d371..c15b88d371 100755..100644 --- a/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py +++ b/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py diff --git a/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py b/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py index bb13d54019..bb13d54019 100755..100644 --- a/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py +++ b/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py diff --git a/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py b/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py index a2020ffa55..6344f7bb40 100755..100644 --- a/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py +++ b/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py @@ -23,7 +23,7 @@ # """ -test_bgp_multiview_topo1.py: Simple Quagga/FRR Route-Server Test +test_bgp_multiview_topo1.py: Simple FRR Route-Server Test +----------+ +----------+ +----------+ +----------+ +----------+ | peer1 | | peer2 | | peer3 | | peer4 | | peer5 | @@ -165,7 +165,7 @@ def setup_module(module): print("peer%s" % i), print("") - # For debugging after starting Quagga/FRR daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -193,7 +193,7 @@ def test_router_running(): if fatal_error != "": pytest.skip(fatal_error) - print("\n\n** Check if FRR/Quagga is running on each Router node") + print("\n\n** Check if FRR is running on each Router node") print("******************************************\n") # Starting Routers @@ -201,7 +201,7 @@ def test_router_running(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -262,7 +262,7 @@ def test_bgp_converge(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting Quagga/FRR daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -300,7 +300,7 @@ def test_bgp_routingTable(): .rstrip() ) - # Fix inconsitent spaces between 0.99.24 and newer versions of Quagga... + # Fix inconsitent spaces between 0.99.24 and newer versions actual = re.sub("0 0", "0 0", actual) actual = re.sub( r"([0-9]) 32768", r"\1 32768", actual @@ -347,7 +347,7 @@ def test_bgp_routingTable(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) diff --git a/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py b/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py index fef6eb71dc..fef6eb71dc 100755..100644 --- a/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py +++ b/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py diff --git a/tests/topotests/bgp_rfapi_basic_sanity/customize.py b/tests/topotests/bgp_rfapi_basic_sanity/customize.py index ea548a7337..2c85cf6e9d 100644 --- a/tests/topotests/bgp_rfapi_basic_sanity/customize.py +++ b/tests/topotests/bgp_rfapi_basic_sanity/customize.py @@ -23,7 +23,7 @@ # """ -customize.py: Simple FRR/Quagga MPLS L3VPN test topology +customize.py: Simple FRR MPLS L3VPN test topology +---------+ | r1 | diff --git a/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py b/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py index 0fabd90341..0fabd90341 100755..100644 --- a/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py +++ b/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py index 1947548b3e..1947548b3e 100755..100644 --- a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py +++ b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo2.py b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo2.py index 6c106060b8..6c106060b8 100755..100644 --- a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo2.py +++ b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo2.py diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py index 50b9b092d6..97d98415db 100644 --- a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py +++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py @@ -22,7 +22,7 @@ # """ - test_bgp_ipv6_rtadv.py: Test the FRR/Quagga BGP daemon with BGP IPv6 interface + test_bgp_ipv6_rtadv.py: Test the FRR BGP daemon with BGP IPv6 interface with route advertisements on a separate netns. """ diff --git a/tests/topotests/eigrp-topo1/test_eigrp_topo1.py b/tests/topotests/eigrp-topo1/test_eigrp_topo1.py index 70666a3d61..3ce1472ac0 100644 --- a/tests/topotests/eigrp-topo1/test_eigrp_topo1.py +++ b/tests/topotests/eigrp-topo1/test_eigrp_topo1.py @@ -252,7 +252,7 @@ def ip_eigrp_topo(node): if code not in ["P", "A", "U", "Q", "R", "r", "s"]: continue - if not result.has_key(code): + if code not in result: result[code] = {} # Split network from the rest diff --git a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py index e913105e43..e913105e43 100755..100644 --- a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py +++ b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py diff --git a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py index 9e385823fc..c1eb7d68bb 100755..100644 --- a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py +++ b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py @@ -26,9 +26,9 @@ Following tests are covered to test EVPN-Type5 functionality: 1. RD verification (manual/auto). 2. RT verification(manual) 3. In an active/standby EVPN implementation, if active DCG goes down, - secondary takes over. + secondary takes over. 4. EVPN routes are advertised/withdrawn, based on VNFs - advertising/withdrawing IP prefixes. + advertising/withdrawing IP prefixes. 5. Route-map operations for EVPN address family. 6. BGP attributes for EVPN address-family. """ diff --git a/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py b/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py index 65515f22cc..7943b94189 100644 --- a/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py +++ b/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py @@ -210,7 +210,7 @@ def test_isis_linux_route_installation(): dist = platform.dist() if (dist[1] == "16.04"): - pytest.skip("Kernel not supported for vrf") + pytest.skip("Kernel not supported for vrf") "Check whether all expected routes are present and installed in the OS" tgen = get_topogen() @@ -267,7 +267,7 @@ def test_isis_linux_route6_installation(): dist = platform.dist() if (dist[1] == "16.04"): - pytest.skip("Kernel not supported for vrf") + pytest.skip("Kernel not supported for vrf") "Check whether all expected routes are present and installed in the OS" tgen = get_topogen() diff --git a/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py index dadb2065e6..3b3ed3383c 100644 --- a/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py +++ b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py @@ -22,7 +22,7 @@ # """ -test_ldp_oc_acl_topo1.py: Simple FRR/Quagga LDP Test +test_ldp_oc_acl_topo1.py: Simple FRR LDP Test +---------+ | r1 | diff --git a/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py index ea449e4aba..ead991b183 100644 --- a/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py +++ b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py @@ -22,7 +22,7 @@ # """ -test_ldp_oc_topo1.py: Simple FRR/Quagga LDP Test +test_ldp_oc_topo1.py: Simple FRR LDP Test +---------+ | r1 | diff --git a/tests/topotests/ldp-topo1/test_ldp_topo1.py b/tests/topotests/ldp-topo1/test_ldp_topo1.py index cef4d6587e..31adeafbf6 100755..100644 --- a/tests/topotests/ldp-topo1/test_ldp_topo1.py +++ b/tests/topotests/ldp-topo1/test_ldp_topo1.py @@ -23,7 +23,7 @@ # """ -test_ldp_topo1.py: Simple FRR/Quagga LDP Test +test_ldp_topo1.py: Simple FRR LDP Test +---------+ | r1 | @@ -186,7 +186,7 @@ def setup_module(module): if fatal_error != "": break - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -208,7 +208,7 @@ def test_router_running(): if fatal_error != "": pytest.skip(fatal_error) - print("\n\n** Check if FRR/Quagga is running on each Router node") + print("\n\n** Check if FRR is running on each Router node") print("******************************************\n") sleep(5) @@ -217,7 +217,7 @@ def test_router_running(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -283,7 +283,7 @@ def test_mpls_interfaces(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -420,7 +420,7 @@ def test_mpls_ldp_discovery(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -490,7 +490,7 @@ def test_mpls_ldp_neighbor(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -582,7 +582,7 @@ def test_mpls_ldp_binding(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -612,7 +612,7 @@ def test_zebra_ipv4_routingTable(): .cmd('vtysh -c "show ip route" 2> /dev/null | grep "^O"') .rstrip() ) - # Drop timers on end of line (older Quagga Versions) + # Drop timers on end of line actual = re.sub(r", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual) # Mask out label - all LDP labels should be >= 10 (2-digit) @@ -657,7 +657,7 @@ def test_zebra_ipv4_routingTable(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -736,7 +736,7 @@ def test_mpls_table(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -820,7 +820,7 @@ def test_linux_mpls_routes(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py index a3d846edbb..72b99eeba8 100644 --- a/tests/topotests/lib/bgp.py +++ b/tests/topotests/lib/bgp.py @@ -28,6 +28,7 @@ from lib import topotest from lib.topolog import logger from lib.topogen import TopoRouter, get_topogen +from lib.topotest import frr_unicode # Import common_config to use commomnly used APIs from lib.common_config import ( @@ -393,7 +394,7 @@ def __create_bgp_unicast_neighbor( # Generating IPs for verification network_list = generate_ips(network, no_of_network) for ip in network_list: - ip = str(ipaddress.ip_network(unicode(ip))) + ip = str(ipaddress.ip_network(frr_unicode(ip))) cmd = "network {}".format(ip) if del_action: @@ -1037,7 +1038,7 @@ def verify_router_id(tgen, topo, input_dict): logger.info("Checking router %s router-id", router) show_bgp_json = run_frr_cmd(rnode, "show bgp summary json", isjson=True) router_id_out = show_bgp_json["ipv4Unicast"]["routerId"] - router_id_out = ipaddress.IPv4Address(unicode(router_id_out)) + router_id_out = ipaddress.IPv4Address(frr_unicode(router_id_out)) # Once router-id is deleted, highest interface ip should become # router-id @@ -1045,7 +1046,7 @@ def verify_router_id(tgen, topo, input_dict): router_id = find_interface_with_greater_ip(topo, router) else: router_id = input_dict[router]["bgp"]["router_id"] - router_id = ipaddress.IPv4Address(unicode(router_id)) + router_id = ipaddress.IPv4Address(frr_unicode(router_id)) if router_id == router_id_out: logger.info("Found expected router-id %s for router %s", router_id, router) @@ -2286,7 +2287,7 @@ def verify_best_path_as_per_bgp_attribute( routes = generate_ips(_network, no_of_ip) for route in routes: - route = str(ipaddress.ip_network(unicode(route))) + route = str(ipaddress.ip_network(frr_unicode(route))) if route in sh_ip_bgp_json["routes"]: route_attributes = sh_ip_bgp_json["routes"][route] @@ -2604,7 +2605,7 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None) ip_list = generate_ips(network, no_of_ip) for st_rt in ip_list: - st_rt = str(ipaddress.ip_network(unicode(st_rt))) + st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) _addr_type = validate_ip_address(st_rt) if _addr_type != addr_type: @@ -2742,7 +2743,7 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None) ip_list = generate_ips(network, no_of_network) for st_rt in ip_list: - st_rt = str(ipaddress.ip_network(unicode(st_rt))) + st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) _addr_type = validate_ip_address(st_rt) if _addr_type != addr_type: diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index 6dd8d646f3..1fa6d35101 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -31,16 +31,14 @@ from re import search as re_search from tempfile import mkdtemp import os +import io import sys -import ConfigParser import traceback import socket import ipaddress import platform - if sys.version_info[0] > 2: - import io import configparser else: import StringIO @@ -48,7 +46,7 @@ else: from lib.topolog import logger, logger_config from lib.topogen import TopoRouter, get_topogen -from lib.topotest import interface_set_status, version_cmp +from lib.topotest import interface_set_status, version_cmp, frr_unicode FRRCFG_FILE = "frr_json.conf" FRRCFG_BKUP_FILE = "frr_json_initial.conf" @@ -638,7 +636,7 @@ def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None): ll_per_if_count = 0 # Interface ip - m1 = re_search("inet6 (fe80[:a-fA-F0-9]+[\/0-9]+)", line) + m1 = re_search("inet6 (fe80[:a-fA-F0-9]+[/0-9]+)", line) if m1: local = m1.group(1) ll_per_if_count += 1 @@ -700,18 +698,20 @@ def start_topology(tgen, daemon=None): router_list = tgen.routers() ROUTER_LIST = sorted( - router_list.keys(), key=lambda x: int(re_search("\d+", x).group(0)) + router_list.keys(), key=lambda x: int(re_search("[0-9]+", x).group(0)) ) TMPDIR = os.path.join(LOGDIR, tgen.modname) + linux_ver = '' router_list = tgen.routers() for rname in ROUTER_LIST: router = router_list[rname] # It will help in debugging the failures, will give more details on which # specific kernel version tests are failing - linux_ver = router.run("uname -a") - logger.info("Logging platform related details: \n %s \n", linux_ver) + if linux_ver == '': + linux_ver = router.run("uname -a") + logger.info("Logging platform related details: \n %s \n", linux_ver) try: os.chdir(TMPDIR) @@ -827,7 +827,7 @@ def topo_daemons(tgen, topo): router_list = tgen.routers() ROUTER_LIST = sorted( - router_list.keys(), key=lambda x: int(re_search("\d+", x).group(0)) + router_list.keys(), key=lambda x: int(re_search("[0-9]+", x).group(0)) ) for rtr in ROUTER_LIST: @@ -1152,10 +1152,10 @@ def generate_ips(network, no_of_ips): addr_type = validate_ip_address(start_ip) if addr_type == "ipv4": - start_ip = ipaddress.IPv4Address(unicode(start_ip)) + start_ip = ipaddress.IPv4Address(frr_unicode(start_ip)) step = 2 ** (32 - mask) if addr_type == "ipv6": - start_ip = ipaddress.IPv6Address(unicode(start_ip)) + start_ip = ipaddress.IPv6Address(frr_unicode(start_ip)) step = 2 ** (128 - mask) next_ip = start_ip @@ -2667,7 +2667,7 @@ def verify_rib( nh_found = False for st_rt in ip_list: - st_rt = str(ipaddress.ip_network(unicode(st_rt))) + st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) _addr_type = validate_ip_address(st_rt) if _addr_type != addr_type: @@ -2863,7 +2863,7 @@ def verify_rib( nh_found = False for st_rt in ip_list: - st_rt = str(ipaddress.ip_network(unicode(st_rt))) + st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) _addr_type = validate_ip_address(st_rt) if _addr_type != addr_type: @@ -3012,7 +3012,7 @@ def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None): nh_found = False for st_rt in ip_list: - st_rt = str(ipaddress.ip_network(unicode(st_rt))) + st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) #st_rt = str(ipaddr.IPNetwork(unicode(st_rt))) _addr_type = validate_ip_address(st_rt) @@ -3119,7 +3119,7 @@ def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None): for st_rt in ip_list: #st_rt = str(ipaddr.IPNetwork(unicode(st_rt))) - st_rt = str(ipaddress.ip_network(unicode(st_rt))) + st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) _addr_type = validate_ip_address(st_rt) if _addr_type != addr_type: @@ -3268,7 +3268,7 @@ def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None): nh_found = False for st_rt in ip_list: - st_rt = str(ipaddress.ip_network(unicode(st_rt))) + st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) _addr_type = validate_ip_address(st_rt) if _addr_type != addr_type: @@ -3373,7 +3373,7 @@ def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None): nh_found = False for st_rt in ip_list: - st_rt = str(ipaddress.ip_network(unicode(st_rt))) + st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) _addr_type = validate_ip_address(st_rt) if _addr_type != addr_type: diff --git a/tests/topotests/lib/ltemplate.py b/tests/topotests/lib/ltemplate.py index 192c121008..3c93e1ac5c 100644 --- a/tests/topotests/lib/ltemplate.py +++ b/tests/topotests/lib/ltemplate.py @@ -157,8 +157,8 @@ def ltemplateTest(script, SkipIfFailed=True, CallOnFail=None, CheckFuncStr=None, if SkipIfFailed and tgen.routers_have_failure(): pytest.skip(tgen.errors) if numEntry > 0: - if not KeepGoing: - pytest.skip("Have %d errors" % numEntry) + if not KeepGoing: + pytest.skip("Have %d errors" % numEntry) if CheckFuncStr != None: check = eval(CheckFuncStr) @@ -172,8 +172,8 @@ def ltemplateTest(script, SkipIfFailed=True, CallOnFail=None, CheckFuncStr=None, if numFail > 0: luShowFail() fatal_error = "%d tests failed" % numFail - if not KeepGoing: - assert "scripts/cleanup_all.py failed" == "See summary output above", fatal_error + if not KeepGoing: + assert "scripts/cleanup_all.py failed" == "See summary output above", fatal_error # Memory leak test template def test_memory_leak(): diff --git a/tests/topotests/lib/lutil.py b/tests/topotests/lib/lutil.py index 4ea97a3692..05ed9c007d 100755..100644 --- a/tests/topotests/lib/lutil.py +++ b/tests/topotests/lib/lutil.py @@ -204,17 +204,17 @@ Total %-4d %-4d %d\n\ self.log('WARNING: JSON load failed -- confirm command output is in JSON format.') self.log('COMMAND OUTPUT:%s:' % report) - # Experiment: can we achieve the same match behavior via DOTALL - # without converting newlines to spaces? - out_nl = out - search_nl = re.search(regexp, out_nl, re.DOTALL); - self.l_last_nl = search_nl - # Set up for comparison - if search_nl != None: - group_nl = search_nl.group() - group_nl_converted = " ".join(group_nl.splitlines()) + # Experiment: can we achieve the same match behavior via DOTALL + # without converting newlines to spaces? + out_nl = out + search_nl = re.search(regexp, out_nl, re.DOTALL); + self.l_last_nl = search_nl + # Set up for comparison + if search_nl != None: + group_nl = search_nl.group() + group_nl_converted = " ".join(group_nl.splitlines()) else: - group_nl_converted = None + group_nl_converted = None out = " ".join(out.splitlines()) search = re.search(regexp, out) @@ -234,9 +234,9 @@ Total %-4d %-4d %d\n\ success = False level = 5 self.log('found:%s:' % ret, level) - # Experiment: compare matched strings obtained each way - if self.l_dotall_experiment and (group_nl_converted != ret): - self.log('DOTALL experiment: strings differ dotall=[%s] orig=[%s]' % (group_nl_converted, ret), 9) + # Experiment: compare matched strings obtained each way + if self.l_dotall_experiment and (group_nl_converted != ret): + self.log('DOTALL experiment: strings differ dotall=[%s] orig=[%s]' % (group_nl_converted, ret), 9) if op == 'pass' or op == 'fail': self.result(target, success, result) if js != None: @@ -297,13 +297,13 @@ def luCommand(target, command, regexp='.', op='none', result='', time=10, return def luLast(usenl=False): if usenl: - if LUtil.l_last_nl != None: - LUtil.log('luLast:%s:' % LUtil.l_last_nl.group(), 7) - return LUtil.l_last_nl + if LUtil.l_last_nl != None: + LUtil.log('luLast:%s:' % LUtil.l_last_nl.group(), 7) + return LUtil.l_last_nl else: - if LUtil.l_last != None: - LUtil.log('luLast:%s:' % LUtil.l_last.group(), 7) - return LUtil.l_last + if LUtil.l_last != None: + LUtil.log('luLast:%s:' % LUtil.l_last.group(), 7) + return LUtil.l_last def luInclude(filename, CallOnFail=None): tstFile = LUtil.base_script_dir + '/' + filename diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py index a2351bf747..9d6b8fa691 100644 --- a/tests/topotests/lib/ospf.py +++ b/tests/topotests/lib/ospf.py @@ -23,7 +23,7 @@ import traceback from time import sleep from lib.topolog import logger import ipaddr - +from lib.topotest import frr_unicode # Import common_config to use commomnly used APIs from lib.common_config import (create_common_configuration, @@ -516,7 +516,7 @@ def verify_ospf_neighbor(tgen, topo, dut=None, input_dict=None, lan=False): logger.debug("Entering lib API: verify_ospf_neighbor()") result = False if input_dict: - for router, rnode in tgen.routers().iteritems(): + for router, rnode in tgen.routers().items(): if 'ospf' not in topo['routers'][router]: continue @@ -584,7 +584,7 @@ def verify_ospf_neighbor(tgen, topo, dut=None, input_dict=None, lan=False): return errormsg continue else: - for router, rnode in tgen.routers().iteritems(): + for router, rnode in tgen.routers().items(): if 'ospf' not in topo['routers'][router]: continue @@ -694,7 +694,7 @@ def verify_ospf_rib(tgen, dut, input_dict, next_hop=None, additional_nexthops_in_required_nhs = [] found_hops = [] for routerInput in input_dict.keys(): - for router, rnode in router_list.iteritems(): + for router, rnode in router_list.items(): if router != dut: continue @@ -739,7 +739,7 @@ def verify_ospf_rib(tgen, dut, input_dict, next_hop=None, nh_found = False for st_rt in ip_list: - st_rt = str(ipaddr.IPNetwork(unicode(st_rt))) + st_rt = str(ipaddr.IPNetwork(frr_unicode(st_rt))) _addr_type = validate_ip_address(st_rt) if _addr_type != 'ipv4': @@ -927,7 +927,7 @@ def verify_ospf_interface(tgen, topo, dut=None,lan=False, input_dict=None): logger.debug("Entering lib API: verify_ospf_interface()") result = False - for router, rnode in tgen.routers().iteritems(): + for router, rnode in tgen.routers().items(): if 'ospf' not in topo['routers'][router]: continue diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index b9f82877e2..ffdcb683e7 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -40,6 +40,7 @@ Basic usage instructions: import os import sys +import io import logging import json @@ -96,9 +97,8 @@ def set_topogen(tgen): tgen_defaults = { "verbosity": "info", "frrdir": "/usr/lib/frr", - "quaggadir": "/usr/lib/quagga", "routertype": "frr", - "memleak_path": None, + "memleak_path": "", } @@ -173,7 +173,7 @@ class Topogen(object): options: * `name`: (optional) select the router name * `daemondir`: (optional) custom daemon binary directory - * `routertype`: (optional) `quagga` or `frr` + * `routertype`: (optional) `frr` Returns a TopoRouter. """ if name is None: @@ -182,9 +182,8 @@ class Topogen(object): raise KeyError("router already exists") params["frrdir"] = self.config.get(self.CONFIG_SECTION, "frrdir") - params["quaggadir"] = self.config.get(self.CONFIG_SECTION, "quaggadir") params["memleak_path"] = self.config.get(self.CONFIG_SECTION, "memleak_path") - if not params.has_key("routertype"): + if "routertype" not in params: params["routertype"] = self.config.get(self.CONFIG_SECTION, "routertype") self.gears[name] = TopoRouter(self, cls, name, **params) @@ -362,7 +361,7 @@ class Topogen(object): memleak_file = os.environ.get("TOPOTESTS_CHECK_MEMLEAK") or self.config.get( self.CONFIG_SECTION, "memleak_path" ) - if memleak_file is None: + if memleak_file == "" or memleak_file == None: return False return True @@ -529,12 +528,10 @@ class TopoRouter(TopoGear): Router abstraction. """ - # The default required directories by Quagga/FRR + # The default required directories by FRR PRIVATE_DIRS = [ "/etc/frr", - "/etc/quagga", "/var/run/frr", - "/var/run/quagga", "/var/log", ] @@ -581,7 +578,7 @@ class TopoRouter(TopoGear): * cls: router class that will be used to instantiate * name: router name * daemondir: daemon binary directory - * routertype: 'quagga' or 'frr' + * routertype: 'frr' """ super(TopoRouter, self).__init__() self.tgen = tgen @@ -590,7 +587,7 @@ class TopoRouter(TopoGear): self.cls = cls self.options = {} self.routertype = params.get("routertype", "frr") - if not params.has_key("privateDirs"): + if "privateDirs" not in params: params["privateDirs"] = self.PRIVATE_DIRS self.options["memleak_path"] = params.get("memleak_path", None) @@ -626,7 +623,7 @@ class TopoRouter(TopoGear): except OSError: pass - # Allow unprivileged daemon user (frr/quagga) to create log files + # Allow unprivileged daemon user (frr) to create log files try: # Only allow group, if it exist. gid = grp.getgrnam(self.routertype)[2] @@ -675,7 +672,7 @@ class TopoRouter(TopoGear): * Load modules * Clean up files * Configure interfaces - * Start daemons (e.g. FRR/Quagga) + * Start daemons (e.g. FRR) * Configure daemon logging files """ self.logger.debug("starting") @@ -724,7 +721,7 @@ class TopoRouter(TopoGear): def startDaemons(self, daemons): """ Start Daemons: to start specific daemon(user defined daemon only) - * Start daemons (e.g. FRR/Quagga) + * Start daemons (e.g. FRR) * Configure daemon logging files """ self.logger.debug('starting') @@ -826,7 +823,7 @@ class TopoRouter(TopoGear): memleak_file = ( os.environ.get("TOPOTESTS_CHECK_MEMLEAK") or self.options["memleak_path"] ) - if memleak_file is None: + if memleak_file == "" or memleak_file == None: return self.stop() @@ -1015,7 +1012,7 @@ def diagnose_env_linux(): logger.info("Running environment diagnostics") # Load configuration - config = configparser.ConfigParser(tgen_defaults) + config = configparser.ConfigParser(defaults=tgen_defaults) pytestini_path = os.path.join(CWD, "../pytest.ini") config.read(pytestini_path) @@ -1041,12 +1038,10 @@ def diagnose_env_linux(): # Assert that FRR utilities exist frrdir = config.get("topogen", "frrdir") - hasfrr = False if not os.path.isdir(frrdir): logger.error("could not find {} directory".format(frrdir)) ret = False else: - hasfrr = True try: pwd.getpwnam("frr")[2] except KeyError: @@ -1095,56 +1090,6 @@ def diagnose_env_linux(): os.system("{} -v 2>&1 >/tmp/topotests/frr_zebra.txt".format(path)) - # Assert that Quagga utilities exist - quaggadir = config.get("topogen", "quaggadir") - if hasfrr: - # if we have frr, don't check for quagga - pass - elif not os.path.isdir(quaggadir): - logger.info( - "could not find {} directory (quagga tests will not run)".format(quaggadir) - ) - else: - ret = True - try: - pwd.getpwnam("quagga")[2] - except KeyError: - logger.info('could not find "quagga" user') - - try: - grp.getgrnam("quagga")[2] - except KeyError: - logger.info('could not find "quagga" group') - - try: - if "quagga" not in grp.getgrnam("quaggavty").gr_mem: - logger.error( - '"quagga" user and group exist, but user is not under "quaggavty"' - ) - except KeyError: - logger.warning('could not find "quaggavty" group') - - for fname in [ - "zebra", - "ospfd", - "ospf6d", - "bgpd", - "ripd", - "ripngd", - "isisd", - "pimd", - "pbrd" - ]: - path = os.path.join(quaggadir, fname) - if not os.path.isfile(path): - logger.warning("could not find {} in {}".format(fname, quaggadir)) - ret = False - else: - if fname != "zebra": - continue - - os.system("{} -v 2>&1 >/tmp/topotests/quagga_zebra.txt".format(path)) - # Test MPLS availability krel = platform.release() if topotest.version_cmp(krel, "4.5") < 0: @@ -1162,10 +1107,10 @@ def diagnose_env_linux(): # TODO remove me when we start supporting exabgp >= 4 try: - output = subprocess.check_output(["exabgp", "-v"]) - line = output.split("\n")[0] - version = line.split(" ")[2] - if topotest.version_cmp(version, "4") >= 0: + p = os.popen("exabgp -v") + line = p.readlines() + version = line[0].split() + if topotest.version_cmp(version[2], "4") >= 0: logger.warning( "BGP topologies are still using exabgp version 3, expect failures" ) diff --git a/tests/topotests/lib/topojson.py b/tests/topotests/lib/topojson.py index b3af09aa99..6535918e36 100644 --- a/tests/topotests/lib/topojson.py +++ b/tests/topotests/lib/topojson.py @@ -216,7 +216,7 @@ def build_topo_from_json(tgen, topo): # Physical Interfaces if "links" in topo['switches'][curSwitch]: for destRouterLink, data in sorted( - topo['switches'][curSwitch]['links'].iteritems()): + topo['switches'][curSwitch]['links'].items()): # Loopback interfaces if "dst_node" in data: diff --git a/tests/topotests/lib/topolog.py b/tests/topotests/lib/topolog.py index 0dfa870930..9fde01cca0 100644 --- a/tests/topotests/lib/topolog.py +++ b/tests/topotests/lib/topolog.py @@ -93,7 +93,7 @@ class Logger(object): """ if log_level is None: log_level = self.log_level - if self.loggers.has_key(name): + if name in self.loggers: return self.loggers[name] nlogger = logging.Logger(name, level=log_level) diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index e34d1cf0be..a187971e41 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -628,7 +628,7 @@ def ip4_route_zebra(node, vrf_name=None): lines = output.splitlines() header_found = False while lines and (not lines[0].strip() or not header_found): - if "> - selected route" in lines[0]: + if "o - offload failure" in lines[0]: header_found = True lines = lines[1:] return "\n".join(lines) @@ -654,7 +654,7 @@ def ip6_route_zebra(node, vrf_name=None): lines = output.splitlines() header_found = False while lines and (not lines[0].strip() or not header_found): - if "> - selected route" in lines[0]: + if "o - offload failure" in lines[0]: header_found = True lines = lines[1:] @@ -947,13 +947,11 @@ def checkAddressSanitizerError(output, router, component): def addRouter(topo, name): - "Adding a FRRouter (or Quagga) to Topology" + "Adding a FRRouter to Topology" MyPrivateDirs = [ "/etc/frr", - "/etc/quagga", "/var/run/frr", - "/var/run/quagga", "/var/log", ] if sys.platform.startswith("linux"): @@ -985,7 +983,7 @@ def assert_sysctl(node, sysctl, value): class Router(Node): - "A Node with IPv4/IPv6 forwarding enabled and Quagga as Routing Engine" + "A Node with IPv4/IPv6 forwarding enabled" def __init__(self, name, **params): super(Router, self).__init__(name, **params) @@ -994,12 +992,11 @@ class Router(Node): # Backward compatibility: # Load configuration defaults like topogen. self.config_defaults = configparser.ConfigParser( - { + defaults = { "verbosity": "info", "frrdir": "/usr/lib/frr", - "quaggadir": "/usr/lib/quagga", "routertype": "frr", - "memleak_path": None, + "memleak_path": "", } ) self.config_defaults.read( @@ -1055,18 +1052,6 @@ class Router(Node): if not os.path.isfile(zebra_path): raise Exception("FRR zebra binary doesn't exist at {}".format(zebra_path)) - def _config_quagga(self, **params): - "Configure Quagga binaries" - self.daemondir = params.get("quaggadir") - if self.daemondir is None: - self.daemondir = self.config_defaults.get("topogen", "quaggadir") - - zebra_path = os.path.join(self.daemondir, "zebra") - if not os.path.isfile(zebra_path): - raise Exception( - "Quagga zebra binary doesn't exist at {}".format(zebra_path) - ) - # pylint: disable=W0221 # Some params are only meaningful for the parent class. def config(self, **params): @@ -1078,10 +1063,7 @@ class Router(Node): self.routertype = params.get( "routertype", self.config_defaults.get("topogen", "routertype") ) - if self.routertype == "quagga": - self._config_quagga(**params) - else: - self._config_frr(**params) + self._config_frr(**params) else: # Test the provided path zpath = os.path.join(self.daemondir, "zebra") @@ -1340,7 +1322,9 @@ class Router(Node): # If `daemons` was specified then some upper API called us with # specific daemons, otherwise just use our own configuration. daemons_list = [] - if daemons is None: + if daemons != None: + daemons_list = daemons + else: # Append all daemons configured. for daemon in self.daemons: if self.daemons[daemon] == 1: @@ -1406,7 +1390,7 @@ class Router(Node): def killRouterDaemons( self, daemons, wait=True, assertOnError=True, minErrorVersion="5.1" ): - # Kill Running Quagga or FRR specific + # Kill Running FRR # Daemons(user specified daemon only) using SIGKILL rundaemons = self.cmd("ls -1 /var/run/%s/*.pid" % self.routertype) errors = "" @@ -1541,7 +1525,7 @@ class Router(Node): for daemon in self.daemons: if (self.daemons[daemon] == 1) and not (daemon in daemonsRunning): sys.stderr.write("%s: Daemon %s not running\n" % (self.name, daemon)) - if daemon is "staticd": + if daemon == "staticd": sys.stderr.write( "You may have a copy of staticd installed but are attempting to test against\n" ) @@ -1607,7 +1591,7 @@ class Router(Node): logger.info("{}: running version: {}".format(self.name, self.version)) rversion = self.version - if rversion is None: + if rversion == None: return False result = version_cmp(rversion, version) @@ -1668,7 +1652,7 @@ class Router(Node): return True def get_routertype(self): - "Return the type of Router (frr or quagga)" + "Return the type of Router (frr)" return self.routertype @@ -1753,3 +1737,10 @@ class LegacySwitch(OVSSwitch): def __init__(self, name, **params): OVSSwitch.__init__(self, name, failMode="standalone", **params) self.switchIP = None + +def frr_unicode(s): + '''Convert string to unicode, depending on python version''' + if sys.version_info[0] > 2: + return s + else: + return unicode(s) diff --git a/tests/topotests/ospf-topo1-vrf/test_ospf_topo1_vrf.py b/tests/topotests/ospf-topo1-vrf/test_ospf_topo1_vrf.py index 4ec09b10d3..6d44d02e5e 100644 --- a/tests/topotests/ospf-topo1-vrf/test_ospf_topo1_vrf.py +++ b/tests/topotests/ospf-topo1-vrf/test_ospf_topo1_vrf.py @@ -23,7 +23,7 @@ # """ -test_ospf_topo1.py: Test the FRR/Quagga OSPF routing daemon. +test_ospf_topo1.py: Test the FRR OSPF routing daemon. """ import os diff --git a/tests/topotests/ospf-topo1/test_ospf_topo1.py b/tests/topotests/ospf-topo1/test_ospf_topo1.py index 3af60fd48f..95193afb2a 100644 --- a/tests/topotests/ospf-topo1/test_ospf_topo1.py +++ b/tests/topotests/ospf-topo1/test_ospf_topo1.py @@ -23,7 +23,7 @@ # """ -test_ospf_topo1.py: Test the FRR/Quagga OSPF routing daemon. +test_ospf_topo1.py: Test the FRR OSPF routing daemon. """ import os diff --git a/tests/topotests/ospf-topo2/test_ospf_topo2.py b/tests/topotests/ospf-topo2/test_ospf_topo2.py index 0b6f568462..79e8e6bf58 100644 --- a/tests/topotests/ospf-topo2/test_ospf_topo2.py +++ b/tests/topotests/ospf-topo2/test_ospf_topo2.py @@ -86,19 +86,19 @@ def setup_module(mod): os.path.join(CWD, '{}/ospfd.conf'.format(rname)) ) - # What is this? OSPF Unnumbered depends on the rp_filter - # being set appropriately( HA! ) - # Effectively we are putting different /32's on the interface - # the multicast packet delivery is somewhat controlled by - # the rp_filter. Setting it to '0' allows the OS to pass - # up the mcast packet not destined for the local routers - # network. - topotest.set_sysctl(tgen.net['r1'], - 'net.ipv4.conf.r1-eth1.rp_filter', 0) + # What is this? OSPF Unnumbered depends on the rp_filter + # being set appropriately( HA! ) + # Effectively we are putting different /32's on the interface + # the multicast packet delivery is somewhat controlled by + # the rp_filter. Setting it to '0' allows the OS to pass + # up the mcast packet not destined for the local routers + # network. + topotest.set_sysctl(tgen.net['r1'], + 'net.ipv4.conf.r1-eth1.rp_filter', 0) topotest.set_sysctl(tgen.net['r1'], 'net.ipv4.conf.all.rp_filter', 0) - topotest.set_sysctl(tgen.net['r2'], - 'net.ipv4.conf.r2-eth1.rp_filter', 0) + topotest.set_sysctl(tgen.net['r2'], + 'net.ipv4.conf.r2-eth1.rp_filter', 0) topotest.set_sysctl(tgen.net['r2'], 'net.ipv4.conf.all.rp_filter', 0) diff --git a/tests/topotests/pbr-topo1/test_pbr_topo1.py b/tests/topotests/pbr-topo1/test_pbr_topo1.py index 9ae4cce360..91979a8f04 100644 --- a/tests/topotests/pbr-topo1/test_pbr_topo1.py +++ b/tests/topotests/pbr-topo1/test_pbr_topo1.py @@ -88,8 +88,8 @@ def setup_module(module): krel = platform.release() if topotest.version_cmp(krel, "4.10") < 0: - tgen.errors = "Newer kernel than 4.9 needed for pbr tests" - pytest.skip(tgen.errors) + tgen.errors = "Newer kernel than 4.9 needed for pbr tests" + pytest.skip(tgen.errors) router_list = tgen.routers() for rname, router in router_list.items(): @@ -150,8 +150,8 @@ def test_pbr_data(): test_func = partial(topotest.router_json_cmp, router, "show pbr interface json", expected) _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) assertmsg = '"show pbr interface" mismatches on {}'.format(router.name) - if result is not None: - gather_pbr_data_on_error(router) + if result is not None: + gather_pbr_data_on_error(router) assert result is None, assertmsg map_file = "{}/{}/pbr-map.json".format(CWD, router.name) @@ -164,8 +164,8 @@ def test_pbr_data(): test_func = partial(topotest.router_json_cmp, router, "show pbr map json", expected) _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) assertmsg = '"show pbr map" mismatches on {}'.format(router.name) - if result is not None: - gather_pbr_data_on_error(router) + if result is not None: + gather_pbr_data_on_error(router) assert result is None, assertmsg nexthop_file = "{}/{}/pbr-nexthop-groups.json".format(CWD, router.name) @@ -178,8 +178,8 @@ def test_pbr_data(): test_func = partial(topotest.router_json_cmp, router, "show pbr nexthop-groups json", expected) _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) assertmsg = '"show pbr nexthop-groups" mismatches on {}'.format(router.name) - if result is not None: - gather_pbr_data_on_error(router) + if result is not None: + gather_pbr_data_on_error(router) assert result is None, assertmsg def test_pbr_flap(): @@ -215,8 +215,8 @@ def test_pbr_flap(): test_func = partial(topotest.router_json_cmp, router, "show pbr interface json", expected) _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) assertmsg = '"show pbr interface" mismatches on {}'.format(router.name) - if result is not None: - gather_pbr_data_on_error(router) + if result is not None: + gather_pbr_data_on_error(router) assert result is None, assertmsg diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini index 77b8c2b478..2e9c4901bc 100644 --- a/tests/topotests/pytest.ini +++ b/tests/topotests/pytest.ini @@ -19,10 +19,9 @@ norecursedirs = .git example-test example-topojson-test lib docker evpn_type5_te # Default daemons binaries path. #frrdir = /usr/lib/frr -#quaggadir = /usr/lib/quagga # Default router type to use. Possible values are: -# 'frr' and 'quagga'. +# 'frr' #routertype = frr # Memory leak test reports path diff --git a/tests/topotests/rip-topo1/test_rip_topo1.py b/tests/topotests/rip-topo1/test_rip_topo1.py index 3098812a24..de11b78824 100755..100644 --- a/tests/topotests/rip-topo1/test_rip_topo1.py +++ b/tests/topotests/rip-topo1/test_rip_topo1.py @@ -91,11 +91,11 @@ class NetworkTopo(Topo): switch[4] = self.addSwitch("sw4", cls=topotest.LegacySwitch) self.addLink(switch[4], router[3], intfName2="r3-eth0") - switch[5] = self.addSwitch("sw5", cls=topotest.LegacySwitch) - self.addLink(switch[5], router[1], intfName2="r1-eth2") + switch[5] = self.addSwitch("sw5", cls=topotest.LegacySwitch) + self.addLink(switch[5], router[1], intfName2="r1-eth2") - switch[6] = self.addSwitch("sw6", cls=topotest.LegacySwitch) - self.addLink(switch[6], router[1], intfName2="r1-eth3") + switch[6] = self.addSwitch("sw6", cls=topotest.LegacySwitch) + self.addLink(switch[6], router[1], intfName2="r1-eth3") ##################################################### @@ -127,7 +127,7 @@ def setup_module(module): net["r%s" % i].loadConf("ripd", "%s/r%s/ripd.conf" % (thisDir, i)) net["r%s" % i].startRouter() - # For debugging after starting Quagga/FRR daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -149,7 +149,7 @@ def test_router_running(): if fatal_error != "": pytest.skip(fatal_error) - print("\n\n** Check if FRR/Quagga is running on each Router node") + print("\n\n** Check if FRR is running on each Router node") print("******************************************\n") # Make sure that all daemons are running @@ -157,7 +157,7 @@ def test_router_running(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -182,7 +182,7 @@ def test_converge_protocols(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -243,7 +243,7 @@ def test_rip_status(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -298,7 +298,7 @@ def test_rip_routes(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -330,7 +330,7 @@ def test_zebra_ipv4_routingTable(): .cmd('vtysh -c "show ip route" 2> /dev/null | grep "^R"') .rstrip() ) - # Drop timers on end of line (older Quagga Versions) + # Drop timers on end of line actual = re.sub(r", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual) # Fix newlines (make them all the same) actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) @@ -362,7 +362,7 @@ def test_zebra_ipv4_routingTable(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) diff --git a/tests/topotests/ripng-topo1/test_ripng_topo1.py b/tests/topotests/ripng-topo1/test_ripng_topo1.py index 23e689235c..2976cdefe4 100755..100644 --- a/tests/topotests/ripng-topo1/test_ripng_topo1.py +++ b/tests/topotests/ripng-topo1/test_ripng_topo1.py @@ -127,7 +127,7 @@ def setup_module(module): net["r%s" % i].loadConf("ripngd", "%s/r%s/ripngd.conf" % (thisDir, i)) net["r%s" % i].startRouter() - # For debugging after starting Quagga/FRR daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -149,7 +149,7 @@ def test_router_running(): if fatal_error != "": pytest.skip(fatal_error) - print("\n\n** Check if FRR/Quagga is running on each Router node") + print("\n\n** Check if FRR is running on each Router node") print("******************************************\n") # Starting Routers @@ -157,7 +157,7 @@ def test_router_running(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -182,7 +182,7 @@ def test_converge_protocols(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -250,7 +250,7 @@ def test_ripng_status(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -317,7 +317,7 @@ def test_ripng_routes(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) @@ -351,7 +351,7 @@ def test_zebra_ipv6_routingTable(): ) # Mask out Link-Local mac address portion. They are random... actual = re.sub(r" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual) - # Drop timers on end of line (older Quagga Versions) + # Drop timers on end of line actual = re.sub(r", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual) # Fix newlines (make them all the same) actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) @@ -383,7 +383,7 @@ def test_zebra_ipv6_routingTable(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR/Quagga daemons, uncomment the next line + # For debugging after starting FRR daemons, uncomment the next line # CLI(net) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 4edbb7a889..9993e73353 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1173,12 +1173,14 @@ static char **new_completion(const char *text, int start, int end) } /* Vty node structures. */ +#ifdef HAVE_BGPD static struct cmd_node bgp_node = { .name = "bgp", .node = BGP_NODE, .parent_node = CONFIG_NODE, .prompt = "%s(config-router)# ", }; +#endif /* HAVE_BGPD */ static struct cmd_node rip_node = { .name = "rip", @@ -1187,19 +1189,23 @@ static struct cmd_node rip_node = { .prompt = "%s(config-router)# ", }; +#ifdef HAVE_ISISD static struct cmd_node isis_node = { .name = "isis", .node = ISIS_NODE, .parent_node = CONFIG_NODE, .prompt = "%s(config-router)# ", }; +#endif /* HAVE_ISISD */ +#ifdef HAVE_FABRICD static struct cmd_node openfabric_node = { .name = "openfabric", .node = OPENFABRIC_NODE, .parent_node = CONFIG_NODE, .prompt = "%s(config-router)# ", }; +#endif /* HAVE_FABRICD */ static struct cmd_node interface_node = { .name = "interface", @@ -1236,12 +1242,14 @@ static struct cmd_node rmap_node = { .prompt = "%s(config-route-map)# ", }; +#ifdef HAVE_PBRD static struct cmd_node pbr_map_node = { .name = "pbr-map", .node = PBRMAP_NODE, .parent_node = CONFIG_NODE, .prompt = "%s(config-pbr-map)# ", }; +#endif /* HAVE_PBRD */ static struct cmd_node zebra_node = { .name = "zebra", @@ -1250,6 +1258,7 @@ static struct cmd_node zebra_node = { .prompt = "%s(config-router)# ", }; +#ifdef HAVE_BGPD static struct cmd_node bgp_vpnv4_node = { .name = "bgp vpnv4", .node = BGP_VPNV4_NODE, @@ -1334,6 +1343,7 @@ static struct cmd_node bgp_ipv6l_node = { .prompt = "%s(config-router-af)# ", }; +#ifdef ENABLE_BGP_VNC static struct cmd_node bgp_vnc_defaults_node = { .name = "bgp vnc defaults", .node = BGP_VNC_DEFAULTS_NODE, @@ -1361,6 +1371,7 @@ static struct cmd_node bgp_vnc_l2_group_node = { .parent_node = BGP_NODE, .prompt = "%s(config-router-vnc-l2-group)# ", }; +#endif /* ENABLE_BGP_VNC */ static struct cmd_node bmp_node = { .name = "bmp", @@ -1368,27 +1379,34 @@ static struct cmd_node bmp_node = { .parent_node = BGP_NODE, .prompt = "%s(config-bgp-bmp)# " }; +#endif /* HAVE_BGPD */ +#ifdef HAVE_OSPFD static struct cmd_node ospf_node = { .name = "ospf", .node = OSPF_NODE, .parent_node = CONFIG_NODE, .prompt = "%s(config-router)# ", }; +#endif /* HAVE_OSPFD */ +#ifdef HAVE_EIGRPD static struct cmd_node eigrp_node = { .name = "eigrp", .node = EIGRP_NODE, .parent_node = CONFIG_NODE, .prompt = "%s(config-router)# ", }; +#endif /* HAVE_EIGRPD */ +#ifdef HAVE_BABELD static struct cmd_node babel_node = { .name = "babel", .node = BABEL_NODE, .parent_node = CONFIG_NODE, .prompt = "%s(config-router)# ", }; +#endif /* HAVE_BABELD */ static struct cmd_node ripng_node = { .name = "ripng", @@ -1397,13 +1415,16 @@ static struct cmd_node ripng_node = { .prompt = "%s(config-router)# ", }; +#ifdef HAVE_OSPF6D static struct cmd_node ospf6_node = { .name = "ospf6", .node = OSPF6_NODE, .parent_node = CONFIG_NODE, .prompt = "%s(config-ospf6)# ", }; +#endif /* HAVE_OSPF6D */ +#ifdef HAVE_LDPD static struct cmd_node ldp_node = { .name = "ldp", .node = LDP_NODE, @@ -1452,6 +1473,7 @@ static struct cmd_node ldp_pseudowire_node = { .parent_node = LDP_L2VPN_NODE, .prompt = "%s(config-l2vpn-pw)# ", }; +#endif /* HAVE_LDPD */ static struct cmd_node keychain_node = { .name = "keychain", @@ -1474,12 +1496,14 @@ struct cmd_node link_params_node = { .prompt = "%s(config-link-params)# ", }; +#ifdef HAVE_BGPD static struct cmd_node rpki_node = { .name = "rpki", .node = RPKI_NODE, .parent_node = CONFIG_NODE, .prompt = "%s(config-rpki)# ", }; +#endif /* HAVE_BGPD */ #if HAVE_BFDD > 0 static struct cmd_node bfd_node = { @@ -1528,6 +1552,7 @@ DEFUNSH(VTYSH_REALLYALL, vtysh_end_all, vtysh_end_all_cmd, "end", return vtysh_end(); } +#ifdef HAVE_BGPD DEFUNSH(VTYSH_BGPD, router_bgp, router_bgp_cmd, "router bgp [(1-4294967295) [<view|vrf> WORD]]", ROUTER_STR BGP_STR AS_STR @@ -1748,6 +1773,7 @@ DEFUNSH(VTYSH_BGPD, vnc_l2_group, vnc_l2_group_cmd, "vnc l2-group NAME", return CMD_SUCCESS; } #endif +#endif /* HAVE_BGPD */ DEFUNSH(VTYSH_KEYS, key_chain, key_chain_cmd, "key chain WORD", "Authentication key management\n" @@ -1766,20 +1792,25 @@ DEFUNSH(VTYSH_KEYS, key, key_cmd, "key (0-2147483647)", return CMD_SUCCESS; } +#ifdef HAVE_RIPD DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]", ROUTER_STR "RIP\n" VRF_CMD_HELP_STR) { vty->node = RIP_NODE; return CMD_SUCCESS; } +#endif /* HAVE_RIPD */ +#ifdef HAVE_RIPNGD DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng [vrf NAME]", ROUTER_STR "RIPng\n" VRF_CMD_HELP_STR) { vty->node = RIPNG_NODE; return CMD_SUCCESS; } +#endif /* HAVE_RIPNGD */ +#ifdef HAVE_OSPFD DEFUNSH(VTYSH_OSPFD, router_ospf, router_ospf_cmd, "router ospf [(1-65535)] [vrf NAME]", "Enable a routing process\n" @@ -1790,7 +1821,9 @@ DEFUNSH(VTYSH_OSPFD, router_ospf, router_ospf_cmd, vty->node = OSPF_NODE; return CMD_SUCCESS; } +#endif /* HAVE_OSPFD */ +#ifdef HAVE_EIGRPD DEFUNSH(VTYSH_EIGRPD, router_eigrp, router_eigrp_cmd, "router eigrp (1-65535) [vrf NAME]", "Enable a routing process\n" "Start EIGRP configuration\n" @@ -1800,7 +1833,9 @@ DEFUNSH(VTYSH_EIGRPD, router_eigrp, router_eigrp_cmd, "router eigrp (1-65535) [v vty->node = EIGRP_NODE; return CMD_SUCCESS; } +#endif /* HAVE_EIGRPD */ +#ifdef HAVE_BABELD DEFUNSH(VTYSH_BABELD, router_babel, router_babel_cmd, "router babel", "Enable a routing process\n" "Make Babel instance command\n") @@ -1808,13 +1843,16 @@ DEFUNSH(VTYSH_BABELD, router_babel, router_babel_cmd, "router babel", vty->node = BABEL_NODE; return CMD_SUCCESS; } +#endif /* HAVE_BABELD */ +#ifdef HAVE_OSPF6D DEFUNSH(VTYSH_OSPF6D, router_ospf6, router_ospf6_cmd, "router ospf6", ROUTER_STR OSPF6_STR) { vty->node = OSPF6_NODE; return CMD_SUCCESS; } +#endif #if defined(HAVE_LDPD) DEFUNSH(VTYSH_LDPD, ldp_mpls_ldp, ldp_mpls_ldp_cmd, "mpls ldp", @@ -1892,6 +1930,7 @@ DEFUNSH(VTYSH_LDPD, ldp_member_pseudowire_ifname, } #endif +#ifdef HAVE_ISISD DEFUNSH(VTYSH_ISISD, router_isis, router_isis_cmd, "router isis WORD [vrf NAME]", ROUTER_STR @@ -1901,7 +1940,9 @@ DEFUNSH(VTYSH_ISISD, router_isis, router_isis_cmd, vty->node = ISIS_NODE; return CMD_SUCCESS; } +#endif /* HAVE_ISISD */ +#ifdef HAVE_FABRICD DEFUNSH(VTYSH_FABRICD, router_openfabric, router_openfabric_cmd, "router openfabric WORD", ROUTER_STR "OpenFabric routing protocol\n" @@ -1910,6 +1951,7 @@ DEFUNSH(VTYSH_FABRICD, router_openfabric, router_openfabric_cmd, "router openfab vty->node = OPENFABRIC_NODE; return CMD_SUCCESS; } +#endif /* HAVE_FABRICD */ DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd, "route-map WORD <deny|permit> (1-65535)", @@ -1923,6 +1965,7 @@ DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd, return CMD_SUCCESS; } +#ifdef HAVE_PBRD DEFUNSH(VTYSH_PBRD, vtysh_pbr_map, vtysh_pbr_map_cmd, "pbr-map PBRMAP seq (1-700)", "Create pbr-map or enter pbr-map command mode\n" @@ -1934,6 +1977,14 @@ DEFUNSH(VTYSH_PBRD, vtysh_pbr_map, vtysh_pbr_map_cmd, return CMD_SUCCESS; } +DEFSH(VTYSH_PBRD, vtysh_no_pbr_map_cmd, "no pbr-map PBRMAP [seq (1-700)]", + NO_STR + "Delete pbr-map\n" + "The name of the PBR MAP\n" + "Sequence to delete from existing pbr-map entry\n" + "Sequence number\n") +#endif /* HAVE_PBRD */ + #if HAVE_BFDD > 0 DEFUNSH(VTYSH_BFDD, bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n") { @@ -1969,13 +2020,6 @@ DEFUNSH(VTYSH_BFDD, bfd_profile_enter, bfd_profile_enter_cmd, } #endif /* HAVE_BFDD */ -DEFSH(VTYSH_PBRD, vtysh_no_pbr_map_cmd, "no pbr-map PBRMAP [seq (1-700)]", - NO_STR - "Delete pbr-map\n" - "The name of the PBR MAP\n" - "Sequence to delete from existing pbr-map entry\n" - "Sequence number\n") - DEFUNSH(VTYSH_ALL, vtysh_line_vty, vtysh_line_vty_cmd, "line vty", "Configure a terminal line\n" "Virtual terminal\n") @@ -2039,6 +2083,7 @@ DEFUNSH(VTYSH_ALL, vtysh_quit_all, vtysh_quit_all_cmd, "quit", return vtysh_exit_all(self, vty, argc, argv); } +#ifdef HAVE_BGPD DEFUNSH(VTYSH_BGPD, exit_address_family, exit_address_family_cmd, "exit-address-family", "Exit from Address Family configuration mode\n") { @@ -2097,14 +2142,6 @@ DEFUNSH(VTYSH_BGPD, bmp_quit, bmp_quit_cmd, "quit", return bmp_exit(self, vty, argc, argv); } -DEFUNSH(VTYSH_VRF, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf", - "Exit from VRF configuration mode\n") -{ - if (vty->node == VRF_NODE) - vty->node = CONFIG_NODE; - return CMD_SUCCESS; -} - DEFUNSH(VTYSH_BGPD, exit_vrf_policy, exit_vrf_policy_cmd, "exit-vrf-policy", "Exit from VRF policy configuration mode\n") { @@ -2112,7 +2149,17 @@ DEFUNSH(VTYSH_BGPD, exit_vrf_policy, exit_vrf_policy_cmd, "exit-vrf-policy", vty->node = BGP_NODE; return CMD_SUCCESS; } +#endif /* HAVE_BGPD */ +DEFUNSH(VTYSH_VRF, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf", + "Exit from VRF configuration mode\n") +{ + if (vty->node == VRF_NODE) + vty->node = CONFIG_NODE; + return CMD_SUCCESS; +} + +#ifdef HAVE_RIPD DEFUNSH(VTYSH_RIPD, vtysh_exit_ripd, vtysh_exit_ripd_cmd, "exit", "Exit current mode and down to previous mode\n") { @@ -2124,7 +2171,9 @@ DEFUNSH(VTYSH_RIPD, vtysh_quit_ripd, vtysh_quit_ripd_cmd, "quit", { return vtysh_exit_ripd(self, vty, argc, argv); } +#endif /* HAVE_RIPD */ +#ifdef HAVE_RIPNGD DEFUNSH(VTYSH_RIPNGD, vtysh_exit_ripngd, vtysh_exit_ripngd_cmd, "exit", "Exit current mode and down to previous mode\n") { @@ -2136,6 +2185,7 @@ DEFUNSH(VTYSH_RIPNGD, vtysh_quit_ripngd, vtysh_quit_ripngd_cmd, "quit", { return vtysh_exit_ripngd(self, vty, argc, argv); } +#endif /* HAVE_RIPNGD */ DEFUNSH(VTYSH_RMAP, vtysh_exit_rmap, vtysh_exit_rmap_cmd, "exit", "Exit current mode and down to previous mode\n") @@ -2149,6 +2199,7 @@ DEFUNSH(VTYSH_RMAP, vtysh_quit_rmap, vtysh_quit_rmap_cmd, "quit", return vtysh_exit_rmap(self, vty, argc, argv); } +#ifdef HAVE_PBRD DEFUNSH(VTYSH_PBRD, vtysh_exit_pbr_map, vtysh_exit_pbr_map_cmd, "exit", "Exit current mode and down to previous mode\n") { @@ -2160,7 +2211,9 @@ DEFUNSH(VTYSH_PBRD, vtysh_quit_pbr_map, vtysh_quit_pbr_map_cmd, "quit", { return vtysh_exit_rmap(self, vty, argc, argv); } +#endif /* HAVE_PBRD */ +#ifdef HAVE_BGPD DEFUNSH(VTYSH_BGPD, vtysh_exit_bgpd, vtysh_exit_bgpd_cmd, "exit", "Exit current mode and down to previous mode\n") { @@ -2172,7 +2225,9 @@ DEFUNSH(VTYSH_BGPD, vtysh_quit_bgpd, vtysh_quit_bgpd_cmd, "quit", { return vtysh_exit_bgpd(self, vty, argc, argv); } +#endif /* HAVE_BGPD */ +#ifdef HAVE_OSPFD DEFUNSH(VTYSH_OSPFD, vtysh_exit_ospfd, vtysh_exit_ospfd_cmd, "exit", "Exit current mode and down to previous mode\n") { @@ -2184,7 +2239,9 @@ DEFUNSH(VTYSH_OSPFD, vtysh_quit_ospfd, vtysh_quit_ospfd_cmd, "quit", { return vtysh_exit_ospfd(self, vty, argc, argv); } +#endif /* HAVE_OSPFD */ +#ifdef HAVE_EIGRPD DEFUNSH(VTYSH_EIGRPD, vtysh_exit_eigrpd, vtysh_exit_eigrpd_cmd, "exit", "Exit current mode and down to previous mode\n") { @@ -2196,8 +2253,10 @@ DEFUNSH(VTYSH_EIGRPD, vtysh_quit_eigrpd, vtysh_quit_eigrpd_cmd, "quit", { return vtysh_exit(vty); } +#endif /* HAVE_EIGRPD */ -DEFUNSH(VTYSH_EIGRPD, vtysh_exit_babeld, vtysh_exit_babeld_cmd, "exit", +#ifdef HAVE_BABELD +DEFUNSH(VTYSH_BABELD, vtysh_exit_babeld, vtysh_exit_babeld_cmd, "exit", "Exit current mode and down to previous mode\n") { return vtysh_exit(vty); @@ -2208,7 +2267,9 @@ DEFUNSH(VTYSH_BABELD, vtysh_quit_babeld, vtysh_quit_babeld_cmd, "quit", { return vtysh_exit(vty); } +#endif /* HAVE_BABELD */ +#ifdef HAVE_OSPF6D DEFUNSH(VTYSH_OSPF6D, vtysh_exit_ospf6d, vtysh_exit_ospf6d_cmd, "exit", "Exit current mode and down to previous mode\n") { @@ -2220,6 +2281,7 @@ DEFUNSH(VTYSH_OSPF6D, vtysh_quit_ospf6d, vtysh_quit_ospf6d_cmd, "quit", { return vtysh_exit_ospf6d(self, vty, argc, argv); } +#endif /* HAVE_OSPF6D */ #if defined(HAVE_LDPD) DEFUNSH(VTYSH_LDPD, vtysh_exit_ldpd, vtysh_exit_ldpd_cmd, "exit", @@ -2232,6 +2294,7 @@ ALIAS(vtysh_exit_ldpd, vtysh_quit_ldpd_cmd, "quit", "Exit current mode and down to previous mode\n") #endif +#ifdef HAVE_ISISD DEFUNSH(VTYSH_ISISD, vtysh_exit_isisd, vtysh_exit_isisd_cmd, "exit", "Exit current mode and down to previous mode\n") { @@ -2243,6 +2306,7 @@ DEFUNSH(VTYSH_ISISD, vtysh_quit_isisd, vtysh_quit_isisd_cmd, "quit", { return vtysh_exit_isisd(self, vty, argc, argv); } +#endif /* HAVE_ISISD */ #if HAVE_BFDD > 0 DEFUNSH(VTYSH_BFDD, vtysh_exit_bfdd, vtysh_exit_bfdd_cmd, "exit", @@ -2255,6 +2319,7 @@ ALIAS(vtysh_exit_bfdd, vtysh_quit_bfdd_cmd, "quit", "Exit current mode and down to previous mode\n") #endif +#ifdef HAVE_FABRICD DEFUNSH(VTYSH_FABRICD, vtysh_exit_fabricd, vtysh_exit_fabricd_cmd, "exit", "Exit current mode and down to previous mode\n") { @@ -2266,6 +2331,19 @@ DEFUNSH(VTYSH_FABRICD, vtysh_quit_fabricd, vtysh_quit_fabricd_cmd, "quit", { return vtysh_exit_fabricd(self, vty, argc, argv); } +#endif /* HAVE_FABRICD */ + +DEFUNSH(VTYSH_KEYS, vtysh_exit_keys, vtysh_exit_keys_cmd, "exit", + "Exit current mode and down to previous mode\n") +{ + return vtysh_exit(vty); +} + +DEFUNSH(VTYSH_KEYS, vtysh_quit_keys, vtysh_quit_keys_cmd, "quit", + "Exit current mode and down to previous mode\n") +{ + return vtysh_exit_keys(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") @@ -3771,331 +3849,394 @@ void vtysh_init_vty(void) cmd_init(0); cmd_variable_handler_register(vtysh_var_handler); - /* Install nodes. */ + /* bgpd */ +#ifdef HAVE_BGPD install_node(&bgp_node); - install_node(&rip_node); - install_node(&interface_node); - install_node(&pw_node); - install_node(&link_params_node); - install_node(&vrf_node); - install_node(&nh_group_node); - install_node(&rmap_node); - install_node(&pbr_map_node); - install_node(&zebra_node); + install_element(CONFIG_NODE, &router_bgp_cmd); + install_element(BGP_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_NODE, &vtysh_end_all_cmd); + install_node(&bgp_vpnv4_node); + install_element(BGP_NODE, &address_family_ipv4_vpn_cmd); +#ifdef KEEP_OLD_VPN_COMMANDS + install_element(BGP_NODE, &address_family_vpnv4_cmd); +#endif /* KEEP_OLD_VPN_COMMANDS */ + install_element(BGP_VPNV4_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VPNV4_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VPNV4_NODE, &vtysh_end_all_cmd); + install_element(BGP_VPNV4_NODE, &exit_address_family_cmd); + install_node(&bgp_vpnv6_node); + install_element(BGP_NODE, &address_family_ipv6_vpn_cmd); +#ifdef KEEP_OLD_VPN_COMMANDS + install_element(BGP_NODE, &address_family_vpnv6_cmd); +#endif /* KEEP_OLD_VPN_COMMANDS */ + install_element(BGP_VPNV6_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VPNV6_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VPNV6_NODE, &vtysh_end_all_cmd); + install_element(BGP_VPNV6_NODE, &exit_address_family_cmd); + install_node(&bgp_flowspecv4_node); + install_element(BGP_NODE, &address_family_flowspecv4_cmd); + install_element(BGP_FLOWSPECV4_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_FLOWSPECV4_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_FLOWSPECV4_NODE, &vtysh_end_all_cmd); + install_element(BGP_FLOWSPECV4_NODE, &exit_address_family_cmd); + install_node(&bgp_flowspecv6_node); + install_element(BGP_NODE, &address_family_flowspecv6_cmd); + install_element(BGP_FLOWSPECV6_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_FLOWSPECV6_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_FLOWSPECV6_NODE, &vtysh_end_all_cmd); + install_element(BGP_FLOWSPECV6_NODE, &exit_address_family_cmd); + install_node(&bgp_ipv4_node); + install_element(BGP_NODE, &address_family_ipv4_cmd); + install_element(BGP_IPV4_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV4_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV4_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV4_NODE, &exit_address_family_cmd); + install_node(&bgp_ipv4m_node); + install_element(BGP_NODE, &address_family_ipv4_multicast_cmd); + install_element(BGP_IPV4M_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV4M_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV4M_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV4M_NODE, &exit_address_family_cmd); + install_node(&bgp_ipv4l_node); + install_element(BGP_NODE, &address_family_ipv4_labeled_unicast_cmd); + install_element(BGP_IPV4L_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV4L_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV4L_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV4L_NODE, &exit_address_family_cmd); + install_node(&bgp_ipv6_node); + install_element(BGP_NODE, &address_family_ipv6_cmd); + install_element(BGP_IPV6_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV6_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV6_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV6_NODE, &exit_address_family_cmd); + install_node(&bgp_ipv6m_node); + install_element(BGP_NODE, &address_family_ipv6_multicast_cmd); + install_element(BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV6M_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV6M_NODE, &exit_address_family_cmd); + install_node(&bgp_ipv6l_node); + install_element(BGP_NODE, &address_family_ipv6_labeled_unicast_cmd); + install_element(BGP_IPV6L_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV6L_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV6L_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV6L_NODE, &exit_address_family_cmd); + +#if defined(ENABLE_BGP_VNC) install_node(&bgp_vrf_policy_node); - install_node(&bgp_evpn_node); - install_node(&bgp_evpn_vni_node); + install_element(BGP_NODE, &vnc_vrf_policy_cmd); + install_element(BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VRF_POLICY_NODE, &vtysh_end_all_cmd); + install_element(BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); + install_node(&bgp_vnc_defaults_node); + install_element(BGP_NODE, &vnc_defaults_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd); + install_node(&bgp_vnc_nve_group_node); + install_element(BGP_NODE, &vnc_nve_group_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &exit_vnc_config_cmd); + install_node(&bgp_vnc_l2_group_node); - install_node(&ospf_node); - install_node(&eigrp_node); - install_node(&babel_node); - install_node(&ripng_node); - install_node(&ospf6_node); - install_node(&ldp_node); - install_node(&ldp_ipv4_node); - install_node(&ldp_ipv6_node); - install_node(&ldp_ipv4_iface_node); - install_node(&ldp_ipv6_iface_node); - install_node(&ldp_l2vpn_node); - install_node(&ldp_pseudowire_node); - install_node(&keychain_node); - install_node(&keychain_key_node); - install_node(&isis_node); - install_node(&openfabric_node); - install_node(&vty_node); - install_node(&rpki_node); - install_node(&bmp_node); -#if HAVE_BFDD > 0 - install_node(&bfd_node); - install_node(&bfd_peer_node); - install_node(&bfd_profile_node); -#endif /* HAVE_BFDD */ + install_element(BGP_NODE, &vnc_l2_group_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &exit_vnc_config_cmd); +#endif - struct cmd_node *node; - for (unsigned int i = 0; i < vector_active(cmdvec); i++) { - node = vector_slot(cmdvec, i); - if (!node || node->node == VIEW_NODE) - continue; - vtysh_install_default(node->node); - } + install_node(&bgp_evpn_node); + install_element(BGP_NODE, &address_family_evpn_cmd); +#if defined(HAVE_CUMULUS) + install_element(BGP_NODE, &address_family_evpn2_cmd); +#endif + install_element(BGP_EVPN_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_EVPN_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_EVPN_NODE, &vtysh_end_all_cmd); + install_element(BGP_EVPN_NODE, &exit_address_family_cmd); - install_element(VIEW_NODE, &vtysh_enable_cmd); - install_element(ENABLE_NODE, &vtysh_config_terminal_cmd); - install_element(ENABLE_NODE, &vtysh_disable_cmd); + install_node(&bgp_evpn_vni_node); + install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd); + install_element(BGP_EVPN_VNI_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_EVPN_VNI_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_EVPN_VNI_NODE, &vtysh_end_all_cmd); + install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd); - /* "exit" command. */ - install_element(VIEW_NODE, &vtysh_exit_all_cmd); - install_element(CONFIG_NODE, &vtysh_exit_all_cmd); - install_element(VIEW_NODE, &vtysh_quit_all_cmd); - install_element(CONFIG_NODE, &vtysh_quit_all_cmd); + install_node(&rpki_node); + 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); + + install_node(&bmp_node); + install_element(BGP_NODE, &bmp_targets_cmd); + install_element(BMP_NODE, &bmp_exit_cmd); + install_element(BMP_NODE, &bmp_quit_cmd); + install_element(BMP_NODE, &vtysh_end_all_cmd); +#endif /* HAVE_BGPD */ + + /* ripd */ + install_node(&rip_node); +#ifdef HAVE_RIPD + install_element(CONFIG_NODE, &router_rip_cmd); install_element(RIP_NODE, &vtysh_exit_ripd_cmd); install_element(RIP_NODE, &vtysh_quit_ripd_cmd); + install_element(RIP_NODE, &vtysh_end_all_cmd); +#endif /* HAVE_RIPD */ + + /* ripngd */ + install_node(&ripng_node); +#ifdef HAVE_RIPNGD + install_element(CONFIG_NODE, &router_ripng_cmd); install_element(RIPNG_NODE, &vtysh_exit_ripngd_cmd); install_element(RIPNG_NODE, &vtysh_quit_ripngd_cmd); + install_element(RIPNG_NODE, &vtysh_end_all_cmd); +#endif /* HAVE_RIPNGD */ + + /* ospfd */ +#ifdef HAVE_OSPFD + install_node(&ospf_node); + install_element(CONFIG_NODE, &router_ospf_cmd); install_element(OSPF_NODE, &vtysh_exit_ospfd_cmd); install_element(OSPF_NODE, &vtysh_quit_ospfd_cmd); - install_element(EIGRP_NODE, &vtysh_exit_eigrpd_cmd); - install_element(EIGRP_NODE, &vtysh_quit_eigrpd_cmd); - install_element(BABEL_NODE, &vtysh_exit_babeld_cmd); - install_element(BABEL_NODE, &vtysh_quit_babeld_cmd); + install_element(OSPF_NODE, &vtysh_end_all_cmd); +#endif /* HAVE_OSPFD */ + + /* ospf6d */ +#ifdef HAVE_OSPF6D + install_node(&ospf6_node); + install_element(CONFIG_NODE, &router_ospf6_cmd); install_element(OSPF6_NODE, &vtysh_exit_ospf6d_cmd); install_element(OSPF6_NODE, &vtysh_quit_ospf6d_cmd); + install_element(OSPF6_NODE, &vtysh_end_all_cmd); +#endif /* HAVE_OSPF6D */ + + /* ldpd */ #if defined(HAVE_LDPD) + install_node(&ldp_node); + install_element(CONFIG_NODE, &ldp_mpls_ldp_cmd); install_element(LDP_NODE, &vtysh_exit_ldpd_cmd); install_element(LDP_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_NODE, &vtysh_end_all_cmd); + + install_node(&ldp_ipv4_node); + install_element(LDP_NODE, &ldp_address_family_ipv4_cmd); install_element(LDP_IPV4_NODE, &vtysh_exit_ldpd_cmd); install_element(LDP_IPV4_NODE, &vtysh_quit_ldpd_cmd); install_element(LDP_IPV4_NODE, &ldp_exit_address_family_cmd); + install_element(LDP_IPV4_NODE, &vtysh_end_all_cmd); + + install_node(&ldp_ipv6_node); + install_element(LDP_NODE, &ldp_address_family_ipv6_cmd); install_element(LDP_IPV6_NODE, &vtysh_exit_ldpd_cmd); install_element(LDP_IPV6_NODE, &vtysh_quit_ldpd_cmd); install_element(LDP_IPV6_NODE, &ldp_exit_address_family_cmd); + install_element(LDP_IPV6_NODE, &vtysh_end_all_cmd); + + install_node(&ldp_ipv4_iface_node); + install_element(LDP_IPV4_NODE, &ldp_interface_ifname_cmd); install_element(LDP_IPV4_IFACE_NODE, &vtysh_exit_ldpd_cmd); install_element(LDP_IPV4_IFACE_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_IPV4_IFACE_NODE, &vtysh_end_all_cmd); + + install_node(&ldp_ipv6_iface_node); + install_element(LDP_IPV6_NODE, &ldp_interface_ifname_cmd); install_element(LDP_IPV6_IFACE_NODE, &vtysh_exit_ldpd_cmd); install_element(LDP_IPV6_IFACE_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_IPV6_IFACE_NODE, &vtysh_end_all_cmd); + + install_node(&ldp_l2vpn_node); + install_element(CONFIG_NODE, &ldp_l2vpn_word_type_vpls_cmd); install_element(LDP_L2VPN_NODE, &vtysh_exit_ldpd_cmd); install_element(LDP_L2VPN_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_L2VPN_NODE, &vtysh_end_all_cmd); + + install_node(&ldp_pseudowire_node); + install_element(LDP_L2VPN_NODE, &ldp_member_pseudowire_ifname_cmd); install_element(LDP_PSEUDOWIRE_NODE, &vtysh_exit_ldpd_cmd); install_element(LDP_PSEUDOWIRE_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_PSEUDOWIRE_NODE, &vtysh_end_all_cmd); #endif - install_element(BGP_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_VPNV4_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_VPNV4_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_VPNV6_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_VPNV6_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_FLOWSPECV4_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_FLOWSPECV4_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_FLOWSPECV6_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_FLOWSPECV6_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_IPV4_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_IPV4_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_IPV4M_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_IPV4M_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_IPV4L_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_IPV4L_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_IPV6_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_IPV6_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_EVPN_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_EVPN_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_EVPN_VNI_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_EVPN_VNI_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_IPV6L_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_IPV6L_NODE, &vtysh_quit_bgpd_cmd); -#if defined(ENABLE_BGP_VNC) - install_element(BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_quit_bgpd_cmd); - install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_exit_bgpd_cmd); - install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_quit_bgpd_cmd); -#endif + + /* eigrpd */ +#ifdef HAVE_EIGRPD + install_node(&eigrp_node); + install_element(CONFIG_NODE, &router_eigrp_cmd); + install_element(EIGRP_NODE, &vtysh_exit_eigrpd_cmd); + install_element(EIGRP_NODE, &vtysh_quit_eigrpd_cmd); + install_element(EIGRP_NODE, &vtysh_end_all_cmd); +#endif /* HAVE_EIGRPD */ + + /* babeld */ +#ifdef HAVE_BABELD + install_node(&babel_node); + install_element(CONFIG_NODE, &router_babel_cmd); + install_element(BABEL_NODE, &vtysh_exit_babeld_cmd); + install_element(BABEL_NODE, &vtysh_quit_babeld_cmd); + install_element(BABEL_NODE, &vtysh_end_all_cmd); +#endif /* HAVE_BABELD */ + + /* isisd */ +#ifdef HAVE_ISISD + install_node(&isis_node); + install_element(CONFIG_NODE, &router_isis_cmd); install_element(ISIS_NODE, &vtysh_exit_isisd_cmd); install_element(ISIS_NODE, &vtysh_quit_isisd_cmd); + install_element(ISIS_NODE, &vtysh_end_all_cmd); +#endif /* HAVE_ISISD */ + + /* fabricd */ +#ifdef HAVE_FABRICD + install_node(&openfabric_node); + install_element(CONFIG_NODE, &router_openfabric_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); - install_element(KEYCHAIN_KEY_NODE, &vtysh_quit_ripd_cmd); - install_element(RMAP_NODE, &vtysh_exit_rmap_cmd); - install_element(RMAP_NODE, &vtysh_quit_rmap_cmd); + install_element(OPENFABRIC_NODE, &vtysh_end_all_cmd); +#endif /* HAVE_FABRICD */ + + /* pbrd */ +#ifdef HAVE_PBRD + install_node(&pbr_map_node); + install_element(CONFIG_NODE, &vtysh_pbr_map_cmd); + install_element(CONFIG_NODE, &vtysh_no_pbr_map_cmd); install_element(PBRMAP_NODE, &vtysh_exit_pbr_map_cmd); install_element(PBRMAP_NODE, &vtysh_quit_pbr_map_cmd); + install_element(PBRMAP_NODE, &vtysh_end_all_cmd); +#endif /* HAVE_PBRD */ + + /* bfdd */ #if HAVE_BFDD > 0 - /* Enter node. */ + install_node(&bfd_node); install_element(CONFIG_NODE, &bfd_enter_cmd); - install_element(BFD_NODE, &bfd_peer_enter_cmd); - install_element(BFD_NODE, &bfd_profile_enter_cmd); - - /* Exit/quit node. */ install_element(BFD_NODE, &vtysh_exit_bfdd_cmd); install_element(BFD_NODE, &vtysh_quit_bfdd_cmd); + install_element(BFD_NODE, &vtysh_end_all_cmd); + + install_node(&bfd_peer_node); + install_element(BFD_NODE, &bfd_peer_enter_cmd); install_element(BFD_PEER_NODE, &vtysh_exit_bfdd_cmd); install_element(BFD_PEER_NODE, &vtysh_quit_bfdd_cmd); + install_element(BFD_PEER_NODE, &vtysh_end_all_cmd); + + install_node(&bfd_profile_node); + install_element(BFD_NODE, &bfd_profile_enter_cmd); install_element(BFD_PROFILE_NODE, &vtysh_exit_bfdd_cmd); install_element(BFD_PROFILE_NODE, &vtysh_quit_bfdd_cmd); - - /* End/exit all. */ - install_element(BFD_NODE, &vtysh_end_all_cmd); - install_element(BFD_PEER_NODE, &vtysh_end_all_cmd); install_element(BFD_PROFILE_NODE, &vtysh_end_all_cmd); #endif /* HAVE_BFDD */ - install_element(VTY_NODE, &vtysh_exit_line_vty_cmd); - install_element(VTY_NODE, &vtysh_quit_line_vty_cmd); - /* "end" command. */ - install_element(CONFIG_NODE, &vtysh_end_all_cmd); - install_element(ENABLE_NODE, &vtysh_end_all_cmd); - install_element(RIP_NODE, &vtysh_end_all_cmd); - install_element(RIPNG_NODE, &vtysh_end_all_cmd); - install_element(OSPF_NODE, &vtysh_end_all_cmd); - install_element(EIGRP_NODE, &vtysh_end_all_cmd); - install_element(BABEL_NODE, &vtysh_end_all_cmd); - install_element(OSPF6_NODE, &vtysh_end_all_cmd); - install_element(LDP_NODE, &vtysh_end_all_cmd); - install_element(LDP_IPV4_NODE, &vtysh_end_all_cmd); - install_element(LDP_IPV6_NODE, &vtysh_end_all_cmd); - install_element(LDP_IPV4_IFACE_NODE, &vtysh_end_all_cmd); - install_element(LDP_IPV6_IFACE_NODE, &vtysh_end_all_cmd); - install_element(LDP_L2VPN_NODE, &vtysh_end_all_cmd); - install_element(LDP_PSEUDOWIRE_NODE, &vtysh_end_all_cmd); - install_element(BGP_NODE, &vtysh_end_all_cmd); - install_element(BGP_IPV4_NODE, &vtysh_end_all_cmd); - install_element(BGP_IPV4M_NODE, &vtysh_end_all_cmd); - install_element(BGP_IPV4L_NODE, &vtysh_end_all_cmd); - install_element(BGP_VPNV4_NODE, &vtysh_end_all_cmd); - install_element(BGP_VPNV6_NODE, &vtysh_end_all_cmd); - install_element(BGP_FLOWSPECV4_NODE, &vtysh_end_all_cmd); - install_element(BGP_FLOWSPECV6_NODE, &vtysh_end_all_cmd); - install_element(BGP_IPV6_NODE, &vtysh_end_all_cmd); - install_element(BGP_IPV6M_NODE, &vtysh_end_all_cmd); - install_element(BGP_IPV6L_NODE, &vtysh_end_all_cmd); - install_element(BGP_VRF_POLICY_NODE, &vtysh_end_all_cmd); - install_element(BGP_EVPN_NODE, &vtysh_end_all_cmd); - install_element(BGP_EVPN_VNI_NODE, &vtysh_end_all_cmd); - install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd); - 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); + /* keychain */ + install_node(&keychain_node); + install_element(CONFIG_NODE, &key_chain_cmd); + install_element(KEYCHAIN_NODE, &key_chain_cmd); + install_element(KEYCHAIN_NODE, &vtysh_exit_keys_cmd); + install_element(KEYCHAIN_NODE, &vtysh_quit_keys_cmd); install_element(KEYCHAIN_NODE, &vtysh_end_all_cmd); + + install_node(&keychain_key_node); + install_element(KEYCHAIN_NODE, &key_cmd); + install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd); + install_element(KEYCHAIN_KEY_NODE, &vtysh_exit_keys_cmd); + install_element(KEYCHAIN_KEY_NODE, &vtysh_quit_keys_cmd); install_element(KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd); - install_element(RMAP_NODE, &vtysh_end_all_cmd); - install_element(PBRMAP_NODE, &vtysh_end_all_cmd); - install_element(VTY_NODE, &vtysh_end_all_cmd); + /* nexthop-group */ + install_node(&nh_group_node); + install_element(CONFIG_NODE, &vtysh_nexthop_group_cmd); + install_element(CONFIG_NODE, &vtysh_no_nexthop_group_cmd); + install_element(NH_GROUP_NODE, &vtysh_end_all_cmd); + install_element(NH_GROUP_NODE, &vtysh_exit_nexthop_group_cmd); + install_element(NH_GROUP_NODE, &vtysh_quit_nexthop_group_cmd); + + /* zebra and all */ + install_node(&zebra_node); + + install_node(&interface_node); + install_element(CONFIG_NODE, &vtysh_interface_cmd); install_element(INTERFACE_NODE, &vtysh_end_all_cmd); install_element(INTERFACE_NODE, &vtysh_exit_interface_cmd); + install_element(INTERFACE_NODE, &vtysh_quit_interface_cmd); + + install_node(&link_params_node); + install_element(INTERFACE_NODE, &vtysh_link_params_cmd); install_element(LINK_PARAMS_NODE, &exit_link_params_cmd); install_element(LINK_PARAMS_NODE, &vtysh_end_all_cmd); install_element(LINK_PARAMS_NODE, &vtysh_exit_interface_cmd); - install_element(INTERFACE_NODE, &vtysh_quit_interface_cmd); + install_node(&pw_node); + install_element(CONFIG_NODE, &vtysh_pseudowire_cmd); install_element(PW_NODE, &vtysh_end_all_cmd); install_element(PW_NODE, &vtysh_exit_interface_cmd); install_element(PW_NODE, &vtysh_quit_interface_cmd); - install_element(CONFIG_NODE, &vtysh_nexthop_group_cmd); - install_element(NH_GROUP_NODE, &vtysh_end_all_cmd); - install_element(NH_GROUP_NODE, &vtysh_exit_nexthop_group_cmd); - install_element(NH_GROUP_NODE, &vtysh_quit_nexthop_group_cmd); - + install_node(&vrf_node); + install_element(CONFIG_NODE, &vtysh_vrf_cmd); + install_element(VRF_NODE, &vtysh_vrf_netns_cmd); + install_element(VRF_NODE, &vtysh_no_vrf_netns_cmd); + install_element(VRF_NODE, &exit_vrf_config_cmd); install_element(VRF_NODE, &vtysh_end_all_cmd); install_element(VRF_NODE, &vtysh_exit_vrf_cmd); install_element(VRF_NODE, &vtysh_quit_vrf_cmd); + + install_node(&rmap_node); + install_element(CONFIG_NODE, &vtysh_route_map_cmd); + install_element(RMAP_NODE, &vtysh_exit_rmap_cmd); + install_element(RMAP_NODE, &vtysh_quit_rmap_cmd); + install_element(RMAP_NODE, &vtysh_end_all_cmd); - install_element(CONFIG_NODE, &router_eigrp_cmd); - install_element(CONFIG_NODE, &router_babel_cmd); - install_element(CONFIG_NODE, &router_rip_cmd); - install_element(CONFIG_NODE, &router_ripng_cmd); - install_element(CONFIG_NODE, &router_ospf_cmd); - install_element(CONFIG_NODE, &router_ospf6_cmd); -#if defined(HAVE_LDPD) - install_element(CONFIG_NODE, &ldp_mpls_ldp_cmd); - install_element(LDP_NODE, &ldp_address_family_ipv4_cmd); - install_element(LDP_NODE, &ldp_address_family_ipv6_cmd); - install_element(LDP_IPV4_NODE, &ldp_interface_ifname_cmd); - install_element(LDP_IPV6_NODE, &ldp_interface_ifname_cmd); - install_element(CONFIG_NODE, &ldp_l2vpn_word_type_vpls_cmd); - 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); -#ifdef KEEP_OLD_VPN_COMMANDS - install_element(BGP_NODE, &address_family_vpnv4_cmd); - install_element(BGP_NODE, &address_family_vpnv6_cmd); -#endif /* KEEP_OLD_VPN_COMMANDS */ -#if defined(ENABLE_BGP_VNC) - install_element(BGP_NODE, &vnc_vrf_policy_cmd); - install_element(BGP_NODE, &vnc_defaults_cmd); - install_element(BGP_NODE, &vnc_nve_group_cmd); - install_element(BGP_NODE, &vnc_l2_group_cmd); -#endif - install_element(BGP_NODE, &address_family_ipv4_cmd); - install_element(BGP_NODE, &address_family_ipv4_multicast_cmd); - install_element(BGP_NODE, &address_family_ipv4_vpn_cmd); - install_element(BGP_NODE, &address_family_ipv4_labeled_unicast_cmd); - install_element(BGP_NODE, &address_family_ipv6_cmd); - install_element(BGP_NODE, &address_family_ipv6_multicast_cmd); - install_element(BGP_NODE, &address_family_ipv6_vpn_cmd); - install_element(BGP_NODE, &address_family_ipv6_labeled_unicast_cmd); - install_element(BGP_NODE, &address_family_evpn_cmd); - install_element(BGP_NODE, &address_family_flowspecv4_cmd); - install_element(BGP_NODE, &address_family_flowspecv6_cmd); -#if defined(HAVE_CUMULUS) - install_element(BGP_NODE, &address_family_evpn2_cmd); -#endif - install_element(BGP_VPNV4_NODE, &exit_address_family_cmd); - install_element(BGP_VPNV6_NODE, &exit_address_family_cmd); - install_element(BGP_IPV4_NODE, &exit_address_family_cmd); - install_element(BGP_IPV4M_NODE, &exit_address_family_cmd); - install_element(BGP_IPV4L_NODE, &exit_address_family_cmd); - install_element(BGP_IPV6_NODE, &exit_address_family_cmd); - install_element(BGP_IPV6M_NODE, &exit_address_family_cmd); - install_element(BGP_EVPN_NODE, &exit_address_family_cmd); - install_element(BGP_IPV6L_NODE, &exit_address_family_cmd); - install_element(BGP_FLOWSPECV4_NODE, &exit_address_family_cmd); - install_element(BGP_FLOWSPECV6_NODE, &exit_address_family_cmd); + install_node(&vty_node); + install_element(CONFIG_NODE, &vtysh_line_vty_cmd); + install_element(VTY_NODE, &vtysh_exit_line_vty_cmd); + install_element(VTY_NODE, &vtysh_quit_line_vty_cmd); + install_element(VTY_NODE, &vtysh_end_all_cmd); - install_element(BGP_NODE, &bmp_targets_cmd); - install_element(BMP_NODE, &bmp_exit_cmd); - install_element(BMP_NODE, &bmp_quit_cmd); - install_element(BMP_NODE, &vtysh_end_all_cmd); - 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); + struct cmd_node *node; + for (unsigned int i = 0; i < vector_active(cmdvec); i++) { + node = vector_slot(cmdvec, i); + if (!node || node->node == VIEW_NODE) + continue; + vtysh_install_default(node->node); + } - /* EVPN commands */ - install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd); - install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd); + /* vtysh */ - install_element(BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); - install_element(BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd); - install_element(BGP_VNC_NVE_GROUP_NODE, &exit_vnc_config_cmd); - install_element(BGP_VNC_L2_GROUP_NODE, &exit_vnc_config_cmd); + install_element(VIEW_NODE, &vtysh_enable_cmd); + install_element(ENABLE_NODE, &vtysh_config_terminal_cmd); + install_element(ENABLE_NODE, &vtysh_disable_cmd); + + /* "exit" command. */ + install_element(VIEW_NODE, &vtysh_exit_all_cmd); + install_element(CONFIG_NODE, &vtysh_exit_all_cmd); + install_element(VIEW_NODE, &vtysh_quit_all_cmd); + install_element(CONFIG_NODE, &vtysh_quit_all_cmd); + + /* "end" command. */ + install_element(CONFIG_NODE, &vtysh_end_all_cmd); + install_element(ENABLE_NODE, &vtysh_end_all_cmd); - install_element(CONFIG_NODE, &key_chain_cmd); - install_element(CONFIG_NODE, &vtysh_route_map_cmd); - install_element(CONFIG_NODE, &vtysh_pbr_map_cmd); - install_element(CONFIG_NODE, &vtysh_no_pbr_map_cmd); - install_element(CONFIG_NODE, &vtysh_line_vty_cmd); - install_element(KEYCHAIN_NODE, &key_cmd); - install_element(KEYCHAIN_NODE, &key_chain_cmd); - install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd); - install_element(CONFIG_NODE, &vtysh_interface_cmd); - install_element(CONFIG_NODE, &vtysh_pseudowire_cmd); - install_element(INTERFACE_NODE, &vtysh_link_params_cmd); install_element(ENABLE_NODE, &vtysh_show_running_config_cmd); install_element(ENABLE_NODE, &vtysh_copy_running_config_cmd); install_element(ENABLE_NODE, &vtysh_copy_to_running_cmd); - install_element(CONFIG_NODE, &vtysh_vrf_cmd); - install_element(VRF_NODE, &vtysh_vrf_netns_cmd); - install_element(VRF_NODE, &vtysh_no_vrf_netns_cmd); - install_element(VRF_NODE, &exit_vrf_config_cmd); - - install_element(CONFIG_NODE, &vtysh_no_nexthop_group_cmd); - /* "write terminal" command. */ install_element(ENABLE_NODE, &vtysh_write_terminal_cmd); diff --git a/yang/frr-bfdd.yang b/yang/frr-bfdd.yang index 4b7785e690..5b434162d0 100644 --- a/yang/frr-bfdd.yang +++ b/yang/frr-bfdd.yang @@ -12,6 +12,9 @@ module frr-bfdd { import frr-interface { prefix frr-interface; } + import frr-vrf { + prefix frr-vrf; + } import frr-route-types { prefix frr-route-types; } @@ -396,14 +399,12 @@ module frr-bfdd { } leaf interface { - type string { - length "0..16"; - } + type frr-interface:interface-ref; description "Interface to use to contact peer"; } leaf vrf { - type string; + type frr-vrf:vrf-ref; description "Virtual Routing Domain name"; } @@ -441,14 +442,12 @@ module frr-bfdd { } leaf interface { - type string { - length "0..16"; - } + type frr-interface:interface-ref; description "Interface to use to contact peer"; } leaf vrf { - type string; + type frr-vrf:vrf-ref; description "Virtual Routing Domain name"; } diff --git a/yang/frr-bgp-common-structure.yang b/yang/frr-bgp-common-structure.yang index 8162527e90..6543b1d1c3 100644 --- a/yang/frr-bgp-common-structure.yang +++ b/yang/frr-bgp-common-structure.yang @@ -9,6 +9,10 @@ submodule frr-bgp-common-structure { prefix inet; } + import frr-route-map { + prefix frr-route-map; + } + import frr-interface { prefix frr-interface; } @@ -371,7 +375,7 @@ submodule frr-bgp-common-structure { } leaf rmap-policy-export { - type frr-bt:rmap-ref; + type frr-route-map:route-map-ref; description "Route-map to specify criteria to originate default."; } diff --git a/yang/frr-bgp-common.yang b/yang/frr-bgp-common.yang index 188cf856db..96ec9dc969 100644 --- a/yang/frr-bgp-common.yang +++ b/yang/frr-bgp-common.yang @@ -17,6 +17,10 @@ submodule frr-bgp-common { prefix frr-bt; } + import frr-route-map { + prefix frr-route-map; + } + import frr-route-types { prefix frr-rt-type; } @@ -73,25 +77,25 @@ submodule frr-bgp-common { grouping rmap-policy-import { leaf rmap-import { - type frr-bt:rmap-ref; + type frr-route-map:route-map-ref; } } grouping rmap-policy-export { leaf rmap-export { - type frr-bt:rmap-ref; + type frr-route-map:route-map-ref; } } grouping unsupress-map-policy-import { leaf unsupress-map-import { - type frr-bt:rmap-ref; + type frr-route-map:route-map-ref; } } grouping unsupress-map-policy-export { leaf unsupress-map-export { - type frr-bt:rmap-ref; + type frr-route-map:route-map-ref; } } @@ -728,7 +732,7 @@ submodule frr-bgp-common { } leaf rmap-policy-import { - type frr-bt:rmap-ref; + type frr-route-map:route-map-ref; description "Route-map to be applied for redistributed routes into the bgp."; } @@ -743,7 +747,7 @@ submodule frr-bgp-common { } leaf rmap-policy-export { - type frr-bt:rmap-ref; + type frr-route-map:route-map-ref; description "Route-map to modify the attributes for Routes going out via BGP updates."; @@ -771,7 +775,7 @@ submodule frr-bgp-common { } leaf rmap-policy-export { - type frr-bt:rmap-ref; + type frr-route-map:route-map-ref; description "Apply route map to aggregate network."; } @@ -1097,7 +1101,7 @@ submodule frr-bgp-common { } leaf rmap-policy-export { - type frr-bt:rmap-ref; + type frr-route-map:route-map-ref; description "Route-map to modify the attributes for Routes going out via BGP updates."; diff --git a/yang/frr-bgp-types.yang b/yang/frr-bgp-types.yang index 0afdea1ba6..55834df2ee 100644 --- a/yang/frr-bgp-types.yang +++ b/yang/frr-bgp-types.yang @@ -41,10 +41,6 @@ module frr-bgp-types { "Initial revision."; } - typedef rmap-ref { - type string; - } - typedef plist-ref { type string; } diff --git a/yang/frr-eigrpd.yang b/yang/frr-eigrpd.yang index 3d1bf3baa5..2127ac4988 100644 --- a/yang/frr-eigrpd.yang +++ b/yang/frr-eigrpd.yang @@ -12,6 +12,12 @@ module frr-eigrpd { import frr-interface { prefix frr-interface; } + import frr-vrf { + prefix frr-vrf; + } + import frr-route-map { + prefix frr-route-map; + } import frr-route-types { prefix frr-route-types; } @@ -109,9 +115,7 @@ module frr-eigrpd { leaf vrf { description "Virtual Routing Domain name"; - type string { - length "0..16"; - } + type frr-vrf:vrf-ref; } /* @@ -235,9 +239,7 @@ module frr-eigrpd { "Applies the conditions of the specified route-map to routes that are redistributed into the EIGRP routing instance"; - type string { - length "1..max"; - } + type frr-route-map:route-map-ref; } container metrics { diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index cc959bd9fe..79941a50e7 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -15,6 +15,14 @@ module frr-isisd { prefix frr-interface; } + import frr-vrf { + prefix frr-vrf; + } + + import frr-route-map { + prefix frr-route-map; + } + import frr-route-types { prefix frr-route-types; } @@ -240,9 +248,7 @@ module frr-isisd { description "Common optional attributes of any redistribute entry."; leaf route-map { - type string { - length "1..max"; - } + type frr-route-map:route-map-ref; description "Applies the conditions of the specified route-map to routes that are redistributed into this routing instance."; @@ -341,7 +347,7 @@ module frr-isisd { } leaf vrf { - type string; + type frr-vrf:vrf-ref; default "default"; description "VRF NAME."; @@ -830,7 +836,7 @@ module frr-isisd { } leaf vrf { - type string; + type frr-vrf:vrf-ref; description "VRF NAME."; } diff --git a/yang/frr-nexthop.yang b/yang/frr-nexthop.yang index 0cb0f93ee4..52155dcd16 100644 --- a/yang/frr-nexthop.yang +++ b/yang/frr-nexthop.yang @@ -156,7 +156,7 @@ module frr-nexthop { } leaf vrf { - type string; + type frr-vrf:vrf-ref; description "The nexthop vrf name, if different from the route."; } @@ -167,7 +167,7 @@ module frr-nexthop { } leaf interface { - type string; + type frr-interface:interface-ref; description "The nexthop egress interface."; } @@ -275,7 +275,7 @@ module frr-nexthop { description "List of nexthop groups, each contains group of nexthops"; leaf name { - type string; + type nexthop-group-ref; description "The nexthop-group name."; } diff --git a/yang/frr-ospfd.yang b/yang/frr-ospfd.yang index 466dd42ce4..42a7e8784c 100644 --- a/yang/frr-ospfd.yang +++ b/yang/frr-ospfd.yang @@ -15,6 +15,10 @@ module frr-ospfd { prefix frr-interface; } + import frr-route-map { + prefix frr-route-map; + } + import frr-route-types { prefix frr-route-types; } @@ -41,10 +45,6 @@ module frr-ospfd { } /* Policy types to be removed later, once policy Yang finalized */ - typedef rmap-ref { - type string; - } - typedef plist-ref { type string; } @@ -425,7 +425,7 @@ module frr-ospfd { } leaf route-map { - type rmap-ref; + type frr-route-map:route-map-ref; description "Route map reference."; } diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang index f5775ab968..929c916069 100644 --- a/yang/frr-ripd.yang +++ b/yang/frr-ripd.yang @@ -12,6 +12,12 @@ module frr-ripd { import frr-interface { prefix frr-interface; } + import frr-vrf { + prefix frr-vrf; + } + import frr-route-map { + prefix frr-route-map; + } import frr-route-types { prefix frr-route-types; } @@ -72,7 +78,7 @@ module frr-ripd { "RIP routing instance."; leaf vrf { - type string; + type frr-vrf:vrf-ref; description "VRF name."; } @@ -227,9 +233,7 @@ module frr-ripd { must '. != "rip"'; } leaf route-map { - type string { - length "1..max"; - } + type frr-route-map:route-map-ref; description "Applies the conditions of the specified route-map to routes that are redistributed into the RIP routing @@ -396,7 +400,7 @@ module frr-ripd { "Next hop IPv4 address."; } leaf interface { - type string; + type frr-interface:interface-ref; description "The interface that the route uses."; } @@ -587,7 +591,7 @@ module frr-ripd { input { leaf vrf { - type string; + type frr-vrf:vrf-ref; description "VRF name identifying a specific RIP instance. This leaf is optional for the rpc. @@ -608,7 +612,7 @@ module frr-ripd { receives a PDU with the wrong authentication type field."; leaf interface-name { - type string; + type frr-interface:interface-ref; description "Describes the name of the RIP interface."; } @@ -624,7 +628,7 @@ module frr-ripd { receives a PDU with the wrong authentication information."; leaf interface-name { - type string; + type frr-interface:interface-ref; description "Describes the name of the RIP interface."; } diff --git a/yang/frr-ripngd.yang b/yang/frr-ripngd.yang index 52e208b2c9..07d38bd416 100644 --- a/yang/frr-ripngd.yang +++ b/yang/frr-ripngd.yang @@ -12,6 +12,12 @@ module frr-ripngd { import frr-interface { prefix frr-interface; } + import frr-vrf { + prefix frr-vrf; + } + import frr-route-map { + prefix frr-route-map; + } import frr-route-types { prefix frr-route-types; } @@ -71,7 +77,7 @@ module frr-ripngd { "RIPng routing instance."; leaf vrf { - type string; + type frr-vrf:vrf-ref; description "VRF name."; } @@ -170,9 +176,7 @@ module frr-ripngd { must '. != "ripng"'; } leaf route-map { - type string { - length "1..max"; - } + type frr-route-map:route-map-ref; description "Applies the conditions of the specified route-map to routes that are redistributed into the RIPng routing @@ -298,7 +302,7 @@ module frr-ripngd { "Next hop IPv6 address."; } leaf interface { - type string; + type frr-interface:interface-ref; description "The interface that the route uses."; } @@ -359,7 +363,7 @@ module frr-ripngd { input { leaf vrf { - type string; + type frr-vrf:vrf-ref; description "VRF name identifying a specific RIPng instance. This leaf is optional for the rpc. diff --git a/yang/frr-routing.yang b/yang/frr-routing.yang index 52607f9ad0..f8441669af 100644 --- a/yang/frr-routing.yang +++ b/yang/frr-routing.yang @@ -249,7 +249,7 @@ module frr-routing { instance."; } leaf vrf { - type string; + type frr-vrf:vrf-ref; description "vrf for control-plane protocol"; } diff --git a/yang/frr-test-module.yang b/yang/frr-test-module.yang index 61915b1349..2f89ebca88 100644 --- a/yang/frr-test-module.yang +++ b/yang/frr-test-module.yang @@ -57,7 +57,7 @@ module frr-test-module { } container interfaces { leaf-list interface { - type string; + type frr-interface:interface-ref; } } container routes { @@ -69,7 +69,7 @@ module frr-test-module { type inet:ipv4-address; } leaf interface { - type string; + type frr-interface:interface-ref; } leaf metric { type uint8; diff --git a/yang/frr-zebra.yang b/yang/frr-zebra.yang index 2efc45c146..782e0a4b74 100644 --- a/yang/frr-zebra.yang +++ b/yang/frr-zebra.yang @@ -2137,7 +2137,7 @@ module frr-zebra { "The admin distance to use for imported routes."; } leaf route-map { - type string; + type frr-route-map:route-map-ref; description "A route-map to filter imported routes."; } diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c deleted file mode 100644 index 2a2504ebf8..0000000000 --- a/zebra/if_ioctl_solaris.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Interface looking up by ioctl () on Solaris. - * Copyright (C) 1997, 98 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra 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. - * - * GNU Zebra 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> - -#ifdef SUNOS_5 - -#include "if.h" -#include "sockunion.h" -#include "prefix.h" -#include "ioctl.h" -#include "connected.h" -#include "memory.h" -#include "zebra_memory.h" -#include "log.h" -#include "privs.h" -#include "vrf.h" -#include "vty.h" -#include "lib_errors.h" - -#include "zebra/interface.h" -#include "zebra/ioctl_solaris.h" -#include "zebra/rib.h" -#include "zebra/rt.h" -#include "zebra/zebra_errors.h" - -static int if_get_addr(struct interface *, struct sockaddr *, const char *); -static void interface_info_ioctl(struct interface *); -extern struct zebra_privs_t zserv_privs; - -static int interface_list_ioctl(int af) -{ - int ret; - int sock; -#define IFNUM_BASE 32 - struct lifnum lifn; - int ifnum; - struct lifreq *lifreq; - struct lifconf lifconf; - struct interface *ifp; - int n; - size_t needed, lastneeded = 0; - char *buf = NULL; - - frr_with_privs(&zserv_privs) { - sock = socket(af, SOCK_DGRAM, 0); - } - - if (sock < 0) { - flog_err_sys(EC_LIB_SOCKET, "Can't make %s socket stream: %s", - (af == AF_INET ? "AF_INET" : "AF_INET6"), - safe_strerror(errno)); - return -1; - } - -calculate_lifc_len: - frr_with_privs(&zserv_privs) { - lifn.lifn_family = af; - lifn.lifn_flags = LIFC_NOXMIT; - /* we want NOXMIT interfaces too */ - ret = ioctl(sock, SIOCGLIFNUM, &lifn); - } - - if (ret < 0) { - flog_err_sys(EC_LIB_SYSTEM_CALL, - "interface_list_ioctl: SIOCGLIFNUM failed %s", - safe_strerror(errno)); - close(sock); - return -1; - } - ifnum = lifn.lifn_count; - - /* - * When calculating the buffer size needed, add a small number - * of interfaces to those we counted. We do this to capture - * the interface status of potential interfaces which may have - * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF. - */ - needed = (ifnum + 4) * sizeof(struct lifreq); - if (needed > lastneeded || needed < lastneeded / 2) { - if (buf != NULL) - XFREE(MTYPE_TMP, buf); - buf = XMALLOC(MTYPE_TMP, needed); - } - lastneeded = needed; - - lifconf.lifc_family = af; - lifconf.lifc_flags = LIFC_NOXMIT; - lifconf.lifc_len = needed; - lifconf.lifc_buf = buf; - - frr_with_privs(&zserv_privs) { - ret = ioctl(sock, SIOCGLIFCONF, &lifconf); - } - - if (ret < 0) { - if (errno == EINVAL) - goto calculate_lifc_len; - - flog_err_sys(EC_LIB_SYSTEM_CALL, "SIOCGLIFCONF: %s", - safe_strerror(errno)); - goto end; - } - - /* Allocate interface. */ - lifreq = lifconf.lifc_req; - - for (n = 0; n < lifconf.lifc_len; n += sizeof(struct lifreq)) { - /* we treat Solaris logical interfaces as addresses, because - * that is - * how PF_ROUTE on Solaris treats them. Hence we can not - * directly use - * the lifreq_name to get the ifp. We need to normalise the - * name - * before attempting get. - * - * Solaris logical interface names are in the form of: - * <interface name>:<logical interface id> - */ - unsigned int normallen = 0; - uint64_t lifflags; - - /* We should exclude ~IFF_UP interfaces, as we'll find out about - * them - * coming up later through RTM_NEWADDR message on the route - * socket. - */ - if (if_get_flags_direct(lifreq->lifr_name, &lifflags, - lifreq->lifr_addr.ss_family) - || !CHECK_FLAG(lifflags, IFF_UP)) { - lifreq++; - continue; - } - - /* Find the normalised name */ - while ((normallen < sizeof(lifreq->lifr_name)) - && (*(lifreq->lifr_name + normallen) != '\0') - && (*(lifreq->lifr_name + normallen) != ':')) - normallen++; - - ifp = if_get_by_name(lifreq->lifr_name, VRF_DEFAULT); - - if (lifreq->lifr_addr.ss_family == AF_INET) - ifp->flags |= IFF_IPV4; - - if (lifreq->lifr_addr.ss_family == AF_INET6) { - ifp->flags |= IFF_IPV6; - } - - if_add_update(ifp); - - interface_info_ioctl(ifp); - - /* If a logical interface pass the full name so it can be - * as a label on the address - */ - if (*(lifreq->lifr_name + normallen) != '\0') - if_get_addr(ifp, (struct sockaddr *)&lifreq->lifr_addr, - lifreq->lifr_name); - else - if_get_addr(ifp, (struct sockaddr *)&lifreq->lifr_addr, - NULL); - - /* Poke the interface flags. Lets IFF_UP mangling kick in */ - if_flags_update(ifp, ifp->flags); - - lifreq++; - } - -end: - close(sock); - XFREE(MTYPE_TMP, lifconf.lifc_buf); - return ret; -} - -/* Get interface's index by ioctl. */ -static int if_get_index(struct interface *ifp) -{ - int ret; - struct lifreq lifreq; - - lifreq_set_name(&lifreq, ifp->name); - - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL(AF_INET, SIOCGLIFINDEX, (caddr_t)&lifreq); - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL(AF_INET6, SIOCGLIFINDEX, (caddr_t)&lifreq); - else - ret = -1; - - if (ret < 0) { - flog_err_sys(EC_LIB_SYSTEM_CALL, "SIOCGLIFINDEX(%s) failed", - ifp->name); - return ret; - } - -/* OK we got interface index. */ -#ifdef ifr_ifindex - if_set_index(ifp, lifreq.lifr_ifindex); -#else - if_set_index(ifp, lifreq.lifr_index); -#endif - return ifp->ifindex; -} - - -/* Interface address lookup by ioctl. This function only looks up - IPv4 address. */ -#define ADDRLEN(sa) \ - (((sa)->sa_family == AF_INET ? sizeof(struct sockaddr_in) \ - : sizeof(struct sockaddr_in6))) - -#define SIN(s) ((struct sockaddr_in *)(s)) -#define SIN6(s) ((struct sockaddr_in6 *)(s)) - -/* Retrieve address information for the given ifp */ -static int if_get_addr(struct interface *ifp, struct sockaddr *addr, - const char *label) -{ - int ret; - struct lifreq lifreq; - struct sockaddr_storage mask, dest; - char *dest_pnt = NULL; - uint8_t prefixlen = 0; - afi_t af; - int flags = 0; - - /* Interface's name and address family. - * We need to use the logical interface name / label, if we've been - * given one, in order to get the right address - */ - strlcpy(lifreq.lifr_name, (label ? label : ifp->name), - sizeof(lifreq.lifr_name)); - - /* Interface's address. */ - memcpy(&lifreq.lifr_addr, addr, ADDRLEN(addr)); - af = addr->sa_family; - - /* Point to point or broad cast address pointer init. */ - dest_pnt = NULL; - - if (AF_IOCTL(af, SIOCGLIFDSTADDR, (caddr_t)&lifreq) >= 0) { - memcpy(&dest, &lifreq.lifr_dstaddr, ADDRLEN(addr)); - if (af == AF_INET) - dest_pnt = (char *)&(SIN(&dest)->sin_addr); - else - dest_pnt = (char *)&(SIN6(&dest)->sin6_addr); - flags = ZEBRA_IFA_PEER; - } - - if (af == AF_INET) { - ret = if_ioctl(SIOCGLIFNETMASK, (caddr_t)&lifreq); - - if (ret < 0) { - if (errno != EADDRNOTAVAIL) { - flog_err_sys(EC_LIB_SYSTEM_CALL, - "SIOCGLIFNETMASK (%s) fail: %s", - ifp->name, safe_strerror(errno)); - return ret; - } - return 0; - } - memcpy(&mask, &lifreq.lifr_addr, ADDRLEN(addr)); - - prefixlen = ip_masklen(SIN(&mask)->sin_addr); - if (!dest_pnt - && (if_ioctl(SIOCGLIFBRDADDR, (caddr_t)&lifreq) >= 0)) { - memcpy(&dest, &lifreq.lifr_broadaddr, - sizeof(struct sockaddr_in)); - dest_pnt = (char *)&SIN(&dest)->sin_addr; - } - } else if (af == AF_INET6) { - if (if_ioctl_ipv6(SIOCGLIFSUBNET, (caddr_t)&lifreq) < 0) { - if (ifp->flags & IFF_POINTOPOINT) - prefixlen = IPV6_MAX_BITLEN; - else - flog_err_sys(EC_LIB_SYSTEM_CALL, - "SIOCGLIFSUBNET (%s) fail: %s", - ifp->name, safe_strerror(errno)); - } else { - prefixlen = lifreq.lifr_addrlen; - } - } - - /* Set address to the interface. */ - if (af == AF_INET) - connected_add_ipv4(ifp, flags, &SIN(addr)->sin_addr, prefixlen, - (struct in_addr *)dest_pnt, label, - METRIC_MAX); - else if (af == AF_INET6) - connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr, NULL, - prefixlen, label, METRIC_MAX); - - return 0; -} - -/* Fetch interface information via ioctl(). */ -static void interface_info_ioctl(struct interface *ifp) -{ - if_get_index(ifp); - if_get_flags(ifp); - if_get_mtu(ifp); - if_get_metric(ifp); -} - -/* Lookup all interface information. */ -void interface_list(struct zebra_ns *zns) -{ - if (zns->ns_id != NS_DEFAULT) { - zlog_debug("interface_list: ignore NS %u", zns->ns_id); - return; - } - interface_list_ioctl(AF_INET); - interface_list_ioctl(AF_INET6); - interface_list_ioctl(AF_UNSPEC); -} - -struct connected *if_lookup_linklocal(struct interface *ifp) -{ - struct listnode *node; - struct connected *ifc; - - if (ifp == NULL) - return NULL; - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { - if ((ifc->address->family == AF_INET6) - && (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6))) - return ifc; - } - - return NULL; -} - -#endif /* SUNOS_5 */ diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c index 44afd266bc..695cef1995 100644 --- a/zebra/if_sysctl.c +++ b/zebra/if_sysctl.c @@ -21,7 +21,7 @@ #include <zebra.h> -#if !defined(GNU_LINUX) && !defined(OPEN_BSD) && !defined(SUNOS_5) +#if !defined(GNU_LINUX) && !defined(OPEN_BSD) #include "if.h" #include "sockunion.h" @@ -144,4 +144,4 @@ void interface_list(struct zebra_ns *zns) XFREE(MTYPE_TMP, ref); } -#endif /* !defined(GNU_LINUX) && !defined(OPEN_BSD) && !defined(SUNOS_5) */ +#endif /* !defined(GNU_LINUX) && !defined(OPEN_BSD) */ diff --git a/zebra/interface.c b/zebra/interface.c index d29f61450e..3210855801 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -464,17 +464,7 @@ int if_subnet_delete(struct interface *ifp, struct connected *ifc) */ static void if_flags_mangle(struct interface *ifp, uint64_t *newflags) { -#ifdef SUNOS_5 - struct zebra_if *zif = ifp->info; - - zif->primary_state = *newflags & (IFF_UP & 0xff); - - if (CHECK_FLAG(zif->primary_state, IFF_UP) - || listcount(ifp->connected) > 0) - SET_FLAG(*newflags, IFF_UP); - else - UNSET_FLAG(*newflags, IFF_UP); -#endif /* SUNOS_5 */ + return; } /* Update the flags field of the ifp with the new flag set provided. diff --git a/zebra/interface.h b/zebra/interface.h index 1a8e3caed5..626225836e 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -334,15 +334,6 @@ struct zebra_if { }; #endif -#ifdef SUNOS_5 - /* the real IFF_UP state of the primary interface. - * need this to differentiate between all interfaces being - * down (but primary still plumbed) and primary having gone - * ~IFF_UP, and all addresses gone. - */ - uint8_t primary_state; -#endif /* SUNOS_5 */ - /* ptm enable configuration */ uint8_t ptm_enable; diff --git a/zebra/ioctl.c b/zebra/ioctl.c index b461a08881..11b252fc18 100644 --- a/zebra/ioctl.c +++ b/zebra/ioctl.c @@ -36,8 +36,6 @@ #include "zebra/zebra_errors.h" #include "zebra/debug.h" -#ifndef SUNOS_5 - #ifdef HAVE_BSD_LINK_DETECT #include <net/if_media.h> #endif /* HAVE_BSD_LINK_DETECT*/ @@ -166,11 +164,7 @@ void if_get_mtu(struct interface *ifp) return; } -#ifdef SUNOS_5 - ifp->mtu6 = ifp->mtu = ifreq.ifr_metric; -#else ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu; -#endif /* SUNOS_5 */ /* propogate */ zebra_interface_up_update(ifp); @@ -378,11 +372,7 @@ int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx) } mask.sin_family = p->family; -#ifdef SUNOS_5 - memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); -#else memcpy(&ifreq.ifr_addr, &mask, sizeof(struct sockaddr_in)); -#endif /* SUNOS5 */ ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); if (ret < 0) return ret; @@ -620,5 +610,3 @@ static int if_unset_prefix6_ctx(const struct zebra_dplane_ctx *ctx) #endif /* HAVE_STRUCT_IN6_ALIASREQ */ #endif /* LINUX_IPV6 */ - -#endif /* !SUNOS_5 */ diff --git a/zebra/ioctl.h b/zebra/ioctl.h index 03f3911d52..debe5ba1ca 100644 --- a/zebra/ioctl.h +++ b/zebra/ioctl.h @@ -38,19 +38,8 @@ extern void if_get_flags(struct interface *); extern void if_get_metric(struct interface *); extern void if_get_mtu(struct interface *); -#ifdef SOLARIS_IPV6 -extern int if_ioctl_ipv6(unsigned long, caddr_t); -extern struct connected *if_lookup_linklocal(struct interface *); - -#define AF_IOCTL(af, request, buffer) \ - ((af) == AF_INET ? if_ioctl(request, buffer) \ - : if_ioctl_ipv6(request, buffer)) -#else /* SOLARIS_IPV6 */ - #define AF_IOCTL(af, request, buffer) if_ioctl(request, buffer) -#endif /* SOLARIS_IPV6 */ - #ifdef __cplusplus } #endif diff --git a/zebra/ioctl_solaris.c b/zebra/ioctl_solaris.c deleted file mode 100644 index 2c71d949f7..0000000000 --- a/zebra/ioctl_solaris.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Common ioctl functions for Solaris. - * Copyright (C) 1997, 98 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra 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. - * - * GNU Zebra 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> - -#ifdef SUNOS_5 - -#include "linklist.h" -#include "if.h" -#include "prefix.h" -#include "ioctl.h" -#include "log.h" -#include "privs.h" -#include "vty.h" -#include "vrf.h" -#include "lib_errors.h" - -#include "zebra/rib.h" -#include "zebra/rt.h" -#include "zebra/interface.h" -#include "zebra/ioctl_solaris.h" -#include "zebra/zebra_errors.h" -#include "zebra/debug.h" - -extern struct zebra_privs_t zserv_privs; - -/* Prototypes */ -static int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx); -static int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx); -static int if_set_prefix6_ctx(const struct zebra_dplane_ctx *ctx); -static int if_unset_prefix6_ctx(const struct zebra_dplane_ctx *ctx); - -/* clear and set interface name string */ -void lifreq_set_name(struct lifreq *lifreq, const char *ifname) -{ - strlcpy(lifreq->lifr_name, ifname, sizeof(lifreq->lifr_name)); -} - -int vrf_if_ioctl(unsigned long request, caddr_t buffer, vrf_id_t vrf_id) -{ - return if_ioctl(request, buffer); -} - -/* call ioctl system call */ -int if_ioctl(unsigned long request, caddr_t buffer) -{ - int sock; - int ret; - int err; - - frr_with_privs(&zserv_privs) { - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - zlog_err("Cannot create UDP socket: %s", - safe_strerror(errno)); - exit(1); - } - - if ((ret = ioctl(sock, request, buffer)) < 0) - err = errno; - - } - - close(sock); - - if (ret < 0) { - errno = err; - return ret; - } - return 0; -} - - -int if_ioctl_ipv6(unsigned long request, caddr_t buffer) -{ - int sock; - int ret; - int err; - - frr_with_privs(&zserv_privs) { - - sock = socket(AF_INET6, SOCK_DGRAM, 0); - if (sock < 0) { - zlog_err("Cannot create IPv6 datagram socket: %s", - safe_strerror(errno)); - exit(1); - } - - if ((ret = ioctl(sock, request, buffer)) < 0) - err = errno; - - } - - close(sock); - - if (ret < 0) { - errno = err; - return ret; - } - - return 0; -} - -/* - * get interface metric - * -- if value is not avaliable set -1 - */ -void if_get_metric(struct interface *ifp) -{ - struct lifreq lifreq; - int ret; - - lifreq_set_name(&lifreq, ifp->name); - - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL(AF_INET, SIOCGLIFMETRIC, (caddr_t)&lifreq); -#ifdef SOLARIS_IPV6 - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL(AF_INET6, SIOCGLIFMETRIC, (caddr_t)&lifreq); -#endif /* SOLARIS_IPV6 */ - else - ret = -1; - - if (ret < 0) - return; - - ifp->metric = lifreq.lifr_metric; - - if (ifp->metric == 0) - ifp->metric = 1; -} - -/* get interface MTU */ -void if_get_mtu(struct interface *ifp) -{ - struct lifreq lifreq; - int ret; - uint8_t changed = 0; - - if (ifp->flags & IFF_IPV4) { - lifreq_set_name(&lifreq, ifp->name); - ret = AF_IOCTL(AF_INET, SIOCGLIFMTU, (caddr_t)&lifreq); - if (ret < 0) { - zlog_info( - "Can't lookup mtu on %s by ioctl(SIOCGLIFMTU)", - ifp->name); - ifp->mtu = -1; - } else { - ifp->mtu = lifreq.lifr_metric; - changed = 1; - } - } - - if (ifp->flags & IFF_IPV6) { - memset(&lifreq, 0, sizeof(lifreq)); - lifreq_set_name(&lifreq, ifp->name); - - ret = AF_IOCTL(AF_INET6, SIOCGLIFMTU, (caddr_t)&lifreq); - if (ret < 0) { - zlog_info( - "Can't lookup mtu6 on %s by ioctl(SIOCGIFMTU)", - ifp->name); - ifp->mtu6 = -1; - } else { - ifp->mtu6 = lifreq.lifr_metric; - changed = 1; - } - } - - if (changed) - zebra_interface_up_update(ifp); -} - -/* - * - */ -enum zebra_dplane_result kernel_address_update_ctx( - struct zebra_dplane_ctx *ctx) -{ - int ret = -1; - const struct prefix *p; - - p = dplane_ctx_get_intf_addr(ctx); - - if (dplane_ctx_get_op(ctx) == DPLANE_OP_ADDR_INSTALL) { - if (p->family == AF_INET) - ret = if_set_prefix_ctx(ctx); - else - ret = if_set_prefix6_ctx(ctx); - } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ADDR_UNINSTALL) { - if (p->family == AF_INET) - ret = if_unset_prefix_ctx(ctx); - else - ret = if_unset_prefix6_ctx(ctx); - } else { - if (IS_ZEBRA_DEBUG_DPLANE) - zlog_debug("Invalid op in interface-addr install"); - } - - return (ret == 0 ? - ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE); -} - -/* Set up interface's address, netmask (and broadcast? ). - Solaris uses ifname:number semantics to set IP address aliases. */ -static int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx) -{ - int ret; - struct ifreq ifreq; - struct sockaddr_in addr, broad, mask; - struct prefix_ipv4 ifaddr; - struct prefix_ipv4 *p; - - p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx); - - ifaddr = *p; - - strlcpy(ifreq.ifr_name, dplane_ctx_get_ifname(ctx), - sizeof(ifreq.ifr_name)); - - addr.sin_addr = p->prefix; - addr.sin_family = p->family; - memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); - - ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); - - if (ret < 0) - return ret; - - /* We need mask for make broadcast addr. */ - masklen2ip(p->prefixlen, &mask.sin_addr); - - if (dplane_ctx_intf_is_broadcast(ctx)) { - apply_mask_ipv4(&ifaddr); - addr.sin_addr = ifaddr.prefix; - - broad.sin_addr.s_addr = - (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); - broad.sin_family = p->family; - - memcpy(&ifreq.ifr_broadaddr, &broad, - sizeof(struct sockaddr_in)); - ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq); - if (ret < 0) - return ret; - } - - mask.sin_family = p->family; -#ifdef SUNOS_5 - memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); -#else - memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in)); -#endif /* SUNOS_5 */ - ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); - - return ((ret < 0) ? ret : 0); -} - -/* Set up interface's address, netmask (and broadcast). - Solaris uses ifname:number semantics to set IP address aliases. */ -static int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx) -{ - int ret; - struct ifreq ifreq; - struct sockaddr_in addr; - struct prefix_ipv4 *p; - - p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx); - - strlcpy(ifreq.ifr_name, dplane_ctx_get_ifname(ctx), - sizeof(ifreq.ifr_name)); - - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = p->family; - memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); - - ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); - - if (ret < 0) - return ret; - - return 0; -} - -/* Get just the flags for the given name. - * Used by the normal 'if_get_flags' function, as well - * as the bootup interface-list code, which has to peek at per-address - * flags in order to figure out which ones should be ignored.. - */ -int if_get_flags_direct(const char *ifname, uint64_t *flags, unsigned int af) -{ - struct lifreq lifreq; - int ret; - - lifreq_set_name(&lifreq, ifname); - - ret = AF_IOCTL(af, SIOCGLIFFLAGS, (caddr_t)&lifreq); - - if (ret) - zlog_debug("%s: ifname %s, error %s (%d)", __func__, ifname, - safe_strerror(errno), errno); - - *flags = lifreq.lifr_flags; - - return ret; -} - -/* get interface flags */ -void if_get_flags(struct interface *ifp) -{ - int ret4 = 0, ret6 = 0; - uint64_t newflags = 0; - uint64_t tmpflags; - - if (ifp->flags & IFF_IPV4) { - ret4 = if_get_flags_direct(ifp->name, &tmpflags, AF_INET); - - if (!ret4) - newflags |= tmpflags; - else if (errno == ENXIO) { - /* it's gone */ - UNSET_FLAG(ifp->flags, IFF_UP); - if_flags_update(ifp, ifp->flags); - } - } - - if (ifp->flags & IFF_IPV6) { - ret6 = if_get_flags_direct(ifp->name, &tmpflags, AF_INET6); - - if (!ret6) - newflags |= tmpflags; - else if (errno == ENXIO) { - /* it's gone */ - UNSET_FLAG(ifp->flags, IFF_UP); - if_flags_update(ifp, ifp->flags); - } - } - - /* only update flags if one of above succeeded */ - if (!(ret4 && ret6)) - if_flags_update(ifp, newflags); -} - -/* Set interface flags */ -int if_set_flags(struct interface *ifp, uint64_t flags) -{ - int ret; - struct lifreq lifreq; - - lifreq_set_name(&lifreq, ifp->name); - - lifreq.lifr_flags = ifp->flags; - lifreq.lifr_flags |= flags; - - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL(AF_INET, SIOCSLIFFLAGS, (caddr_t)&lifreq); - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL(AF_INET6, SIOCSLIFFLAGS, (caddr_t)&lifreq); - else - ret = -1; - - if (ret < 0) - zlog_info("can't set interface flags on %s: %s", ifp->name, - safe_strerror(errno)); - else - ret = 0; - - return ret; -} - -/* Unset interface's flag. */ -int if_unset_flags(struct interface *ifp, uint64_t flags) -{ - int ret; - struct lifreq lifreq; - - lifreq_set_name(&lifreq, ifp->name); - - lifreq.lifr_flags = ifp->flags; - lifreq.lifr_flags &= ~flags; - - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL(AF_INET, SIOCSLIFFLAGS, (caddr_t)&lifreq); - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL(AF_INET6, SIOCSLIFFLAGS, (caddr_t)&lifreq); - else - ret = -1; - - if (ret < 0) - zlog_info("can't unset interface flags"); - else - ret = 0; - - return ret; -} - -/* Interface's address add/delete functions. */ -static int if_set_prefix6_ctx(const struct zebra_dplane_ctx *ctx) -{ - char addrbuf[PREFIX_STRLEN]; - - prefix2str(dplane_ctx_get_intf_addr(ctx), addrbuf, sizeof(addrbuf)); - - flog_warn(EC_LIB_DEVELOPMENT, "Can't set %s on interface %s", - addrbuf, dplane_ctx_get_ifname(ctx)); - - return 0; -} - -static int if_unset_prefix6_ctx(const struct zebra_dplane_ctx *ctx) -{ - char addrbuf[PREFIX_STRLEN]; - - prefix2str(dplane_ctx_get_intf_addr(ctx), addrbuf, sizeof(addrbuf)); - - flog_warn(EC_LIB_DEVELOPMENT, "Can't delete %s on interface %s", - addrbuf, dplane_ctx_get_ifname(ctx)); - - return 0; -} - -#endif /* SUNOS_5 */ diff --git a/zebra/ioctl_solaris.h b/zebra/ioctl_solaris.h deleted file mode 100644 index 363f382896..0000000000 --- a/zebra/ioctl_solaris.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Interface looking up by ioctl () on Solaris. - * Copyright (C) 1999 Kunihiro Ishiguro - * - * This file is part of Quagga. - * - * Quagga 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. - * - * Quagga 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 _ZEBRA_IF_IOCTL_SOLARIS_H -#define _ZEBRA_IF_IOCTL_SOLARIS_H - -#ifdef __cplusplus -extern "C" { -#endif - -void lifreq_set_name(struct lifreq *, const char *); -int if_get_flags_direct(const char *, uint64_t *, unsigned int af); - -#ifdef __cplusplus -} -#endif - -#endif /* _ZEBRA_IF_IOCTL_SOLARIS_H */ diff --git a/zebra/ipforward_solaris.c b/zebra/ipforward_solaris.c deleted file mode 100644 index 3d6a29bec6..0000000000 --- a/zebra/ipforward_solaris.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * ipforward value get function for solaris. - * Copyright (C) 1997 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra 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. - * - * GNU Zebra 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> - -#ifdef SUNOS_5 - -#include "log.h" -#include "prefix.h" -#include "lib_errors.h" - -#include "privs.h" -#include "zebra/ipforward.h" -#include "zebra/zebra_errors.h" - -/* -** Solaris should define IP_DEV_NAME in <inet/ip.h>, but we'll save -** configure.in changes for another day. We can use the same device -** for both IPv4 and IPv6. -*/ -/* #include <inet/ip.h> */ -#ifndef IP_DEV_NAME -#define IP_DEV_NAME "/dev/ip" -#endif - - -extern struct zebra_privs_t zserv_privs; - -/* This is a limited ndd style function that operates one integer -** value only. Errors return -1. ND_SET commands return 0 on -** success. ND_GET commands return the value on success (which could -** be -1 and be confused for an error). The parameter is the string -** name of the parameter being referenced. -*/ - -static int solaris_nd(const int cmd, const char *parameter, const int value) -{ -#define ND_BUFFER_SIZE 1024 - int fd; - char nd_buf[ND_BUFFER_SIZE]; - struct strioctl strioctl; - const char *device = IP_DEV_NAME; - int retval; - memset(nd_buf, '\0', ND_BUFFER_SIZE); - /* - ** ND_SET takes a NULL delimited list of strings further terminated - ** buy a NULL. ND_GET returns a list in a similar layout, although - ** here we only use the first result. - */ - if (cmd == ND_SET) - snprintf(nd_buf, ND_BUFFER_SIZE, "%s%c%d%c", parameter, '\0', - value, '\0'); - else if (cmd == ND_GET) - snprintf(nd_buf, ND_BUFFER_SIZE, "%s", parameter); - else { - flog_err_sys(EC_LIB_SYSTEM_CALL, - "internal error - inappropriate command given to solaris_nd()%s:%d", - __FILE__, __LINE__); - return -1; - } - - strioctl.ic_cmd = cmd; - strioctl.ic_timout = 0; - strioctl.ic_len = ND_BUFFER_SIZE; - strioctl.ic_dp = nd_buf; - - frr_with_privs(&zserv_privs) { - if ((fd = open(device, O_RDWR)) < 0) { - flog_err_sys(EC_LIB_SYSTEM_CALL, - "failed to open device %s - %s", device, - safe_strerror(errno)); - return -1; - } - if (ioctl(fd, I_STR, &strioctl) < 0) { - close(fd); - flog_err_sys(EC_LIB_SYSTEM_CALL, - "ioctl I_STR failed on device %s - %s", - device, safe_strerror(errno)); - return -1; - } - close(fd); - } - - if (cmd == ND_GET) { - errno = 0; - retval = atoi(nd_buf); - if (errno) { - zlog_debug( - "failed to convert returned value to integer - %s", - safe_strerror(errno)); - retval = -1; - } - } else { - retval = 0; - } - return retval; -} - -static int solaris_nd_set(const char *parameter, const int value) -{ - return solaris_nd(ND_SET, parameter, value); -} -static int solaris_nd_get(const char *parameter) -{ - return solaris_nd(ND_GET, parameter, 0); -} -int ipforward(void) -{ - return solaris_nd_get("ip_forwarding"); -} - -int ipforward_on(void) -{ - (void)solaris_nd_set("ip_forwarding", 1); - return ipforward(); -} - -int ipforward_off(void) -{ - (void)solaris_nd_set("ip_forwarding", 0); - return ipforward(); -} -int ipforward_ipv6(void) -{ - return solaris_nd_get("ip6_forwarding"); -} -int ipforward_ipv6_on(void) -{ - (void)solaris_nd_set("ip6_forwarding", 1); - return ipforward_ipv6(); -} -int ipforward_ipv6_off(void) -{ - (void)solaris_nd_set("ip6_forwarding", 0); - return ipforward_ipv6(); -} - -#endif /* SUNOS_5 */ diff --git a/zebra/ipforward_sysctl.c b/zebra/ipforward_sysctl.c index 48ab95d1ba..0015018f94 100644 --- a/zebra/ipforward_sysctl.c +++ b/zebra/ipforward_sysctl.c @@ -20,7 +20,7 @@ #include <zebra.h> -#if !defined(GNU_LINUX) && !defined(SUNOS_5) +#if !defined(GNU_LINUX) #include "privs.h" #include "zebra/ipforward.h" @@ -141,4 +141,4 @@ int ipforward_ipv6_off(void) return ip6forwarding; } -#endif /* !defined(GNU_LINUX) && !defined(SUNOS_5) */ +#endif /* !defined(GNU_LINUX) */ diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index ad0d4bf56b..c53d28a18c 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1462,6 +1462,9 @@ void kernel_init(struct zebra_ns *zns) one = 1; ret = setsockopt(zns->netlink_dplane.sock, SOL_NETLINK, NETLINK_CAP_ACK, &one, sizeof(one)); + if (ret < 0) + zlog_notice( + "Registration for reduced ACK packet size failed, probably running an early kernel"); #endif /* Register kernel socket. */ diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 2b6caace8e..40ac44b77f 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -80,12 +80,6 @@ extern struct zebra_privs_t zserv_privs; #define ROUNDUP(a) RT_ROUNDUP(a) #endif /* defined(RT_ROUNDUP) */ -#if defined(SUNOS_5) -/* Solaris has struct sockaddr_in[6] definitions at 16 / 32 bytes size, - * so the whole concept doesn't really apply. */ -#define ROUNDUP(a) (a) -#endif - /* * If ROUNDUP has not yet been defined in terms of platform-provided * defines, attempt to cope with heuristics. @@ -547,18 +541,6 @@ int ifm_read(struct if_msghdr *ifm) */ cp = (void *)(ifm + 1); -#ifdef SUNOS_5 - /* - * XXX This behavior should be narrowed to only the kernel versions - * for which the structures returned do not match the headers. - * - * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions - * is 12 bytes larger than the 32 bit version. - */ - if (((struct sockaddr *)cp)->sa_family == AF_UNSPEC) - cp += 12; -#endif - /* Look up for RTA_IFP and skip others. */ for (maskbit = 1; maskbit; maskbit <<= 1) { if ((maskbit & ifm->ifm_addrs) == 0) @@ -946,23 +928,6 @@ int ifam_read(struct ifa_msghdr *ifam) /* Check interface flag for implicit up of the interface. */ if_refresh(ifp); -#ifdef SUNOS_5 - /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange. - * See comments for SUNOS_5 in interface.c::if_flags_mangle. - * - * Here we take care of case where the real IFF_UP was previously - * unset (as kept in struct zebra_if.primary_state) and the mangled - * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned - * to unset due to the lost non-primary address having DELADDR'd. - * - * we must delete the interface, because in between here and next - * event for this interface-name the administrator could unplumb - * and replumb the interface. - */ - if (!if_is_up(ifp)) - if_delete_update(ifp); -#endif /* SUNOS_5 */ - return 0; } diff --git a/zebra/rib.h b/zebra/rib.h index be680a112f..9ddc35b091 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -333,6 +333,10 @@ extern void route_entry_copy_nexthops(struct route_entry *re, int route_entry_update_nhe(struct route_entry *re, struct nhg_hash_entry *new_nhghe); +/* NHG replace has happend, we have to update route_entry pointers to new one */ +void rib_handle_nhg_replace(struct nhg_hash_entry *old, + struct nhg_hash_entry *new); + #define route_entry_dump(prefix, src, re) _route_entry_dump(__func__, prefix, src, re) extern void _route_entry_dump(const char *func, union prefixconstptr pp, union prefixconstptr src_pp, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 50b1a62d86..1ce3c435fe 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -126,6 +126,31 @@ static bool kernel_nexthops_supported(void) } /* + * Some people may only want to use NHGs created by protos and not + * implicitly created by Zebra. This check accounts for that. + */ +static bool proto_nexthops_only(void) +{ + return zebra_nhg_proto_nexthops_only(); +} + +/* Is this a proto created NHG? */ +static bool is_proto_nhg(uint32_t id, int type) +{ + /* If type is available, use it as the source of truth */ + if (type) { + if (type != ZEBRA_ROUTE_NHG) + return true; + return false; + } + + if (id >= ZEBRA_NHG_PROTO_LOWER) + return true; + + return false; +} + +/* * The ipv4_ll data structure is used for all 5549 * additions to the kernel. Let's figure out the * correct value one time instead for every @@ -643,6 +668,11 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, return 0; } + if (rtm->rtm_flags & RTM_F_TRAP) + flags |= ZEBRA_FLAG_TRAPPED; + if (rtm->rtm_flags & RTM_F_OFFLOAD) + flags |= ZEBRA_FLAG_OFFLOADED; + /* Route which inserted by Zebra. */ if (selfroute) { flags |= ZEBRA_FLAG_SELFROUTE; @@ -1743,7 +1773,10 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, nl_attr_nest_end(&req->n, nest); } - if ((!fpm && kernel_nexthops_supported()) || (fpm && force_nhg)) { + if ((!fpm && kernel_nexthops_supported() + && (!proto_nexthops_only() + || is_proto_nhg(dplane_ctx_get_nhe_id(ctx), 0))) + || (fpm && force_nhg)) { /* Kernel supports nexthop objects */ if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("%s: %pFX nhg_id is %u", __func__, p, @@ -2067,6 +2100,35 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd, mpls_lse_t out_lse[MPLS_MAX_LABELS]; char label_buf[256]; int num_labels = 0; + uint32_t id = dplane_ctx_get_nhe_id(ctx); + int type = dplane_ctx_get_nhe_type(ctx); + + if (!id) { + flog_err( + EC_ZEBRA_NHG_FIB_UPDATE, + "Failed trying to update a nexthop group in the kernel that does not have an ID"); + return -1; + } + + /* + * Nothing to do if the kernel doesn't support nexthop objects or + * we dont want to install this type of NHG + */ + if (!kernel_nexthops_supported()) { + if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_NHG) + zlog_debug( + "%s: nhg_id %u (%s): kernel nexthops not supported, ignoring", + __func__, id, zebra_route_string(type)); + return 0; + } + + if (proto_nexthops_only() && !is_proto_nhg(id, type)) { + if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_NHG) + zlog_debug( + "%s: nhg_id %u (%s): proto-based nexthops only, ignoring", + __func__, id, zebra_route_string(type)); + return 0; + } label_buf[0] = '\0'; @@ -2087,15 +2149,6 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd, req->nhm.nh_family = AF_UNSPEC; /* TODO: Scope? */ - uint32_t id = dplane_ctx_get_nhe_id(ctx); - - if (!id) { - flog_err( - EC_ZEBRA_NHG_FIB_UPDATE, - "Failed trying to update a nexthop group in the kernel that does not have an ID"); - return -1; - } - if (!nl_attr_put32(&req->n, buflen, NHA_ID, id)) return 0; @@ -2216,8 +2269,7 @@ nexthop_done: nh->vrf_id, label_buf); } - req->nhm.nh_protocol = - zebra2proto(dplane_ctx_get_nhe_type(ctx)); +req->nhm.nh_protocol = zebra2proto(type); } else if (cmd != RTM_DELNEXTHOP) { flog_err( @@ -2680,9 +2732,9 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, static ssize_t netlink_neigh_update_msg_encode( const struct zebra_dplane_ctx *ctx, int cmd, const struct ethaddr *mac, const struct ipaddr *ip, bool replace_obj, uint8_t family, uint8_t type, - uint8_t flags, uint16_t state, uint32_t nhg_id, - bool nfy, uint8_t nfy_flags, - void *data, size_t datalen) + uint8_t flags, uint16_t state, uint32_t nhg_id, bool nfy, + uint8_t nfy_flags, bool ext, uint32_t ext_flags, void *data, + size_t datalen) { uint8_t protocol = RTPROT_ZEBRA; struct { @@ -2731,6 +2783,12 @@ static ssize_t netlink_neigh_update_msg_encode( return 0; } + if (ext) { + if (!nl_attr_put(&req->n, datalen, NDA_EXT_FLAGS, &ext_flags, + sizeof(ext_flags))) + return 0; + } + ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; if (!nl_attr_put(&req->n, datalen, NDA_DST, &ip->ip.addr, ipa_len)) return 0; @@ -2764,7 +2822,8 @@ netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx, int cmd, return netlink_neigh_update_msg_encode( ctx, cmd, &dst_mac, dplane_ctx_neigh_get_ipaddr(ctx), false, PF_BRIDGE, 0, NTF_SELF, (NUD_NOARP | NUD_PERMANENT), 0 /*nhg*/, - false /*nfy*/, 0 /*nfy_flags*/, buf, buflen); + false /*nfy*/, 0 /*nfy_flags*/, false /*ext*/, 0 /*ext_flags*/, + buf, buflen); } #ifndef NDA_RTA @@ -3174,30 +3233,26 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data, else vid_buf[0] = '\0'; - zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s dst %s nhg %u%s%s%s%s%s", - nl_msg_type_to_str(cmd), nl_family_to_str(AF_BRIDGE), - dplane_ctx_get_ifname(ctx), - dplane_ctx_get_ifindex(ctx), vid_buf, - dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "", - prefix_mac2str(mac, buf, sizeof(buf)), - ipaddr2str(&vtep_ip, ipbuf, sizeof(ipbuf)), - nhg_id, - (update_flags & - DPLANE_MAC_REMOTE) ? " rem" : "", - (update_flags & - DPLANE_MAC_WAS_STATIC) ? " clr_sync" : "", - (update_flags & - DPLANE_MAC_SET_STATIC) ? " static" : "", - (update_flags & - DPLANE_MAC_SET_INACTIVE) ? " inactive" : "", - (nfy & - DPLANE_MAC_SET_INACTIVE) ? " nfy" : ""); + zlog_debug( + "Tx %s family %s IF %s(%u)%s %sMAC %s dst %s nhg %u%s%s%s%s%s", + nl_msg_type_to_str(cmd), nl_family_to_str(AF_BRIDGE), + dplane_ctx_get_ifname(ctx), dplane_ctx_get_ifindex(ctx), + vid_buf, dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "", + prefix_mac2str(mac, buf, sizeof(buf)), + ipaddr2str(&vtep_ip, ipbuf, sizeof(ipbuf)), nhg_id, + (update_flags & DPLANE_MAC_REMOTE) ? " rem" : "", + (update_flags & DPLANE_MAC_WAS_STATIC) ? " clr_sync" + : "", + (update_flags & DPLANE_MAC_SET_STATIC) ? " static" : "", + (update_flags & DPLANE_MAC_SET_INACTIVE) ? " inactive" + : "", + nfy ? " nfy" : ""); } total = netlink_neigh_update_msg_encode( ctx, cmd, dplane_ctx_mac_get_addr(ctx), &vtep_ip, true, AF_BRIDGE, 0, flags, state, nhg_id, nfy, nfy_flags, - data, datalen); + false /*ext*/, 0 /*ext_flags*/, data, datalen); return total; } @@ -3598,17 +3653,42 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx, uint8_t flags; uint16_t state; uint8_t family; + uint32_t update_flags; + uint32_t ext_flags = 0; + bool ext = false; ip = dplane_ctx_neigh_get_ipaddr(ctx); mac = dplane_ctx_neigh_get_mac(ctx); if (is_zero_mac(mac)) mac = NULL; + update_flags = dplane_ctx_neigh_get_update_flags(ctx); flags = neigh_flags_to_netlink(dplane_ctx_neigh_get_flags(ctx)); state = neigh_state_to_netlink(dplane_ctx_neigh_get_state(ctx)); family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6; + if (update_flags & DPLANE_NEIGH_REMOTE) { + flags |= NTF_EXT_LEARNED; + /* if it was static-local previously we need to clear the + * ext flags on replace with remote + */ + if (update_flags & DPLANE_NEIGH_WAS_STATIC) + ext = true; + } else { + ext = true; + /* local neigh */ + if (update_flags & DPLANE_NEIGH_SET_STATIC) + ext_flags |= NTF_E_MH_PEER_SYNC; + + /* the ndm_state set for local entries can be REACHABLE or + * STALE. if the dataplane has already establish reachability + * (in the meantime) FRR must not over-write it with STALE. + * this accidental race/over-write is avoided by using the + * WEAK_OVERRIDE_STATE + */ + ext_flags |= NTF_E_WEAK_OVERRIDE_STATE; + } if (IS_ZEBRA_DEBUG_KERNEL) { char buf[INET6_ADDRSTRLEN]; char buf2[ETHER_ADDR_STRLEN]; @@ -3624,7 +3704,8 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx, return netlink_neigh_update_msg_encode( ctx, cmd, mac, ip, true, family, RTN_UNICAST, flags, state, - 0 /*nhg*/, false /*nfy*/, 0 /*nfy_flags*/, buf, buflen); + 0 /*nhg*/, false /*nfy*/, 0 /*nfy_flags*/, ext, ext_flags, buf, + buflen); } static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx, diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c deleted file mode 100644 index 0a1fb82d95..0000000000 --- a/zebra/rtread_getmsg.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Kernel routing table readup by getmsg(2) - * Copyright (C) 1999 Michael Handler - * - * This file is part of GNU Zebra. - * - * GNU Zebra 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. - * - * GNU Zebra 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> - -#ifdef SUNOS_5 - -#include "prefix.h" -#include "log.h" -#include "if.h" -#include "vrf.h" -#include "vty.h" -#include "lib_errors.h" - -#include "zebra/rib.h" -#include "zebra/rt.h" -#include "zebra/zebra_pbr.h" -#include "zebra/zebra_errors.h" - -/* Thank you, Solaris, for polluting application symbol namespace. */ -#undef hook_register -#undef hook_unregister - -#include <sys/stream.h> -#include <sys/tihdr.h> - -/* Solaris defines these in both <netinet/in.h> and <inet/in.h>, sigh */ -#ifdef SUNOS_5 -#include <sys/tiuser.h> -#ifndef T_CURRENT -#define T_CURRENT MI_T_CURRENT -#endif /* T_CURRENT */ -#ifndef IRE_CACHE -#define IRE_CACHE 0x0020 /* Cached Route entry */ -#endif /* IRE_CACHE */ -#ifndef IRE_HOST_REDIRECT -#define IRE_HOST_REDIRECT 0x0200 /* Host route entry from redirects */ -#endif /* IRE_HOST_REDIRECT */ -#ifndef IRE_CACHETABLE -#define IRE_CACHETABLE (IRE_CACHE | IRE_BROADCAST | IRE_LOCAL | IRE_LOOPBACK) -#endif /* IRE_CACHETABLE */ -#undef IPOPT_EOL -#undef IPOPT_NOP -#undef IPOPT_LSRR -#undef IPOPT_RR -#undef IPOPT_SSRR -#endif /* SUNOS_5 */ - -#include <inet/common.h> -#include <inet/ip.h> -#include <inet/mib2.h> - -/* device to read IP routing table from */ -#ifndef _PATH_GETMSG_ROUTE -#define _PATH_GETMSG_ROUTE "/dev/ip" -#endif /* _PATH_GETMSG_ROUTE */ - -#define RT_BUFSIZ 8192 - -static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry) -{ - struct prefix prefix; - struct in_addr tmpaddr; - struct nexthop nh; - uint8_t zebra_flags = 0; - - if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE) - return; - - if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT) - zebra_flags |= ZEBRA_FLAG_SELFROUTE; - - prefix.family = AF_INET; - - tmpaddr.s_addr = routeEntry->ipRouteDest; - prefix.u.prefix4 = tmpaddr; - - tmpaddr.s_addr = routeEntry->ipRouteMask; - prefix.prefixlen = ip_masklen(tmpaddr); - - memset(&nh, 0, sizeof(nh)); - nh.vrf_id = VRF_DEFAULT; - nh.type = NEXTHOP_TYPE_IPV4; - nh.gate.ipv4.s_addr = routeEntry->ipRouteNextHop; - - rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, - zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0, 0, 0); -} - -void route_read(struct zebra_ns *zns) -{ - char storage[RT_BUFSIZ]; - - struct T_optmgmt_req *TLIreq = (struct T_optmgmt_req *)storage; - struct T_optmgmt_ack *TLIack = (struct T_optmgmt_ack *)storage; - struct T_error_ack *TLIerr = (struct T_error_ack *)storage; - - struct opthdr *MIB2hdr; - - mib2_ipRouteEntry_t *routeEntry, *lastRouteEntry; - - struct strbuf msgdata; - int flags, dev, retval, process; - - if ((dev = open(_PATH_GETMSG_ROUTE, O_RDWR)) == -1) { - flog_err_sys(EC_LIB_SYSTEM_CALL, "can't open %s: %s", - _PATH_GETMSG_ROUTE, safe_strerror(errno)); - return; - } - - TLIreq->PRIM_type = T_OPTMGMT_REQ; - TLIreq->OPT_offset = sizeof(struct T_optmgmt_req); - TLIreq->OPT_length = sizeof(struct opthdr); - TLIreq->MGMT_flags = T_CURRENT; - - MIB2hdr = (struct opthdr *)&TLIreq[1]; - - MIB2hdr->level = MIB2_IP; - MIB2hdr->name = 0; - MIB2hdr->len = 0; - - msgdata.buf = storage; - msgdata.len = sizeof(struct T_optmgmt_req) + sizeof(struct opthdr); - - flags = 0; - - if (putmsg(dev, &msgdata, NULL, flags) == -1) { - flog_err_sys(EC_LIB_SOCKET, "putmsg failed: %s", - safe_strerror(errno)); - goto exit; - } - - MIB2hdr = (struct opthdr *)&TLIack[1]; - msgdata.maxlen = sizeof(storage); - - while (1) { - flags = 0; - retval = getmsg(dev, &msgdata, NULL, &flags); - - if (retval == -1) { - flog_err_sys(EC_LIB_SYSTEM_CALL, - "getmsg(ctl) failed: %s", - safe_strerror(errno)); - goto exit; - } - - /* This is normal loop termination */ - if (retval == 0 - && (size_t)msgdata.len >= sizeof(struct T_optmgmt_ack) - && TLIack->PRIM_type == T_OPTMGMT_ACK - && TLIack->MGMT_flags == T_SUCCESS && MIB2hdr->len == 0) - break; - - if ((size_t)msgdata.len >= sizeof(struct T_error_ack) - && TLIerr->PRIM_type == T_ERROR_ACK) { - zlog_debug("getmsg(ctl) returned T_ERROR_ACK: %s", - safe_strerror((TLIerr->TLI_error == TSYSERR) - ? TLIerr->UNIX_error - : EPROTO)); - break; - } - - /* should dump more debugging info to the log statement, - like what GateD does in this instance, but not - critical yet. */ - if (retval != MOREDATA - || (size_t)msgdata.len < sizeof(struct T_optmgmt_ack) - || TLIack->PRIM_type != T_OPTMGMT_ACK - || TLIack->MGMT_flags != T_SUCCESS) { - errno = ENOMSG; - zlog_debug("getmsg(ctl) returned bizarreness"); - break; - } - - /* MIB2_IP_21 is the the pseudo-MIB2 ipRouteTable - entry, see <inet/mib2.h>. "This isn't the MIB data - you're looking for." */ - process = (MIB2hdr->level == MIB2_IP - && MIB2hdr->name == MIB2_IP_21) - ? 1 - : 0; - - /* getmsg writes the data buffer out completely, not - to the closest smaller multiple. Unless reassembling - data structures across buffer boundaries is your idea - of a good time, set maxlen to the closest smaller - multiple of the size of the datastructure you're - retrieving. */ - msgdata.maxlen = - sizeof(storage) - - (sizeof(storage) % sizeof(mib2_ipRouteEntry_t)); - - msgdata.len = 0; - flags = 0; - - do { - retval = getmsg(dev, NULL, &msgdata, &flags); - - if (retval == -1) { - flog_err_sys(EC_LIB_SYSTEM_CALL, - "getmsg(data) failed: %s", - safe_strerror(errno)); - goto exit; - } - - if (!(retval == 0 || retval == MOREDATA)) { - zlog_debug("getmsg(data) returned %d", retval); - goto exit; - } - - if (process) { - if (msgdata.len % sizeof(mib2_ipRouteEntry_t) - != 0) { - zlog_debug( - "getmsg(data) returned msgdata.len = %d (%% sizeof(mib2_ipRouteEntry_t) != 0)", - msgdata.len); - goto exit; - } - - routeEntry = (mib2_ipRouteEntry_t *)msgdata.buf; - lastRouteEntry = - (mib2_ipRouteEntry_t *)(msgdata.buf - + msgdata.len); - do { - handle_route_entry(routeEntry); - } while (++routeEntry < lastRouteEntry); - } - } while (retval == MOREDATA); - } - -exit: - close(dev); -} - -/* Only implemented for netlink method */ -void macfdb_read(struct zebra_ns *zns) -{ -} - -void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, - struct interface *br_if) -{ -} - -void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if, - struct ethaddr *mac, vlanid_t vid) -{ -} - -void neigh_read(struct zebra_ns *zns) -{ -} - -void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) -{ -} - -void neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if) -{ -} - -void kernel_read_pbr_rules(struct zebra_ns *zns) -{ -} - -#endif /* SUNOS_5 */ diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c index 4150092d4a..01a97db8b3 100644 --- a/zebra/rtread_sysctl.c +++ b/zebra/rtread_sysctl.c @@ -21,7 +21,7 @@ #include <zebra.h> -#if !defined(GNU_LINUX) && !defined(SUNOS_5) +#if !defined(GNU_LINUX) #include "memory.h" #include "zebra_memory.h" @@ -109,4 +109,4 @@ void kernel_read_pbr_rules(struct zebra_ns *zns) { } -#endif /* !defined(GNU_LINUX) && !defined(SUNOS_5) */ +#endif /* !defined(GNU_LINUX) */ diff --git a/zebra/subdir.am b/zebra/subdir.am index a6ef1537c0..ab53351ae3 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -51,14 +51,11 @@ zebra_zebra_SOURCES = \ zebra/connected.c \ zebra/debug.c \ zebra/if_ioctl.c \ - zebra/if_ioctl_solaris.c \ zebra/if_netlink.c \ zebra/if_sysctl.c \ zebra/interface.c \ zebra/ioctl.c \ - zebra/ioctl_solaris.c \ zebra/ipforward_proc.c \ - zebra/ipforward_solaris.c \ zebra/ipforward_sysctl.c \ zebra/kernel_netlink.c \ zebra/kernel_socket.c \ @@ -69,7 +66,6 @@ zebra_zebra_SOURCES = \ zebra/rt_netlink.c \ zebra/rt_socket.c \ zebra/rtadv.c \ - zebra/rtread_getmsg.c \ zebra/rtread_netlink.c \ zebra/rtread_sysctl.c \ zebra/rule_netlink.c \ @@ -133,7 +129,6 @@ noinst_HEADERS += \ zebra/if_netlink.h \ zebra/interface.h \ zebra/ioctl.h \ - zebra/ioctl_solaris.h \ zebra/ipforward.h \ zebra/irdp.h \ zebra/kernel_netlink.h \ diff --git a/zebra/table_manager.c b/zebra/table_manager.c index 7ed673a88f..bb060588d2 100644 --- a/zebra/table_manager.c +++ b/zebra/table_manager.c @@ -40,11 +40,7 @@ /* routing table identifiers * */ -#ifdef SUNOS_5 -/* SunOS - */ -#else -#if !defined(GNU_LINUX) && !defined(SUNOS_5) +#if !defined(GNU_LINUX) /* BSD systems */ #else @@ -55,8 +51,7 @@ #define RT_TABLE_ID_DEFAULT 253 #define RT_TABLE_ID_COMPAT 252 #define RT_TABLE_ID_UNSPEC 0 -#endif /* !def(GNU_LINUX) && !defined(SUNOS_5) */ -#endif /* SUNOS_5 */ +#endif /* !def(GNU_LINUX) */ #define RT_TABLE_ID_UNRESERVED_MIN 1 #define RT_TABLE_ID_UNRESERVED_MAX 0xffffffff @@ -126,11 +121,7 @@ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, start = ((struct table_manager_chunk *)listgetdata( listtail(tbl_mgr.lc_list)))->end + 1; -#ifdef SUNOS_5 -/* SunOS - */ -#else -#if !defined(GNU_LINUX) && !defined(SUNOS_5) +#if !defined(GNU_LINUX) /* BSD systems */ #else @@ -143,8 +134,7 @@ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, RT_TABLE_ID_COMPAT - RT_TABLE_ID_UNRESERVED_MIN)) start = RT_TABLE_ID_LOCAL + 1; -#endif /* !def(GNU_LINUX) && !defined(SUNOS_5) */ -#endif /* SUNOS_5 */ +#endif /* !def(GNU_LINUX) */ tmc->start = start; if (RT_TABLE_ID_UNRESERVED_MAX - size + 1 < start) { flog_err(EC_ZEBRA_TM_EXHAUSTED_IDS, diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index e436e5a288..c33bca3d86 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -712,6 +712,34 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, return zserv_send_message(client, s); } +static int nhg_notify(uint16_t type, uint16_t instance, uint32_t id, + enum zapi_nhg_notify_owner note) +{ + struct zserv *client; + struct stream *s; + + client = zserv_find_client(type, instance); + if (!client) { + if (IS_ZEBRA_DEBUG_PACKET) { + zlog_debug("Not Notifying Owner: %u(%u) about %u(%d)", + type, instance, id, note); + } + return 0; + } + + s = stream_new(ZEBRA_MAX_PACKET_SIZ); + stream_reset(s); + + zclient_create_header(s, ZEBRA_NHG_NOTIFY_OWNER, VRF_DEFAULT); + + stream_put(s, ¬e, sizeof(note)); + stream_putl(s, id); + + stream_putw_at(s, 0, stream_get_endp(s)); + + return zserv_send_message(client, s); +} + /* * Common utility send route notification, called from a path using a * route_entry and from a path using a dataplane context. @@ -1411,27 +1439,32 @@ stream_failure: return; } - -void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, +bool zserv_nexthop_num_warn(const char *caller, const struct prefix *p, const unsigned int nexthop_num) { if (nexthop_num > zrouter.multipath_num) { char buff[PREFIX2STR_BUFFER]; - prefix2str(p, buff, sizeof(buff)); + if (p) + prefix2str(p, buff, sizeof(buff)); + flog_warn( EC_ZEBRA_MORE_NH_THAN_MULTIPATH, "%s: Prefix %s has %d nexthops, but we can only use the first %d", - caller, buff, nexthop_num, zrouter.multipath_num); + caller, (p ? buff : "(NULL)"), nexthop_num, + zrouter.multipath_num); + return true; } + + return false; } /* * Create a new nexthop based on a zapi nexthop. */ -static struct nexthop *nexthop_from_zapi(struct route_entry *re, - const struct zapi_nexthop *api_nh, - const struct zapi_route *api) +static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh, + uint32_t flags, struct prefix *p, + uint16_t backup_nexthop_num) { struct nexthop *nexthop = NULL; struct ipaddr vtep_ip; @@ -1469,14 +1502,13 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re, /* Special handling for IPv4 routes sourced from EVPN: * the nexthop and associated MAC need to be installed. */ - if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE)) { + if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) { memset(&vtep_ip, 0, sizeof(struct ipaddr)); vtep_ip.ipa_type = IPADDR_V4; memcpy(&(vtep_ip.ipaddr_v4), &(api_nh->gate.ipv4), sizeof(struct in_addr)); zebra_vxlan_evpn_vrf_route_add( - api_nh->vrf_id, &api_nh->rmac, - &vtep_ip, &api->prefix); + api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p); } break; case NEXTHOP_TYPE_IPV6: @@ -1503,14 +1535,13 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re, /* Special handling for IPv6 routes sourced from EVPN: * the nexthop and associated MAC need to be installed. */ - if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE)) { + if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) { memset(&vtep_ip, 0, sizeof(struct ipaddr)); vtep_ip.ipa_type = IPADDR_V6; memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6), sizeof(struct in6_addr)); zebra_vxlan_evpn_vrf_route_add( - api_nh->vrf_id, &api_nh->rmac, - &vtep_ip, &api->prefix); + api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p); } break; case NEXTHOP_TYPE_BLACKHOLE: @@ -1558,7 +1589,7 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re, for (i = 0; i < api_nh->backup_num; i++) { /* Validate backup index */ - if (api_nh->backup_idx[i] < api->backup_nexthop_num) { + if (api_nh->backup_idx[i] < backup_nexthop_num) { nexthop->backup_idx[i] = api_nh->backup_idx[i]; } else { if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT) @@ -1576,99 +1607,69 @@ done: return nexthop; } -static void zread_route_add(ZAPI_HANDLER_ARGS) +static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, + struct zapi_nexthop *nhops, uint32_t flags, + uint32_t message, uint16_t nexthop_num, + uint16_t backup_nh_num, + struct nexthop_group **png, + struct nhg_backup_info **pbnhg) { - struct stream *s; - struct zapi_route api; - struct zapi_nexthop *api_nh; - afi_t afi; - struct prefix_ipv6 *src_p = NULL; - struct route_entry *re; - struct nexthop *nexthop = NULL, *last_nh; struct nexthop_group *ng = NULL; struct nhg_backup_info *bnhg = NULL; - int i, ret; - vrf_id_t vrf_id; - struct nhg_hash_entry nhe; - enum lsp_types_t label_type; - char nhbuf[NEXTHOP_STRLEN]; - char labelbuf[MPLS_LABEL_STRLEN]; - - s = msg; - if (zapi_route_decode(s, &api) < 0) { - if (IS_ZEBRA_DEBUG_RECV) - zlog_debug("%s: Unable to decode zapi_route sent", - __func__); - return; - } - - vrf_id = zvrf_id(zvrf); - - if (IS_ZEBRA_DEBUG_RECV) { - char buf_prefix[PREFIX_STRLEN]; + uint16_t i; + struct nexthop *last_nh = NULL; - prefix2str(&api.prefix, buf_prefix, sizeof(buf_prefix)); - zlog_debug("%s: p=(%u:%u)%s, msg flags=0x%x, flags=0x%x", - __func__, vrf_id, api.tableid, buf_prefix, (int)api.message, api.flags); - } - - /* Allocate new route. */ - re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); - re->type = api.type; - re->instance = api.instance; - re->flags = api.flags; - re->uptime = monotime(NULL); - re->vrf_id = vrf_id; - - if (api.tableid) - re->table = api.tableid; - else - re->table = zvrf->table_id; + assert(!(png && pbnhg)); - if (!CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) - || api.nexthop_num == 0) { - flog_warn(EC_ZEBRA_RX_ROUTE_NO_NEXTHOPS, - "%s: received a route without nexthops for prefix %pFX from client %s", - __func__, &api.prefix, - zebra_route_string(client->proto)); + if (png) + ng = nexthop_group_new(); - XFREE(MTYPE_RE, re); - return; - } + if (pbnhg && backup_nh_num > 0) { + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: adding %d backup nexthops", __func__, + backup_nh_num); - /* Report misuse of the backup flag */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS) && - api.backup_nexthop_num == 0) { - if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: client %s: BACKUP flag set but no backup nexthops, prefix %pFX", - __func__, - zebra_route_string(client->proto), &api.prefix); + bnhg = zebra_nhg_backup_alloc(); } - /* Use temporary list of nexthops */ - ng = nexthop_group_new(); - /* * TBD should _all_ of the nexthop add operations use * api_nh->vrf_id instead of re->vrf_id ? I only changed * for cases NEXTHOP_TYPE_IPV4 and NEXTHOP_TYPE_IPV6. */ - for (i = 0; i < api.nexthop_num; i++) { - api_nh = &api.nexthops[i]; + for (i = 0; i < nexthop_num; i++) { + struct nexthop *nexthop; + enum lsp_types_t label_type; + char nhbuf[NEXTHOP_STRLEN]; + char labelbuf[MPLS_LABEL_STRLEN]; + struct zapi_nexthop *api_nh = &nhops[i]; /* Convert zapi nexthop */ - nexthop = nexthop_from_zapi(re, api_nh, &api); + nexthop = nexthop_from_zapi(api_nh, flags, p, backup_nh_num); if (!nexthop) { flog_warn( EC_ZEBRA_NEXTHOP_CREATION_FAILED, - "%s: Nexthops Specified: %d but we failed to properly create one", - __func__, api.nexthop_num); - nexthop_group_delete(&ng); - XFREE(MTYPE_RE, re); - return; + "%s: Nexthops Specified: %u(%u) but we failed to properly create one", + __func__, nexthop_num, i); + if (ng) + nexthop_group_delete(&ng); + if (bnhg) + zebra_nhg_backup_free(&bnhg); + return false; } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRTE)) { + if (bnhg + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + if (IS_ZEBRA_DEBUG_RECV) { + nexthop2str(nexthop, nhbuf, sizeof(nhbuf)); + zlog_debug("%s: backup nh %s with BACKUP flag!", + __func__, nhbuf); + } + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP); + nexthop->backup_num = 0; + } + + if (CHECK_FLAG(message, ZAPI_MESSAGE_SRTE)) { SET_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE); nexthop->srte_color = api_nh->srte_color; } @@ -1703,100 +1704,266 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) __func__, nhbuf, api_nh->vrf_id, labelbuf); } - /* Add new nexthop to temporary list. This list is - * canonicalized - sorted - so that it can be hashed later - * in route processing. We expect that the sender has sent - * the list sorted, and the zapi client api attempts to enforce - * that, so this should be inexpensive - but it is necessary - * to support shared nexthop-groups. - */ - nexthop_group_add_sorted(ng, nexthop); + if (ng) { + /* Add new nexthop to temporary list. This list is + * canonicalized - sorted - so that it can be hashed + * later in route processing. We expect that the sender + * has sent the list sorted, and the zapi client api + * attempts to enforce that, so this should be + * inexpensive - but it is necessary to support shared + * nexthop-groups. + */ + nexthop_group_add_sorted(ng, nexthop); + } + if (bnhg) { + /* Note that the order of the backup nexthops is + * significant, so we don't sort this list as we do the + * primary nexthops, we just append. + */ + if (last_nh) + NEXTHOP_APPEND(last_nh, nexthop); + else + bnhg->nhe->nhg.nexthop = nexthop; + + last_nh = nexthop; + } } - /* Allocate temporary list of backup nexthops, if necessary */ - if (api.backup_nexthop_num > 0) { - if (IS_ZEBRA_DEBUG_RECV) - zlog_debug("%s: adding %d backup nexthops", - __func__, api.backup_nexthop_num); - bnhg = zebra_nhg_backup_alloc(); - nexthop = NULL; - last_nh = NULL; + /* succesfully read, set caller pointers now */ + if (png) + *png = ng; + + if (pbnhg) + *pbnhg = bnhg; + + return true; +} + +int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg) +{ + uint16_t i; + struct zapi_nexthop *znh; + + STREAM_GETW(s, api_nhg->proto); + STREAM_GETL(s, api_nhg->id); + + if (cmd == ZEBRA_NHG_DEL) + goto done; + + /* Nexthops */ + STREAM_GETW(s, api_nhg->nexthop_num); + + if (zserv_nexthop_num_warn(__func__, NULL, api_nhg->nexthop_num)) + return -1; + + if (api_nhg->nexthop_num <= 0) { + flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED, + "%s: No nexthops sent", __func__); + return -1; } - /* Copy backup nexthops also, if present */ - for (i = 0; i < api.backup_nexthop_num; i++) { - api_nh = &api.backup_nexthops[i]; + for (i = 0; i < api_nhg->nexthop_num; i++) { + znh = &((api_nhg->nexthops)[i]); - /* Convert zapi backup nexthop */ - nexthop = nexthop_from_zapi(re, api_nh, &api); - if (!nexthop) { - flog_warn( - EC_ZEBRA_NEXTHOP_CREATION_FAILED, - "%s: Backup Nexthops Specified: %d but we failed to properly create one", - __func__, api.backup_nexthop_num); - nexthop_group_delete(&ng); - zebra_nhg_backup_free(&bnhg); - XFREE(MTYPE_RE, re); - return; + if (zapi_nexthop_decode(s, znh, 0, 0) != 0) { + flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED, + "%s: Nexthop creation failed", __func__); + return -1; } + } - /* Backup nexthops can't have backups; that's not valid. */ - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { - if (IS_ZEBRA_DEBUG_RECV) { - nexthop2str(nexthop, nhbuf, sizeof(nhbuf)); - zlog_debug("%s: backup nh %s with BACKUP flag!", - __func__, nhbuf); - } - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP); - nexthop->backup_num = 0; - } + /* Backup Nexthops */ + STREAM_GETW(s, api_nhg->backup_nexthop_num); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRTE)) { - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE); - nexthop->srte_color = api_nh->srte_color; - } + if (zserv_nexthop_num_warn(__func__, NULL, api_nhg->backup_nexthop_num)) + return -1; - /* MPLS labels for BGP-LU or Segment Routing */ - if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL) - && api_nh->type != NEXTHOP_TYPE_IFINDEX - && api_nh->type != NEXTHOP_TYPE_BLACKHOLE - && api_nh->label_num > 0) { + for (i = 0; i < api_nhg->backup_nexthop_num; i++) { + znh = &((api_nhg->backup_nexthops)[i]); - label_type = lsp_type_from_re_type(client->proto); - nexthop_add_labels(nexthop, label_type, - api_nh->label_num, - &api_nh->labels[0]); + if (zapi_nexthop_decode(s, znh, 0, 0) != 0) { + flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED, + "%s: Backup Nexthop creation failed", + __func__); + return -1; } + } - if (IS_ZEBRA_DEBUG_RECV) { - labelbuf[0] = '\0'; - nhbuf[0] = '\0'; +done: + return 0; - nexthop2str(nexthop, nhbuf, sizeof(nhbuf)); +stream_failure: + flog_warn( + EC_ZEBRA_NEXTHOP_CREATION_FAILED, + "%s: Nexthop Group decode failed with some sort of stream read failure", + __func__); + return -1; +} - if (nexthop->nh_label && - nexthop->nh_label->num_labels > 0) { - mpls_label2str(nexthop->nh_label->num_labels, - nexthop->nh_label->label, - labelbuf, sizeof(labelbuf), - false); - } +static void zread_nhg_del(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + struct zapi_nhg api_nhg = {}; + struct nhg_hash_entry *nhe; - zlog_debug("%s: backup nh=%s, vrf_id=%d %s", - __func__, nhbuf, api_nh->vrf_id, labelbuf); - } + s = msg; + if (zapi_nhg_decode(s, hdr->command, &api_nhg) < 0) { + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: Unable to decode zapi_nhg sent", + __func__); + return; + } - /* Note that the order of the backup nexthops is significant, - * so we don't sort this list as we do the primary nexthops, - * we just append. - */ - if (last_nh) - NEXTHOP_APPEND(last_nh, nexthop); - else - bnhg->nhe->nhg.nexthop = nexthop; + /* + * Delete the received nhg id + */ + + nhe = zebra_nhg_proto_del(api_nhg.id, api_nhg.proto); + + if (nhe) { + zebra_nhg_decrement_ref(nhe); + nhg_notify(api_nhg.proto, client->instance, api_nhg.id, + ZAPI_NHG_REMOVED); + } else + nhg_notify(api_nhg.proto, client->instance, api_nhg.id, + ZAPI_NHG_REMOVE_FAIL); +} + +static void zread_nhg_add(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + struct zapi_nhg api_nhg = {}; + struct nexthop_group *nhg = NULL; + struct nhg_backup_info *bnhg = NULL; + struct nhg_hash_entry *nhe; - last_nh = nexthop; + s = msg; + if (zapi_nhg_decode(s, hdr->command, &api_nhg) < 0) { + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: Unable to decode zapi_nhg sent", + __func__); + return; + } + + if ((!zapi_read_nexthops(client, NULL, api_nhg.nexthops, 0, 0, + api_nhg.nexthop_num, + api_nhg.backup_nexthop_num, &nhg, NULL)) + || (!zapi_read_nexthops(client, NULL, api_nhg.backup_nexthops, 0, 0, + api_nhg.backup_nexthop_num, + api_nhg.backup_nexthop_num, NULL, &bnhg))) { + + flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED, + "%s: Nexthop Group Creation failed", __func__); + return; + } + + /* + * Create the nhg + */ + nhe = zebra_nhg_proto_add(api_nhg.id, api_nhg.proto, nhg, 0); + + nexthop_group_delete(&nhg); + zebra_nhg_backup_free(&bnhg); + + /* + * TODO: + * Assume fully resolved for now and install. + * + * Resolution is going to need some more work. + */ + if (nhe) + nhg_notify(api_nhg.proto, client->instance, api_nhg.id, + ZAPI_NHG_INSTALLED); + else + nhg_notify(api_nhg.proto, client->instance, api_nhg.id, + ZAPI_NHG_FAIL_INSTALL); +} + +static void zread_route_add(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + struct zapi_route api; + afi_t afi; + struct prefix_ipv6 *src_p = NULL; + struct route_entry *re; + struct nexthop_group *ng = NULL; + struct nhg_backup_info *bnhg = NULL; + int ret; + vrf_id_t vrf_id; + struct nhg_hash_entry nhe; + + s = msg; + if (zapi_route_decode(s, &api) < 0) { + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: Unable to decode zapi_route sent", + __func__); + return; + } + + vrf_id = zvrf_id(zvrf); + + if (IS_ZEBRA_DEBUG_RECV) { + char buf_prefix[PREFIX_STRLEN]; + + prefix2str(&api.prefix, buf_prefix, sizeof(buf_prefix)); + zlog_debug("%s: p=(%u:%u)%s, msg flags=0x%x, flags=0x%x", + __func__, vrf_id, api.tableid, buf_prefix, + (int)api.message, api.flags); + } + + /* Allocate new route. */ + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + re->type = api.type; + re->instance = api.instance; + re->flags = api.flags; + re->uptime = monotime(NULL); + re->vrf_id = vrf_id; + + if (api.tableid) + re->table = api.tableid; + else + re->table = zvrf->table_id; + + if (!CHECK_FLAG(api.message, ZAPI_MESSAGE_NHG) + && (!CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) + || api.nexthop_num == 0)) { + flog_warn( + EC_ZEBRA_RX_ROUTE_NO_NEXTHOPS, + "%s: received a route without nexthops for prefix %pFX from client %s", + __func__, &api.prefix, + zebra_route_string(client->proto)); + + XFREE(MTYPE_RE, re); + return; + } + + /* Report misuse of the backup flag */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS) + && api.backup_nexthop_num == 0) { + if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s: client %s: BACKUP flag set but no backup nexthops, prefix %pFX", + __func__, zebra_route_string(client->proto), + &api.prefix); + } + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NHG)) + re->nhe_id = api.nhgid; + + if (!re->nhe_id + && (!zapi_read_nexthops(client, &api.prefix, api.nexthops, + api.flags, api.message, api.nexthop_num, + api.backup_nexthop_num, &ng, NULL) + || !zapi_read_nexthops(client, &api.prefix, api.backup_nexthops, + api.flags, api.message, + api.backup_nexthop_num, + api.backup_nexthop_num, NULL, &bnhg))) { + + nexthop_group_delete(&ng); + zebra_nhg_backup_free(&bnhg); + XFREE(MTYPE_RE, re); + return; } if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) @@ -1831,13 +1998,21 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) return; } - /* Include backup info with the route. We use a temporary nhe here; + /* + * If we have an ID, this proto owns the NHG it sent along with the + * route, so we just send the ID into rib code with it. + * + * Havent figured out how to handle backup NHs with this yet, so lets + * keep that separate. + * Include backup info with the route. We use a temporary nhe here; * if this is a new/unknown nhe, a new copy will be allocated * and stored. */ - zebra_nhe_init(&nhe, afi, ng->nexthop); - nhe.nhg.nexthop = ng->nexthop; - nhe.backup_info = bnhg; + if (!re->nhe_id) { + zebra_nhe_init(&nhe, afi, ng->nexthop); + nhe.nhg.nexthop = ng->nexthop; + nhe.backup_info = bnhg; + } ret = rib_add_multipath_nhe(afi, api.safi, &api.prefix, src_p, re, &nhe); @@ -3118,7 +3293,10 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister, [ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg, [ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities, - [ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover}; + [ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover, + [ZEBRA_NHG_ADD] = zread_nhg_add, + [ZEBRA_NHG_DEL] = zread_nhg_del, +}; /* * Process a batch of zapi messages. diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index e7c755c2bf..9f23a313bf 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -90,7 +90,7 @@ zsend_ipset_entry_notify_owner(struct zebra_pbr_ipset_entry *ipset, enum zapi_ipset_entry_notify_owner note); extern void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable, enum zapi_iptable_notify_owner note); -extern void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, +extern bool zserv_nexthop_num_warn(const char *caller, const struct prefix *p, const unsigned int nexthop_num); extern void zsend_capabilities_all_clients(void); diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index abd0adb64e..76d7d00e4a 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -73,6 +73,7 @@ const uint32_t DPLANE_DEFAULT_NEW_WORK = 100; */ struct dplane_nexthop_info { uint32_t id; + uint32_t old_id; afi_t afi; vrf_id_t vrf_id; int type; @@ -1242,6 +1243,12 @@ uint32_t dplane_ctx_get_nhe_id(const struct zebra_dplane_ctx *ctx) return ctx->u.rinfo.nhe.id; } +uint32_t dplane_ctx_get_old_nhe_id(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + return ctx->u.rinfo.nhe.old_id; +} + afi_t dplane_ctx_get_nhe_afi(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -1912,6 +1919,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, struct nhg_hash_entry *nhe = zebra_nhg_resolve(re->nhe); ctx->u.rinfo.nhe.id = nhe->id; + ctx->u.rinfo.nhe.old_id = 0; /* * Check if the nhe is installed/queued before doing anything * with this route. @@ -2328,6 +2336,7 @@ dplane_route_update_internal(struct route_node *rn, ctx->u.rinfo.zd_old_instance = old_re->instance; ctx->u.rinfo.zd_old_distance = old_re->distance; ctx->u.rinfo.zd_old_metric = old_re->metric; + ctx->u.rinfo.nhe.old_id = old_re->nhe->id; #ifndef HAVE_NETLINK /* For bsd, capture previous re's nexthops too, sigh. @@ -2349,6 +2358,40 @@ dplane_route_update_internal(struct route_node *rn, #endif /* !HAVE_NETLINK */ } + /* + * If the old and new context type, and nexthop group id + * are the same there is no need to send down a route replace + * as that we know we have sent a nexthop group replace + * or an upper level protocol has sent us the exact + * same route again. + */ + if ((dplane_ctx_get_type(ctx) == dplane_ctx_get_old_type(ctx)) + && (dplane_ctx_get_nhe_id(ctx) + == dplane_ctx_get_old_nhe_id(ctx)) + && (dplane_ctx_get_nhe_id(ctx) >= ZEBRA_NHG_PROTO_LOWER)) { + struct nexthop *nexthop; + + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug( + "%s: Ignoring Route exactly the same", + __func__); + + for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), + nexthop)) { + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) + continue; + + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_ACTIVE)) + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } + + dplane_ctx_free(&ctx); + return ZEBRA_DPLANE_REQUEST_SUCCESS; + } + /* Enqueue context for processing */ ret = dplane_update_enqueue(ctx); } diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 1d852b1bac..fd70211f7c 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -316,6 +316,7 @@ dplane_ctx_get_old_backup_ng(const struct zebra_dplane_ctx *ctx); /* Accessors for nexthop information */ uint32_t dplane_ctx_get_nhe_id(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_old_nhe_id(const struct zebra_dplane_ctx *ctx); afi_t dplane_ctx_get_nhe_afi(const struct zebra_dplane_ctx *ctx); vrf_id_t dplane_ctx_get_nhe_vrf_id(const struct zebra_dplane_ctx *ctx); int dplane_ctx_get_nhe_type(const struct zebra_dplane_ctx *ctx); diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index 2567171c5e..f71065cdcf 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -60,7 +60,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, ZES_VTEP, "VTEP attached to the ES"); static void zebra_evpn_es_get_one_base_evpn(void); static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es, zebra_evpn_t *zevpn, bool add); -static void zebra_evpn_local_es_del(struct zebra_evpn_es *es); +static void zebra_evpn_local_es_del(struct zebra_evpn_es **esp); static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid, struct ethaddr *sysmac); @@ -820,7 +820,7 @@ void zebra_evpn_if_cleanup(struct zebra_if *zif) /* Delete associated Ethernet Segment */ if (zif->es_info.es) - zebra_evpn_local_es_del(zif->es_info.es); + zebra_evpn_local_es_del(&zif->es_info.es); } /***************************************************************************** @@ -1107,15 +1107,17 @@ static struct zebra_evpn_es *zebra_evpn_es_new(esi_t *esi) * This just frees appropriate memory, caller should have taken other * needed actions. */ -static struct zebra_evpn_es *zebra_evpn_es_free(struct zebra_evpn_es *es) +static void zebra_evpn_es_free(struct zebra_evpn_es **esp) { + struct zebra_evpn_es *es = *esp; + /* If the ES has a local or remote reference it cannot be freed. * Free is also prevented if there are MAC entries referencing * it. */ if ((es->flags & (ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_REMOTE)) || listcount(es->mac_list)) - return es; + return; if (IS_ZEBRA_DEBUG_EVPN_MH_ES) zlog_debug("es %s free", es->esi_str); @@ -1137,7 +1139,7 @@ static struct zebra_evpn_es *zebra_evpn_es_free(struct zebra_evpn_es *es) XFREE(MTYPE_ZES, es); - return NULL; + *esp = NULL; } /* Inform BGP about local ES addition */ @@ -1201,7 +1203,6 @@ static int zebra_evpn_es_send_del_to_client(struct zebra_evpn_es *es) return zserv_send_message(client, s); } -/* XXX - call any time ZEBRA_EVPNES_LOCAL gets set or cleared */ static void zebra_evpn_es_re_eval_send_to_client(struct zebra_evpn_es *es, bool es_evi_re_reval) { @@ -1349,9 +1350,10 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es, false /* force_clear_static */); } -static void zebra_evpn_es_local_info_clear(struct zebra_evpn_es *es) +static void zebra_evpn_es_local_info_clear(struct zebra_evpn_es **esp) { struct zebra_if *zif; + struct zebra_evpn_es *es = *esp; if (!(es->flags & ZEBRA_EVPNES_LOCAL)) return; @@ -1373,16 +1375,17 @@ static void zebra_evpn_es_local_info_clear(struct zebra_evpn_es *es) list_delete_node(zmh_info->local_es_list, &es->local_es_listnode); /* free up the ES if there is no remote reference */ - zebra_evpn_es_free(es); + zebra_evpn_es_free(esp); } /* Delete an ethernet segment and inform BGP */ -static void zebra_evpn_local_es_del(struct zebra_evpn_es *es) +static void zebra_evpn_local_es_del(struct zebra_evpn_es **esp) { struct zebra_evpn_es_evi *es_evi; struct listnode *node = NULL; struct listnode *nnode = NULL; struct zebra_if *zif; + struct zebra_evpn_es *es = *esp; if (!CHECK_FLAG(es->flags, ZEBRA_EVPNES_LOCAL)) return; @@ -1402,12 +1405,14 @@ static void zebra_evpn_local_es_del(struct zebra_evpn_es *es) if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP) zebra_evpn_es_send_del_to_client(es); - zebra_evpn_es_local_info_clear(es); + zebra_evpn_es_local_info_clear(esp); } /* eval remote info associated with the ES */ -static void zebra_evpn_es_remote_info_re_eval(struct zebra_evpn_es *es) +static void zebra_evpn_es_remote_info_re_eval(struct zebra_evpn_es **esp) { + struct zebra_evpn_es *es = *esp; + /* if there are remote VTEPs the ES-EVI is classified as "remote" */ if (listcount(es->es_vtep_list)) { if (!(es->flags & ZEBRA_EVPNES_REMOTE)) { @@ -1422,7 +1427,7 @@ static void zebra_evpn_es_remote_info_re_eval(struct zebra_evpn_es *es) if (IS_ZEBRA_DEBUG_EVPN_MH_ES) zlog_debug("remote es %s del; nhg 0x%x", es->esi_str, es->nhg_id); - zebra_evpn_es_free(es); + zebra_evpn_es_free(esp); } } } @@ -1443,7 +1448,7 @@ static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid, if (!lid || is_zero_mac(sysmac)) { /* if in ES is attached to zif delete it */ if (old_es) - zebra_evpn_local_es_del(old_es); + zebra_evpn_local_es_del(&zif->es_info.es); return 0; } @@ -1468,7 +1473,7 @@ static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid, /* release the old_es against the zif */ if (old_es) - zebra_evpn_local_es_del(old_es); + zebra_evpn_local_es_del(&zif->es_info.es); es = zebra_evpn_es_find(&esi); if (es) { @@ -1497,22 +1502,24 @@ static int zebra_evpn_remote_es_del(esi_t *esi, struct in_addr vtep_ip) es = zebra_evpn_es_find(esi); if (!es) { - /* XXX - error log */ + zlog_warn("remote es %s vtep %pI4 del failed, es missing", + esi_to_str(esi, buf, sizeof(buf)), &vtep_ip); return -1; } zebra_evpn_es_vtep_del(es, vtep_ip); - zebra_evpn_es_remote_info_re_eval(es); + zebra_evpn_es_remote_info_re_eval(&es); return 0; } /* force delete a remote ES on the way down */ -static void zebra_evpn_remote_es_flush(struct zebra_evpn_es *es) +static void zebra_evpn_remote_es_flush(struct zebra_evpn_es **esp) { struct zebra_evpn_es_vtep *es_vtep; struct listnode *node; struct listnode *nnode; + struct zebra_evpn_es *es = *esp; for (ALL_LIST_ELEMENTS(es->es_vtep_list, node, nnode, es_vtep)) { if (IS_ZEBRA_DEBUG_EVPN_MH_ES) @@ -1520,8 +1527,8 @@ static void zebra_evpn_remote_es_flush(struct zebra_evpn_es *es) es->esi_str, inet_ntoa(es_vtep->vtep_ip)); zebra_evpn_es_vtep_free(es_vtep); - zebra_evpn_es_remote_info_re_eval(es); } + zebra_evpn_es_remote_info_re_eval(esp); } static int zebra_evpn_remote_es_add(esi_t *esi, struct in_addr vtep_ip) @@ -1538,13 +1545,15 @@ static int zebra_evpn_remote_es_add(esi_t *esi, struct in_addr vtep_ip) if (!es) { es = zebra_evpn_es_new(esi); if (!es) { - /* XXX - error log */ + zlog_warn( + "remote es %s vtep %pI4 add failed, es missing", + esi_to_str(esi, buf, sizeof(buf)), &vtep_ip); return -1; } } zebra_evpn_es_vtep_add(es, vtep_ip); - zebra_evpn_es_remote_info_re_eval(es); + zebra_evpn_es_remote_info_re_eval(&es); return 0; } @@ -1584,7 +1593,7 @@ void zebra_evpn_es_mac_deref_entry(zebra_mac_t *mac) list_delete_node(es->mac_list, &mac->es_listnode); if (!listcount(es->mac_list)) - zebra_evpn_es_free(es); + zebra_evpn_es_free(&es); } /* Associate a MAC entry with a local or remote ES. Returns false if there @@ -1691,8 +1700,9 @@ void zebra_evpn_es_cleanup(void) RB_FOREACH_SAFE(es, zebra_es_rb_head, &zmh_info->es_rb_tree, es_next) { - zebra_evpn_local_es_del(es); - zebra_evpn_remote_es_flush(es); + zebra_evpn_local_es_del(&es); + if (es) + zebra_evpn_remote_es_flush(&es); } } @@ -2099,7 +2109,7 @@ int zebra_evpn_mh_neigh_holdtime_update(struct vty *vty, uint32_t duration, bool set_default) { if (set_default) - zmh_info->neigh_hold_time = EVPN_MH_NEIGH_HOLD_TIME_DEF; + duration = EVPN_MH_NEIGH_HOLD_TIME_DEF; zmh_info->neigh_hold_time = duration; diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c index 661d1c7f81..6a76a475e6 100644 --- a/zebra/zebra_evpn_neigh.c +++ b/zebra/zebra_evpn_neigh.c @@ -614,6 +614,9 @@ int zebra_evpn_neigh_del(zebra_evpn_t *zevpn, zebra_neigh_t *n) /* Cancel auto recovery */ THREAD_OFF(n->dad_ip_auto_recovery_timer); + /* Cancel proxy hold timer */ + zebra_evpn_neigh_stop_hold_timer(n); + /* Free the VNI hash entry and allocated memory. */ tmp_n = hash_release(zevpn->neigh_table, n); XFREE(MTYPE_NEIGH, tmp_n); diff --git a/zebra/zebra_mlag.c b/zebra/zebra_mlag.c index 3cf4ba8d39..fb8798ebd9 100644 --- a/zebra/zebra_mlag.c +++ b/zebra/zebra_mlag.c @@ -111,10 +111,13 @@ void zebra_mlag_send_deregister(void) void zebra_mlag_process_mlag_data(uint8_t *data, uint32_t len) { struct stream *s = NULL; - struct stream *s1 = NULL; int msg_type = 0; s = stream_new(ZEBRA_MAX_PACKET_SIZ); + /* + * Place holder we need the message type first + */ + stream_putl(s, msg_type); msg_type = zebra_mlag_protobuf_decode_message(s, data, len); if (msg_type <= 0) { @@ -128,12 +131,9 @@ void zebra_mlag_process_mlag_data(uint8_t *data, uint32_t len) /* * additional four bytes are for message type */ - s1 = stream_new(stream_get_endp(s) + ZEBRA_MLAG_METADATA_LEN); - stream_putl(s1, msg_type); - stream_put(s1, s->data, stream_get_endp(s)); + stream_putl_at(s, 0, msg_type); thread_add_event(zrouter.master, zebra_mlag_post_data_from_main_thread, - s1, 0, NULL); - stream_free(s); + s, 0, NULL); } /**********************End of MLAG Interaction********************************/ diff --git a/zebra/zebra_mlag.h b/zebra/zebra_mlag.h index d10a1f9157..85028d2774 100644 --- a/zebra/zebra_mlag.h +++ b/zebra/zebra_mlag.h @@ -30,7 +30,7 @@ extern "C" { #endif -#define ZEBRA_MLAG_BUF_LIMIT 2048 +#define ZEBRA_MLAG_BUF_LIMIT 32768 #define ZEBRA_MLAG_LEN_SIZE 4 DECLARE_HOOK(zebra_mlag_private_write_data, diff --git a/zebra/zebra_mlag_private.c b/zebra/zebra_mlag_private.c index 0f0285ed31..1dae758b12 100644 --- a/zebra/zebra_mlag_private.c +++ b/zebra/zebra_mlag_private.c @@ -117,6 +117,15 @@ static int zebra_mlag_read(struct thread *thread) /* This will be the actual length of the packet */ tot_len = h_msglen + ZEBRA_MLAG_LEN_SIZE; + /* + * If the buffer read we are about to do is too large + * we are really really really not double plus good + * + * I'm not sure what to do here other than to bail + * We'll need to revisit this in the future. + */ + assert(tot_len < ZEBRA_MLAG_BUF_LIMIT); + if (curr_len < tot_len) { ssize_t data_len; diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c index 79121bb086..81d610940d 100644 --- a/zebra/zebra_netns_id.c +++ b/zebra/zebra_netns_id.c @@ -39,9 +39,6 @@ #include "zebra/zebra_netns_id.h" #include "zebra/zebra_errors.h" -/* default NS ID value used when VRF backend is not NETNS */ -#define NS_DEFAULT_INTERNAL 0 - /* in case NEWNSID not available, the NSID will be locally obtained */ #define NS_BASE_NSID 0 @@ -185,7 +182,7 @@ ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param) if (sock < 0) { flog_err_sys(EC_LIB_SOCKET, "netlink( %u) socket() error: %s", sock, safe_strerror(errno)); - if (fd_param == -1) + if (netnspath) close(fd); return NS_UNKNOWN; } @@ -199,7 +196,7 @@ ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param) "netlink( %u) socket() bind error: %s", sock, safe_strerror(errno)); close(sock); - if (fd_param == -1) + if (netnspath) close(fd); return NS_UNKNOWN; } @@ -222,7 +219,7 @@ ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param) ret = send_receive(sock, nlh, seq, buf); if (ret < 0) { close(sock); - if (fd_param == -1) + if (netnspath) close(fd); return NS_UNKNOWN; } @@ -267,7 +264,7 @@ ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param) "netlink( %u) recvfrom() error 2 when reading: %s", fd, safe_strerror(errno)); close(sock); - if (fd_param == -1) + if (netnspath) close(fd); if (errno == ENOTSUP) { zlog_debug("NEWNSID locally generated"); @@ -289,7 +286,7 @@ ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param) ret = send_receive(sock, nlh, seq, buf); if (ret < 0) { close(sock); - if (fd_param == -1) + if (netnspath) close(fd); return NS_UNKNOWN; } @@ -321,7 +318,7 @@ ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param) } while (len != 0 && ret == 0); } - if (fd_param == -1) + if (netnspath) close(fd); close(sock); return return_nsid; @@ -362,14 +359,14 @@ ns_id_t zebra_ns_id_get_default(void) fd = open(NS_DEFAULT_NAME, O_RDONLY); if (fd == -1) - return NS_DEFAULT_INTERNAL; + return NS_DEFAULT; if (!vrf_is_backend_netns()) { close(fd); - return NS_DEFAULT_INTERNAL; + return NS_DEFAULT; } close(fd); return zebra_ns_id_get((char *)NS_DEFAULT_NAME, -1); #else /* HAVE_NETNS */ - return NS_DEFAULT_INTERNAL; + return NS_DEFAULT; #endif /* !HAVE_NETNS */ } diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index b8faaa43fd..de79c59caa 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -53,14 +53,15 @@ uint32_t id_counter; /* */ static bool g_nexthops_enabled = true; +static bool proto_nexthops_only; -static struct nhg_hash_entry *depends_find(const struct nexthop *nh, - afi_t afi); +static struct nhg_hash_entry *depends_find(const struct nexthop *nh, afi_t afi, + int type); static void depends_add(struct nhg_connected_tree_head *head, struct nhg_hash_entry *depend); static struct nhg_hash_entry * depends_find_add(struct nhg_connected_tree_head *head, struct nexthop *nh, - afi_t afi); + afi_t afi, int type); static struct nhg_hash_entry * depends_find_id_add(struct nhg_connected_tree_head *head, uint32_t id); static void depends_decrement_free(struct nhg_connected_tree_head *head); @@ -68,6 +69,35 @@ static void depends_decrement_free(struct nhg_connected_tree_head *head); static struct nhg_backup_info * nhg_backup_copy(const struct nhg_backup_info *orig); +/* Helper function for getting the next allocatable ID */ +static uint32_t nhg_get_next_id(void) +{ + while (1) { + id_counter++; + + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: ID %u checking", __func__, id_counter); + + if (id_counter == ZEBRA_NHG_PROTO_LOWER) { + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: ID counter wrapped", __func__); + + id_counter = 0; + continue; + } + + if (zebra_nhg_lookup_id(id_counter)) { + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: ID already exists", __func__); + + continue; + } + + break; + } + + return id_counter; +} static void nhg_connected_free(struct nhg_connected *dep) { @@ -431,7 +461,6 @@ static void *zebra_nhg_hash_alloc(void *arg) nhe->nhg.nexthop->vrf_id, nhe->id); } - zebra_nhg_insert_id(nhe); return nhe; } @@ -439,17 +468,17 @@ static void *zebra_nhg_hash_alloc(void *arg) uint32_t zebra_nhg_hash_key(const void *arg) { const struct nhg_hash_entry *nhe = arg; - uint32_t val, key = 0x5a351234; + uint32_t key = 0x5a351234; + uint32_t primary = 0; + uint32_t backup = 0; - val = nexthop_group_hash(&(nhe->nhg)); - if (nhe->backup_info) { - val = jhash_2words(val, - nexthop_group_hash( - &(nhe->backup_info->nhe->nhg)), - key); - } + primary = nexthop_group_hash(&(nhe->nhg)); + if (nhe->backup_info) + backup = nexthop_group_hash(&(nhe->backup_info->nhe->nhg)); + + key = jhash_3words(primary, backup, nhe->type, key); - key = jhash_3words(nhe->vrf_id, nhe->afi, val, key); + key = jhash_2words(nhe->vrf_id, nhe->afi, key); return key; } @@ -512,6 +541,9 @@ bool zebra_nhg_hash_equal(const void *arg1, const void *arg2) if (nhe1->id && nhe2->id && (nhe1->id == nhe2->id)) return true; + if (nhe1->type != nhe2->type) + return false; + if (nhe1->vrf_id != nhe2->vrf_id) return false; @@ -611,7 +643,7 @@ static int zebra_nhg_process_grp(struct nexthop_group *nhg, } static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends, - struct nexthop *nh, afi_t afi) + struct nexthop *nh, afi_t afi, int type) { struct nhg_hash_entry *depend = NULL; struct nexthop_group resolved_ng = {}; @@ -622,7 +654,7 @@ static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends, zlog_debug("%s: head %p, nh %pNHv", __func__, nhg_depends, nh); - depend = zebra_nhg_rib_find(0, &resolved_ng, afi); + depend = zebra_nhg_rib_find(0, &resolved_ng, afi, type); if (IS_ZEBRA_DEBUG_NHG_DETAIL) zlog_debug("%s: nh %pNHv => %p (%u)", @@ -671,8 +703,26 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */ * assign the next global id value if necessary. */ if (lookup->id == 0) - lookup->id = ++id_counter; - newnhe = hash_get(zrouter.nhgs, lookup, zebra_nhg_hash_alloc); + lookup->id = nhg_get_next_id(); + + if (lookup->id < ZEBRA_NHG_PROTO_LOWER) { + /* + * This is a zebra hashed/owned NHG. + * + * It goes in HASH and ID table. + */ + newnhe = hash_get(zrouter.nhgs, lookup, zebra_nhg_hash_alloc); + zebra_nhg_insert_id(newnhe); + } else { + /* + * This is upperproto owned NHG and should not be hashed to. + * + * It goes in ID table. + */ + newnhe = + hash_get(zrouter.nhgs_id, lookup, zebra_nhg_hash_alloc); + } + created = true; /* Mail back the new object */ @@ -709,14 +759,16 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */ if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE)) SET_FLAG(newnhe->flags, NEXTHOP_GROUP_VALID); - if (nh->next == NULL) { + if (nh->next == NULL && newnhe->id < ZEBRA_NHG_PROTO_LOWER) { if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)) { /* Single recursive nexthop */ handle_recursive_depend(&newnhe->nhg_depends, - nh->resolved, afi); + nh->resolved, afi, + newnhe->type); recursive = true; } } else { + /* Proto-owned are groups by default */ /* List of nexthops */ for (nh = newnhe->nhg.nexthop; nh; nh = nh->next) { if (IS_ZEBRA_DEBUG_NHG_DETAIL) @@ -726,7 +778,8 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */ NEXTHOP_FLAG_RECURSIVE) ? "(R)" : ""); - depends_find_add(&newnhe->nhg_depends, nh, afi); + depends_find_add(&newnhe->nhg_depends, nh, afi, + newnhe->type); } } @@ -753,8 +806,8 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */ __func__, nh); /* Single recursive nexthop */ - handle_recursive_depend(&backup_nhe->nhg_depends, - nh->resolved, afi); + handle_recursive_depend(&backup_nhe->nhg_depends, nh->resolved, + afi, backup_nhe->type); recursive = true; } else { /* One or more backup NHs */ @@ -766,8 +819,8 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */ NEXTHOP_FLAG_RECURSIVE) ? "(R)" : ""); - depends_find_add(&backup_nhe->nhg_depends, - nh, afi); + depends_find_add(&backup_nhe->nhg_depends, nh, afi, + backup_nhe->type); } } @@ -960,30 +1013,6 @@ static struct nhg_ctx *nhg_ctx_init(uint32_t id, struct nexthop *nh, return ctx; } -static bool zebra_nhg_contains_unhashable(struct nhg_hash_entry *nhe) -{ - struct nhg_connected *rb_node_dep = NULL; - - frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) { - if (CHECK_FLAG(rb_node_dep->nhe->flags, - NEXTHOP_GROUP_UNHASHABLE)) - return true; - } - - return false; -} - -static void zebra_nhg_set_unhashable(struct nhg_hash_entry *nhe) -{ - SET_FLAG(nhe->flags, NEXTHOP_GROUP_UNHASHABLE); - SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); - - flog(LOG_INFO, - EC_ZEBRA_DUPLICATE_NHG_MESSAGE, - "Nexthop Group with ID (%d) is a duplicate, therefore unhashable, ignoring", - nhe->id); -} - static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe) { struct nhg_connected *rb_node_dep; @@ -1025,23 +1054,27 @@ done: zebra_nhg_set_invalid(nhe); } - -static void zebra_nhg_release(struct nhg_hash_entry *nhe) +static void zebra_nhg_release_all_deps(struct nhg_hash_entry *nhe) { - if (IS_ZEBRA_DEBUG_NHG_DETAIL) - zlog_debug("%s: nhe %p (%u)", __func__, nhe, nhe->id); - /* Remove it from any lists it may be on */ zebra_nhg_depends_release(nhe); zebra_nhg_dependents_release(nhe); if (nhe->ifp) if_nhg_dependents_del(nhe->ifp, nhe); +} + +static void zebra_nhg_release(struct nhg_hash_entry *nhe) +{ + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: nhe %p (%u)", __func__, nhe, nhe->id); + + zebra_nhg_release_all_deps(nhe); /* - * If its unhashable, we didn't store it here and have to be + * If its not zebra owned, we didn't store it here and have to be * sure we don't clear one thats actually being used. */ - if (!CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_UNHASHABLE)) + if (nhe->id < ZEBRA_NHG_PROTO_LOWER) hash_release(zrouter.nhgs, nhe); hash_release(zrouter.nhgs_id, nhe); @@ -1117,8 +1150,8 @@ static int nhg_ctx_process_new(struct nhg_ctx *ctx) return -ENOENT; } - if (!zebra_nhg_find(&nhe, id, nhg, &nhg_depends, vrf_id, type, - afi)) + if (!zebra_nhg_find(&nhe, id, nhg, &nhg_depends, vrf_id, afi, + type)) depends_decrement_free(&nhg_depends); /* These got copied over in zebra_nhg_alloc() */ @@ -1127,54 +1160,7 @@ static int nhg_ctx_process_new(struct nhg_ctx *ctx) nhe = zebra_nhg_find_nexthop(id, nhg_ctx_get_nh(ctx), afi, type); - if (nhe) { - if (id != nhe->id) { - struct nhg_hash_entry *kernel_nhe = NULL; - - /* Duplicate but with different ID from - * the kernel - */ - - /* The kernel allows duplicate nexthops - * as long as they have different IDs. - * We are ignoring those to prevent - * syncing problems with the kernel - * changes. - * - * We maintain them *ONLY* in the ID hash table to - * track them and set the flag to indicated - * their attributes are unhashable. - */ - - kernel_nhe = zebra_nhe_copy(nhe, id); - - if (IS_ZEBRA_DEBUG_NHG_DETAIL) - zlog_debug("%s: copying kernel nhe (%u), dup of %u", - __func__, id, nhe->id); - - zebra_nhg_insert_id(kernel_nhe); - zebra_nhg_set_unhashable(kernel_nhe); - } else if (zebra_nhg_contains_unhashable(nhe)) { - /* The group we got contains an unhashable/duplicated - * depend, so lets mark this group as unhashable as well - * and release it from the non-ID hash. - */ - if (IS_ZEBRA_DEBUG_NHG_DETAIL) - zlog_debug("%s: nhe %p (%u) unhashable", - __func__, nhe, nhe->id); - - hash_release(zrouter.nhgs, nhe); - zebra_nhg_set_unhashable(nhe); - } else { - /* It actually created a new nhe */ - if (IS_ZEBRA_DEBUG_NHG_DETAIL) - zlog_debug("%s: nhe %p (%u) is new", - __func__, nhe, nhe->id); - - SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID); - SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); - } - } else { + if (!nhe) { flog_err( EC_ZEBRA_TABLE_LOOKUP_FAILED, "Zebra failed to find or create a nexthop hash entry for ID (%u)", @@ -1182,6 +1168,12 @@ static int nhg_ctx_process_new(struct nhg_ctx *ctx) return -1; } + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: nhe %p (%u) is new", __func__, nhe, nhe->id); + + SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID); + SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); + return 0; } @@ -1283,7 +1275,7 @@ int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh, struct nh_grp *grp, zlog_debug("%s: nh %pNHv, id %u, count %d", __func__, nh, id, (int)count); - if (id > id_counter) + if (id > id_counter && id < ZEBRA_NHG_PROTO_LOWER) /* Increase our counter so we don't try to create * an ID that already exists */ @@ -1326,14 +1318,14 @@ int zebra_nhg_kernel_del(uint32_t id, vrf_id_t vrf_id) /* Some dependency helper functions */ static struct nhg_hash_entry *depends_find_recursive(const struct nexthop *nh, - afi_t afi) + afi_t afi, int type) { struct nhg_hash_entry *nhe; struct nexthop *lookup = NULL; lookup = nexthop_dup(nh, NULL); - nhe = zebra_nhg_find_nexthop(0, lookup, afi, 0); + nhe = zebra_nhg_find_nexthop(0, lookup, afi, type); nexthops_free(lookup); @@ -1341,7 +1333,7 @@ static struct nhg_hash_entry *depends_find_recursive(const struct nexthop *nh, } static struct nhg_hash_entry *depends_find_singleton(const struct nexthop *nh, - afi_t afi) + afi_t afi, int type) { struct nhg_hash_entry *nhe; struct nexthop lookup = {}; @@ -1351,7 +1343,7 @@ static struct nhg_hash_entry *depends_find_singleton(const struct nexthop *nh, */ nexthop_copy_no_recurse(&lookup, nh, NULL); - nhe = zebra_nhg_find_nexthop(0, &lookup, afi, 0); + nhe = zebra_nhg_find_nexthop(0, &lookup, afi, type); /* The copy may have allocated labels; free them if necessary. */ nexthop_del_labels(&lookup); @@ -1363,10 +1355,10 @@ static struct nhg_hash_entry *depends_find_singleton(const struct nexthop *nh, return nhe; } -static struct nhg_hash_entry *depends_find(const struct nexthop *nh, afi_t afi) +static struct nhg_hash_entry *depends_find(const struct nexthop *nh, afi_t afi, + int type) { struct nhg_hash_entry *nhe = NULL; - char rbuf[10]; if (!nh) goto done; @@ -1374,18 +1366,18 @@ static struct nhg_hash_entry *depends_find(const struct nexthop *nh, afi_t afi) /* We are separating these functions out to increase handling speed * in the non-recursive case (by not alloc/freeing) */ - if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)) { - nhe = depends_find_recursive(nh, afi); - strlcpy(rbuf, "(R)", sizeof(rbuf)); - } else { - nhe = depends_find_singleton(nh, afi); - rbuf[0] = '\0'; - } + if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)) + nhe = depends_find_recursive(nh, afi, type); + else + nhe = depends_find_singleton(nh, afi, type); - if (IS_ZEBRA_DEBUG_NHG_DETAIL) - zlog_debug("%s: nh %pNHv %s => %p (%u)", - __func__, nh, rbuf, + + if (IS_ZEBRA_DEBUG_NHG_DETAIL) { + zlog_debug("%s: nh %pNHv %s => %p (%u)", __func__, nh, + CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE) ? "(R)" + : "", nhe, nhe ? nhe->id : 0); + } done: return nhe; @@ -1410,11 +1402,11 @@ static void depends_add(struct nhg_connected_tree_head *head, static struct nhg_hash_entry * depends_find_add(struct nhg_connected_tree_head *head, struct nexthop *nh, - afi_t afi) + afi_t afi, int type) { struct nhg_hash_entry *depend = NULL; - depend = depends_find(nh, afi); + depend = depends_find(nh, afi, type); if (IS_ZEBRA_DEBUG_NHG_DETAIL) zlog_debug("%s: nh %pNHv => %p", @@ -1446,8 +1438,9 @@ static void depends_decrement_free(struct nhg_connected_tree_head *head) } /* Find an nhe based on a list of nexthops */ -struct nhg_hash_entry * -zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi) +struct nhg_hash_entry *zebra_nhg_rib_find(uint32_t id, + struct nexthop_group *nhg, + afi_t rt_afi, int type) { struct nhg_hash_entry *nhe = NULL; vrf_id_t vrf_id; @@ -1459,7 +1452,7 @@ zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi) assert(nhg->nexthop); vrf_id = !vrf_is_backend_netns() ? VRF_DEFAULT : nhg->nexthop->vrf_id; - zebra_nhg_find(&nhe, id, nhg, NULL, vrf_id, rt_afi, 0); + zebra_nhg_find(&nhe, id, nhg, NULL, vrf_id, rt_afi, type); if (IS_ZEBRA_DEBUG_NHG_DETAIL) zlog_debug("%s: => nhe %p (%u)", @@ -1830,13 +1823,13 @@ 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) { - if (IS_ZEBRA_DEBUG_NHG_DETAIL) + if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug("nexthop %pNHv marked onlink but nhif %u doesn't exist", nexthop, nexthop->ifindex); return 0; } if (!if_is_operative(ifp)) { - if (IS_ZEBRA_DEBUG_NHG_DETAIL) + if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug("nexthop %pNHv marked onlink but nhif %s is not operational", nexthop, ifp->name); return 0; @@ -1992,6 +1985,11 @@ static int nexthop_active(afi_t afi, struct route_entry *re, || nexthop->type == NEXTHOP_TYPE_IPV6) nexthop->ifindex = newhop->ifindex; else if (nexthop->ifindex != newhop->ifindex) { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%s: %pNHv given ifindex does not match nexthops ifindex found found: %pNHv", + __func__, nexthop, + newhop); /* * NEXTHOP_TYPE_*_IFINDEX but ifindex * doesn't match what we found. @@ -2013,7 +2011,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re, /* Only useful if installed */ if (!CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED)) { - if (IS_ZEBRA_DEBUG_NHG_DETAIL) + if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug("%s: match %p (%u) not installed", __func__, match, match->nhe->id); @@ -2327,6 +2325,22 @@ static uint32_t nexthop_list_active_update(struct route_node *rn, return counter; } + +static uint32_t proto_nhg_nexthop_active_update(struct nexthop_group *nhg) +{ + struct nexthop *nh; + uint32_t curr_active = 0; + + /* Assume all active for now */ + + for (nh = nhg->nexthop; nh; nh = nh->next) { + SET_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE); + curr_active++; + } + + return curr_active; +} + /* * Iterate over all nexthops of the given RIB entry and refresh their * ACTIVE flag. If any nexthop is found to toggle the ACTIVE flag, @@ -2339,6 +2353,9 @@ int nexthop_active_update(struct route_node *rn, struct route_entry *re) struct nhg_hash_entry *curr_nhe; uint32_t curr_active = 0, backup_active = 0; + if (re->nhe->id >= ZEBRA_NHG_PROTO_LOWER) + return proto_nhg_nexthop_active_update(&re->nhe->nhg); + afi_t rt_afi = family2afi(rn->p.family); UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED); @@ -2544,7 +2561,8 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe) && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED)) { /* Change its type to us since we are installing it */ - nhe->type = ZEBRA_ROUTE_NHG; + if (!ZEBRA_NHG_CREATED(nhe)) + nhe->type = ZEBRA_ROUTE_NHG; int ret = dplane_nexthop_add(nhe); @@ -2701,3 +2719,251 @@ bool zebra_nhg_kernel_nexthops_enabled(void) { return g_nexthops_enabled; } + +/* + * Global control to only use kernel nexthops for protocol created NHGs. + * There are some use cases where you may not want zebra to implicitly + * create kernel nexthops for all routes and only create them for NHGs + * passed down by upper level protos. + * + * Default is off. + */ +void zebra_nhg_set_proto_nexthops_only(bool set) +{ + proto_nexthops_only = set; +} + +bool zebra_nhg_proto_nexthops_only(void) +{ + return proto_nexthops_only; +} + +/* Add NHE from upper level proto */ +struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type, + struct nexthop_group *nhg, afi_t afi) +{ + struct nhg_hash_entry lookup; + struct nhg_hash_entry *new, *old; + struct nhg_connected *rb_node_dep = NULL; + struct nexthop *newhop; + bool replace = false; + + if (!nhg->nexthop) { + if (IS_ZEBRA_DEBUG_NHG) + zlog_debug("%s: id %u, no nexthops passed to add", + __func__, id); + return NULL; + } + + + /* Set nexthop list as active, since they wont go through rib + * processing. + * + * Assuming valid/onlink for now. + * + * Once resolution is figured out, we won't need this! + */ + for (ALL_NEXTHOPS_PTR(nhg, newhop)) { + if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + if (IS_ZEBRA_DEBUG_NHG) + zlog_debug( + "%s: id %u, backup nexthops not supported", + __func__, id); + return NULL; + } + + if (newhop->type == NEXTHOP_TYPE_BLACKHOLE) { + if (IS_ZEBRA_DEBUG_NHG) + zlog_debug( + "%s: id %u, blackhole nexthop not supported", + __func__, id); + return NULL; + } + + if (newhop->type == NEXTHOP_TYPE_IFINDEX) { + if (IS_ZEBRA_DEBUG_NHG) + zlog_debug( + "%s: id %u, nexthop without gateway not supported", + __func__, id); + return NULL; + } + + if (!newhop->ifindex) { + if (IS_ZEBRA_DEBUG_NHG) + zlog_debug( + "%s: id %u, nexthop without ifindex is not supported", + __func__, id); + return NULL; + } + SET_FLAG(newhop->flags, NEXTHOP_FLAG_ACTIVE); + } + + zebra_nhe_init(&lookup, afi, nhg->nexthop); + lookup.nhg.nexthop = nhg->nexthop; + lookup.id = id; + lookup.type = type; + + old = zebra_nhg_lookup_id(id); + + if (old) { + /* + * This is a replace, just release NHE from ID for now, The + * depends/dependents may still be used in the replacement. + */ + replace = true; + hash_release(zrouter.nhgs_id, old); + } + + new = zebra_nhg_rib_find_nhe(&lookup, afi); + + zebra_nhg_increment_ref(new); + + zebra_nhg_set_valid_if_active(new); + + zebra_nhg_install_kernel(new); + + if (old) { + /* + * Check to handle recving DEL while routes still in use then + * a replace. + * + * In this case we would have decremented the refcnt already + * but set the FLAG here. Go ahead and increment once to fix + * the misordering we have been sent. + */ + if (CHECK_FLAG(old->flags, NEXTHOP_GROUP_PROTO_RELEASED)) + zebra_nhg_increment_ref(old); + + rib_handle_nhg_replace(old, new); + + /* if this != 1 at this point, we have a bug */ + assert(old->refcnt == 1); + + /* We have to decrement its singletons + * because some might not exist in NEW. + */ + if (!zebra_nhg_depends_is_empty(old)) { + frr_each (nhg_connected_tree, &old->nhg_depends, + rb_node_dep) + zebra_nhg_decrement_ref(rb_node_dep->nhe); + } + + /* Free all the things */ + zebra_nhg_release_all_deps(old); + + /* Dont call the dec API, we dont want to uninstall the ID */ + old->refcnt = 0; + zebra_nhg_free(old); + old = NULL; + } + + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: %s nhe %p (%u), vrf %d, type %s", __func__, + (replace ? "replaced" : "added"), new, new->id, + new->vrf_id, zebra_route_string(new->type)); + + return new; +} + +/* Delete NHE from upper level proto, caller must decrement ref */ +struct nhg_hash_entry *zebra_nhg_proto_del(uint32_t id, int type) +{ + struct nhg_hash_entry *nhe; + + nhe = zebra_nhg_lookup_id(id); + + if (!nhe) { + if (IS_ZEBRA_DEBUG_NHG) + zlog_debug("%s: id %u, lookup failed", __func__, id); + + return NULL; + } + + if (type != nhe->type) { + if (IS_ZEBRA_DEBUG_NHG) + zlog_debug( + "%s: id %u, type %s mismatch, sent by %s, ignoring", + __func__, id, zebra_route_string(nhe->type), + zebra_route_string(type)); + return NULL; + } + + if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_PROTO_RELEASED)) { + if (IS_ZEBRA_DEBUG_NHG) + zlog_debug("%s: id %u, already released", __func__, id); + + return NULL; + } + + SET_FLAG(nhe->flags, NEXTHOP_GROUP_PROTO_RELEASED); + + if (nhe->refcnt > 1) { + if (IS_ZEBRA_DEBUG_NHG) + zlog_debug( + "%s: id %u, still being used by routes refcnt %u", + __func__, nhe->id, nhe->refcnt); + return nhe; + } + + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: deleted nhe %p (%u), vrf %d, type %s", __func__, + nhe, nhe->id, nhe->vrf_id, + zebra_route_string(nhe->type)); + + return nhe; +} + +struct nhg_score_proto_iter { + int type; + struct list *found; +}; + +static void zebra_nhg_score_proto_entry(struct hash_bucket *bucket, void *arg) +{ + struct nhg_hash_entry *nhe; + struct nhg_score_proto_iter *iter; + + nhe = (struct nhg_hash_entry *)bucket->data; + iter = arg; + + /* Needs to match type and outside zebra ID space */ + if (nhe->type == iter->type && nhe->id >= ZEBRA_NHG_PROTO_LOWER) { + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug( + "%s: found nhe %p (%u), vrf %d, type %s after client disconnect", + __func__, nhe, nhe->id, nhe->vrf_id, + zebra_route_string(nhe->type)); + + /* Add to removal list */ + listnode_add(iter->found, nhe); + } +} + +/* Remove specific by proto NHGs */ +unsigned long zebra_nhg_score_proto(int type) +{ + struct nhg_hash_entry *nhe; + struct nhg_score_proto_iter iter = {}; + struct listnode *ln; + unsigned long count; + + iter.type = type; + iter.found = list_new(); + + /* Find matching entries to remove */ + hash_iterate(zrouter.nhgs_id, zebra_nhg_score_proto_entry, &iter); + + /* Now remove them */ + for (ALL_LIST_ELEMENTS_RO(iter.found, ln, nhe)) { + /* + * This should be the last ref if we remove client routes too, + * and thus should remove and free them. + */ + zebra_nhg_decrement_ref(nhe); + } + + count = iter.found->count; + list_delete(&iter.found); + + return count; +} diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h index de5f097472..052fa65d06 100644 --- a/zebra/zebra_nhg.h +++ b/zebra/zebra_nhg.h @@ -102,20 +102,23 @@ struct nhg_hash_entry { * Is this a nexthop that is recursively resolved? */ #define NEXTHOP_GROUP_RECURSIVE (1 << 3) -/* - * This is a nexthop group we got from the kernel, it is identical to - * one we already have. (The kernel allows duplicate nexthops, we don't - * since we hash on them). We are only tracking it in our ID table, - * it is unusable by our created routes but may be used by routes we get - * from the kernel. Therefore, it is unhashable. - */ -#define NEXTHOP_GROUP_UNHASHABLE (1 << 4) /* * Backup nexthop support - identify groups that are backups for * another group. */ -#define NEXTHOP_GROUP_BACKUP (1 << 5) +#define NEXTHOP_GROUP_BACKUP (1 << 4) + +/* + * The NHG has been release by an upper level protocol via the + * `zebra_nhg_proto_del()` API. + * + * We use this flag to track this state in case the NHG is still being used + * by routes therefore holding their refcnts as well. Otherwise, the NHG will + * be removed and uninstalled. + * + */ +#define NEXTHOP_GROUP_PROTO_RELEASED (1 << 5) /* * Track FPM installation status.. @@ -124,7 +127,11 @@ struct nhg_hash_entry { }; /* Was this one we created, either this session or previously? */ -#define ZEBRA_NHG_CREATED(NHE) ((NHE->type) == ZEBRA_ROUTE_NHG) +#define ZEBRA_NHG_CREATED(NHE) \ + (((NHE->type) <= ZEBRA_ROUTE_MAX) && (NHE->type != ZEBRA_ROUTE_KERNEL)) + +/* Is this an NHE owned by zebra and not an upper level protocol? */ +#define ZEBRA_OWNED(NHE) (NHE->type == ZEBRA_ROUTE_NHG) /* * Backup nexthops: this is a group object itself, so @@ -186,6 +193,10 @@ struct nhg_ctx { void zebra_nhg_enable_kernel_nexthops(bool set); bool zebra_nhg_kernel_nexthops_enabled(void); +/* Global control for zebra to only use proto-owned nexthops */ +void zebra_nhg_set_proto_nexthops_only(bool set); +bool zebra_nhg_proto_nexthops_only(void); + /** * NHE abstracted tree functions. * Use these where possible instead of direct access. @@ -249,13 +260,50 @@ extern int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh, extern int zebra_nhg_kernel_del(uint32_t id, vrf_id_t vrf_id); /* Find an nhe based on a nexthop_group */ -extern struct nhg_hash_entry * -zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi); +extern struct nhg_hash_entry *zebra_nhg_rib_find(uint32_t id, + struct nexthop_group *nhg, + afi_t rt_afi, int type); /* Find an nhe based on a route's nhe, used during route creation */ struct nhg_hash_entry * zebra_nhg_rib_find_nhe(struct nhg_hash_entry *rt_nhe, afi_t rt_afi); + +/** + * Functions for Add/Del/Replace via protocol NHG creation. + * + * The NHEs will not be hashed. They will only be present in the + * ID table and therefore not sharable. + * + * It is the owning protocols job to manage these. + */ + +/* + * Add NHE. If already exists, Replace. + * + * Returns allocated NHE on success, otherwise NULL. + */ +struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type, + struct nexthop_group *nhg, + afi_t afi); + +/* + * Del NHE. + * + * Returns deleted NHE on success, otherwise NULL. + * + * Caller must decrement ref with zebra_nhg_decrement_ref() when done. + */ +struct nhg_hash_entry *zebra_nhg_proto_del(uint32_t id, int type); + +/* + * Remove specific by proto NHGs. + * + * Called after client disconnect. + * + */ +unsigned long zebra_nhg_score_proto(int type); + /* Reference counter functions */ extern void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe); extern void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe); diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 6462daf687..e9ff3fcc08 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -199,7 +199,7 @@ int zebra_ns_init(const char *optional_default_name) if (ns) ns->relative_default_ns = ns_id; - default_ns = ns_lookup(ns_get_default_id()); + default_ns = ns_lookup(NS_DEFAULT); if (!default_ns) { flog_err(EC_ZEBRA_NS_NO_DEFAULT, "%s: failed to find default ns", __func__); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index ff30de18a3..aac0e628fe 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -235,7 +235,7 @@ int route_entry_update_nhe(struct route_entry *re, goto done; } - if ((re->nhe_id != 0) && (re->nhe_id != new_nhghe->id)) { + if ((re->nhe_id != 0) && re->nhe && (re->nhe != new_nhghe)) { old = re->nhe; route_entry_attach_ref(re, new_nhghe); @@ -250,6 +250,29 @@ done: return ret; } +void rib_handle_nhg_replace(struct nhg_hash_entry *old, + struct nhg_hash_entry *new) +{ + struct zebra_router_table *zrt; + struct route_node *rn; + struct route_entry *re, *next; + + if (IS_ZEBRA_DEBUG_RIB_DETAILED || IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: replacing routes nhe (%u) OLD %p NEW %p", + __func__, new->id, new, old); + + /* We have to do them ALL */ + RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) { + for (rn = route_top(zrt->table); rn; + rn = srcdest_route_next(rn)) { + RNODE_FOREACH_RE_SAFE (rn, re, next) { + if (re->nhe && re->nhe == old) + route_entry_update_nhe(re, new); + } + } + } +} + struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id, union g_addr *addr, struct route_node **rn_out) { @@ -2906,14 +2929,14 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, if (!table) return -1; - if (re_nhe->id > 0) { - nhe = zebra_nhg_lookup_id(re_nhe->id); + if (re->nhe_id > 0) { + nhe = zebra_nhg_lookup_id(re->nhe_id); if (!nhe) { flog_err( EC_ZEBRA_TABLE_LOOKUP_FAILED, "Zebra failed to find the nexthop hash entry for id=%u in a route entry", - re_nhe->id); + re->nhe_id); return -1; } diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c index 66f2924555..fc4390f7f8 100644 --- a/zebra/zebra_router.c +++ b/zebra/zebra_router.c @@ -290,4 +290,6 @@ void zebra_router_init(void) zrouter.nhgs_id = hash_create_size(8, zebra_nhg_id_key, zebra_nhg_hash_id_equal, "Zebra Router Nexthop Groups ID index"); + + zrouter.asic_offloaded = false; } diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h index f73a8f2d59..67f94bfcfe 100644 --- a/zebra/zebra_router.h +++ b/zebra/zebra_router.h @@ -182,6 +182,11 @@ struct zebra_router { */ struct hash *nhgs; struct hash *nhgs_id; + + /* + * Does the underlying system provide an asic offload + */ + bool asic_offloaded; }; #define GRACEFUL_RESTART_TIME 60 diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index b6d0b26125..6785151705 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -54,6 +54,7 @@ #include "zebra/zebra_vxlan_private.h" #include "zebra/zebra_pbr.h" #include "zebra/zebra_nhg.h" +#include "zebra/zebra_evpn_mh.h" #include "zebra/interface.h" #include "northbound_cli.h" #include "zebra/zebra_nb.h" @@ -61,12 +62,19 @@ extern int allow_delete; +/* context to manage dumps in multiple tables or vrfs */ +struct route_show_ctx { + bool multi; /* dump multiple tables or vrf */ + bool header_done; /* common header already displayed */ +}; + static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, safi_t safi, bool use_fib, bool use_json, route_tag_t tag, const struct prefix *longer_prefix_p, bool supernets_only, int type, - unsigned short ospf_instance_id, uint32_t tableid); + unsigned short ospf_instance_id, uint32_t tableid, + struct route_show_ctx *ctx); static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, int mcast, bool use_fib, bool show_ng); static void vty_show_ip_route_summary(struct vty *vty, @@ -140,8 +148,12 @@ DEFUN (show_ip_rpf, JSON_STR) { bool uj = use_json(argc, argv); + struct route_show_ctx ctx = { + .multi = false, + }; + return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST, - false, uj, 0, NULL, false, 0, 0, 0); + false, uj, 0, NULL, false, 0, 0, 0, &ctx); } DEFUN (show_ip_rpf_addr, @@ -192,6 +204,14 @@ static char re_status_output_char(const struct route_entry *re, star_p = true; } + if (zrouter.asic_offloaded + && CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED)) + return 't'; + + if (zrouter.asic_offloaded + && !CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED)) + return 'o'; + if (star_p) return '*'; else @@ -331,15 +351,8 @@ static void show_nexthop_detail_helper(struct vty *vty, } if ((re->vrf_id != nexthop->vrf_id) - && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) { - struct vrf *vrf = - vrf_lookup_by_id(nexthop->vrf_id); - - if (vrf) - vty_out(vty, "(vrf %s)", vrf->name); - else - vty_out(vty, "(vrf UNKNOWN)"); - } + && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) + vty_out(vty, "(vrf %s)", vrf_id_to_name(nexthop->vrf_id)); if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) vty_out(vty, " (duplicate nexthop removed)"); @@ -537,15 +550,9 @@ static void show_route_nexthop_helper(struct vty *vty, break; } - if ((re == NULL || (nexthop->vrf_id != re->vrf_id)) && - (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) { - struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id); - - if (vrf) - vty_out(vty, " (vrf %s)", vrf->name); - else - vty_out(vty, " (vrf UNKNOWN)"); - } + if ((re == NULL || (nexthop->vrf_id != re->vrf_id)) + && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) + vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id)); if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) vty_out(vty, " inactive"); @@ -609,7 +616,6 @@ static void show_nexthop_json_helper(json_object *json_nexthop, const struct route_entry *re) { char buf[SRCDEST2STR_BUFFER]; - struct vrf *vrf = NULL; json_object *json_labels = NULL; json_object *json_backups = NULL; int i; @@ -703,11 +709,10 @@ static void show_nexthop_json_helper(json_object *json_nexthop, } if ((nexthop->vrf_id != re->vrf_id) - && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) { - vrf = vrf_lookup_by_id(nexthop->vrf_id); + && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) json_object_string_add(json_nexthop, "vrf", - vrf->name); - } + vrf_id_to_name(nexthop->vrf_id)); + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) json_object_boolean_true_add(json_nexthop, "duplicate"); @@ -802,7 +807,6 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, json_object *json_nexthop = NULL; json_object *json_route = NULL; time_t uptime; - const struct vrf *vrf = NULL; const rib_dest_t *dest = rib_dest_from_rnode(rn); const struct nexthop_group *nhg; char up_str[MONOTIME_STRLEN]; @@ -835,13 +839,10 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, json_object_int_add(json_route, "instance", re->instance); - if (re->vrf_id) { - json_object_int_add(json_route, "vrfId", re->vrf_id); - vrf = vrf_lookup_by_id(re->vrf_id); - json_object_string_add(json_route, "vrfName", - vrf->name); + json_object_int_add(json_route, "vrfId", re->vrf_id); + json_object_string_add(json_route, "vrfName", + vrf_id_to_name(re->vrf_id)); - } if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) json_object_boolean_true_add(json_route, "selected"); @@ -862,6 +863,12 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED)) json_object_boolean_true_add(json_route, "queued"); + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED)) + json_object_boolean_true_add(json_route, "trapped"); + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED)) + json_object_boolean_true_add(json_route, "offloaded"); + if (re->tag) json_object_int_add(json_route, "tag", re->tag); @@ -1038,7 +1045,7 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf, const struct prefix *longer_prefix_p, bool supernets_only, int type, unsigned short ospf_instance_id, bool use_json, - uint32_t tableid) + uint32_t tableid, struct route_show_ctx *ctx) { struct route_node *rn; struct route_entry *re; @@ -1049,6 +1056,17 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf, uint32_t addr; char buf[BUFSIZ]; + /* + * ctx->multi indicates if we are dumping multiple tables or vrfs. + * if set: + * => display the common header at most once + * => add newline at each call except first + * => always display the VRF and table + * else: + * => display the common header if at least one entry is found + * => display the VRF and table if specific + */ + if (use_json) json = json_object_new_object(); @@ -1092,23 +1110,30 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf, if (use_json) { if (!json_prefix) json_prefix = json_object_new_array(); - } else { - if (first) { + } else if (first) { + if (!ctx->header_done) { if (afi == AFI_IP) vty_out(vty, SHOW_ROUTE_V4_HEADER); else vty_out(vty, SHOW_ROUTE_V6_HEADER); - - if (tableid && tableid != RT_TABLE_MAIN) - vty_out(vty, "\nVRF %s table %u:\n", - zvrf_name(zvrf), tableid); - else if (zvrf_id(zvrf) != VRF_DEFAULT) - vty_out(vty, "\nVRF %s:\n", + } + if (ctx->multi && ctx->header_done) + vty_out(vty, "\n"); + if (ctx->multi || zvrf_id(zvrf) != VRF_DEFAULT + || tableid) { + if (!tableid) + vty_out(vty, "VRF %s:\n", zvrf_name(zvrf)); - first = 0; + else + vty_out(vty, + "VRF %s table %u:\n", + zvrf_name(zvrf), + tableid); } + ctx->header_done = true; + first = 0; } vty_show_ip_route(vty, rn, re, json_prefix, use_fib); @@ -1133,7 +1158,8 @@ static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf, route_tag_t tag, const struct prefix *longer_prefix_p, bool supernets_only, int type, - unsigned short ospf_instance_id) + unsigned short ospf_instance_id, + struct route_show_ctx *ctx) { struct zebra_router_table *zrt; struct rib_table_info *info; @@ -1148,11 +1174,10 @@ static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf, zrt->safi != SAFI_UNICAST) continue; - do_show_ip_route(vty, zvrf_name(zvrf), afi, - SAFI_UNICAST, use_fib, use_json, - tag, longer_prefix_p, - supernets_only, type, - ospf_instance_id, zrt->tableid); + do_show_ip_route(vty, zvrf_name(zvrf), afi, SAFI_UNICAST, + use_fib, use_json, tag, longer_prefix_p, + supernets_only, type, ospf_instance_id, + zrt->tableid, ctx); } } @@ -1161,7 +1186,8 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, route_tag_t tag, const struct prefix *longer_prefix_p, bool supernets_only, int type, - unsigned short ospf_instance_id, uint32_t tableid) + unsigned short ospf_instance_id, uint32_t tableid, + struct route_show_ctx *ctx) { struct route_table *table; struct zebra_vrf *zvrf = NULL; @@ -1194,7 +1220,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, do_show_route_helper(vty, zvrf, table, afi, use_fib, tag, longer_prefix_p, supernets_only, type, - ospf_instance_id, use_json, tableid); + ospf_instance_id, use_json, tableid, ctx); return CMD_SUCCESS; } @@ -1272,21 +1298,11 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe) { struct nexthop *nexthop = NULL; struct nhg_connected *rb_node_dep = NULL; - struct vrf *nhe_vrf = vrf_lookup_by_id(nhe->vrf_id); struct nexthop_group *backup_nhg; - vty_out(vty, "ID: %u\n", nhe->id); + vty_out(vty, "ID: %u (%s)\n", nhe->id, zebra_route_string(nhe->type)); vty_out(vty, " RefCnt: %d\n", nhe->refcnt); - - if (nhe_vrf) - vty_out(vty, " VRF: %s AFI: %s\n", nhe_vrf->name, - afi2str(nhe->afi)); - else - vty_out(vty, " VRF: UNKNOWN AFI: %s\n", - afi2str(nhe->afi)); - - if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_UNHASHABLE)) - vty_out(vty, " Duplicate - from kernel not hashable\n"); + vty_out(vty, " VRF: %s\n", vrf_id_to_name(nhe->vrf_id)); if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) { vty_out(vty, " Valid"); @@ -1550,6 +1566,17 @@ DEFPY_HIDDEN(nexthop_group_use_enable, return CMD_SUCCESS; } +DEFPY_HIDDEN(proto_nexthop_group_only, proto_nexthop_group_only_cmd, + "[no] zebra nexthop proto only", + NO_STR ZEBRA_STR + "Nexthop configuration\n" + "Configure exclusive use of proto nexthops\n" + "Only use proto nexthops\n") +{ + zebra_nhg_set_proto_nexthops_only(!no); + return CMD_SUCCESS; +} + DEFUN (no_ip_nht_default_route, no_ip_nht_default_route_cmd, "no ip nht resolve-via-default", @@ -1671,6 +1698,9 @@ DEFPY (show_route, struct vrf *vrf; int type = 0; struct zebra_vrf *zvrf; + struct route_show_ctx ctx = { + .multi = vrf_all || table_all, + }; if (!vrf_is_backend_netns()) { if ((vrf_all || vrf_name) && (table || table_all)) { @@ -1698,17 +1728,18 @@ DEFPY (show_route, continue; if (table_all) - do_show_ip_route_all(vty, zvrf, afi, - !!fib, !!json, - tag, prefix_str ? prefix : NULL, + do_show_ip_route_all(vty, zvrf, afi, !!fib, + !!json, tag, + prefix_str ? prefix : NULL, !!supernets_only, type, - ospf_instance_id); + ospf_instance_id, &ctx); else do_show_ip_route(vty, zvrf_name(zvrf), afi, - SAFI_UNICAST, !!fib, !!json, tag, + SAFI_UNICAST, !!fib, !!json, + tag, prefix_str ? prefix : NULL, !!supernets_only, type, - ospf_instance_id, table); + ospf_instance_id, table, &ctx); } } else { vrf_id_t vrf_id = VRF_DEFAULT; @@ -1722,15 +1753,16 @@ DEFPY (show_route, return CMD_SUCCESS; if (table_all) - do_show_ip_route_all(vty, zvrf, afi, - !!fib, !!json, - tag, prefix_str ? prefix : NULL, + do_show_ip_route_all(vty, zvrf, afi, !!fib, !!json, tag, + prefix_str ? prefix : NULL, !!supernets_only, type, - ospf_instance_id); + ospf_instance_id, &ctx); else - do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib, - !!json, tag, prefix_str ? prefix : NULL, - !!supernets_only, type, ospf_instance_id, table); + do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, + !!fib, !!json, tag, + prefix_str ? prefix : NULL, + !!supernets_only, type, + ospf_instance_id, table, &ctx); } return CMD_SUCCESS; @@ -2346,6 +2378,33 @@ DEFUN (show_vrf, return CMD_SUCCESS; } +DEFPY (evpn_mh_mac_holdtime, + evpn_mh_mac_holdtime_cmd, + "[no$no] evpn mh mac-holdtime (0-86400)$duration", + NO_STR + "EVPN\n" + "Multihoming\n" + "MAC hold time\n" + "Duration in seconds\n") +{ + return zebra_evpn_mh_mac_holdtime_update(vty, duration, + no ? true : false); +} + +DEFPY (evpn_mh_neigh_holdtime, + evpn_mh_neigh_holdtime_cmd, + "[no$no] evpn mh neigh-holdtime (0-86400)$duration", + NO_STR + "EVPN\n" + "Multihoming\n" + "Neighbor entry hold time\n" + "Duration in seconds\n") +{ + + return zebra_evpn_mh_neigh_holdtime_update(vty, duration, + no ? true : false); +} + DEFUN (default_vrf_vni_mapping, default_vrf_vni_mapping_cmd, "vni " CMD_VNI_RANGE "[prefix-routes-only]", @@ -3394,10 +3453,15 @@ static int config_write_protocol(struct vty *vty) /* Include dataplane info */ dplane_config_write_helper(vty); + zebra_evpn_mh_config_write(vty); + /* Include nexthop-group config */ if (!zebra_nhg_kernel_nexthops_enabled()) vty_out(vty, "no zebra nexthop kernel enable\n"); + if (zebra_nhg_proto_nexthops_only()) + vty_out(vty, "zebra nexthop proto only\n"); + #ifdef HAVE_NETLINK /* Include netlink info */ netlink_config_write_helper(vty); @@ -3414,6 +3478,9 @@ DEFUN (show_zebra, { struct vrf *vrf; + if (zrouter.asic_offloaded) + vty_out(vty, "Asic Offload is being used\n"); + vty_out(vty, " Route Route Neighbor LSP LSP\n"); vty_out(vty, @@ -3829,6 +3896,7 @@ void zebra_vty_init(void) install_element(CONFIG_NODE, &zebra_packet_process_cmd); install_element(CONFIG_NODE, &no_zebra_packet_process_cmd); install_element(CONFIG_NODE, &nexthop_group_use_enable_cmd); + install_element(CONFIG_NODE, &proto_nexthop_group_only_cmd); install_element(VIEW_NODE, &show_nexthop_group_cmd); install_element(VIEW_NODE, &show_interface_nexthop_group_cmd); @@ -3890,6 +3958,8 @@ void zebra_vty_init(void) install_element(VIEW_NODE, &show_pbr_ipset_cmd); install_element(VIEW_NODE, &show_pbr_iptable_cmd); + install_element(CONFIG_NODE, &evpn_mh_mac_holdtime_cmd); + install_element(CONFIG_NODE, &evpn_mh_neigh_holdtime_cmd); install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd); install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd); install_element(VRF_NODE, &vrf_vni_mapping_cmd); diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 61498973e9..d8ed58edef 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -4594,6 +4594,11 @@ int zebra_vxlan_if_down(struct interface *ifp) assert(zevpn->vxlan_if == ifp); + /* remove from l3-vni list */ + zl3vni = zl3vni_from_vrf(zevpn->vrf_id); + if (zl3vni) + listnode_delete(zl3vni->l2vnis, zevpn); + /* Delete this VNI from BGP. */ zebra_evpn_send_del_to_client(zevpn); @@ -4668,7 +4673,7 @@ int zebra_vxlan_if_up(struct interface *ifp) zevpn->vrf_id = vlan_if->vrf_id; zl3vni = zl3vni_from_vrf(vlan_if->vrf_id); if (zl3vni) - listnode_add_sort(zl3vni->l2vnis, zevpn); + listnode_add_sort_nodup(zl3vni->l2vnis, zevpn); } /* If part of a bridge, inform BGP about this VNI. */ @@ -5007,7 +5012,7 @@ int zebra_vxlan_if_add(struct interface *ifp) zevpn->vrf_id = vlan_if->vrf_id; zl3vni = zl3vni_from_vrf(vlan_if->vrf_id); if (zl3vni) - listnode_add_sort(zl3vni->l2vnis, zevpn); + listnode_add_sort_nodup(zl3vni->l2vnis, zevpn); } if (IS_ZEBRA_DEBUG_VXLAN) { diff --git a/zebra/zserv.c b/zebra/zserv.c index 4c8656af0d..44f4641fcf 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -590,6 +590,7 @@ static void zserv_client_free(struct zserv *client) /* Close file descriptor. */ if (client->sock) { unsigned long nroutes; + unsigned long nnhgs; close(client->sock); @@ -600,6 +601,13 @@ static void zserv_client_free(struct zserv *client) "client %d disconnected %lu %s routes removed from the rib", client->sock, nroutes, zebra_route_string(client->proto)); + + /* Not worrying about instance for now */ + nnhgs = zebra_nhg_score_proto(client->proto); + zlog_notice( + "client %d disconnected %lu %s nhgs removed from the rib", + client->sock, nnhgs, + zebra_route_string(client->proto)); } client->sock = -1; } |
