diff options
205 files changed, 2640 insertions, 2613 deletions
diff --git a/Makefile.am b/Makefile.am index e4149b62ed..a5101df2f0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,11 +11,19 @@ AM_CFLAGS = \ $(SAN_FLAGS) \ $(WERROR) \ # end -AM_CPPFLAGS = \ + +# CPPFLAGS_BASE does not contain the include path for overriding assert.h, +# therefore should be used in tools that do *not* link libfrr or do not want +# assert() overridden +CPPFLAGS_BASE = \ -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/lib \ -I$(top_builddir) \ $(LUA_INCLUDE) \ # end +AM_CPPFLAGS = \ + -I$(top_srcdir)/lib/assert \ + $(CPPFLAGS_BASE) \ + # end AM_LDFLAGS = \ -export-dynamic \ $(AC_LDFLAGS) \ diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c index b9ea26e862..6e80765f86 100644 --- a/bgpd/bgp_conditional_adv.c +++ b/bgpd/bgp_conditional_adv.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "bgpd/bgp_conditional_adv.h" #include "bgpd/bgp_vty.h" diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index a9fceb6cde..047b9742ee 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -586,7 +586,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, uint8_t flags, uint32_t seq, esi_t *esi) { struct stream *s; - int ipa_len; + uint16_t ipa_len; static struct in_addr zero_remote_vtep_ip; /* Check socket. */ @@ -614,11 +614,11 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, stream_put(s, &p->prefix.macip_addr.mac.octet, ETH_ALEN); /* Mac Addr */ /* IP address length and IP address, if any. */ if (is_evpn_prefix_ipaddr_none(p)) - stream_putl(s, 0); + stream_putw(s, 0); else { ipa_len = is_evpn_prefix_ipaddr_v4(p) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; - stream_putl(s, ipa_len); + stream_putw(s, ipa_len); stream_put(s, &p->prefix.macip_addr.ip.ip.addr, ipa_len); } /* If the ESI is valid that becomes the nexthop; tape out the diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index 5d1a7a98d7..8d6691945f 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -40,9 +40,6 @@ struct as_list_list { /* AS path filter master. */ struct as_list_master { - /* List of access_list which name is number. */ - struct as_list_list num; - /* List of access_list which name is string. */ struct as_list_list str; @@ -71,8 +68,6 @@ struct as_filter { struct as_list { char *name; - enum access_type type; - struct as_list *next; struct as_list *prev; @@ -115,7 +110,6 @@ static struct as_filter *bgp_aslist_seq_check(struct as_list *list, int64_t seq) /* as-path access-list 10 permit AS1. */ static struct as_list_master as_list_master = {{NULL, NULL}, - {NULL, NULL}, NULL, NULL}; @@ -237,10 +231,6 @@ struct as_list *as_list_lookup(const char *name) if (name == NULL) return NULL; - for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) - if (strcmp(aslist->name, name) == 0) - return aslist; - for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) if (strcmp(aslist->name, name) == 0) return aslist; @@ -263,8 +253,6 @@ static void as_list_free(struct as_list *aslist) the name. */ static struct as_list *as_list_insert(const char *name) { - size_t i; - long number; struct as_list *aslist; struct as_list *point; struct as_list_list *list; @@ -274,36 +262,13 @@ static struct as_list *as_list_insert(const char *name) aslist->name = XSTRDUP(MTYPE_AS_STR, name); assert(aslist->name); - /* If name is made by all digit character. We treat it as - number. */ - for (number = 0, i = 0; i < strlen(name); i++) { - if (isdigit((unsigned char)name[i])) - number = (number * 10) + (name[i] - '0'); - else - break; - } - - /* In case of name is all digit character */ - if (i == strlen(name)) { - aslist->type = ACCESS_TYPE_NUMBER; - - /* Set access_list to number list. */ - list = &as_list_master.num; - - for (point = list->head; point; point = point->next) - if (atol(point->name) >= number) - break; - } else { - aslist->type = ACCESS_TYPE_STRING; - - /* Set access_list to string list. */ - list = &as_list_master.str; + /* Set access_list to string list. */ + list = &as_list_master.str; - /* Set point to insertion point. */ - for (point = list->head; point; point = point->next) - if (strcmp(point->name, name) >= 0) - break; - } + /* Set point to insertion point. */ + for (point = list->head; point; point = point->next) + if (strcmp(point->name, name) >= 0) + break; /* In case of this is the first element of master. */ if (list->head == NULL) { @@ -371,10 +336,7 @@ static void as_list_delete(struct as_list *aslist) as_filter_free(filter); } - if (aslist->type == ACCESS_TYPE_NUMBER) - list = &as_list_master.num; - else - list = &as_list_master.str; + list = &as_list_master.str; if (aslist->next) aslist->next->prev = aslist->prev; @@ -667,17 +629,6 @@ static void as_list_show_all(struct vty *vty) struct as_list *aslist; struct as_filter *asfilter; - for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) { - vty_out(vty, "AS path access list %s\n", aslist->name); - - for (asfilter = aslist->head; asfilter; - asfilter = asfilter->next) { - vty_out(vty, " %s %s\n", - filter_type_str(asfilter->type), - asfilter->reg_str); - } - } - for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) { vty_out(vty, "AS path access list %s\n", aslist->name); @@ -740,18 +691,6 @@ static int config_write_as_list(struct vty *vty) struct as_filter *asfilter; int write = 0; - for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) - for (asfilter = aslist->head; asfilter; - asfilter = asfilter->next) { - vty_out(vty, - "bgp as-path access-list %s seq %" PRId64 - " %s %s\n", - aslist->name, asfilter->seq, - filter_type_str(asfilter->type), - asfilter->reg_str); - write++; - } - for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) { @@ -794,19 +733,11 @@ void bgp_filter_reset(void) struct as_list *aslist; struct as_list *next; - for (aslist = as_list_master.num.head; aslist; aslist = next) { - next = aslist->next; - as_list_delete(aslist); - } - for (aslist = as_list_master.str.head; aslist; aslist = next) { next = aslist->next; as_list_delete(aslist); } - assert(as_list_master.num.head == NULL); - assert(as_list_master.num.tail == NULL); - assert(as_list_master.str.head == NULL); assert(as_list_master.str.tail == NULL); } diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c index c2d8cae580..e9b0f9e46a 100644 --- a/bgpd/bgp_io.c +++ b/bgpd/bgp_io.c @@ -32,7 +32,6 @@ #include "stream.h" // for stream_get_endp, stream_getw_from, str... #include "ringbuf.h" // for ringbuf_remain, ringbuf_peek, ringbuf_... #include "thread.h" // for THREAD_OFF, THREAD_ARG, thread... -#include "zassert.h" // for assert #include "bgpd/bgp_io.h" #include "bgpd/bgp_debug.h" // for bgp_debug_neighbor_events, bgp_type_str @@ -462,10 +461,13 @@ done : { */ static uint16_t bgp_read(struct peer *peer, int *code_p) { + size_t readsize; // how many bytes we want to read ssize_t nbytes; // how many bytes we actually read uint16_t status = 0; - nbytes = ringbuf_read(peer->ibuf_work, peer->fd); + readsize = + MIN(ringbuf_space(peer->ibuf_work), sizeof(peer->ibuf_scratch)); + nbytes = read(peer->fd, peer->ibuf_scratch, readsize); /* EAGAIN or EWOULDBLOCK; come back later */ if (nbytes < 0 && ERRNO_IO_RETRY(errno)) { @@ -493,6 +495,9 @@ static uint16_t bgp_read(struct peer *peer, int *code_p) *code_p = TCP_connection_closed; SET_FLAG(status, BGP_IO_FATAL_ERR); + } else { + assert(ringbuf_put(peer->ibuf_work, peer->ibuf_scratch, nbytes) + == (size_t)nbytes); } return status; diff --git a/bgpd/bgp_nb.c b/bgpd/bgp_nb.c index 2547439499..21810b634d 100644 --- a/bgpd/bgp_nb.c +++ b/bgpd/bgp_nb.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "northbound.h" #include "libfrr.h" #include "bgpd/bgp_nb.h" diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c index 307fa4e9bc..ff2c8ce93e 100644 --- a/bgpd/bgp_nb_config.c +++ b/bgpd/bgp_nb_config.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "northbound.h" #include "libfrr.h" #include "log.h" diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 8d9024e07c..55d7a29d98 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -376,7 +376,6 @@ static int bgp_accept(struct thread *thread) accept_sock); return -1; } - listener->thread = NULL; thread_add_read(bm->master, bgp_accept, listener, accept_sock, &listener->thread); @@ -838,7 +837,6 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen, listener->bgp = bgp; memcpy(&listener->su, sa, salen); - listener->thread = NULL; thread_add_read(bm->master, bgp_accept, listener, sock, &listener->thread); listnode_add(bm->listen_sockets, listener); diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 24df324633..d79621a749 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1000,98 +1000,90 @@ static int bgp_collision_detect(struct peer *new, struct in_addr remote_id) { struct peer *peer; - /* Upon receipt of an OPEN message, the local system must examine - all of its connections that are in the OpenConfirm state. A BGP - speaker may also examine connections in an OpenSent state if it - knows the BGP Identifier of the peer by means outside of the - protocol. If among these connections there is a connection to a - remote BGP speaker whose BGP Identifier equals the one in the - OPEN message, then the local system performs the following - collision resolution procedure: */ - - if ((peer = new->doppelganger) != NULL) { - /* Do not accept the new connection in Established or Clearing - * states. - * Note that a peer GR is handled by closing the existing - * connection - * upon receipt of new one. + /* + * Upon receipt of an OPEN message, the local system must examine + * all of its connections that are in the OpenConfirm state. A BGP + * speaker may also examine connections in an OpenSent state if it + * knows the BGP Identifier of the peer by means outside of the + * protocol. If among these connections there is a connection to a + * remote BGP speaker whose BGP Identifier equals the one in the + * OPEN message, then the local system performs the following + * collision resolution procedure: + */ + peer = new->doppelganger; + if (peer == NULL) + return 0; + + /* + * Do not accept the new connection in Established or Clearing + * states. Note that a peer GR is handled by closing the existing + * connection upon receipt of new one. + */ + if (peer->status == Established || peer->status == Clearing) { + bgp_notify_send(new, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return -1; + } + + if ((peer->status != OpenConfirm) && (peer->status != OpenSent)) + return 0; + + /* + * 1. The BGP Identifier of the local system is + * compared to the BGP Identifier of the remote + * system (as specified in the OPEN message). + * + * If the BGP Identifiers of the peers + * involved in the connection collision + * are identical, then the connection + * initiated by the BGP speaker with the + * larger AS number is preserved. + */ + if (ntohl(peer->local_id.s_addr) < ntohl(remote_id.s_addr) + || (ntohl(peer->local_id.s_addr) == ntohl(remote_id.s_addr) + && peer->local_as < peer->as)) + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) { + /* + * 2. If the value of the local BGP + * Identifier is less than the remote one, + * the local system closes BGP connection + * that already exists (the one that is + * already in the OpenConfirm state), + * and accepts BGP connection initiated by + * the remote system. + */ + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return 1; + } else { + bgp_notify_send(new, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return -1; + } + else { + if (ntohl(peer->local_id.s_addr) == ntohl(remote_id.s_addr) + && peer->local_as == peer->as) + flog_err(EC_BGP_ROUTER_ID_SAME, + "Peer's router-id %pI4 is the same as ours", + &remote_id); + + /* + * 3. Otherwise, the local system closes newly + * created BGP connection (the one associated with the + * newly received OPEN message), and continues to use + * the existing one (the one that is already in the + * OpenConfirm state). */ - if (peer->status == Established || peer->status == Clearing) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) { + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return 1; + } else { bgp_notify_send(new, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); return -1; - } else if ((peer->status == OpenConfirm) - || (peer->status == OpenSent)) { - /* 1. The BGP Identifier of the local system is - * compared to the BGP Identifier of the remote - * system (as specified in the OPEN message). - * - * If the BGP Identifiers of the peers - * involved in the connection collision - * are identical, then the connection - * initiated by the BGP speaker with the - * larger AS number is preserved. - */ - if (ntohl(peer->local_id.s_addr) - < ntohl(remote_id.s_addr) - || (ntohl(peer->local_id.s_addr) - == ntohl(remote_id.s_addr) - && peer->local_as < peer->as)) - if (!CHECK_FLAG(peer->sflags, - PEER_STATUS_ACCEPT_PEER)) { - /* 2. If the value of the local BGP - Identifier is less - than the remote one, the local system - closes BGP - connection that already exists (the - one that is - already in the OpenConfirm state), - and accepts BGP - connection initiated by the remote - system. */ - bgp_notify_send( - peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - return 1; - } else { - bgp_notify_send( - new, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - return -1; - } - else { - if (ntohl(peer->local_id.s_addr) - == ntohl(remote_id.s_addr) - && peer->local_as == peer->as) - flog_err( - EC_BGP_ROUTER_ID_SAME, - "Peer's router-id %pI4 is the same as ours", - &remote_id); - - /* 3. Otherwise, the local system closes newly - created - BGP connection (the one associated with the - newly - received OPEN message), and continues to use - the - existing one (the one that is already in the - OpenConfirm state). */ - if (CHECK_FLAG(peer->sflags, - PEER_STATUS_ACCEPT_PEER)) { - bgp_notify_send( - peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - return 1; - } else { - bgp_notify_send( - new, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - return -1; - } - } } } - return 0; } /* Packet processing routines ---------------------------------------------- */ @@ -1269,9 +1261,6 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) return BGP_Stop; } - /* Set remote router-id */ - peer->remote_id = remote_id; - /* Peer BGP version check. */ if (version != BGP_VERSION_4) { uint16_t maxver = htons(BGP_VERSION_4); @@ -1331,6 +1320,25 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) return BGP_Stop; } + /* + * When collision is detected and this peer is closed. + * Return immediately. + */ + ret = bgp_collision_detect(peer, remote_id); + if (ret < 0) + return BGP_Stop; + + /* Get sockname. */ + if (bgp_getsockname(peer) < 0) { + flog_err_sys(EC_LIB_SOCKET, + "%s: bgp_getsockname() failed for peer: %s", + __func__, peer->host); + return BGP_Stop; + } + + /* Set remote router-id */ + peer->remote_id = remote_id; + /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST calculate the value of the Hold Timer by using the smaller of its configured Hold Time and the Hold Time received in the OPEN message. @@ -1411,21 +1419,6 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) peer->afc[AFI_IP6][SAFI_FLOWSPEC]; } - /* When collision is detected and this peer is closed. - * Return immediately. - */ - ret = bgp_collision_detect(peer, remote_id); - if (ret < 0) - return BGP_Stop; - - /* Get sockname. */ - if (bgp_getsockname(peer) < 0) { - flog_err_sys(EC_LIB_SOCKET, - "%s: bgp_getsockname() failed for peer: %s", - __func__, peer->host); - return BGP_Stop; - } - /* Verify valid local address present based on negotiated * address-families. */ if (peer->afc_nego[AFI_IP][SAFI_UNICAST] diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 2c6c2c3861..8b27b39c46 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -2684,6 +2684,7 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_or_filter bpof; struct bgp_pbr_val_mask bpvm; + memset(&range, 0, sizeof(range)); memset(&nh, 0, sizeof(struct nexthop)); memset(&bpf, 0, sizeof(struct bgp_pbr_filter)); memset(&bpof, 0, sizeof(struct bgp_pbr_or_filter)); diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c index fc59122184..b165c5d0ee 100644 --- a/bgpd/bgp_routemap_nb.c +++ b/bgpd/bgp_routemap_nb.c @@ -18,6 +18,8 @@ */ +#include <zebra.h> + #include "lib/command.h" #include "lib/log.h" #include "lib/northbound.h" diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c index ec6284273e..ff08c16a82 100644 --- a/bgpd/bgp_routemap_nb_config.c +++ b/bgpd/bgp_routemap_nb_config.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "lib/command.h" #include "lib/log.h" #include "lib/northbound.h" diff --git a/bgpd/bgp_trace.c b/bgpd/bgp_trace.c index 2ebc63b6b5..02afbeb46f 100644 --- a/bgpd/bgp_trace.c +++ b/bgpd/bgp_trace.c @@ -1,4 +1,6 @@ #define TRACEPOINT_CREATE_PROBES #define TRACEPOINT_DEFINE +#include <zebra.h> + #include "bgp_trace.h" diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index ae0bf7fe92..288c2851b3 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1975,7 +1975,7 @@ void bgp_zebra_instance_deregister(struct bgp *bgp) void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer) { - int ra_interval = BGP_UNNUM_DEFAULT_RA_INTERVAL; + uint32_t ra_interval = BGP_UNNUM_DEFAULT_RA_INTERVAL; /* Don't try to initiate if we're not connected to Zebra */ if (zclient->sock < 0) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 51134dc8c5..88588952ba 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -44,6 +44,7 @@ #include "bgp_addpath_types.h" #include "bgp_nexthop.h" #include "bgp_damp.h" +#include "bgp_io.h" #include "lib/bfd.h" @@ -1047,6 +1048,9 @@ struct peer { struct stream_fifo *ibuf; // packets waiting to be processed struct stream_fifo *obuf; // packets waiting to be written + /* used as a block to deposit raw wire data to */ + uint8_t ibuf_scratch[BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE + * BGP_READ_PACKET_MAX]; struct ringbuf *ibuf_work; // WiP buffer used by bgp_read() only struct stream *obuf_work; // WiP buffer used to construct packets diff --git a/configure.ac b/configure.ac index f9fa8e0713..c082a9e527 100644 --- a/configure.ac +++ b/configure.ac @@ -1866,7 +1866,7 @@ AC_SUBST([SNMP_CFLAGS]) dnl --------------- dnl libyang dnl --------------- -PKG_CHECK_MODULES([LIBYANG], [libyang >= 1.0.184], , [ +PKG_CHECK_MODULES([LIBYANG], [libyang >= 1.0.184 libyang < 2.0], , [ AC_MSG_ERROR([libyang (>= 1.0.184) was not found on your system.]) ]) ac_cflags_save="$CFLAGS" diff --git a/doc/developer/building-frr-for-openbsd6.rst b/doc/developer/building-frr-for-openbsd6.rst index f307cacdfc..88446685e0 100644 --- a/doc/developer/building-frr-for-openbsd6.rst +++ b/doc/developer/building-frr-for-openbsd6.rst @@ -14,6 +14,7 @@ Add packages: :: + pkg_add clang libcares python3 pkg_add git autoconf-2.69p2 automake-1.15.1 libtool bison pkg_add gmake json-c py-test py-sphinx libexecinfo @@ -47,6 +48,19 @@ Download Source, configure and compile it (You may prefer different options on configure statement. These are just an example) +.. warning:: + + In openbsd the proper links for the libyang library may not have been created. + +:: + + ln -s /usr/lib/libyang.so.1.10.17 /usr/lib/libyang.so + +.. warning:: + + ``openbsd`` since version 6.2 has ``clang`` as the default compiler so to + build frr, clang must be used (the included gcc version is very old). + :: git clone https://github.com/frrouting/frr.git frr @@ -67,7 +81,8 @@ an example) --enable-logfile-mask=0640 \ --enable-fpm \ --with-pkg-git-version \ - --with-pkg-extra-version=-MyOwnFRRVersion + --with-pkg-extra-version=-MyOwnFRRVersion \ + CC=clang gmake gmake check doas gmake install diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst index 86db788c0e..553bd1f596 100644 --- a/doc/developer/lists.rst +++ b/doc/developer/lists.rst @@ -108,6 +108,8 @@ Functions provided: | _first, _next, _next_safe, | yes | yes | yes | yes | yes | | _const_first, _const_next | | | | | | +------------------------------------+------+------+------+---------+------------+ +| _swap_all | yes | yes | yes | yes | yes | ++------------------------------------+------+------+------+---------+------------+ | _add_head, _add_tail, _add_after | yes | -- | -- | -- | -- | +------------------------------------+------+------+------+---------+------------+ | _add | -- | yes | yes | yes | yes | @@ -322,6 +324,14 @@ The following documentation assumes that a list has been defined using return ``item``. The function may also call ``assert()`` (but most don't.) +.. c:function:: itemtype *Z_swap_all(struct Z_head *, struct Z_head *) + + Swap the contents of 2 containers (of identical type). This exchanges the + contents of the two head structures and updates pointers if necessary for + the particular data structure. Fast for all structures. + + (Not currently available on atomic containers.) + .. todo:: ``Z_del_after()`` / ``Z_del_hint()``? diff --git a/doc/user/basic.rst b/doc/user/basic.rst index 519f30d5e6..2def835f0b 100644 --- a/doc/user/basic.rst +++ b/doc/user/basic.rst @@ -188,6 +188,12 @@ Basic Config Commands This command clears all current filters in the log-filter table. Can be daemon independent. + +.. clicmd:: log immediate-mode + + Use unbuffered output for log and debug messages; normally there is + some internal buffering. + .. clicmd:: service password-encryption Encrypt password. diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 1da9e3ba73..87710e98c6 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -2567,6 +2567,24 @@ address-family: Ethernet Virtual Network - EVPN ------------------------------- +Note: When using EVPN features and if you have a large number of hosts, make +sure to adjust the size of the arp neighbor cache to avoid neighbor table +overflow and/or excessive garbage collection. On Linux, the size of the table +and garbage collection frequency can be controlled via the following +sysctl configurations: + +.. code-block:: shell + + net.ipv4.neigh.default.gc_thresh1 + net.ipv4.neigh.default.gc_thresh2 + net.ipv4.neigh.default.gc_thresh3 + + net.ipv6.neigh.default.gc_thresh1 + net.ipv6.neigh.default.gc_thresh2 + net.ipv6.neigh.default.gc_thresh3 + +For more information, see ``man 7 arp``. + .. _bgp-evpn-advertise-pip: EVPN advertise-PIP @@ -2592,10 +2610,10 @@ other EVPN routes. To support this feature there needs to have ability to co-exist a (system-MAC, system-IP) pair with a (anycast-MAC, anycast-IP) pair with the ability to terminate VxLAN-encapsulated packets received for either pair on -the same L3VNI (i.e associated VLAN). This capability is need per tenant +the same L3VNI (i.e associated VLAN). This capability is needed per tenant VRF instance. -To derive the system-MAC and the anycast MAC, there needs to have a +To derive the system-MAC and the anycast MAC, there must be a separate/additional MAC-VLAN interface corresponding to L3VNI’s SVI. The SVI interface’s MAC address can be interpreted as system-MAC and MAC-VLAN interface's MAC as anycast MAC. @@ -2607,7 +2625,7 @@ User has an option to configure the system-IP and/or system-MAC value if the auto derived value is not preferred. Note: By default, advertise-pip feature is enabled and user has an option to -disable the feature via configuration CLI. Once the feature is disable under +disable the feature via configuration CLI. Once the feature is disabled under bgp vrf instance or MAC-VLAN interface is not configured, all the routes follow the same behavior of using same next-hop and RMAC values. @@ -2616,6 +2634,19 @@ the same behavior of using same next-hop and RMAC values. Enables or disables advertise-pip feature, specifiy system-IP and/or system-MAC parameters. +EVPN advertise-svi-ip +^^^^^^^^^^^^^^^^^^^^^ +Typically, the SVI IP address is reused on VTEPs across multiple racks. However, +if you have unique SVI IP addresses that you want to be reachable you can use the +advertise-svi-ip option. This option advertises the SVI IP/MAC address as a type-2 +route and eliminates the need for any flooding over VXLAN to reach the IP from a +remote VTEP. + +.. clicmd:: advertise-svi-ip + +Note that you should not enable both the advertise-svi-ip and the advertise-default-gw +at the same time. + EVPN Multihoming ^^^^^^^^^^^^^^^^ diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index ef2bf16166..66f8fd5678 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -77,7 +77,7 @@ writing, *isisd* does not support multiple ISIS processes. - transition Send and accept both styles of TLVs during transition - wide - Use new style of TLVs to carry wider metric + Use new style of TLVs to carry wider metric. FRR uses this as a default value .. clicmd:: set-overload-bit @@ -172,7 +172,7 @@ ISIS interface .. _ip-router-isis-word: -.. clicmd:: <ip|ipv6> router isis WORD [vrf NAME] +.. clicmd:: <ip|ipv6> router isis WORD Activate ISIS adjacency on this interface. Note that the name of ISIS instance must be the same as the one used to configure the ISIS process (see @@ -261,10 +261,11 @@ ISIS interface Limit Remote LFA PQ node selection within the specified metric. -.. clicmd:: isis fast-reroute ti-lfa [level-1|level-2] [node-protection] +.. clicmd:: isis fast-reroute ti-lfa [level-1|level-2] [node-protection [link-fallback]] Enable per-prefix TI-LFA fast reroute link or node protection. - + When node protection is used, option link-fallback enables the computation and use of + link-protecting LFAs for destinations unprotected by node protection. .. _showing-isis-information: diff --git a/doc/user/kernel.rst b/doc/user/kernel.rst index 4c2c7a5008..210ede7e91 100644 --- a/doc/user/kernel.rst +++ b/doc/user/kernel.rst @@ -6,6 +6,9 @@ Kernel Interface There are several different methods for reading kernel routing table information, updating kernel routing tables, and for looking up interfaces. +FRR relies heavily on the Netlink (``man 7 netlink``) interface to +communicate with the Kernel. However, other interfaces are still used +in some parts of the code. - ioctl This method is a very traditional way for reading or writing kernel @@ -27,16 +30,7 @@ information, updating kernel routing tables, and for looking up interfaces. kernel information. - routing socket / Netlink - On recent Linux kernels (2.0.x and 2.2.x), there is a kernel/user - communication support called `Netlink`. It makes asynchronous communication - between kernel and FRR possible, similar to a routing socket on BSD systems. - - Before you use this feature, be sure to select (in kernel configuration) the - kernel/Netlink support option 'Kernel/User network link driver' and 'Routing - messages'. - - Today, the :file:`/dev/route` special device file is obsolete. Netlink - communication is done by reading/writing over Netlink socket. - - After the kernel configuration, please reconfigure and rebuild FRR. You can - use Netlink as a dynamic routing update channel between FRR and the kernel. + Netlink first appeard in Linux kernel 2.0. It makes asynchronous + communication between the kernel and FRR possible, similar to a routing + socket on BSD systems. Netlink communication is done by reading/writing + over Netlink socket. diff --git a/doc/user/pim.rst b/doc/user/pim.rst index 6b7cae2c5d..103760933c 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -154,20 +154,6 @@ Certain signals have special meanings to *pimd*. urib-only Lookup in the Unicast Rib only. -.. clicmd:: ip msdp mesh-group [WORD] - - Create or Delete a multicast source discovery protocol mesh-group using - [WORD] as the group name. - -.. clicmd:: ip msdp mesh-group WORD member A.B.C.D - - Attach or Delete A.B.C.D to the MSDP mesh group WORD specified. - -.. clicmd:: ip msdp mesh-group WORD source A.B.C.D - - For the address specified A.B.C.D use that as the source address for - mesh group packets being sent. - .. clicmd:: ip igmp generate-query-once [version (2-3)] Generate IGMP query (v2/v3) on user requirement. This will not depend on @@ -308,27 +294,43 @@ caution. Most of the time this will not be necessary. Multicast Source Discovery Protocol (MSDP) Configuration ======================================================== -.. clicmd:: ip msdp mesh-group [WORD] member A.B.C.D +MSDP can be setup in different ways: - Include a MSDP peer as a member of a MSDP mesh-group. +* MSDP meshed-group: where all peers are connected with each other creating + a fully meshed network. SAs (source active) messages are not forwarded in + this mode because the origin is able to send SAs to all members. -.. clicmd:: ip msdp mesh-group [WORD] source A.B.C.D + This setup is commonly used with anycast. - Create a MSDP mesh-group, defining a name for it and an associated local source - address. +* MSDP peering: when there is one or more peers that are not fully meshed. SAs + may be forwarded depending on the result of filtering and RPF checks. -.. clicmd:: ip msdp peer A.B.C.D source A.B.C.D + This setup is commonly consistent with BGP peerings (for RPF checks). - Establish a MSDP connection with a peer. +* MSDP default peer: there is only one peer and all SAs will be forwarded + there. +.. note:: - Remove a MSDP peer member from a MSDP mesh-group. + MSDP default peer and SA filtering is not implemented. - Delete a MSDP mesh-group. +Commands available for MSDP: + + +.. clicmd:: ip msdp mesh-group WORD member A.B.C.D + + Create or update a mesh group to include the specified MSDP peer. + +.. clicmd:: ip msdp mesh-group WORD source A.B.C.D + + Create or update a mesh group to set the source address used to connect to + peers. + +.. clicmd:: ip msdp peer A.B.C.D source A.B.C.D + Create a regular MSDP session with peer using the specified source address. - Delete a MSDP peer connection. .. _show-pim-information: diff --git a/eigrpd/eigrp_metric.c b/eigrpd/eigrp_metric.c index 2b05db71d5..ea62f9d1be 100644 --- a/eigrpd/eigrp_metric.c +++ b/eigrpd/eigrp_metric.c @@ -21,6 +21,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "eigrpd/eigrp_structs.h" #include "eigrpd/eigrpd.h" #include "eigrpd/eigrp_types.h" diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 0b37733990..39e384c121 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -572,9 +572,14 @@ int eigrp_read(struct thread *thread) && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL)) eigrp_header_dump(eigrph); - // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) - - // stream_get_getp(ibuf))) - // return -1; + if (ntohs(eigrph->ASNumber) != eigrp->AS) { + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_debug( + "ignoring packet from router %u sent to %pI4, wrong AS Number received: %u", + ntohs(eigrph->vrid), &iph->ip_dst, + ntohs(eigrph->ASNumber)); + return 0; + } /* If incoming interface is passive one, ignore it. */ if (eigrp_if_is_passive(ei)) { diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index a637429e84..7fd9c07ed2 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -73,61 +73,42 @@ DEFINE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp)); int isis_if_new_hook(struct interface *); int isis_if_delete_hook(struct interface *); -static int isis_circuit_smmp_id_gen(struct isis_circuit *circuit) -{ - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); - struct isis *isis = NULL; - uint32_t id; - uint32_t i; - - isis = isis_lookup_by_vrfid(vrf->vrf_id); - if (isis == NULL) - return 0; - - id = isis->snmp_circuit_id_last; - id++; +DEFINE_HOOK(isis_circuit_new_hook, (struct isis_circuit *circuit), (circuit)); +DEFINE_HOOK(isis_circuit_del_hook, (struct isis_circuit *circuit), (circuit)); - /* find next unused entry */ - for (i = 0; i < SNMP_CIRCUITS_MAX; i++) { - if (id >= SNMP_CIRCUITS_MAX) { - id = 0; - continue; - } - - if (id == 0) - continue; +static void isis_circuit_enable(struct isis_circuit *circuit) +{ + struct isis_area *area; + struct interface *ifp = circuit->interface; - if (isis->snmp_circuits[id] == NULL) - break; + area = isis_area_lookup(circuit->tag, ifp->vrf_id); + if (area) + isis_area_add_circuit(area, circuit); - id++; - } + if (if_is_operative(ifp)) + isis_csm_state_change(IF_UP_FROM_Z, circuit, ifp); +} - if (i == SNMP_CIRCUITS_MAX) { - zlog_warn("Could not allocate a smmp-circuit-id"); - return 0; - } +static void isis_circuit_disable(struct isis_circuit *circuit) +{ + struct isis_area *area = circuit->area; + struct interface *ifp = circuit->interface; - isis->snmp_circuits[id] = circuit; - isis->snmp_circuit_id_last = id; - circuit->snmp_id = id; + if (if_is_operative(ifp)) + isis_csm_state_change(IF_DOWN_FROM_Z, circuit, ifp); - return 1; + if (area) + isis_area_del_circuit(area, circuit); } -struct isis_circuit *isis_circuit_new(struct isis *isis) +struct isis_circuit *isis_circuit_new(struct interface *ifp, const char *tag) { struct isis_circuit *circuit; int i; circuit = XCALLOC(MTYPE_ISIS_CIRCUIT, sizeof(struct isis_circuit)); - circuit->isis = isis; - /* - * Note: if snmp-id generation failed circuit will fail - * up operation - */ - isis_circuit_smmp_id_gen(circuit); + circuit->tag = XSTRDUP(MTYPE_ISIS_CIRCUIT, tag); /* * Default values @@ -193,31 +174,39 @@ struct isis_circuit *isis_circuit_new(struct isis *isis) isis_lfa_excluded_ifaces_init(circuit, ISIS_LEVEL1); isis_lfa_excluded_ifaces_init(circuit, ISIS_LEVEL2); + circuit->ldp_sync_info = ldp_sync_info_create(); + circuit->ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED; + QOBJ_REG(circuit, isis_circuit); + isis_circuit_if_bind(circuit, ifp); + + if (ifp->ifindex != IFINDEX_INTERNAL) + isis_circuit_enable(circuit); + return circuit; } void isis_circuit_del(struct isis_circuit *circuit) { - struct isis *isis = NULL; - if (!circuit) return; - QOBJ_UNREG(circuit); - - if (circuit->interface) { - isis = isis_lookup_by_vrfid(circuit->interface->vrf_id); - isis->snmp_circuits[circuit->snmp_id] = NULL; - } + if (circuit->interface->ifindex != IFINDEX_INTERNAL) + isis_circuit_disable(circuit); isis_circuit_if_unbind(circuit, circuit->interface); + QOBJ_UNREG(circuit); + + ldp_sync_info_free(&circuit->ldp_sync_info); + circuit_mt_finish(circuit); isis_lfa_excluded_ifaces_clear(circuit, ISIS_LEVEL1); isis_lfa_excluded_ifaces_clear(circuit, ISIS_LEVEL2); + XFREE(MTYPE_ISIS_CIRCUIT, circuit->tag); + /* and lastly the circuit itself */ XFREE(MTYPE_ISIS_CIRCUIT, circuit); @@ -228,6 +217,7 @@ void isis_circuit_configure(struct isis_circuit *circuit, struct isis_area *area) { assert(area); + circuit->isis = area->isis; circuit->area = area; /* @@ -247,12 +237,16 @@ void isis_circuit_configure(struct isis_circuit *circuit, circuit->idx = flags_get_index(&area->flags); + hook_call(isis_circuit_new_hook, circuit); + return; } void isis_circuit_deconfigure(struct isis_circuit *circuit, struct isis_area *area) { + hook_call(isis_circuit_del_hook, circuit); + /* Free the index of SRM and SSN flags */ flags_free_index(&area->flags, circuit->idx); circuit->idx = 0; @@ -260,6 +254,7 @@ void isis_circuit_deconfigure(struct isis_circuit *circuit, assert(circuit->area == area); listnode_delete(area->circuit_list, circuit); circuit->area = NULL; + circuit->isis = NULL; return; } @@ -284,29 +279,7 @@ struct isis_circuit *circuit_lookup_by_ifp(struct interface *ifp, struct isis_circuit *circuit_scan_by_ifp(struct interface *ifp) { - struct isis_area *area; - struct listnode *node; - struct isis_circuit *circuit; - struct isis *isis = NULL; - - if (ifp->info) - return (struct isis_circuit *)ifp->info; - - isis = isis_lookup_by_vrfid(ifp->vrf_id); - if (isis == NULL) { - zlog_warn(" %s : ISIS routing instance not found", __func__); - return NULL; - } - - if (isis->area_list) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - circuit = - circuit_lookup_by_ifp(ifp, area->circuit_list); - if (circuit) - return circuit; - } - } - return circuit_lookup_by_ifp(ifp, isis->init_circ_list); + return (struct isis_circuit *)ifp->info; } DEFINE_HOOK(isis_circuit_add_addr_hook, (struct isis_circuit *circuit), @@ -516,8 +489,6 @@ void isis_circuit_if_add(struct isis_circuit *circuit, struct interface *ifp) struct listnode *node, *nnode; struct connected *conn; - isis_circuit_if_bind(circuit, ifp); - if (if_is_broadcast(ifp)) { if (fabricd || circuit->circ_type_config == CIRCUIT_T_P2P) circuit->circ_type = CIRCUIT_T_P2P; @@ -681,13 +652,6 @@ int isis_circuit_up(struct isis_circuit *circuit) return ISIS_OK; } - if (circuit->snmp_id == 0) { - /* We cannot bring circuit up if does not have snmp-id */ - flog_err(EC_ISIS_CONFIG, - "No snnmp-id: there are too many circuits:"); - return ISIS_ERROR; - } - if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit)) { flog_err( EC_ISIS_CONFIG, @@ -789,6 +753,11 @@ int isis_circuit_up(struct isis_circuit *circuit) circuit->last_uptime = time(NULL); + if (circuit->area->mta && circuit->area->mta->status) + isis_link_params_update(circuit, circuit->interface); + + isis_if_ldp_sync_enable(circuit); + #ifndef FABRICD /* send northbound notification */ isis_notif_if_state_change(circuit, false); @@ -804,6 +773,8 @@ void isis_circuit_down(struct isis_circuit *circuit) isis_notif_if_state_change(circuit, true); #endif /* ifndef FABRICD */ + isis_if_ldp_sync_disable(circuit); + /* log adjacency changes if configured to do so */ if (circuit->area->log_adj_changes) { struct isis_adjacency *adj = NULL; @@ -1345,23 +1316,6 @@ static int isis_interface_config_write(struct vty *vty) } #endif /* ifdef FABRICD */ -struct isis_circuit *isis_circuit_create(struct isis_area *area, - struct interface *ifp) -{ - struct isis_circuit *circuit = circuit_scan_by_ifp(ifp); - - if (circuit && circuit->area) - return NULL; - circuit = isis_csm_state_change(ISIS_ENABLE, circuit, area); - if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) - return circuit; - isis_circuit_if_bind(circuit, ifp); - if (circuit->area->mta && circuit->area->mta->status) - isis_link_params_update(circuit, ifp); - - return circuit; -} - void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router, bool ipv6_router) { @@ -1377,24 +1331,13 @@ void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router, circuit->ipv6_router = ipv6_router; circuit_update_nlpids(circuit); - /* the area should always be there if we get here, but in the past - * there were corner cases where the area was NULL (e.g. because the - * circuit was deconfigured following a validation error). Do not - * segfault if this happens again. - */ - if (!area) { - zlog_err("%s: NULL area for circuit %u", __func__, - circuit->circuit_id); - return; - } - - area->ip_circuits += ip_router - old_ipr; - area->ipv6_circuits += ipv6_router - old_ipv6r; + if (area) { + area->ip_circuits += ip_router - old_ipr; + area->ipv6_circuits += ipv6_router - old_ipv6r; - if (!ip_router && !ipv6_router) - isis_csm_state_change(ISIS_DISABLE, circuit, area); - else - lsp_regenerate_schedule(area, circuit->is_type, 0); + if (ip_router || ipv6_router) + lsp_regenerate_schedule(area, circuit->is_type, 0); + } } ferr_r isis_circuit_passive_set(struct isis_circuit *circuit, bool passive) @@ -1516,8 +1459,9 @@ int isis_circuit_mt_enabled_set(struct isis_circuit *circuit, uint16_t mtid, setting = circuit_get_mt_setting(circuit, mtid); if (setting->enabled != enabled) { setting->enabled = enabled; - lsp_regenerate_schedule(circuit->area, IS_LEVEL_1 | IS_LEVEL_2, - 0); + if (circuit->area) + lsp_regenerate_schedule(circuit->area, + IS_LEVEL_1 | IS_LEVEL_2, 0); } return CMD_SUCCESS; @@ -1530,27 +1474,19 @@ int isis_if_new_hook(struct interface *ifp) int isis_if_delete_hook(struct interface *ifp) { - struct isis_circuit *circuit; - /* Clean up the circuit data */ - if (ifp && ifp->info) { - circuit = ifp->info; - isis_csm_state_change(IF_DOWN_FROM_Z, circuit, ifp); - } + if (ifp->info) + isis_circuit_del(ifp->info); return 0; } static int isis_ifp_create(struct interface *ifp) { - struct vrf *vrf = NULL; + struct isis_circuit *circuit = ifp->info; + + if (circuit) + isis_circuit_enable(circuit); - if (if_is_operative(ifp)) { - vrf = vrf_lookup_by_id(ifp->vrf_id); - if (vrf) - isis_global_instance_create(vrf->name); - isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), - ifp); - } hook_call(isis_if_new_hook, ifp); return 0; @@ -1558,34 +1494,33 @@ static int isis_ifp_create(struct interface *ifp) static int isis_ifp_up(struct interface *ifp) { - isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp); + struct isis_circuit *circuit = ifp->info; + + if (circuit) + isis_csm_state_change(IF_UP_FROM_Z, circuit, ifp); return 0; } static int isis_ifp_down(struct interface *ifp) { - struct isis_circuit *circuit; + struct isis_circuit *circuit = ifp->info; + + if (circuit) { + isis_csm_state_change(IF_DOWN_FROM_Z, circuit, ifp); - circuit = isis_csm_state_change(IF_DOWN_FROM_Z, - circuit_scan_by_ifp(ifp), ifp); - if (circuit) SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF); + } return 0; } static int isis_ifp_destroy(struct interface *ifp) { - if (if_is_operative(ifp)) - zlog_warn("Zebra: got delete of %s, but interface is still up", - ifp->name); - - isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp); + struct isis_circuit *circuit = ifp->info; - /* Cannot call if_delete because we should retain the pseudo interface - in case there is configuration info attached to it. */ - if_delete_retain(ifp); + if (circuit) + isis_circuit_disable(circuit); return 0; } diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index d4c7baea1a..84c3ca3ff2 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -122,6 +122,7 @@ struct isis_circuit { /* * Configurables */ + char *tag; /* area tag */ struct isis_passwd passwd; /* Circuit rx/tx password */ int is_type; /* circuit is type == level of circuit * differentiated from circuit type (media) */ @@ -151,6 +152,7 @@ struct isis_circuit { struct hash *lfa_excluded_ifaces[ISIS_LEVELS]; bool tilfa_protection[ISIS_LEVELS]; bool tilfa_node_protection[ISIS_LEVELS]; + bool tilfa_link_fallback[ISIS_LEVELS]; /* * Counters as in 10589--11.2.5.9 */ @@ -180,7 +182,7 @@ struct isis_circuit { DECLARE_QOBJ_TYPE(isis_circuit); void isis_circuit_init(void); -struct isis_circuit *isis_circuit_new(struct isis *isis); +struct isis_circuit *isis_circuit_new(struct interface *ifp, const char *tag); void isis_circuit_del(struct isis_circuit *circuit); struct isis_circuit *circuit_lookup_by_ifp(struct interface *ifp, struct list *list); @@ -207,8 +209,6 @@ void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty, size_t isis_circuit_pdu_size(struct isis_circuit *circuit); void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream); -struct isis_circuit *isis_circuit_create(struct isis_area *area, - struct interface *ifp); void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router, bool ipv6_router); ferr_r isis_circuit_passive_set(struct isis_circuit *circuit, bool passive); @@ -238,4 +238,7 @@ DECLARE_HOOK(isis_circuit_config_write, DECLARE_HOOK(isis_circuit_add_addr_hook, (struct isis_circuit *circuit), (circuit)); +DECLARE_HOOK(isis_circuit_new_hook, (struct isis_circuit *circuit), (circuit)); +DECLARE_HOOK(isis_circuit_del_hook, (struct isis_circuit *circuit), (circuit)); + #endif /* _ZEBRA_ISIS_CIRCUIT_H */ diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index b108210686..f316e0279c 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -62,19 +62,7 @@ DEFPY_YANG_NOSH(router_isis, router_isis_cmd, "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag, vrf_name); nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); - /* default value in yang for is-type is level-1, but in FRR - * the first instance is assigned is-type level-1-2. We - * need to make sure to set it in the yang model so that it - * is consistent with what FRR sees. - */ - - if (!im) { - return CMD_SUCCESS; - } - if (listcount(im->isis) == 0) - nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY, - "level-1-2"); ret = nb_cli_apply_changes(vty, base_xpath); if (ret == CMD_SUCCESS) VTY_PUSH_XPATH(ISIS_NODE, base_xpath); @@ -82,16 +70,42 @@ DEFPY_YANG_NOSH(router_isis, router_isis_cmd, return ret; } +struct if_iter { + struct vty *vty; + const char *tag; +}; + +static int if_iter_cb(const struct lyd_node *dnode, void *arg) +{ + struct if_iter *iter = arg; + const char *tag; + + if (!yang_dnode_exists(dnode, "frr-isisd:isis/area-tag")) + return YANG_ITER_CONTINUE; + + tag = yang_dnode_get_string(dnode, "frr-isisd:isis/area-tag"); + if (strmatch(tag, iter->tag)) { + char xpath[XPATH_MAXLEN]; + const char *name = yang_dnode_get_string(dnode, "name"); + const char *vrf = yang_dnode_get_string(dnode, "vrf"); + + snprintf( + xpath, XPATH_MAXLEN, + "/frr-interface:lib/interface[name='%s'][vrf='%s']/frr-isisd:isis", + name, vrf); + nb_cli_enqueue_change(iter->vty, xpath, NB_OP_DESTROY, NULL); + } + + return YANG_ITER_CONTINUE; +} + DEFPY_YANG(no_router_isis, no_router_isis_cmd, "no router isis WORD$tag [vrf NAME$vrf_name]", NO_STR ROUTER_STR "ISO IS-IS\n" "ISO Routing area tag\n" VRF_CMD_HELP_STR) { - char temp_xpath[XPATH_MAXLEN]; - struct listnode *node, *nnode; - struct isis_circuit *circuit = NULL; - struct isis_area *area = NULL; + struct if_iter iter; if (!vrf_name) vrf_name = VRF_DEFAULT_NAME; @@ -104,24 +118,13 @@ DEFPY_YANG(no_router_isis, no_router_isis_cmd, return CMD_ERR_NOTHING_TODO; } + iter.vty = vty; + iter.tag = tag; + + yang_dnode_iterate(if_iter_cb, &iter, vty->candidate_config->dnode, + "/frr-interface:lib/interface[vrf='%s']", vrf_name); + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); - area = isis_area_lookup_by_vrf(tag, vrf_name); - if (area && area->circuit_list && listcount(area->circuit_list)) { - for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode, - circuit)) { - /* add callbacks to delete each of the circuits listed - */ - const char *vrf_name = - vrf_lookup_by_id(circuit->interface->vrf_id) - ->name; - snprintf( - temp_xpath, XPATH_MAXLEN, - "/frr-interface:lib/interface[name='%s'][vrf='%s']/frr-isisd:isis", - circuit->interface->name, vrf_name); - nb_cli_enqueue_change(vty, temp_xpath, NB_OP_DESTROY, - NULL); - } - } return nb_cli_apply_changes( vty, "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag, @@ -150,95 +153,48 @@ void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode, * XPath: /frr-isisd:isis/instance */ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, - "ip router isis WORD$tag [vrf NAME$vrf_name]", + "ip router isis WORD$tag", "Interface Internet Protocol config commands\n" "IP router interface commands\n" "IS-IS routing protocol\n" - "Routing process tag\n" VRF_CMD_HELP_STR) + "Routing process tag\n") { - char temp_xpath[XPATH_MAXLEN]; - const char *circ_type; - struct isis_area *area = NULL; + char inst_xpath[XPATH_MAXLEN]; + struct lyd_node *if_dnode, *inst_dnode; + const char *circ_type = NULL; + const char *vrf_name; struct interface *ifp; - struct vrf *vrf; - - /* area will be created if it is not present. make sure the yang model - * is synced with FRR and call the appropriate NB cb. - */ - if (!im) { - return CMD_SUCCESS; - } - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); - if (!vrf_name) { - if (ifp) { - if (ifp->vrf_id == VRF_DEFAULT) - vrf_name = VRF_DEFAULT_NAME; - else { - vrf = vrf_lookup_by_id(ifp->vrf_id); - if (vrf && !vrf_name) - vrf_name = vrf->name; - } - } else - vrf_name = VRF_DEFAULT_NAME; + if_dnode = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!if_dnode) { + vty_out(vty, "%% Failed to get iface dnode in candidate DB\n"); + return CMD_WARNING_CONFIG_FAILED; } - area = isis_area_lookup_by_vrf(tag, vrf_name); - if (!area) { - isis_global_instance_create(vrf_name); - snprintf(temp_xpath, XPATH_MAXLEN, - "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", - tag, vrf_name); - nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag); - snprintf( - temp_xpath, XPATH_MAXLEN, - "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']/is-type", - tag, vrf_name); - nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY, - listcount(im->isis) == 0 ? "level-1-2" - : NULL); - nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, - NULL); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", - NB_OP_MODIFY, tag); + vrf_name = yang_dnode_get_string(if_dnode, "vrf"); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY, - vrf_name); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing", - NB_OP_MODIFY, "true"); - nb_cli_enqueue_change( - vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY, - listcount(im->isis) == 0 ? "level-1-2" : "level-1"); - } else { - /* area exists, circuit type defaults to its area's is_type */ - switch (area->is_type) { - case IS_LEVEL_1: - circ_type = "level-1"; - break; - case IS_LEVEL_2: - circ_type = "level-2"; - break; - case IS_LEVEL_1_AND_2: - circ_type = "level-1-2"; - break; - default: - /* just to silence compiler warnings */ - return CMD_WARNING_CONFIG_FAILED; - } - nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, - NULL); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", - NB_OP_MODIFY, tag); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY, - vrf_name); + snprintf(inst_xpath, XPATH_MAXLEN, + "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag, + vrf_name); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing", - NB_OP_MODIFY, "true"); + /* if instance exists then inherit its type, create it otherwise */ + inst_dnode = yang_dnode_get(vty->candidate_config->dnode, inst_xpath); + if (inst_dnode) + circ_type = yang_dnode_get_string(inst_dnode, "is-type"); + else + nb_cli_enqueue_change(vty, inst_xpath, NB_OP_CREATE, NULL); + + nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", NB_OP_MODIFY, + tag); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing", + NB_OP_MODIFY, "true"); + if (circ_type) nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY, circ_type); - } /* check if the interface is a loopback and if so set it as passive */ + ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); if (ifp && if_is_loopback(ifp)) nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive", NB_OP_MODIFY, "true"); @@ -246,95 +202,56 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, return nb_cli_apply_changes(vty, NULL); } +ALIAS_HIDDEN(ip_router_isis, ip_router_isis_vrf_cmd, + "ip router isis WORD$tag vrf NAME$vrf_name", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n" VRF_CMD_HELP_STR) + DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, - "ipv6 router isis WORD$tag [vrf NAME$vrf_name]", + "ipv6 router isis WORD$tag", "Interface Internet Protocol config commands\n" "IP router interface commands\n" "IS-IS routing protocol\n" - "Routing process tag\n" VRF_CMD_HELP_STR) + "Routing process tag\n") { - char temp_xpath[XPATH_MAXLEN]; - const char *circ_type; + char inst_xpath[XPATH_MAXLEN]; + struct lyd_node *if_dnode, *inst_dnode; + const char *circ_type = NULL; + const char *vrf_name; struct interface *ifp; - struct isis_area *area; - struct vrf *vrf; - /* area will be created if it is not present. make sure the yang model - * is synced with FRR and call the appropriate NB cb. - */ - - if (!im) - return CMD_SUCCESS; - - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); - if (!vrf_name) { - if (ifp) { - if (ifp->vrf_id == VRF_DEFAULT) - vrf_name = VRF_DEFAULT_NAME; - else { - vrf = vrf_lookup_by_id(ifp->vrf_id); - if (vrf && !vrf_name) - vrf_name = vrf->name; - } - } else - vrf_name = VRF_DEFAULT_NAME; + if_dnode = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!if_dnode) { + vty_out(vty, "%% Failed to get iface dnode in candidate DB\n"); + return CMD_WARNING_CONFIG_FAILED; } - area = isis_area_lookup_by_vrf(tag, vrf_name); - if (!area) { - isis_global_instance_create(vrf_name); - snprintf(temp_xpath, XPATH_MAXLEN, - "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", - tag, vrf_name); - nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag); - snprintf( - temp_xpath, XPATH_MAXLEN, - "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']/is-type", - tag, vrf_name); - nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY, - listcount(im->isis) == 0 ? "level-1-2" - : NULL); - nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, - NULL); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", - NB_OP_MODIFY, tag); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY, - vrf_name); + vrf_name = yang_dnode_get_string(if_dnode, "vrf"); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing", - NB_OP_MODIFY, "true"); - nb_cli_enqueue_change( - vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY, - listcount(im->isis) == 0 ? "level-1-2" : "level-1"); - } else { - /* area exists, circuit type defaults to its area's is_type */ - switch (area->is_type) { - case IS_LEVEL_1: - circ_type = "level-1"; - break; - case IS_LEVEL_2: - circ_type = "level-2"; - break; - case IS_LEVEL_1_AND_2: - circ_type = "level-1-2"; - break; - default: - /* just to silence compiler warnings */ - return CMD_WARNING_CONFIG_FAILED; - } - nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, - NULL); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", - NB_OP_MODIFY, tag); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY, - vrf_name); - nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing", - NB_OP_MODIFY, "true"); + snprintf(inst_xpath, XPATH_MAXLEN, + "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag, + vrf_name); + + /* if instance exists then inherit its type, create it otherwise */ + inst_dnode = yang_dnode_get(vty->candidate_config->dnode, inst_xpath); + if (inst_dnode) + circ_type = yang_dnode_get_string(inst_dnode, "is-type"); + else + nb_cli_enqueue_change(vty, inst_xpath, NB_OP_CREATE, NULL); + + nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", NB_OP_MODIFY, + tag); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing", + NB_OP_MODIFY, "true"); + if (circ_type) nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY, circ_type); - } /* check if the interface is a loopback and if so set it as passive */ + ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); if (ifp && if_is_loopback(ifp)) nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive", NB_OP_MODIFY, "true"); @@ -342,15 +259,21 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, return nb_cli_apply_changes(vty, NULL); } +ALIAS_HIDDEN(ip6_router_isis, ip6_router_isis_vrf_cmd, + "ipv6 router isis WORD$tag vrf NAME$vrf_name", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n" VRF_CMD_HELP_STR) + DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd, - "no <ip|ipv6>$ip router isis [WORD]$tag [vrf NAME$vrf_name]", + "no <ip|ipv6>$ip router isis [WORD]$tag", NO_STR "Interface Internet Protocol config commands\n" "IP router interface commands\n" "IP router interface commands\n" "IS-IS routing protocol\n" - "Routing process tag\n" - VRF_CMD_HELP_STR) + "Routing process tag\n") { const struct lyd_node *dnode; @@ -383,36 +306,32 @@ DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd, return nb_cli_apply_changes(vty, NULL); } +ALIAS_HIDDEN(no_ip_router_isis, no_ip_router_isis_vrf_cmd, + "no <ip|ipv6>$ip router isis WORD$tag vrf NAME$vrf_name", + NO_STR + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n" + VRF_CMD_HELP_STR) + void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { - const char *vrf; - - vrf = yang_dnode_get_string(dnode, "../vrf"); - if (!yang_dnode_get_bool(dnode, NULL)) vty_out(vty, " no"); - vty_out(vty, " ip router isis %s", + vty_out(vty, " ip router isis %s\n", yang_dnode_get_string(dnode, "../area-tag")); - if (!strmatch(vrf, VRF_DEFAULT_NAME)) - vty_out(vty, " vrf %s", vrf); - vty_out(vty, "\n"); } void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { - const char *vrf; - - vrf = yang_dnode_get_string(dnode, "../vrf"); - if (!yang_dnode_get_bool(dnode, NULL)) vty_out(vty, " no"); - vty_out(vty, " ipv6 router isis %s", + vty_out(vty, " ipv6 router isis %s\n", yang_dnode_get_string(dnode, "../area-tag")); - if (!strmatch(vrf, VRF_DEFAULT_NAME)) - vty_out(vty, " vrf %s", vrf); - vty_out(vty, "\n"); } /* @@ -2584,50 +2503,41 @@ DEFPY_YANG(no_isis_circuit_type, no_isis_circuit_type_cmd, "Level-1-2 adjacencies are formed\n" "Level-2 only adjacencies are formed\n") { - struct interface *ifp; - struct isis_circuit *circuit; - int is_type; - const char *circ_type; + char inst_xpath[XPATH_MAXLEN]; + struct lyd_node *if_dnode, *inst_dnode; + const char *vrf_name; + const char *tag; + const char *circ_type = NULL; /* * Default value depends on whether the circuit is part of an area, * and the is-type of the area if there is one. So we need to do this * here. */ - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); - if (!ifp) - goto def_val; + if_dnode = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!if_dnode) { + vty_out(vty, "%% Failed to get iface dnode in candidate DB\n"); + return CMD_WARNING_CONFIG_FAILED; + } - circuit = circuit_scan_by_ifp(ifp); - if (!circuit) - goto def_val; + if (!yang_dnode_exists(if_dnode, "frr-isisd:isis/area-tag")) { + vty_out(vty, "%% ISIS is not configured on the interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (circuit->state == C_STATE_UP) - is_type = circuit->area->is_type; - else - goto def_val; + vrf_name = yang_dnode_get_string(if_dnode, "vrf"); + tag = yang_dnode_get_string(if_dnode, "frr-isisd:isis/area-tag"); - switch (is_type) { - case IS_LEVEL_1: - circ_type = "level-1"; - break; - case IS_LEVEL_2: - circ_type = "level-2"; - break; - case IS_LEVEL_1_AND_2: - circ_type = "level-1-2"; - break; - default: - return CMD_ERR_NO_MATCH; - } - nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type", - NB_OP_MODIFY, circ_type); + snprintf(inst_xpath, XPATH_MAXLEN, + "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag, + vrf_name); - return nb_cli_apply_changes(vty, NULL); + inst_dnode = yang_dnode_get(vty->candidate_config->dnode, inst_xpath); + if (inst_dnode) + circ_type = yang_dnode_get_string(inst_dnode, "is-type"); -def_val: nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type", - NB_OP_MODIFY, NULL); + NB_OP_MODIFY, circ_type); return nb_cli_apply_changes(vty, NULL); } @@ -2737,6 +2647,7 @@ void cli_show_ip_isis_frr(struct vty *vty, struct lyd_node *dnode, { bool l1_enabled, l2_enabled; bool l1_node_protection, l2_node_protection; + bool l1_link_fallback, l2_link_fallback; /* Classic LFA */ l1_enabled = yang_dnode_get_bool(dnode, "./level-1/lfa/enable"); @@ -2782,13 +2693,21 @@ void cli_show_ip_isis_frr(struct vty *vty, struct lyd_node *dnode, yang_dnode_get_bool(dnode, "./level-1/ti-lfa/node-protection"); l2_node_protection = yang_dnode_get_bool(dnode, "./level-2/ti-lfa/node-protection"); + l1_link_fallback = + yang_dnode_get_bool(dnode, "./level-1/ti-lfa/link-fallback"); + l2_link_fallback = + yang_dnode_get_bool(dnode, "./level-2/ti-lfa/link-fallback"); + if (l1_enabled || l2_enabled) { if (l1_enabled == l2_enabled - && l1_node_protection == l2_node_protection) { + && l1_node_protection == l2_node_protection + && l1_link_fallback == l2_link_fallback) { vty_out(vty, " isis fast-reroute ti-lfa"); if (l1_node_protection) vty_out(vty, " node-protection"); + if (l1_link_fallback) + vty_out(vty, " link-fallback"); vty_out(vty, "\n"); } else { if (l1_enabled) { @@ -2796,6 +2715,8 @@ void cli_show_ip_isis_frr(struct vty *vty, struct lyd_node *dnode, " isis fast-reroute ti-lfa level-1"); if (l1_node_protection) vty_out(vty, " node-protection"); + if (l1_link_fallback) + vty_out(vty, " link-fallback"); vty_out(vty, "\n"); } if (l2_enabled) { @@ -2803,6 +2724,8 @@ void cli_show_ip_isis_frr(struct vty *vty, struct lyd_node *dnode, " isis fast-reroute ti-lfa level-2"); if (l2_node_protection) vty_out(vty, " node-protection"); + if (l2_link_fallback) + vty_out(vty, " link-fallback"); vty_out(vty, "\n"); } } @@ -3007,14 +2930,15 @@ void cli_show_frr_remote_lfa_max_metric(struct vty *vty, struct lyd_node *dnode, * XPath: /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-{1,2}/ti-lfa/enable */ DEFPY(isis_ti_lfa, isis_ti_lfa_cmd, - "[no] isis fast-reroute ti-lfa [level-1|level-2]$level [node-protection$node_protection]", + "[no] isis fast-reroute ti-lfa [level-1|level-2]$level [node-protection$node_protection [link-fallback$link_fallback]]", NO_STR "IS-IS routing protocol\n" "Interface IP Fast-reroute configuration\n" "Enable TI-LFA computation\n" "Enable TI-LFA computation for Level 1 only\n" "Enable TI-LFA computation for Level 2 only\n" - "Protect against node failures\n") + "Protect against node failures\n" + "Enable link-protection fallback\n") { if (!level || strmatch(level, "level-1")) { if (no) { @@ -3026,6 +2950,10 @@ DEFPY(isis_ti_lfa, isis_ti_lfa_cmd, vty, "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/node-protection", NB_OP_MODIFY, "false"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/link-fallback", + NB_OP_MODIFY, "false"); } else { nb_cli_enqueue_change( vty, @@ -3036,6 +2964,10 @@ DEFPY(isis_ti_lfa, isis_ti_lfa_cmd, "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/node-protection", NB_OP_MODIFY, node_protection ? "true" : "false"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/link-fallback", + NB_OP_MODIFY, link_fallback ? "true" : "false"); } } if (!level || strmatch(level, "level-2")) { @@ -3048,6 +2980,10 @@ DEFPY(isis_ti_lfa, isis_ti_lfa_cmd, vty, "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/node-protection", NB_OP_MODIFY, "false"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/link-fallback", + NB_OP_MODIFY, "false"); } else { nb_cli_enqueue_change( vty, @@ -3058,6 +2994,10 @@ DEFPY(isis_ti_lfa, isis_ti_lfa_cmd, "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/node-protection", NB_OP_MODIFY, node_protection ? "true" : "false"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/link-fallback", + NB_OP_MODIFY, link_fallback ? "true" : "false"); } } @@ -3147,7 +3087,6 @@ DEFPY(isis_mpls_if_ldp_sync, isis_mpls_if_ldp_sync_cmd, NO_STR "IS-IS routing protocol\n" MPLS_STR MPLS_LDP_SYNC_STR) { const struct lyd_node *dnode; - struct interface *ifp; dnode = yang_dnode_get(vty->candidate_config->dnode, "%s/frr-isisd:isis", VTY_CURR_XPATH); @@ -3156,17 +3095,6 @@ DEFPY(isis_mpls_if_ldp_sync, isis_mpls_if_ldp_sync_cmd, return CMD_SUCCESS; } - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); - if (if_is_loopback(ifp)) { - vty_out(vty, "ldp-sync does not run on loopback interface\n"); - return CMD_SUCCESS; - } - - if (ifp->vrf_id != VRF_DEFAULT) { - vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n"); - return CMD_SUCCESS; - } - nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/ldp-sync", NB_OP_MODIFY, no ? "false" : "true"); @@ -3190,7 +3118,6 @@ DEFPY(isis_mpls_if_ldp_sync_holddown, isis_mpls_if_ldp_sync_holddown_cmd, "Time in seconds\n") { const struct lyd_node *dnode; - struct interface *ifp; dnode = yang_dnode_get(vty->candidate_config->dnode, "%s/frr-isisd:isis", VTY_CURR_XPATH); @@ -3199,17 +3126,6 @@ DEFPY(isis_mpls_if_ldp_sync_holddown, isis_mpls_if_ldp_sync_holddown_cmd, return CMD_SUCCESS; } - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); - if (if_is_loopback(ifp)) { - vty_out(vty, "ldp-sync does not run on loopback interface\n"); - return CMD_SUCCESS; - } - - if (ifp->vrf_id != VRF_DEFAULT) { - vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n"); - return CMD_SUCCESS; - } - nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/holddown", NB_OP_MODIFY, holddown_str); @@ -3222,7 +3138,6 @@ DEFPY(no_isis_mpls_if_ldp_sync_holddown, no_isis_mpls_if_ldp_sync_holddown_cmd, NO_MPLS_LDP_SYNC_HOLDDOWN_STR "Time in seconds\n") { const struct lyd_node *dnode; - struct interface *ifp; dnode = yang_dnode_get(vty->candidate_config->dnode, "%s/frr-isisd:isis", VTY_CURR_XPATH); @@ -3231,17 +3146,6 @@ DEFPY(no_isis_mpls_if_ldp_sync_holddown, no_isis_mpls_if_ldp_sync_holddown_cmd, return CMD_SUCCESS; } - ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false); - if (if_is_loopback(ifp)) { - vty_out(vty, "ldp-sync does not run on loopback interface\n"); - return CMD_SUCCESS; - } - - if (ifp->vrf_id != VRF_DEFAULT) { - vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n"); - return CMD_SUCCESS; - } - nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/holddown", NB_OP_DESTROY, NULL); @@ -3262,8 +3166,11 @@ void isis_cli_init(void) install_element(CONFIG_NODE, &no_router_isis_cmd); install_element(INTERFACE_NODE, &ip_router_isis_cmd); + install_element(INTERFACE_NODE, &ip_router_isis_vrf_cmd); install_element(INTERFACE_NODE, &ip6_router_isis_cmd); + install_element(INTERFACE_NODE, &ip6_router_isis_vrf_cmd); install_element(INTERFACE_NODE, &no_ip_router_isis_cmd); + install_element(INTERFACE_NODE, &no_ip_router_isis_vrf_cmd); install_element(INTERFACE_NODE, &isis_bfd_cmd); install_element(INTERFACE_NODE, &isis_bfd_profile_cmd); diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c index ebb68ba3f0..0a29dcd09a 100644 --- a/isisd/isis_csm.c +++ b/isisd/isis_csm.c @@ -65,70 +65,56 @@ struct isis_circuit *isis_csm_state_change(enum isis_circuit_event event, void *arg) { enum isis_circuit_state old_state; - struct isis *isis = NULL; struct isis_area *area = NULL; struct interface *ifp; - old_state = circuit ? circuit->state : C_STATE_NA; + assert(circuit); + + old_state = circuit->state; if (IS_DEBUG_EVENTS) - zlog_debug("CSM_EVENT: %s", EVENT2STR(event)); + zlog_debug("CSM_EVENT for %s: %s", circuit->interface->name, + EVENT2STR(event)); switch (old_state) { case C_STATE_NA: - if (circuit) - zlog_warn("Non-null circuit while state C_STATE_NA"); - assert(circuit == NULL); switch (event) { case ISIS_ENABLE: area = arg; - circuit = isis_circuit_new(area->isis); isis_circuit_configure(circuit, area); circuit->state = C_STATE_CONF; break; case IF_UP_FROM_Z: ifp = arg; - isis = isis_lookup_by_vrfid(ifp->vrf_id); - if (isis == NULL) { - if (IS_DEBUG_EVENTS) - zlog_debug( - " %s : ISIS routing instance not found when attempting to apply against interface %s", - __func__, ifp->name); - break; - } - circuit = isis_circuit_new(isis); + isis_circuit_if_add(circuit, ifp); - listnode_add(isis->init_circ_list, circuit); circuit->state = C_STATE_INIT; break; case ISIS_DISABLE: if (IS_DEBUG_EVENTS) - zlog_debug( - "circuit disable event passed for a non existent circuit"); + zlog_debug("circuit %s already disabled", + circuit->interface->name); break; case IF_DOWN_FROM_Z: if (IS_DEBUG_EVENTS) - zlog_debug( - "circuit disconnect event passed for a non existent circuit"); + zlog_debug("circuit %s already disconnected", + circuit->interface->name); break; } break; case C_STATE_INIT: - assert(circuit); switch (event) { case ISIS_ENABLE: - isis_circuit_configure(circuit, - (struct isis_area *)arg); + area = arg; + + isis_circuit_configure(circuit, area); if (isis_circuit_up(circuit) != ISIS_OK) { - isis_circuit_deconfigure( - circuit, (struct isis_area *)arg); + isis_circuit_deconfigure(circuit, area); break; } circuit->state = C_STATE_UP; isis_event_circuit_state_change(circuit, circuit->area, 1); - listnode_delete(circuit->isis->init_circ_list, - circuit); break; case IF_UP_FROM_Z: if (IS_DEBUG_EVENTS) @@ -141,26 +127,26 @@ struct isis_circuit *isis_csm_state_change(enum isis_circuit_event event, circuit->interface->name); break; case IF_DOWN_FROM_Z: - isis_circuit_if_del(circuit, (struct interface *)arg); - listnode_delete(circuit->isis->init_circ_list, - circuit); - isis_circuit_del(circuit); - circuit = NULL; + ifp = arg; + + isis_circuit_if_del(circuit, ifp); + circuit->state = C_STATE_NA; break; } break; case C_STATE_CONF: - assert(circuit); switch (event) { case ISIS_ENABLE: if (IS_DEBUG_EVENTS) - zlog_debug("circuit %p is already enabled", - circuit); + zlog_debug("circuit %s is already enabled", + circuit->interface->name); break; case IF_UP_FROM_Z: - isis_circuit_if_add(circuit, (struct interface *)arg); + ifp = arg; + + isis_circuit_if_add(circuit, ifp); if (isis_circuit_up(circuit) != ISIS_OK) { - isis_circuit_if_del(circuit, (struct interface *)arg); + isis_circuit_if_del(circuit, ifp); flog_err( EC_ISIS_CONFIG, "Could not bring up %s because of invalid config.", @@ -172,24 +158,23 @@ struct isis_circuit *isis_csm_state_change(enum isis_circuit_event event, 1); break; case ISIS_DISABLE: - isis_circuit_deconfigure(circuit, - (struct isis_area *)arg); - isis_circuit_del(circuit); - circuit = NULL; + area = arg; + + isis_circuit_deconfigure(circuit, area); + circuit->state = C_STATE_NA; break; case IF_DOWN_FROM_Z: if (IS_DEBUG_EVENTS) - zlog_debug("circuit %p already disconnected", - circuit); + zlog_debug("circuit %s already disconnected", + circuit->interface->name); break; } break; case C_STATE_UP: - assert(circuit); switch (event) { case ISIS_ENABLE: if (IS_DEBUG_EVENTS) - zlog_debug("circuit %s already configured", + zlog_debug("circuit %s already enabled", circuit->interface->name); break; case IF_UP_FROM_Z: @@ -198,18 +183,18 @@ struct isis_circuit *isis_csm_state_change(enum isis_circuit_event event, circuit->interface->name); break; case ISIS_DISABLE: - isis = circuit->isis; + area = arg; + isis_circuit_down(circuit); - isis_circuit_deconfigure(circuit, - (struct isis_area *)arg); + isis_circuit_deconfigure(circuit, area); circuit->state = C_STATE_INIT; - isis_event_circuit_state_change( - circuit, (struct isis_area *)arg, 0); - listnode_add(isis->init_circ_list, circuit); + isis_event_circuit_state_change(circuit, area, 0); break; case IF_DOWN_FROM_Z: + ifp = arg; + isis_circuit_down(circuit); - isis_circuit_if_del(circuit, (struct interface *)arg); + isis_circuit_if_del(circuit, ifp); circuit->state = C_STATE_CONF; isis_event_circuit_state_change(circuit, circuit->area, 0); @@ -220,8 +205,7 @@ struct isis_circuit *isis_csm_state_change(enum isis_circuit_event event, if (IS_DEBUG_EVENTS) zlog_debug("CSM_STATE_CHANGE: %s -> %s ", STATE2STR(old_state), - circuit ? STATE2STR(circuit->state) - : STATE2STR(C_STATE_NA)); + STATE2STR(circuit->state)); return circuit; } diff --git a/isisd/isis_ldp_sync.c b/isisd/isis_ldp_sync.c index 585f769806..62d8b8334a 100644 --- a/isisd/isis_ldp_sync.c +++ b/isisd/isis_ldp_sync.c @@ -65,28 +65,20 @@ int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state) struct interface *ifp; struct isis_circuit *circuit = NULL; struct isis_area *area; - struct listnode *node; - struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); - - /* if isis is not enabled or LDP-SYNC is not configured ignore */ - if (!isis || - !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) - return 0; /* lookup circuit */ ifp = if_lookup_by_index(state.ifindex, VRF_DEFAULT); if (ifp == NULL) return 0; - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - circuit = circuit_lookup_by_ifp(ifp, area->circuit_list); - if (circuit != NULL) - break; - } + circuit = ifp->info; + if (circuit == NULL) + return 0; /* if isis is not enabled or LDP-SYNC is not configured ignore */ - if (circuit == NULL || - !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) + area = circuit->area; + if (area == NULL + || !CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) return 0; /* received ldp-sync interface state from LDP */ @@ -103,15 +95,12 @@ int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state) int isis_ldp_sync_announce_update(struct ldp_igp_sync_announce announce) { struct isis_area *area; - struct listnode *node; - struct vrf *vrf; - struct interface *ifp; + struct listnode *anode, *cnode; struct isis_circuit *circuit; struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); - /* if isis is not enabled or LDP-SYNC is not configured ignore */ - if (!isis || - !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) + /* if isis is not enabled ignore */ + if (!isis) return 0; if (announce.proto != ZEBRA_ROUTE_LDP) @@ -123,15 +112,12 @@ int isis_ldp_sync_announce_update(struct ldp_igp_sync_announce announce) * set cost to LSInfinity * send request to LDP for LDP-SYNC state for each interface */ - vrf = vrf_lookup_by_id(VRF_DEFAULT); - FOR_ALL_INTERFACES (vrf, ifp) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - circuit = circuit_lookup_by_ifp(ifp, - area->circuit_list); - if (circuit == NULL) - continue; + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { + if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) + continue; + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) isis_ldp_sync_if_start(circuit, true); - } } return 0; @@ -157,32 +143,6 @@ void isis_ldp_sync_state_req_msg(struct isis_circuit *circuit) /* * LDP-SYNC general interface routines */ -void isis_ldp_sync_if_init(struct isis_circuit *circuit, struct isis *isis) -{ - struct ldp_sync_info *ldp_sync_info; - struct interface *ifp = circuit->interface; - - /* called when ISIS is configured on an interface - * if LDP-IGP Sync is configured globally set state - * and if ptop interface LDP LDP-SYNC is enabled - */ - ils_debug("ldp_sync: init if %s ", ifp->name); - if (circuit->ldp_sync_info == NULL) - circuit->ldp_sync_info = ldp_sync_info_create(); - ldp_sync_info = circuit->ldp_sync_info; - - /* specifed on interface overrides global config. */ - if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN)) - ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown; - - if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG)) - ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED; - - if ((circuit->circ_type == CIRCUIT_T_P2P || if_is_pointopoint(ifp)) && - ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED) - ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP; -} - void isis_ldp_sync_if_start(struct isis_circuit *circuit, bool send_state_req) { @@ -251,49 +211,17 @@ void isis_ldp_sync_ldp_fail(struct isis_circuit *circuit) } } -void isis_ldp_sync_if_remove(struct isis_circuit *circuit, bool remove) -{ - struct ldp_sync_info *ldp_sync_info; - - if (circuit->ldp_sync_info == NULL) - return; - - ldp_sync_info = circuit->ldp_sync_info; - - /* Stop LDP-SYNC on this interface: - * if holddown timer is running stop it - * delete ldp instance on interface - * restore metric - */ - ils_debug("ldp_sync: remove if %s", circuit->interface - ? circuit->interface->name : ""); - - THREAD_OFF(ldp_sync_info->t_holddown); - ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED; - isis_ldp_sync_set_if_metric(circuit, true); - if (remove) { - /* ISIS instance being removed free ldp-sync info */ - ldp_sync_info_free((struct ldp_sync_info **)&(ldp_sync_info)); - circuit->ldp_sync_info = NULL; - } -} - static int isis_ldp_sync_adj_state_change(struct isis_adjacency *adj) { struct isis_circuit *circuit = adj->circuit; - struct ldp_sync_info *ldp_sync_info; - struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); + struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info; + struct isis_area *area = circuit->area; - if (!isis || - !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) || - circuit->interface->vrf_id != VRF_DEFAULT || - if_is_loopback(circuit->interface)) + if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) + || circuit->interface->vrf_id != VRF_DEFAULT + || if_is_loopback(circuit->interface)) return 0; - if (circuit->ldp_sync_info == NULL) - isis_ldp_sync_if_init(circuit, isis); - ldp_sync_info = circuit->ldp_sync_info; - if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED) return 0; @@ -329,16 +257,15 @@ bool isis_ldp_sync_if_metric_config(struct isis_circuit *circuit, int level, int metric) { struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info; - struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); + struct isis_area *area = circuit->area; /* configured interface metric has been changed: * if LDP-IGP Sync is running and metric has been set to LSInfinity * change saved value so when ldp-sync completes proper metric is * restored */ - if (isis && - CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) && - ldp_sync_info != NULL) { + if (area && CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) + && ldp_sync_info != NULL) { if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_SET_METRIC)) { @@ -471,15 +398,12 @@ void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit) void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info) { struct isis_area *area; - struct listnode *node; + struct listnode *anode, *cnode; struct isis_circuit *circuit; - struct interface *ifp; - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); - /* if isis is not enabled or LDP-SYNC is not configured ignore */ - if (!isis - || !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) + /* if isis is not enabled ignore */ + if (!isis) return; /* Check if the LDP main client session closed */ @@ -492,14 +416,12 @@ void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info) */ zlog_err("ldp_sync: LDP down"); - FOR_ALL_INTERFACES (vrf, ifp) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - circuit = - circuit_lookup_by_ifp(ifp, area->circuit_list); - if (circuit == NULL) - continue; + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { + if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) + continue; + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) isis_ldp_sync_ldp_fail(circuit); - } } } @@ -507,110 +429,130 @@ void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info) * LDP-SYNC routes used by set commands. */ -void isis_if_set_ldp_sync_enable(struct isis_circuit *circuit) +void isis_area_ldp_sync_enable(struct isis_area *area) { - struct ldp_sync_info *ldp_sync_info; - struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); + struct isis_circuit *circuit; + struct listnode *node; + + if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) { + SET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE); + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) + isis_if_ldp_sync_enable(circuit); + } +} + +void isis_area_ldp_sync_disable(struct isis_area *area) +{ + struct isis_circuit *circuit; + struct listnode *node; + + if (CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) { + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) + isis_if_ldp_sync_disable(circuit); + + UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE); + + UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN); + area->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT; + } +} + +void isis_area_ldp_sync_set_holddown(struct isis_area *area, uint16_t holddown) +{ + struct isis_circuit *circuit; + struct listnode *node; + + if (holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT) + UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN); + else + SET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN); + + area->ldp_sync_cmd.holddown = holddown; + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) + isis_if_set_ldp_sync_holddown(circuit); +} + +void isis_if_ldp_sync_enable(struct isis_circuit *circuit) +{ + struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info; + struct isis_area *area = circuit->area; /* called when setting LDP-SYNC at the global level: * specifed on interface overrides global config * if ptop link send msg to LDP indicating ldp-sync enabled */ - if (!isis || if_is_loopback(circuit->interface)) + if (if_is_loopback(circuit->interface)) return; - if (CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) { - if (circuit->ldp_sync_info == NULL) - isis_ldp_sync_if_init(circuit, isis); - ldp_sync_info = circuit->ldp_sync_info; + ils_debug("ldp_sync: enable if %s", circuit->interface->name); - /* config on interface, overrides global config. */ - if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG)) - if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED) - return; + if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) + return; - ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED; - ils_debug("ldp_sync: enable if %s", circuit->interface->name); + /* config on interface, overrides global config. */ + if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG)) + if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED) + return; - /* send message to LDP if ptop link */ - if (circuit->circ_type == CIRCUIT_T_P2P || - if_is_pointopoint(circuit->interface)) { - ldp_sync_info->state = - LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP; - isis_ldp_sync_state_req_msg(circuit); - } else { - ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED; - zlog_debug("ldp_sync: Sync only runs on P2P links %s", - circuit->interface->name); - } - } else - /* delete LDP sync even if configured on an interface */ - isis_ldp_sync_if_remove(circuit, false); + if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN)) + ldp_sync_info->holddown = area->ldp_sync_cmd.holddown; + + if (circuit->circ_type == CIRCUIT_T_P2P + || if_is_pointopoint(circuit->interface)) { + ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP; + isis_ldp_sync_state_req_msg(circuit); + } else { + ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED; + ils_debug("ldp_sync: Sync only runs on P2P links %s", + circuit->interface->name); + } +} + +void isis_if_ldp_sync_disable(struct isis_circuit *circuit) +{ + struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info; + struct isis_area *area = circuit->area; + + /* Stop LDP-SYNC on this interface: + * if holddown timer is running stop it + * delete ldp instance on interface + * restore metric + */ + if (if_is_loopback(circuit->interface)) + return; + + ils_debug("ldp_sync: remove if %s", circuit->interface->name); + + if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) + return; + + THREAD_OFF(ldp_sync_info->t_holddown); + ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED; + isis_ldp_sync_set_if_metric(circuit, true); } void isis_if_set_ldp_sync_holddown(struct isis_circuit *circuit) { - struct ldp_sync_info *ldp_sync_info; - struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); + struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info; + struct isis_area *area = circuit->area; /* called when setting LDP-SYNC at the global level: * specifed on interface overrides global config. */ - if (!isis || if_is_loopback(circuit->interface)) + if (if_is_loopback(circuit->interface)) return; - if (circuit->ldp_sync_info == NULL) - isis_ldp_sync_if_init(circuit, isis); - ldp_sync_info = circuit->ldp_sync_info; - /* config on interface, overrides global config. */ if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN)) return; - if (CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN)) - ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown; + if (CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN)) + ldp_sync_info->holddown = area->ldp_sync_cmd.holddown; else ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT; } -void isis_ldp_sync_gbl_exit(bool remove) -{ - struct isis_area *area; - struct listnode *node; - struct isis_circuit *circuit; - struct interface *ifp; - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); - struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); - - /* if you delete LDP-SYNC at a gobal level is clears all LDP-SYNC - * configuration, even interface configuration - */ - if (isis && - CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) { - /* register with opaque client to recv LDP-IGP Sync msgs */ - zclient_unregister_opaque(zclient, - LDP_IGP_SYNC_IF_STATE_UPDATE); - zclient_unregister_opaque(zclient, - LDP_IGP_SYNC_ANNOUNCE_UPDATE); - - /* disable LDP-SYNC globally */ - UNSET_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE); - UNSET_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN); - isis->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT; - - /* remove LDP-SYNC on all ISIS interfaces */ - FOR_ALL_INTERFACES (vrf, ifp) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, - area)) { - circuit = circuit_lookup_by_ifp(ifp, - area->circuit_list); - if (circuit == NULL) - continue; - isis_ldp_sync_if_remove(circuit, remove); - } - } - } -} - /* * LDP-SYNC routines used by show commands. */ @@ -693,11 +635,6 @@ DEFUN (show_isis_mpls_ldp_interface, return CMD_SUCCESS; } - if (!CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) { - vty_out(vty, "LDP-sync is disabled\n"); - return CMD_SUCCESS; - } - if (argv_find(argv, argc, "INTERFACE", &idx_intf)) ifname = argv[idx_intf]->arg; diff --git a/isisd/isis_ldp_sync.h b/isisd/isis_ldp_sync.h index 977c5ba0de..69a1800007 100644 --- a/isisd/isis_ldp_sync.h +++ b/isisd/isis_ldp_sync.h @@ -29,13 +29,15 @@ zlog_debug(__VA_ARGS__); \ } while (0) -extern void isis_if_set_ldp_sync_enable(struct isis_circuit *circuit); +extern void isis_area_ldp_sync_enable(struct isis_area *area); +extern void isis_area_ldp_sync_disable(struct isis_area *area); +extern void isis_area_ldp_sync_set_holddown(struct isis_area *area, + uint16_t holddown); +extern void isis_if_ldp_sync_enable(struct isis_circuit *circuit); +extern void isis_if_ldp_sync_disable(struct isis_circuit *circuit); extern void isis_if_set_ldp_sync_holddown(struct isis_circuit *circuit); -extern void isis_ldp_sync_if_init(struct isis_circuit *circuit, - struct isis *isis); extern void isis_ldp_sync_if_start(struct isis_circuit *circuit, bool send_state_req); -extern void isis_ldp_sync_if_remove(struct isis_circuit *circuit, bool remove); extern void isis_ldp_sync_if_complete(struct isis_circuit *circuit); extern void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit); extern void @@ -49,5 +51,4 @@ extern void isis_ldp_sync_set_if_metric(struct isis_circuit *circuit, extern bool isis_ldp_sync_if_metric_config(struct isis_circuit *circuit, int level, int metric); extern void isis_ldp_sync_init(void); -extern void isis_ldp_sync_gbl_exit(bool remove); #endif /* _ZEBRA_ISIS_LDP_SYNC_H */ diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c index 085177b943..e033c28fef 100644 --- a/isisd/isis_lfa.c +++ b/isisd/isis_lfa.c @@ -1148,10 +1148,13 @@ static void lfa_calc_pq_spaces(struct isis_spftree *spftree_pc, /* * Compute the reverse SPF in the behalf of the node - * adjacent to the failure. + * adjacent to the failure, if we haven't done that + * before */ - adj_node->lfa.spftree_reverse = - isis_spf_reverse_run(adj_node->lfa.spftree); + if (!adj_node->lfa.spftree_reverse) + adj_node->lfa.spftree_reverse = + isis_spf_reverse_run( + adj_node->lfa.spftree); lfa_calc_reach_nodes(adj_node->lfa.spftree_reverse, spftree_reverse, adj_nodes, false, @@ -2255,6 +2258,11 @@ static void isis_spf_run_tilfa(struct isis_area *area, spftree_pc_node = isis_tilfa_compute(area, spftree, spftree_reverse, resource); isis_spftree_del(spftree_pc_node); + + /* don't do link protection unless link-fallback is configured + */ + if (!circuit->tilfa_link_fallback[spftree->level - 1]) + return; } /* Compute link protecting repair paths. */ diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c index 227724934b..ecad16229c 100644 --- a/isisd/isis_nb.c +++ b/isisd/isis_nb.c @@ -686,13 +686,6 @@ const struct frr_yang_module_info frr_isisd_info = { }, }, { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/vrf", - .cbs = { - .modify = lib_interface_isis_vrf_modify, - }, - }, - - { .xpath = "/frr-interface:lib/interface/frr-isisd:isis/circuit-type", .cbs = { .cli_show = cli_show_ip_isis_circ_type, @@ -985,6 +978,12 @@ const struct frr_yang_module_info frr_isisd_info = { } }, { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-1/ti-lfa/link-fallback", + .cbs = { + .modify = lib_interface_isis_fast_reroute_level_1_ti_lfa_link_fallback_modify, + } + }, + { .xpath = "/frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-2/lfa/enable", .cbs = { .modify = lib_interface_isis_fast_reroute_level_2_lfa_enable_modify, @@ -1025,6 +1024,12 @@ const struct frr_yang_module_info frr_isisd_info = { } }, { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-2/ti-lfa/link-fallback", + .cbs = { + .modify = lib_interface_isis_fast_reroute_level_2_ti_lfa_link_fallback_modify, + } + }, + { .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis", .cbs = { .get_elem = lib_interface_state_isis_get_elem, diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h index a6841b9fd4..0c2f7b6b7e 100644 --- a/isisd/isis_nb.h +++ b/isisd/isis_nb.h @@ -214,7 +214,6 @@ int isis_instance_mpls_te_router_address_destroy( int lib_interface_isis_create(struct nb_cb_create_args *args); int lib_interface_isis_destroy(struct nb_cb_destroy_args *args); int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args); -int lib_interface_isis_vrf_modify(struct nb_cb_modify_args *args); int lib_interface_isis_ipv4_routing_modify(struct nb_cb_modify_args *args); int lib_interface_isis_ipv6_routing_modify(struct nb_cb_modify_args *args); int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args); @@ -320,6 +319,8 @@ int lib_interface_isis_fast_reroute_level_1_ti_lfa_enable_modify( struct nb_cb_modify_args *args); int lib_interface_isis_fast_reroute_level_1_ti_lfa_node_protection_modify( struct nb_cb_modify_args *args); +int lib_interface_isis_fast_reroute_level_1_ti_lfa_link_fallback_modify( + struct nb_cb_modify_args *args); int lib_interface_isis_fast_reroute_level_2_lfa_enable_modify( struct nb_cb_modify_args *args); int lib_interface_isis_fast_reroute_level_2_lfa_exclude_interface_create( @@ -336,6 +337,8 @@ int lib_interface_isis_fast_reroute_level_2_ti_lfa_enable_modify( struct nb_cb_modify_args *args); int lib_interface_isis_fast_reroute_level_2_ti_lfa_node_protection_modify( struct nb_cb_modify_args *args); +int lib_interface_isis_fast_reroute_level_2_ti_lfa_link_fallback_modify( + struct nb_cb_modify_args *args); struct yang_data * lib_interface_state_isis_get_elem(struct nb_cb_get_elem_args *args); const void *lib_interface_state_isis_adjacencies_adjacency_get_next( diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index c8ad816b58..5ca2329dd3 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -32,7 +32,6 @@ #include "spf_backoff.h" #include "lib_errors.h" #include "vrf.h" -#include "zclient.h" #include "ldp_sync.h" #include "isisd/isisd.h" @@ -56,8 +55,6 @@ DEFINE_MTYPE_STATIC(ISISD, ISIS_MPLS_TE, "ISIS MPLS_TE parameters"); DEFINE_MTYPE_STATIC(ISISD, ISIS_PLIST_NAME, "ISIS prefix-list name"); -extern struct zclient *zclient; - /* * XPath: /frr-isisd:isis/instance */ @@ -87,16 +84,10 @@ 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; - - /* remove ldp-sync config */ - if (vrf_id == VRF_DEFAULT) - isis_ldp_sync_gbl_exit(true); isis_area_destroy(area); return NB_OK; @@ -2369,11 +2360,6 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_n_flag_clear_modify( int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args) { struct isis_area *area; - struct listnode *node; - struct isis_circuit *circuit; - struct interface *ifp; - struct vrf *vrf; - struct isis *isis; switch (args->event) { case NB_EV_VALIDATE: @@ -2392,30 +2378,7 @@ int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args) break; case NB_EV_APPLY: area = nb_running_get_entry(args->dnode, NULL, true); - isis = area->isis; - vrf = vrf_lookup_by_id(isis->vrf_id); - - /* register with opaque client to recv LDP-IGP Sync msgs */ - zclient_register_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE); - zclient_register_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE); - - if (!CHECK_FLAG(isis->ldp_sync_cmd.flags, - LDP_SYNC_FLAG_ENABLE)) { - SET_FLAG(isis->ldp_sync_cmd.flags, - LDP_SYNC_FLAG_ENABLE); - - /* turn on LDP-IGP Sync on all ptop ISIS interfaces */ - FOR_ALL_INTERFACES (vrf, ifp) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, - area)) { - circuit = circuit_lookup_by_ifp( - ifp, area->circuit_list); - if (circuit == NULL) - continue; - isis_if_set_ldp_sync_enable(circuit); - } - } - } + isis_area_ldp_sync_enable(area); break; } return NB_OK; @@ -2423,11 +2386,13 @@ int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args) int isis_instance_mpls_ldp_sync_destroy(struct nb_cb_destroy_args *args) { + struct isis_area *area; + if (args->event != NB_EV_APPLY) return NB_OK; - /* remove ldp-sync config */ - isis_ldp_sync_gbl_exit(false); + area = nb_running_get_entry(args->dnode, NULL, true); + isis_area_ldp_sync_disable(area); return NB_OK; } @@ -2438,12 +2403,7 @@ int isis_instance_mpls_ldp_sync_destroy(struct nb_cb_destroy_args *args) int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args) { struct isis_area *area; - struct listnode *node; - struct isis_circuit *circuit; - struct interface *ifp; - struct vrf *vrf; - uint16_t holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT; - struct isis *isis; + uint16_t holddown; switch (args->event) { case NB_EV_VALIDATE: @@ -2462,29 +2422,8 @@ int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args) break; case NB_EV_APPLY: area = nb_running_get_entry(args->dnode, NULL, true); - isis = area->isis; - vrf = vrf_lookup_by_id(isis->vrf_id); holddown = yang_dnode_get_uint16(args->dnode, NULL); - - if (holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT) - UNSET_FLAG(isis->ldp_sync_cmd.flags, - LDP_SYNC_FLAG_HOLDDOWN); - else - SET_FLAG(isis->ldp_sync_cmd.flags, - LDP_SYNC_FLAG_HOLDDOWN); - isis->ldp_sync_cmd.holddown = holddown; - - /* set holddown time on all ISIS interfaces */ - FOR_ALL_INTERFACES (vrf, ifp) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, - area)) { - circuit = circuit_lookup_by_ifp(ifp, - area->circuit_list); - if (circuit == NULL) - continue; - isis_if_set_ldp_sync_holddown(circuit); - } - } + isis_area_ldp_sync_set_holddown(area, holddown); break; } return NB_OK; @@ -2498,9 +2437,7 @@ int lib_interface_isis_create(struct nb_cb_create_args *args) struct isis_area *area = NULL; struct interface *ifp; struct isis_circuit *circuit = NULL; - struct vrf *vrf; const char *area_tag = yang_dnode_get_string(args->dnode, "./area-tag"); - const char *vrf_name = yang_dnode_get_string(args->dnode, "./vrf"); uint32_t min_mtu, actual_mtu; switch (args->event) { @@ -2515,14 +2452,6 @@ int lib_interface_isis_create(struct nb_cb_create_args *args) /* zebra might not know yet about the MTU - nothing we can do */ if (!ifp || ifp->mtu == 0) break; - vrf = vrf_lookup_by_id(ifp->vrf_id); - if (ifp->vrf_id != VRF_DEFAULT && vrf - && strcmp(vrf->name, vrf_name) != 0) { - snprintf(args->errmsg, args->errmsg_len, - "interface %s not in vrf %s\n", ifp->name, - vrf_name); - return NB_ERR_VALIDATION; - } actual_mtu = if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu; @@ -2544,24 +2473,8 @@ int lib_interface_isis_create(struct nb_cb_create_args *args) } break; case NB_EV_APPLY: - area = isis_area_lookup_by_vrf(area_tag, vrf_name); - /* The area should have already be created. We are - * setting the priority of the global isis area creation - * slightly lower, so it should be executed first, but I - * cannot rely on that so here I have to check. - */ - if (!area) { - flog_err( - EC_LIB_NB_CB_CONFIG_APPLY, - "%s: attempt to create circuit for area %s before the area has been created", - __func__, area_tag); - abort(); - } ifp = nb_running_get_entry(args->dnode, NULL, true); - circuit = isis_circuit_create(area, ifp); - assert(circuit - && (circuit->state == C_STATE_CONF - || circuit->state == C_STATE_UP)); + circuit = isis_circuit_new(ifp, area_tag); nb_running_set_entry(args->dnode, circuit); break; } @@ -2577,18 +2490,9 @@ int lib_interface_isis_destroy(struct nb_cb_destroy_args *args) return NB_OK; circuit = nb_running_unset_entry(args->dnode); - if (!circuit) - return NB_ERR_INCONSISTENCY; - /* remove ldp-sync config */ - isis_ldp_sync_if_remove(circuit, true); + isis_circuit_del(circuit); - /* disable both AFs for this circuit. this will also update the - * CSM state by sending an ISIS_DISABLED signal. If there is no - * area associated to the circuit there is nothing to do - */ - if (circuit->area) - isis_circuit_af_set(circuit, false, false); return NB_OK; } @@ -2631,44 +2535,6 @@ int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args) } /* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/vrf - */ -int lib_interface_isis_vrf_modify(struct nb_cb_modify_args *args) -{ - struct interface *ifp; - struct vrf *vrf; - const char *ifname, *vrfname, *vrf_name; - struct isis_circuit *circuit; - - if (args->event == NB_EV_VALIDATE) { - /* libyang doesn't like relative paths across module boundaries - */ - ifname = yang_dnode_get_string(args->dnode->parent->parent, - "./name"); - vrfname = yang_dnode_get_string(args->dnode->parent->parent, - "./vrf"); - vrf = vrf_lookup_by_name(vrfname); - assert(vrf); - ifp = if_lookup_by_name(ifname, vrf->vrf_id); - - if (!ifp) - return NB_OK; - - vrf_name = yang_dnode_get_string(args->dnode, NULL); - circuit = circuit_scan_by_ifp(ifp); - if (circuit && circuit->area && circuit->isis - && strcmp(circuit->isis->name, vrf_name)) { - snprintf(args->errmsg, args->errmsg_len, - "ISIS circuit is already defined on vrf %s", - circuit->isis->name); - return NB_ERR_VALIDATION; - } - } - - return NB_OK; -} - -/* * XPath: /frr-interface:lib/interface/frr-isisd:isis/circuit-type */ int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args) @@ -2678,7 +2544,6 @@ int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args) struct interface *ifp; struct vrf *vrf; const char *ifname, *vrfname; - struct isis *isis = NULL; switch (args->event) { case NB_EV_VALIDATE: @@ -2694,11 +2559,7 @@ int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args) if (!ifp) break; - isis = isis_lookup_by_vrfid(ifp->vrf_id); - if (isis == NULL) - return NB_ERR_VALIDATION; - - circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list); + circuit = circuit_scan_by_ifp(ifp); if (circuit && circuit->state == C_STATE_UP && circuit->area->is_type != IS_LEVEL_1_AND_2 && circuit->area->is_type != circ_type) { @@ -3085,7 +2946,6 @@ int lib_interface_isis_network_type_modify(struct nb_cb_modify_args *args) int lib_interface_isis_passive_modify(struct nb_cb_modify_args *args) { struct isis_circuit *circuit; - struct isis_area *area; struct interface *ifp; bool passive = yang_dnode_get_bool(args->dnode, NULL); @@ -3108,14 +2968,7 @@ int lib_interface_isis_passive_modify(struct nb_cb_modify_args *args) return NB_OK; circuit = nb_running_get_entry(args->dnode, NULL, true); - if (circuit->state != C_STATE_UP) { - circuit->is_passive = passive; - } else { - area = circuit->area; - isis_csm_state_change(ISIS_DISABLE, circuit, area); - circuit->is_passive = passive; - isis_csm_state_change(ISIS_ENABLE, circuit, area); - } + isis_circuit_passive_set(circuit, passive); return NB_OK; } @@ -3318,13 +3171,23 @@ int lib_interface_isis_mpls_ldp_sync_modify(struct nb_cb_modify_args *args) struct isis_circuit *circuit; struct ldp_sync_info *ldp_sync_info; bool ldp_sync_enable; - struct isis *isis; + struct interface *ifp; switch (args->event) { case NB_EV_VALIDATE: + ifp = nb_running_get_entry(args->dnode->parent->parent->parent, + NULL, false); + if (ifp == NULL) + return NB_ERR_VALIDATION; + if (if_is_loopback(ifp)) { + snprintf(args->errmsg, args->errmsg_len, + "LDP-Sync does not run on loopback interface"); + return NB_ERR_VALIDATION; + } + circuit = nb_running_get_entry(args->dnode, NULL, false); if (circuit == NULL || circuit->area == NULL) - return NB_ERR_VALIDATION; + break; if (circuit->isis->vrf_id != VRF_DEFAULT) { snprintf(args->errmsg, args->errmsg_len, @@ -3338,39 +3201,17 @@ int lib_interface_isis_mpls_ldp_sync_modify(struct nb_cb_modify_args *args) case NB_EV_APPLY: circuit = nb_running_get_entry(args->dnode, NULL, true); ldp_sync_enable = yang_dnode_get_bool(args->dnode, NULL); - isis = circuit->isis; - if (circuit->ldp_sync_info == NULL) - isis_ldp_sync_if_init(circuit, isis); - assert(circuit->ldp_sync_info != NULL); ldp_sync_info = circuit->ldp_sync_info; - if (ldp_sync_enable) { - /* enable LDP-SYNC on an interface - * if ptop interface send message to LDP to get state - */ - SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG); - ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED; - if (circuit->circ_type == CIRCUIT_T_P2P) { - ldp_sync_info->state = - LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP; - isis_ldp_sync_state_req_msg(circuit); - } else { - zlog_debug("ldp_sync: only runs on P2P links %s", - circuit->interface->name); - ldp_sync_info->state = - LDP_IGP_SYNC_STATE_NOT_REQUIRED; - } - } else { - /* disable LDP-SYNC on an interface - * stop holddown timer if running - * restore isis metric - */ - SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG); - ldp_sync_info->enabled = LDP_IGP_SYNC_DEFAULT; - ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED; - THREAD_OFF(ldp_sync_info->t_holddown); - isis_ldp_sync_set_if_metric(circuit, true); + SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG); + ldp_sync_info->enabled = ldp_sync_enable; + + if (circuit->area) { + if (ldp_sync_enable) + isis_if_ldp_sync_enable(circuit); + else + isis_if_ldp_sync_disable(circuit); } break; } @@ -3385,13 +3226,23 @@ int lib_interface_isis_mpls_holddown_modify(struct nb_cb_modify_args *args) struct isis_circuit *circuit; struct ldp_sync_info *ldp_sync_info; uint16_t holddown; - struct isis *isis; + struct interface *ifp; switch (args->event) { case NB_EV_VALIDATE: + ifp = nb_running_get_entry(args->dnode->parent->parent->parent, + NULL, false); + if (ifp == NULL) + return NB_ERR_VALIDATION; + if (if_is_loopback(ifp)) { + snprintf(args->errmsg, args->errmsg_len, + "LDP-Sync does not run on loopback interface"); + return NB_ERR_VALIDATION; + } + circuit = nb_running_get_entry(args->dnode, NULL, false); if (circuit == NULL || circuit->area == NULL) - return NB_ERR_VALIDATION; + break; if (circuit->isis->vrf_id != VRF_DEFAULT) { snprintf(args->errmsg, args->errmsg_len, @@ -3405,11 +3256,7 @@ int lib_interface_isis_mpls_holddown_modify(struct nb_cb_modify_args *args) case NB_EV_APPLY: circuit = nb_running_get_entry(args->dnode, NULL, true); holddown = yang_dnode_get_uint16(args->dnode, NULL); - isis = circuit->isis; - if (circuit->ldp_sync_info == NULL) - isis_ldp_sync_if_init(circuit, isis); - assert(circuit->ldp_sync_info != NULL); ldp_sync_info = circuit->ldp_sync_info; SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN); @@ -3423,14 +3270,23 @@ int lib_interface_isis_mpls_holddown_destroy(struct nb_cb_destroy_args *args) { struct isis_circuit *circuit; struct ldp_sync_info *ldp_sync_info; - struct isis *isis; + struct interface *ifp; switch (args->event) { case NB_EV_VALIDATE: - circuit = nb_running_get_entry(args->dnode, NULL, false); - if (circuit == NULL || circuit->ldp_sync_info == NULL - || circuit->area == NULL) + ifp = nb_running_get_entry(args->dnode->parent->parent->parent, + NULL, false); + if (ifp == NULL) + return NB_ERR_VALIDATION; + if (if_is_loopback(ifp)) { + snprintf(args->errmsg, args->errmsg_len, + "LDP-Sync does not run on loopback interface"); return NB_ERR_VALIDATION; + } + + circuit = nb_running_get_entry(args->dnode, NULL, false); + if (circuit == NULL || circuit->area == NULL) + break; if (circuit->isis->vrf_id != VRF_DEFAULT) { snprintf(args->errmsg, args->errmsg_len, @@ -3443,15 +3299,12 @@ int lib_interface_isis_mpls_holddown_destroy(struct nb_cb_destroy_args *args) break; case NB_EV_APPLY: circuit = nb_running_get_entry(args->dnode, NULL, true); - isis = circuit->isis; ldp_sync_info = circuit->ldp_sync_info; + UNSET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN); - if (CHECK_FLAG(isis->ldp_sync_cmd.flags, - LDP_SYNC_FLAG_HOLDDOWN)) - ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown; - else - ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT; + if (circuit->area) + isis_if_set_ldp_sync_holddown(circuit); break; } @@ -3473,15 +3326,18 @@ int lib_interface_isis_fast_reroute_level_1_lfa_enable_modify( circuit = nb_running_get_entry(args->dnode, NULL, true); circuit->lfa_protection[0] = yang_dnode_get_bool(args->dnode, NULL); - if (circuit->lfa_protection[0]) - circuit->area->lfa_protected_links[0]++; - else { - assert(circuit->area->lfa_protected_links[0] > 0); - circuit->area->lfa_protected_links[0]--; - } area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) { + if (circuit->lfa_protection[0]) + area->lfa_protected_links[0]++; + else { + assert(area->lfa_protected_links[0] > 0); + area->lfa_protected_links[0]--; + } + + lsp_regenerate_schedule(area, area->is_type, 0); + } return NB_OK; } @@ -3505,7 +3361,8 @@ int lib_interface_isis_fast_reroute_level_1_lfa_exclude_interface_create( isis_lfa_excluded_iface_add(circuit, ISIS_LEVEL1, exclude_ifname); area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -3525,7 +3382,8 @@ int lib_interface_isis_fast_reroute_level_1_lfa_exclude_interface_destroy( isis_lfa_excluded_iface_delete(circuit, ISIS_LEVEL1, exclude_ifname); area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -3545,15 +3403,18 @@ int lib_interface_isis_fast_reroute_level_1_remote_lfa_enable_modify( circuit = nb_running_get_entry(args->dnode, NULL, true); circuit->rlfa_protection[0] = yang_dnode_get_bool(args->dnode, NULL); - if (circuit->rlfa_protection[0]) - circuit->area->rlfa_protected_links[0]++; - else { - assert(circuit->area->rlfa_protected_links[0] > 0); - circuit->area->rlfa_protected_links[0]--; - } area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) { + if (circuit->rlfa_protection[0]) + area->rlfa_protected_links[0]++; + else { + assert(area->rlfa_protected_links[0] > 0); + area->rlfa_protected_links[0]--; + } + + lsp_regenerate_schedule(area, area->is_type, 0); + } return NB_OK; } @@ -3575,7 +3436,8 @@ int lib_interface_isis_fast_reroute_level_1_remote_lfa_maximum_metric_modify( circuit->rlfa_max_metric[0] = yang_dnode_get_uint32(args->dnode, NULL); area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -3593,7 +3455,8 @@ int lib_interface_isis_fast_reroute_level_1_remote_lfa_maximum_metric_destroy( circuit->rlfa_max_metric[0] = 0; area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -3613,15 +3476,18 @@ int lib_interface_isis_fast_reroute_level_1_ti_lfa_enable_modify( circuit = nb_running_get_entry(args->dnode, NULL, true); circuit->tilfa_protection[0] = yang_dnode_get_bool(args->dnode, NULL); - if (circuit->tilfa_protection[0]) - circuit->area->tilfa_protected_links[0]++; - else { - assert(circuit->area->tilfa_protected_links[0] > 0); - circuit->area->tilfa_protected_links[0]--; - } area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) { + if (circuit->tilfa_protection[0]) + area->tilfa_protected_links[0]++; + else { + assert(area->tilfa_protected_links[0] > 0); + area->tilfa_protected_links[0]--; + } + + lsp_regenerate_schedule(area, area->is_type, 0); + } return NB_OK; } @@ -3644,7 +3510,32 @@ int lib_interface_isis_fast_reroute_level_1_ti_lfa_node_protection_modify( yang_dnode_get_bool(args->dnode, NULL); area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); + + return NB_OK; +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-1/ti-lfa/link-fallback + */ +int lib_interface_isis_fast_reroute_level_1_ti_lfa_link_fallback_modify( + struct nb_cb_modify_args *args) +{ + struct isis_area *area; + struct isis_circuit *circuit; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(args->dnode, NULL, true); + circuit->tilfa_link_fallback[0] = + yang_dnode_get_bool(args->dnode, NULL); + + area = circuit->area; + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -3664,15 +3555,18 @@ int lib_interface_isis_fast_reroute_level_2_lfa_enable_modify( circuit = nb_running_get_entry(args->dnode, NULL, true); circuit->lfa_protection[1] = yang_dnode_get_bool(args->dnode, NULL); - if (circuit->lfa_protection[1]) - circuit->area->lfa_protected_links[1]++; - else { - assert(circuit->area->lfa_protected_links[1] > 0); - circuit->area->lfa_protected_links[1]--; - } area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) { + if (circuit->lfa_protection[1]) + area->lfa_protected_links[1]++; + else { + assert(area->lfa_protected_links[1] > 0); + area->lfa_protected_links[1]--; + } + + lsp_regenerate_schedule(area, area->is_type, 0); + } return NB_OK; } @@ -3696,7 +3590,8 @@ int lib_interface_isis_fast_reroute_level_2_lfa_exclude_interface_create( isis_lfa_excluded_iface_add(circuit, ISIS_LEVEL2, exclude_ifname); area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -3716,7 +3611,8 @@ int lib_interface_isis_fast_reroute_level_2_lfa_exclude_interface_destroy( isis_lfa_excluded_iface_delete(circuit, ISIS_LEVEL2, exclude_ifname); area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -3736,15 +3632,18 @@ int lib_interface_isis_fast_reroute_level_2_remote_lfa_enable_modify( circuit = nb_running_get_entry(args->dnode, NULL, true); circuit->rlfa_protection[1] = yang_dnode_get_bool(args->dnode, NULL); - if (circuit->rlfa_protection[1]) - circuit->area->rlfa_protected_links[1]++; - else { - assert(circuit->area->rlfa_protected_links[1] > 0); - circuit->area->rlfa_protected_links[1]--; - } area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) { + if (circuit->rlfa_protection[1]) + area->rlfa_protected_links[1]++; + else { + assert(area->rlfa_protected_links[1] > 0); + area->rlfa_protected_links[1]--; + } + + lsp_regenerate_schedule(area, area->is_type, 0); + } return NB_OK; } @@ -3766,7 +3665,8 @@ int lib_interface_isis_fast_reroute_level_2_remote_lfa_maximum_metric_modify( circuit->rlfa_max_metric[1] = yang_dnode_get_uint32(args->dnode, NULL); area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -3784,7 +3684,8 @@ int lib_interface_isis_fast_reroute_level_2_remote_lfa_maximum_metric_destroy( circuit->rlfa_max_metric[1] = 0; area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } @@ -3804,15 +3705,18 @@ int lib_interface_isis_fast_reroute_level_2_ti_lfa_enable_modify( circuit = nb_running_get_entry(args->dnode, NULL, true); circuit->tilfa_protection[1] = yang_dnode_get_bool(args->dnode, NULL); - if (circuit->tilfa_protection[1]) - circuit->area->tilfa_protected_links[1]++; - else { - assert(circuit->area->tilfa_protected_links[1] > 0); - circuit->area->tilfa_protected_links[1]--; - } area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) { + if (circuit->tilfa_protection[1]) + area->tilfa_protected_links[1]++; + else { + assert(area->tilfa_protected_links[1] > 0); + area->tilfa_protected_links[1]--; + } + + lsp_regenerate_schedule(area, area->is_type, 0); + } return NB_OK; } @@ -3835,7 +3739,32 @@ int lib_interface_isis_fast_reroute_level_2_ti_lfa_node_protection_modify( yang_dnode_get_bool(args->dnode, NULL); area = circuit->area; - lsp_regenerate_schedule(area, area->is_type, 0); + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); + + return NB_OK; +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-2/ti-lfa/link-fallback + */ +int lib_interface_isis_fast_reroute_level_2_ti_lfa_link_fallback_modify( + struct nb_cb_modify_args *args) +{ + struct isis_area *area; + struct isis_circuit *circuit; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(args->dnode, NULL, true); + circuit->tilfa_link_fallback[1] = + yang_dnode_get_bool(args->dnode, NULL); + + area = circuit->area; + if (area) + lsp_regenerate_schedule(area, area->is_type, 0); return NB_OK; } diff --git a/isisd/isis_snmp.c b/isisd/isis_snmp.c index 1efe9f3bfb..6337faab1c 100644 --- a/isisd/isis_snmp.c +++ b/isisd/isis_snmp.c @@ -629,6 +629,54 @@ static uint8_t isis_null_sysid[ISIS_SYS_ID_LEN]; /* Protocols supported value */ static uint8_t isis_snmp_protocols_supported = 0x7; /* All: iso, ipv4, ipv6 */ +#define SNMP_CIRCUITS_MAX (512) + +static struct isis_circuit *snmp_circuits[SNMP_CIRCUITS_MAX]; +static uint32_t snmp_circuit_id_last; + +static int isis_circuit_snmp_id_gen(struct isis_circuit *circuit) +{ + uint32_t id; + uint32_t i; + + id = snmp_circuit_id_last; + id++; + + /* find next unused entry */ + for (i = 0; i < SNMP_CIRCUITS_MAX; i++) { + if (id >= SNMP_CIRCUITS_MAX) { + id = 0; + continue; + } + + if (id == 0) + continue; + + if (snmp_circuits[id] == NULL) + break; + + id++; + } + + if (i == SNMP_CIRCUITS_MAX) { + zlog_warn("Could not allocate a smmp-circuit-id"); + return 0; + } + + snmp_circuits[id] = circuit; + snmp_circuit_id_last = id; + circuit->snmp_id = id; + + return 0; +} + +static int isis_circuit_snmp_id_free(struct isis_circuit *circuit) +{ + snmp_circuits[circuit->snmp_id] = NULL; + circuit->snmp_id = 0; + return 0; +} + /* * Convenience function to move to the next circuit, */ @@ -636,10 +684,6 @@ static struct isis_circuit *isis_snmp_circuit_next(struct isis_circuit *circuit) { uint32_t start; uint32_t off; - struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); - - if (isis == NULL) - return NULL; start = 1; @@ -647,7 +691,7 @@ static struct isis_circuit *isis_snmp_circuit_next(struct isis_circuit *circuit) start = circuit->snmp_id + 1; for (off = start; off < SNMP_CIRCUITS_MAX; off++) { - circuit = isis->snmp_circuits[off]; + circuit = snmp_circuits[off]; if (circuit != NULL) return circuit; @@ -912,16 +956,12 @@ static int isis_snmp_circuit_lookup_exact(oid *oid_idx, size_t oid_idx_len, struct isis_circuit **ret_circuit) { struct isis_circuit *circuit; - struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); - - if (isis == NULL) - return 0; if (oid_idx == NULL || oid_idx_len < 1 || oid_idx[0] > SNMP_CIRCUITS_MAX) return 0; - circuit = isis->snmp_circuits[oid_idx[0]]; + circuit = snmp_circuits[oid_idx[0]]; if (circuit == NULL) return 0; @@ -937,10 +977,6 @@ static int isis_snmp_circuit_lookup_next(oid *oid_idx, size_t oid_idx_len, oid off; oid start; struct isis_circuit *circuit; - struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); - - if (isis == NULL) - return 0; start = 0; @@ -952,7 +988,7 @@ static int isis_snmp_circuit_lookup_next(oid *oid_idx, size_t oid_idx_len, } for (off = start; off < SNMP_CIRCUITS_MAX; ++off) { - circuit = isis->snmp_circuits[off]; + circuit = snmp_circuits[off]; if (circuit != NULL && off > start) { if (ret_circuit != NULL) @@ -1011,10 +1047,6 @@ static int isis_snmp_circuit_level_lookup_next( oid start; struct isis_circuit *circuit; int level; - struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); - - if (isis == NULL) - return 0; start = 0; @@ -1026,7 +1058,7 @@ static int isis_snmp_circuit_level_lookup_next( } for (off = start; off < SNMP_CIRCUITS_MAX; off++) { - circuit = isis->snmp_circuits[off]; + circuit = snmp_circuits[off]; if (circuit == NULL) continue; @@ -3449,6 +3481,8 @@ static int isis_snmp_module_init(void) hook_register(isis_hook_adj_state_change, isis_snmp_adj_state_change_update); hook_register(isis_hook_lsp_error, isis_snmp_lsp_error_update); + hook_register(isis_circuit_new_hook, isis_circuit_snmp_id_gen); + hook_register(isis_circuit_del_hook, isis_circuit_snmp_id_free); hook_register(frr_late_init, isis_snmp_init); return 0; diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c index 6055984195..7020b6efeb 100644 --- a/isisd/isis_vty_fabricd.c +++ b/isisd/isis_vty_fabricd.c @@ -229,10 +229,10 @@ DEFUN (ip_router_isis, area = isis_area_lookup(area_tag, VRF_DEFAULT); if (!area) - area = isis_area_create(area_tag, VRF_DEFAULT_NAME); + isis_area_create(area_tag, VRF_DEFAULT_NAME); - if (!circuit || !circuit->area) { - circuit = isis_circuit_create(area, ifp); + if (!circuit) { + circuit = isis_circuit_new(ifp, area_tag); if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) { @@ -288,7 +288,7 @@ DEFUN (no_ip_router_isis, return CMD_ERR_NO_MATCH; } - circuit = circuit_lookup_by_ifp(ifp, area->circuit_list); + circuit = circuit_scan_by_ifp(ifp); if (!circuit) { vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name); return CMD_ERR_NO_MATCH; @@ -301,6 +301,10 @@ DEFUN (no_ip_router_isis, ip = false; isis_circuit_af_set(circuit, ip, ipv6); + + if (!ip && !ipv6) + isis_circuit_del(circuit); + return CMD_SUCCESS; } diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index cb4dd2569d..90959eb98c 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -728,6 +728,8 @@ static void isis_zebra_connected(struct zclient *zclient) { zclient_send_reg_requests(zclient, VRF_DEFAULT); zclient_register_opaque(zclient, LDP_RLFA_LABELS); + zclient_register_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE); + zclient_register_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE); } /* @@ -818,6 +820,8 @@ void isis_zebra_init(struct thread_master *master, int instance) void isis_zebra_stop(void) { zclient_unregister_opaque(zclient, LDP_RLFA_LABELS); + zclient_unregister_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE); + zclient_unregister_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE); zclient_stop(zclient_sync); zclient_free(zclient_sync); zclient_stop(zclient); diff --git a/isisd/isisd.c b/isisd/isisd.c index 714961c177..37416fc1a4 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -114,16 +114,6 @@ int show_isis_neighbor_common(struct vty *, const char *id, char, int clear_isis_neighbor_common(struct vty *, const char *id, const char *vrf_name, bool all_vrf); -static void isis_add(struct isis *isis) -{ - listnode_add(im->isis, isis); -} - -static void isis_delete(struct isis *isis) -{ - listnode_delete(im->isis, isis); -} - /* Link ISIS instance to VRF. */ void isis_vrf_link(struct isis *isis, struct vrf *vrf) { @@ -189,10 +179,8 @@ void isis_global_instance_create(const char *vrf_name) struct isis *isis; isis = isis_lookup_by_vrfname(vrf_name); - if (isis == NULL) { - isis = isis_new(vrf_name); - isis_add(isis); - } + if (isis == NULL) + isis_new(vrf_name); } struct isis *isis_new(const char *vrf_name) @@ -201,16 +189,15 @@ struct isis *isis_new(const char *vrf_name) struct isis *isis; isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis)); + + isis->name = XSTRDUP(MTYPE_ISIS_NAME, vrf_name); + vrf = vrf_lookup_by_name(vrf_name); - if (vrf) { - isis->vrf_id = vrf->vrf_id; + if (vrf) isis_vrf_link(isis, vrf); - isis->name = XSTRDUP(MTYPE_ISIS_NAME, vrf->name); - } else { + else isis->vrf_id = VRF_UNKNOWN; - isis->name = XSTRDUP(MTYPE_ISIS_NAME, vrf_name); - } if (IS_DEBUG_EVENTS) zlog_debug( @@ -224,43 +211,81 @@ struct isis *isis_new(const char *vrf_name) isis->process_id = getpid(); isis->router_id = 0; isis->area_list = list_new(); - isis->init_circ_list = list_new(); isis->uptime = time(NULL); isis->snmp_notifications = 1; dyn_cache_init(isis); + listnode_add(im->isis, isis); + return isis; } +void isis_finish(struct isis *isis) +{ + struct vrf *vrf = NULL; + + listnode_delete(im->isis, isis); + + vrf = vrf_lookup_by_name(isis->name); + if (vrf) + isis_vrf_unlink(isis, vrf); + XFREE(MTYPE_ISIS_NAME, isis->name); + + isis_redist_free(isis); + list_delete(&isis->area_list); + XFREE(MTYPE_ISIS, isis); +} + +void isis_area_add_circuit(struct isis_area *area, struct isis_circuit *circuit) +{ + isis_csm_state_change(ISIS_ENABLE, circuit, area); + + area->ip_circuits += circuit->ip_router; + area->ipv6_circuits += circuit->ipv6_router; + + area->lfa_protected_links[0] += circuit->lfa_protection[0]; + area->rlfa_protected_links[0] += circuit->rlfa_protection[0]; + area->tilfa_protected_links[0] += circuit->tilfa_protection[0]; + + area->lfa_protected_links[1] += circuit->lfa_protection[1]; + area->rlfa_protected_links[1] += circuit->rlfa_protection[1]; + area->tilfa_protected_links[1] += circuit->tilfa_protection[1]; +} + +void isis_area_del_circuit(struct isis_area *area, struct isis_circuit *circuit) +{ + area->ip_circuits -= circuit->ip_router; + area->ipv6_circuits -= circuit->ipv6_router; + + area->lfa_protected_links[0] -= circuit->lfa_protection[0]; + area->rlfa_protected_links[0] -= circuit->rlfa_protection[0]; + area->tilfa_protected_links[0] -= circuit->tilfa_protection[0]; + + area->lfa_protected_links[1] -= circuit->lfa_protection[1]; + area->rlfa_protected_links[1] -= circuit->rlfa_protection[1]; + area->tilfa_protected_links[1] -= circuit->tilfa_protection[1]; + + isis_csm_state_change(ISIS_DISABLE, circuit, area); +} + struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name) { struct isis_area *area; struct isis *isis = NULL; struct vrf *vrf = NULL; + struct interface *ifp; + struct isis_circuit *circuit; + area = XCALLOC(MTYPE_ISIS_AREA, sizeof(struct isis_area)); - if (vrf_name) { - vrf = vrf_lookup_by_name(vrf_name); - if (vrf) { - isis = isis_lookup_by_vrfid(vrf->vrf_id); - if (isis == NULL) { - isis = isis_new(vrf_name); - isis_add(isis); - } - } else { - isis = isis_lookup_by_vrfid(VRF_UNKNOWN); - if (isis == NULL) { - isis = isis_new(vrf_name); - isis_add(isis); - } - } - } else { - isis = isis_lookup_by_vrfid(VRF_DEFAULT); - if (isis == NULL) { - isis = isis_new(VRF_DEFAULT_NAME); - isis_add(isis); - } - } + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + + vrf = vrf_lookup_by_name(vrf_name); + isis = isis_lookup_by_vrfname(vrf_name); + + if (isis == NULL) + isis = isis_new(vrf_name); listnode_add(isis->area_list, area); area->isis = isis; @@ -373,9 +398,19 @@ struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name) area->bfd_signalled_down = false; area->bfd_force_spf_refresh = false; - QOBJ_REG(area, isis_area); + if (vrf) { + FOR_ALL_INTERFACES (vrf, ifp) { + if (ifp->ifindex == IFINDEX_INTERNAL) + continue; + + circuit = ifp->info; + if (circuit) + isis_area_add_circuit(area, circuit); + } + } + return area; } @@ -470,11 +505,9 @@ void isis_area_destroy(struct isis_area *area) if (area->circuit_list) { for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode, - circuit)) { - circuit->ip_router = 0; - circuit->ipv6_router = 0; - isis_csm_state_change(ISIS_DISABLE, circuit, area); - } + circuit)) + isis_area_del_circuit(area, circuit); + list_delete(&area->circuit_list); } list_delete(&area->adjacency_list); @@ -572,10 +605,6 @@ static int isis_vrf_enable(struct vrf *vrf) isis = isis_lookup_by_vrfname(vrf->name); if (isis) { - if (isis->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) { - XFREE(MTYPE_ISIS_NAME, isis->name); - isis->name = NULL; - } old_vrf_id = isis->vrf_id; /* We have instance configured, link to VRF and make it "up". */ isis_vrf_link(isis, vrf); @@ -630,28 +659,6 @@ void isis_vrf_init(void) isis_vrf_delete, isis_vrf_enable); } -void isis_finish(struct isis *isis) -{ - struct vrf *vrf = NULL; - - isis_delete(isis); - if (isis->name) { - vrf = vrf_lookup_by_name(isis->name); - if (vrf) - isis_vrf_unlink(isis, vrf); - XFREE(MTYPE_ISIS_NAME, isis->name); - } else { - vrf = vrf_lookup_by_id(VRF_DEFAULT); - if (vrf) - isis_vrf_unlink(isis, vrf); - } - - isis_redist_free(isis); - list_delete(&isis->area_list); - list_delete(&isis->init_circ_list); - XFREE(MTYPE_ISIS, isis); -} - void isis_terminate() { struct isis *isis; @@ -1369,6 +1376,9 @@ DEFUN_NOSH (show_debugging, print_debug(vty, DEBUG_BFD, 1); if (IS_DEBUG_LDP_SYNC) print_debug(vty, DEBUG_LDP_SYNC, 1); + if (IS_DEBUG_LFA) + print_debug(vty, DEBUG_LFA, 1); + return CMD_SUCCESS; } diff --git a/isisd/isisd.h b/isisd/isisd.h index a2e821ad2f..9d0b57e9f6 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -65,8 +65,6 @@ extern void isis_cli_init(void); all_vrf = strmatch(vrf_name, "all"); \ } -#define SNMP_CIRCUITS_MAX (512) - extern struct zebra_privs_t isisd_privs; /* uncomment if you are a developer in bug hunt */ @@ -91,18 +89,14 @@ struct isis { uint8_t sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */ uint32_t router_id; /* Router ID from zebra */ struct list *area_list; /* list of IS-IS areas */ - struct list *init_circ_list; uint8_t max_area_addrs; /* maximumAreaAdresses */ struct area_addr *man_area_addrs; /* manualAreaAddresses */ time_t uptime; /* when did we start */ struct thread *t_dync_clean; /* dynamic hostname cache cleanup thread */ uint32_t circuit_ids_used[8]; /* 256 bits to track circuit ids 1 through 255 */ - struct isis_circuit *snmp_circuits[SNMP_CIRCUITS_MAX]; - uint32_t snmp_circuit_id_last; int snmp_notifications; struct route_table *ext_info[REDIST_PROTOCOL_COUNT]; - struct ldp_sync_info_cmd ldp_sync_cmd; /* MPLS LDP-IGP Sync */ }; extern struct isis_master *im; @@ -214,6 +208,8 @@ struct isis_area { struct prefix_list *rlfa_plist[ISIS_LEVELS]; size_t rlfa_protected_links[ISIS_LEVELS]; size_t tilfa_protected_links[ISIS_LEVELS]; + /* MPLS LDP-IGP Sync */ + struct ldp_sync_info_cmd ldp_sync_cmd; /* Counters */ uint32_t circuit_state_changes; struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT] @@ -248,7 +244,6 @@ DECLARE_MTYPE(ISIS_AREA_ADDR); /* isis_area->area_addrs */ DECLARE_HOOK(isis_area_overload_bit_update, (struct isis_area * area), (area)); void isis_terminate(void); -void isis_finish(struct isis *isis); void isis_master_init(struct thread_master *master); void isis_vrf_link(struct isis *isis, struct vrf *vrf); void isis_vrf_unlink(struct isis *isis, struct vrf *vrf); @@ -261,6 +256,13 @@ void isis_init(void); void isis_vrf_init(void); struct isis *isis_new(const char *vrf_name); +void isis_finish(struct isis *isis); + +void isis_area_add_circuit(struct isis_area *area, + struct isis_circuit *circuit); +void isis_area_del_circuit(struct isis_area *area, + struct isis_circuit *circuit); + struct isis_area *isis_area_create(const char *, const char *); struct isis_area *isis_area_lookup(const char *, vrf_id_t vrf_id); struct isis_area *isis_area_lookup_by_vrf(const char *area_tag, diff --git a/ldpd/lde.c b/ldpd/lde.c index 02dcec750b..724e83adb2 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -1630,6 +1630,30 @@ lde_nbr_addr_update(struct lde_nbr *ln, struct lde_addr *lde_addr, int removed) } } +void +lde_allow_broken_lsp_update(int new_config) +{ + struct fec_node *fn; + struct fec_nh *fnh; + struct fec *f; + + RB_FOREACH(f, fec_tree, &ft) { + fn = (struct fec_node *)f; + + LIST_FOREACH(fnh, &fn->nexthops, entry) { + /* allow-broken-lsp config is changing so + * we need to reprogram labeled routes to + * have proper top-level label + */ + if (!(new_config & F_LDPD_ALLOW_BROKEN_LSP)) + lde_send_delete_klabel(fn, fnh); + + if (fn->local_label != NO_LABEL) + lde_send_change_klabel(fn, fnh); + } + } +} + static __inline int lde_map_compare(const struct lde_map *a, const struct lde_map *b) { diff --git a/ldpd/lde.h b/ldpd/lde.h index e09be01ece..dee6f3fcb9 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -200,6 +200,7 @@ void lde_route_update_release(struct iface *, int); void lde_route_update_release_all(int); struct lde_addr *lde_address_find(struct lde_nbr *, int, union ldpd_addr *); +void lde_allow_broken_lsp_update(int new_config); /* lde_lib.c */ void fec_init(struct fec_tree *); diff --git a/ldpd/ldp_vty.h b/ldpd/ldp_vty.h index 882874f1be..d788fa0687 100644 --- a/ldpd/ldp_vty.h +++ b/ldpd/ldp_vty.h @@ -34,6 +34,7 @@ extern struct cmd_node ldp_debug_node; union ldpd_addr; int ldp_get_address(const char *, int *, union ldpd_addr *); int ldp_vty_mpls_ldp (struct vty *, const char *); +int ldp_vty_allow_broken_lsp(struct vty *, const char *); int ldp_vty_address_family (struct vty *, const char *, const char *); int ldp_vty_disc_holdtime(struct vty *, const char *, enum hello_type, long); int ldp_vty_disc_interval(struct vty *, const char *, enum hello_type, long); diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c index 1f102f86fa..b65ebf6f55 100644 --- a/ldpd/ldp_vty_cmds.c +++ b/ldpd/ldp_vty_cmds.c @@ -241,6 +241,16 @@ DEFPY (ldp_wait_for_sync, } +DEFPY (ldp_allow_broken_lsps, + ldp_allow_broken_lsps_cmd, + "[no] install allow-broken-lsps", + NO_STR + "install lsps\n" + "if no remote-label install with imp-null") +{ + return (ldp_vty_allow_broken_lsp(vty, no)); +} + DEFPY (ldp_discovery_targeted_hello_accept, ldp_discovery_targeted_hello_accept_cmd, "[no] discovery targeted-hello accept [from <(1-199)|(1300-2699)|WORD>$from_acl]", @@ -844,6 +854,7 @@ ldp_vty_init (void) install_element(LDP_NODE, &ldp_router_id_cmd); install_element(LDP_NODE, &ldp_ordered_control_cmd); install_element(LDP_NODE, &ldp_wait_for_sync_cmd); + install_element(LDP_NODE, &ldp_allow_broken_lsps_cmd); install_element(LDP_IPV4_NODE, &ldp_discovery_link_holdtime_cmd); install_element(LDP_IPV4_NODE, &ldp_discovery_targeted_holdtime_cmd); diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index 6e925d1410..b35d3dfa00 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -290,6 +290,9 @@ ldp_config_write(struct vty *vty) vty_out (vty, " wait-for-sync %u\n", ldpd_conf->wait_for_sync_interval); + if (ldpd_conf->flags & F_LDPD_ALLOW_BROKEN_LSP) + vty_out(vty, " install allow-broken-lsp\n"); + RB_FOREACH(nbrp, nbrp_head, &ldpd_conf->nbrp_tree) { if (nbrp->flags & F_NBRP_KEEPALIVE) vty_out (vty, " neighbor %pI4 session holdtime %u\n", @@ -1040,6 +1043,19 @@ int ldp_vty_wait_for_sync_interval(struct vty *vty, const char *negate, } int +ldp_vty_allow_broken_lsp(struct vty *vty, const char *negate) +{ + if (negate) + vty_conf->flags &= ~F_LDPD_ALLOW_BROKEN_LSP; + else + vty_conf->flags |= F_LDPD_ALLOW_BROKEN_LSP; + + ldp_config_apply(vty, vty_conf); + + return (CMD_SUCCESS); +} + +int ldp_vty_ds_cisco_interop(struct vty *vty, const char * negate) { if (negate) diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index 92e329c389..2d90412d17 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -246,12 +246,17 @@ ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr) zl.route.instance = kr->route_instance; } - /* - * For broken LSPs, instruct the forwarding plane to pop the top-level + /* If allow-broken-lsps is enabled then if an lsp is received with + * no remote label, instruct the forwarding plane to pop the top-level * label and forward packets normally. This is a best-effort attempt * to deliver labeled IP packets to their final destination (instead of * dropping them). */ + if (kr->remote_label == NO_LABEL + && !(ldpd_conf->flags & F_LDPD_ALLOW_BROKEN_LSP) + && cmd == ZEBRA_MPLS_LABELS_ADD) + return 0; + if (kr->remote_label == NO_LABEL) kr->remote_label = MPLS_LABEL_IMPLICIT_NULL; @@ -679,9 +684,8 @@ ldp_zebra_filter_update(struct access_list *access) if (access && access->name[0] != '\0') { strlcpy(laccess.name, access->name, sizeof(laccess.name)); - laccess.type = access->type; - debug_evt("%s ACL update filter name %s type %d", __func__, - access->name, access->type); + debug_evt("%s ACL update filter name %s", __func__, + access->name); main_imsg_compose_both(IMSG_FILTER_UPDATE, &laccess, sizeof(laccess)); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index d69a4dcd3c..800b954d65 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -1365,6 +1365,16 @@ merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf) ldpe_reset_ds_nbrs(); } + /* + * Configuration of allow-broken-lsp requires reprograming all + * labeled routes + */ + if ((conf->flags & F_LDPD_ALLOW_BROKEN_LSP) != + (xconf->flags & F_LDPD_ALLOW_BROKEN_LSP)) { + if (ldpd_process == PROC_LDE_ENGINE) + lde_allow_broken_lsp_update(xconf->flags); + } + if (ldpd_process == PROC_LDP_ENGINE) ldpe_set_config_change_time(); diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 7e70aa3a44..616c390e50 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -174,7 +174,6 @@ struct ldpd_init { struct ldp_access { char name[ACL_NAMSIZ]; - enum access_type type; }; union ldpd_addr { @@ -591,7 +590,7 @@ DECLARE_QOBJ_TYPE(ldpd_conf); #define F_LDPD_DS_CISCO_INTEROP 0x0002 #define F_LDPD_ENABLED 0x0004 #define F_LDPD_ORDERED_CONTROL 0x0008 - +#define F_LDPD_ALLOW_BROKEN_LSP 0x0010 struct ldpd_af_global { struct thread *disc_ev; diff --git a/lib/assert/assert.h b/lib/assert/assert.h new file mode 100644 index 0000000000..fbdbd52ce8 --- /dev/null +++ b/lib/assert/assert.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021 David Lamparter, for NetDEF, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* WARNING: this file is "special" in that it overrides the system-provided + * assert.h by being on the include path before it. That means it should + * provide the functional equivalent. + * + * This is intentional because FRR extends assert() to write to the log and + * add backtraces. Overriding the entire file is the simplest and most + * reliable way to get this to work; there were problems previously with the + * system assert.h getting included afterwards and redefining assert() back to + * the system variant. + */ + +#ifndef _FRR_ASSERT_H +#define _FRR_ASSERT_H + +#include "xref.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __cplusplus +/* C++ has this built-in, but C provides it in assert.h for >=C11. Since we + * replace assert.h entirely, we need to provide it here too. + */ +#define static_assert _Static_assert +#endif + +struct xref_assert { + struct xref xref; + + const char *expr; + const char *extra, *args; +}; + +extern void _zlog_assert_failed(const struct xref_assert *xref, + const char *extra, ...) PRINTFRR(2, 3) + __attribute__((noreturn)); + +/* the "do { } while (expr_)" is there to get a warning for assignments inside + * the assert expression aka "assert(x = 1)". The (necessary) braces around + * expr_ in the if () statement would suppress these warnings. Since + * _zlog_assert_failed() is noreturn, the while condition will never be + * checked. + */ +#define assert(expr_) \ + ({ \ + static const struct xref_assert _xref __attribute__( \ + (used)) = { \ + .xref = XREF_INIT(XREFT_ASSERT, NULL, __func__), \ + .expr = #expr_, \ + }; \ + XREF_LINK(_xref.xref); \ + if (__builtin_expect((expr_) ? 0 : 1, 0)) \ + do { \ + _zlog_assert_failed(&_xref, NULL); \ + } while (expr_); \ + }) + +#define assertf(expr_, extra_, ...) \ + ({ \ + static const struct xref_assert _xref __attribute__( \ + (used)) = { \ + .xref = XREF_INIT(XREFT_ASSERT, NULL, __func__), \ + .expr = #expr_, \ + .extra = extra_, \ + .args = #__VA_ARGS__, \ + }; \ + XREF_LINK(_xref.xref); \ + if (__builtin_expect((expr_) ? 0 : 1, 0)) \ + do { \ + _zlog_assert_failed(&_xref, extra_, \ + ##__VA_ARGS__); \ + } while (expr_); \ + }) + +#define zassert assert + +#ifdef __cplusplus +} +#endif + +#endif /* _FRR_ASSERT_H */ diff --git a/lib/clippy.c b/lib/clippy.c index 6223697ae9..7ca99c9a94 100644 --- a/lib/clippy.c +++ b/lib/clippy.c @@ -106,12 +106,7 @@ int main(int argc, char **argv) /* and now for the ugly part... provide simplified logging functions so we * don't need to link libzebra (which would be a circular build dep) */ -#ifdef __ASSERT_FUNCTION -#undef __ASSERT_FUNCTION -#endif - #include "log.h" -#include "zassert.h" void vzlogx(const struct xref_logmsg *xref, int prio, const char *format, va_list args) @@ -120,15 +115,6 @@ void vzlogx(const struct xref_logmsg *xref, int prio, fputs("\n", stderr); } -void _zlog_assert_failed(const char *assertion, const char *file, - unsigned int line, const char *function) -{ - fprintf(stderr, - "Assertion `%s' failed in file %s, line %u, function %s", - assertion, file, line, (function ? function : "?")); - abort(); -} - void memory_oom(size_t size, const char *name) { abort(); diff --git a/lib/compiler.h b/lib/compiler.h index b7a142bdee..86cf347e01 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -373,6 +373,10 @@ CPP_NOTICE("time to remove this CONFDATE block") #else /* !_FRR_ATTRIBUTE_PRINTFRR */ #define PRINTFRR(a, b) __attribute__((format(printf, a, b))) +/* frr-format plugin is C-only for now, so no point in doing these shenanigans + * for C++... (also they can break some C++ stuff...) + */ +#ifndef __cplusplus /* these should be typedefs, but might also be #define */ #ifdef uint64_t #undef uint64_t @@ -400,6 +404,8 @@ _Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8, #define PRIu64 "llu" #define PRId64 "lld" #define PRIx64 "llx" + +#endif /* !__cplusplus */ #endif /* !_FRR_ATTRIBUTE_PRINTFRR */ #ifdef __cplusplus diff --git a/lib/filter.c b/lib/filter.c index ba8a3086af..b7a935d076 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -38,7 +38,6 @@ DEFINE_MTYPE_STATIC(LIB, ACCESS_FILTER, "Access Filter"); /* Static structure for mac access_list's master. */ static struct access_master access_master_mac = { {NULL, NULL}, - {NULL, NULL}, NULL, NULL, }; @@ -46,7 +45,6 @@ static struct access_master access_master_mac = { /* Static structure for IPv4 access_list's master. */ static struct access_master access_master_ipv4 = { {NULL, NULL}, - {NULL, NULL}, NULL, NULL, }; @@ -54,7 +52,6 @@ static struct access_master access_master_ipv4 = { /* Static structure for IPv6 access_list's master. */ static struct access_master access_master_ipv6 = { {NULL, NULL}, - {NULL, NULL}, NULL, NULL, }; @@ -166,10 +163,7 @@ void access_list_delete(struct access_list *access) master = access->master; - if (access->type == ACCESS_TYPE_NUMBER) - list = &master->num; - else - list = &master->str; + list = &master->str; if (access->next) access->next->prev = access->prev; @@ -197,8 +191,6 @@ void access_list_delete(struct access_list *access) is sorted by the name. */ static struct access_list *access_list_insert(afi_t afi, const char *name) { - unsigned int i; - long number; struct access_list *access; struct access_list *point; struct access_list_list *alist; @@ -213,36 +205,13 @@ static struct access_list *access_list_insert(afi_t afi, const char *name) access->name = XSTRDUP(MTYPE_ACCESS_LIST_STR, name); access->master = master; - /* If name is made by all digit character. We treat it as - number. */ - for (number = 0, i = 0; i < strlen(name); i++) { - if (isdigit((unsigned char)name[i])) - number = (number * 10) + (name[i] - '0'); - else - break; - } - - /* In case of name is all digit character */ - if (i == strlen(name)) { - access->type = ACCESS_TYPE_NUMBER; - - /* Set access_list to number list. */ - alist = &master->num; - - for (point = alist->head; point; point = point->next) - if (atol(point->name) >= number) - break; - } else { - access->type = ACCESS_TYPE_STRING; - - /* Set access_list to string list. */ - alist = &master->str; + /* Set access_list to string list. */ + alist = &master->str; - /* Set point to insertion point. */ - for (point = alist->head; point; point = point->next) - if (strcmp(point->name, name) >= 0) - break; - } + /* Set point to insertion point. */ + for (point = alist->head; point; point = point->next) + if (strcmp(point->name, name) >= 0) + break; /* In case of this is the first element of master. */ if (alist->head == NULL) { @@ -290,10 +259,6 @@ struct access_list *access_list_lookup(afi_t afi, const char *name) if (master == NULL) return NULL; - for (access = master->num.head; access; access = access->next) - if (strcmp(access->name, name) == 0) - return access; - for (access = master->str.head; access; access = access->next) if (strcmp(access->name, name) == 0) return access; @@ -493,53 +458,6 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi) /* Print the name of the protocol */ vty_out(vty, "%s:\n", frr_protoname); - for (access = master->num.head; access; access = access->next) { - if (name && strcmp(access->name, name) != 0) - continue; - - write = 1; - - for (mfilter = access->head; mfilter; mfilter = mfilter->next) { - filter = &mfilter->u.cfilter; - - if (write) { - vty_out(vty, "%s %s access list %s\n", - mfilter->cisco ? (filter->extended - ? "Extended" - : "Standard") - : "Zebra", - (afi == AFI_IP) - ? ("IP") - : ((afi == AFI_IP6) ? ("IPv6 ") - : ("MAC ")), - access->name); - write = 0; - } - - vty_out(vty, " seq %" PRId64, mfilter->seq); - vty_out(vty, " %s%s", filter_type_str(mfilter), - mfilter->type == FILTER_DENY ? " " : ""); - - if (!mfilter->cisco) - config_write_access_zebra(vty, mfilter); - else if (filter->extended) - config_write_access_cisco(vty, mfilter); - else { - if (filter->addr_mask.s_addr == 0xffffffff) - vty_out(vty, " any\n"); - else { - vty_out(vty, " %pI4", &filter->addr); - if (filter->addr_mask.s_addr - != INADDR_ANY) - vty_out(vty, - ", wildcard bits %pI4", - &filter->addr_mask); - vty_out(vty, "\n"); - } - } - } - } - for (access = master->str.head; access; access = access->next) { if (name && strcmp(access->name, name) != 0) continue; @@ -739,18 +657,11 @@ static void access_list_reset_mac(void) if (master == NULL) return; - for (access = master->num.head; access; access = next) { - next = access->next; - access_list_delete(access); - } for (access = master->str.head; access; access = next) { next = access->next; access_list_delete(access); } - assert(master->num.head == NULL); - assert(master->num.tail == NULL); - assert(master->str.head == NULL); assert(master->str.tail == NULL); } @@ -797,18 +708,11 @@ static void access_list_reset_ipv4(void) if (master == NULL) return; - for (access = master->num.head; access; access = next) { - next = access->next; - access_list_delete(access); - } for (access = master->str.head; access; access = next) { next = access->next; access_list_delete(access); } - assert(master->num.head == NULL); - assert(master->num.tail == NULL); - assert(master->str.head == NULL); assert(master->str.tail == NULL); } @@ -838,18 +742,11 @@ static void access_list_reset_ipv6(void) if (master == NULL) return; - for (access = master->num.head; access; access = next) { - next = access->next; - access_list_delete(access); - } for (access = master->str.head; access; access = next) { next = access->next; access_list_delete(access); } - assert(master->num.head == NULL); - assert(master->num.tail == NULL); - assert(master->str.head == NULL); assert(master->str.tail == NULL); } diff --git a/lib/filter.h b/lib/filter.h index ade68a4567..941fabd38b 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -50,8 +50,6 @@ extern "C" { /* Filter type is made by `permit', `deny' and `dynamic'. */ enum filter_type { FILTER_DENY, FILTER_PERMIT, FILTER_DYNAMIC }; -enum access_type { ACCESS_TYPE_STRING, ACCESS_TYPE_NUMBER }; - struct filter_cisco { /* Cisco access-list */ int extended; @@ -103,8 +101,6 @@ struct access_list { struct access_master *master; - enum access_type type; - struct access_list *next; struct access_list *prev; @@ -120,9 +116,6 @@ struct access_list_list { /* Master structure of access_list. */ struct access_master { - /* List of access_list which name is number. */ - struct access_list_list num; - /* List of access_list which name is string. */ struct access_list_list str; diff --git a/lib/libfrr_trace.c b/lib/libfrr_trace.c index 2f300e6ee1..59320322ca 100644 --- a/lib/libfrr_trace.c +++ b/lib/libfrr_trace.c @@ -1,4 +1,6 @@ #define TRACEPOINT_CREATE_PROBES #define TRACEPOINT_DEFINE +#include <zebra.h> + #include "libfrr_trace.h" diff --git a/lib/link_state.c b/lib/link_state.c index 8606f8eb09..afeb89c592 100644 --- a/lib/link_state.c +++ b/lib/link_state.c @@ -22,6 +22,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "if.h" #include "linklist.h" #include "log.h" diff --git a/lib/linklist.c b/lib/linklist.c index 5de6c8a817..8137b68d84 100644 --- a/lib/linklist.c +++ b/lib/linklist.c @@ -320,23 +320,6 @@ void list_delete_all_node(struct list *list) list->count = 0; } -void list_filter_out_nodes(struct list *list, bool (*cond)(void *data)) -{ - struct listnode *node; - struct listnode *next; - void *data; - - assert(list); - - for (ALL_LIST_ELEMENTS(list, node, next, data)) { - if ((cond && cond(data)) || (!cond)) { - if (*list->del) - (*list->del)(data); - list_delete_node(list, node); - } - } -} - void list_delete(struct list **list) { assert(*list); diff --git a/lib/linklist.h b/lib/linklist.h index d8820c924d..1452145218 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -295,19 +295,6 @@ extern void list_delete_all_node(struct list *list); extern void list_delete_node(struct list *list, struct listnode *node); /* - * Delete all nodes which satisfy a condition from a list. - * Deletes the node if cond function returns true for the node. - * If function ptr passed is NULL, it deletes all nodes - * - * list - * list to operate on - * cond - * function pointer which takes node data as input and return true or false - */ - -extern void list_filter_out_nodes(struct list *list, bool (*cond)(void *data)); - -/* * Insert a new element into a list with insertion sort if there is no * duplicate element present in the list. This assumes the input list is * sorted. If unsorted, it will check for duplicate until it finds out @@ -311,17 +311,6 @@ void zlog_thread_info(int log_level) zlog(log_level, "Current thread not known/applicable"); } -void _zlog_assert_failed(const char *assertion, const char *file, - unsigned int line, const char *function) -{ - zlog(LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s", - assertion, file, line, (function ? function : "?")); - zlog_backtrace(LOG_CRIT); - zlog_thread_info(LOG_CRIT); - log_memstats(stderr, "log"); - abort(); -} - void memory_oom(size_t size, const char *name) { zlog(LOG_CRIT, @@ -22,8 +22,6 @@ #ifndef _ZEBRA_LOG_H #define _ZEBRA_LOG_H -#include "zassert.h" - #include <syslog.h> #include <stdint.h> #include <stdbool.h> diff --git a/lib/log_vty.c b/lib/log_vty.c index c6788dd35a..9dbf216d31 100644 --- a/lib/log_vty.c +++ b/lib/log_vty.c @@ -647,6 +647,18 @@ DEFPY (show_log_filter, return CMD_SUCCESS; } +/* Enable/disable 'immediate' mode, with no output buffering */ +DEFPY (log_immediate_mode, + log_immediate_mode_cmd, + "[no] log immediate-mode", + NO_STR + "Logging control" + "Output immediately, without buffering") +{ + zlog_set_immediate(!no); + return CMD_SUCCESS; +} + void log_config_write(struct vty *vty) { bool show_cmdline_hint = false; @@ -775,4 +787,5 @@ void log_cmd_init(void) install_element(CONFIG_NODE, &log_filter_clear_cmd); install_element(CONFIG_NODE, &config_log_filterfile_cmd); install_element(CONFIG_NODE, &no_config_log_filterfile_cmd); + install_element(CONFIG_NODE, &log_immediate_mode_cmd); } diff --git a/lib/plist.c b/lib/plist.c index 0663ac5aec..0ee02f8a0b 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -66,9 +66,6 @@ struct prefix_list_list { /* Master structure of prefix_list. */ struct prefix_master { - /* List of prefix_list which name is number. */ - struct prefix_list_list num; - /* List of prefix_list which name is string. */ struct prefix_list_list str; @@ -87,22 +84,22 @@ struct prefix_master { /* Static structure of IPv4 prefix_list's master. */ static struct prefix_master prefix_master_ipv4 = { - {NULL, NULL}, {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV4, + {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV4, }; /* Static structure of IPv6 prefix-list's master. */ static struct prefix_master prefix_master_ipv6 = { - {NULL, NULL}, {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV6, + {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV6, }; /* Static structure of BGP ORF prefix_list's master. */ static struct prefix_master prefix_master_orf_v4 = { - {NULL, NULL}, {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV4, + {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV4, }; /* Static structure of BGP ORF prefix_list's master. */ static struct prefix_master prefix_master_orf_v6 = { - {NULL, NULL}, {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV6, + {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV6, }; static struct prefix_master *prefix_master_get(afi_t afi, int orf) @@ -141,10 +138,6 @@ static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf, if (master == NULL) return NULL; - for (plist = master->num.head; plist; plist = plist->next) - if (strcmp(plist->name, name) == 0) - return plist; - for (plist = master->str.head; plist; plist = plist->next) if (strcmp(plist->name, name) == 0) return plist; @@ -194,8 +187,6 @@ void prefix_list_entry_free(struct prefix_list_entry *pentry) static struct prefix_list *prefix_list_insert(afi_t afi, int orf, const char *name) { - unsigned int i; - long number; struct prefix_list *plist; struct prefix_list *point; struct prefix_list_list *list; @@ -212,36 +203,13 @@ static struct prefix_list *prefix_list_insert(afi_t afi, int orf, plist->trie = XCALLOC(MTYPE_PREFIX_LIST_TRIE, sizeof(struct pltrie_table)); - /* If name is made by all digit character. We treat it as - number. */ - for (number = 0, i = 0; i < strlen(name); i++) { - if (isdigit((unsigned char)name[i])) - number = (number * 10) + (name[i] - '0'); - else - break; - } - - /* In case of name is all digit character */ - if (i == strlen(name)) { - plist->type = PREFIX_TYPE_NUMBER; + /* Set prefix_list to string list. */ + list = &master->str; - /* Set prefix_list to number list. */ - list = &master->num; - - for (point = list->head; point; point = point->next) - if (atol(point->name) >= number) - break; - } else { - plist->type = PREFIX_TYPE_STRING; - - /* Set prefix_list to string list. */ - list = &master->str; - - /* Set point to insertion point. */ - for (point = list->head; point; point = point->next) - if (strcmp(point->name, name) >= 0) - break; - } + /* Set point to insertion point. */ + for (point = list->head; point; point = point->next) + if (strcmp(point->name, name) >= 0) + break; /* In case of this is the first element of master. */ if (list->head == NULL) { @@ -310,10 +278,7 @@ void prefix_list_delete(struct prefix_list *plist) master = plist->master; - if (plist->type == PREFIX_TYPE_NUMBER) - list = &master->num; - else - list = &master->str; + list = &master->str; if (plist->next) plist->next->prev = plist->prev; @@ -1056,10 +1021,6 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name, master->recent->name); } - for (plist = master->num.head; plist; plist = plist->next) - vty_show_prefix_entry(vty, afi, plist, master, dtype, - seqnum); - for (plist = master->str.head; plist; plist = plist->next) vty_show_prefix_entry(vty, afi, plist, master, dtype, seqnum); @@ -1148,11 +1109,6 @@ static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name, return CMD_WARNING; if (name == NULL && prefix == NULL) { - for (plist = master->num.head; plist; plist = plist->next) - for (pentry = plist->head; pentry; - pentry = pentry->next) - pentry->hitcnt = 0; - for (plist = master->str.head; plist; plist = plist->next) for (pentry = plist->head; pentry; pentry = pentry->next) @@ -1509,18 +1465,11 @@ static void prefix_list_reset_afi(afi_t afi, int orf) if (master == NULL) return; - for (plist = master->num.head; plist; plist = next) { - next = plist->next; - prefix_list_delete(plist); - } for (plist = master->str.head; plist; plist = next) { next = plist->next; prefix_list_delete(plist); } - assert(master->num.head == NULL); - assert(master->num.tail == NULL); - assert(master->str.head == NULL); assert(master->str.tail == NULL); @@ -1546,8 +1495,6 @@ static void plist_autocomplete_afi(afi_t afi, vector comps, for (plist = master->str.head; plist; plist = plist->next) vector_set(comps, XSTRDUP(MTYPE_COMPLETION, plist->name)); - for (plist = master->num.head; plist; plist = plist->next) - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, plist->name)); } static void plist_autocomplete(vector comps, struct cmd_token *token) diff --git a/lib/plist_int.h b/lib/plist_int.h index 5e0beabbc6..571978a517 100644 --- a/lib/plist_int.h +++ b/lib/plist_int.h @@ -26,8 +26,6 @@ extern "C" { #endif -enum prefix_name_type { PREFIX_TYPE_STRING, PREFIX_TYPE_NUMBER }; - struct pltrie_table; struct prefix_list { @@ -36,8 +34,6 @@ struct prefix_list { struct prefix_master *master; - enum prefix_name_type type; - int count; int rangecount; diff --git a/lib/printfrr.h b/lib/printfrr.h index 4338ac3a2f..37f1f9c8cd 100644 --- a/lib/printfrr.h +++ b/lib/printfrr.h @@ -305,8 +305,8 @@ struct va_format { #define FMT_NSTD(expr) \ ({ \ - typeof(expr) _v; \ FMT_NSTD_BEGIN \ + typeof(expr) _v; \ _v = expr; \ FMT_NSTD_END \ _v; \ diff --git a/lib/ringbuf.c b/lib/ringbuf.c index 49221e7cb3..6efa8077c2 100644 --- a/lib/ringbuf.c +++ b/lib/ringbuf.c @@ -131,38 +131,3 @@ void ringbuf_wipe(struct ringbuf *buf) memset(buf->data, 0x00, buf->size); ringbuf_reset(buf); } - -ssize_t ringbuf_read(struct ringbuf *buf, int sock) -{ - size_t to_read = ringbuf_space(buf); - size_t bytes_to_end = buf->size - buf->end; - ssize_t bytes_read; - struct iovec iov[2] = {}; - - /* Calculate amount of read blocks. */ - if (to_read > bytes_to_end) { - iov[0].iov_base = buf->data + buf->end; - iov[0].iov_len = bytes_to_end; - iov[1].iov_base = buf->data; - iov[1].iov_len = to_read - bytes_to_end; - } else { - iov[0].iov_base = buf->data + buf->end; - iov[0].iov_len = to_read; - } - - /* Do the system call. */ - bytes_read = readv(sock, iov, 2); - if (bytes_read <= 0) - return bytes_read; - - /* Calculate the new end. */ - if ((size_t)bytes_read > bytes_to_end) - buf->end = bytes_read - bytes_to_end; - else - buf->end += bytes_read; - - /* Set emptiness state. */ - buf->empty = (buf->start == buf->end) && (buf->empty && !bytes_read); - - return bytes_read; -} diff --git a/lib/ringbuf.h b/lib/ringbuf.h index 209687512b..b8f4d9798d 100644 --- a/lib/ringbuf.h +++ b/lib/ringbuf.h @@ -126,17 +126,6 @@ void ringbuf_reset(struct ringbuf *buf); */ void ringbuf_wipe(struct ringbuf *buf); -/** - * Perform a socket/file `read()` in to the ring buffer. - * - * \param buf the ring buffer pointer. - * \param sock the file descriptor. - * \returns the number of bytes read, `0` on connection close or `-1` with - * `errno` pointing the error (see `readv()` man page for more - * information.) - */ -ssize_t ringbuf_read(struct ringbuf *buf, int sock); - #ifdef __cplusplus } #endif diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c index db06e9caac..3473ca2aea 100644 --- a/lib/routemap_northbound.c +++ b/lib/routemap_northbound.c @@ -271,6 +271,7 @@ lib_route_map_entry_description_destroy(struct nb_cb_destroy_args *args) static int lib_route_map_entry_action_modify(struct nb_cb_modify_args *args) { struct route_map_index *rmi; + struct route_map *map; switch (args->event) { case NB_EV_VALIDATE: @@ -281,7 +282,15 @@ static int lib_route_map_entry_action_modify(struct nb_cb_modify_args *args) case NB_EV_APPLY: rmi = nb_running_get_entry(args->dnode, NULL, true); rmi->type = yang_dnode_get_enum(args->dnode, NULL); - /* TODO: notify? */ + map = rmi->map; + + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)(map->name); + route_map_notify_dependencies(map->name, + RMAP_EVENT_CALL_ADDED); + } + break; } diff --git a/lib/routing_nb.c b/lib/routing_nb.c index 0160354a7e..6238fb055d 100644 --- a/lib/routing_nb.c +++ b/lib/routing_nb.c @@ -16,6 +16,8 @@ * with this program; see the file COPYING; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "northbound.h" #include "libfrr.h" #include "routing_nb.h" diff --git a/lib/routing_nb_config.c b/lib/routing_nb_config.c index f66f32015d..594ad6c9e8 100644 --- a/lib/routing_nb_config.c +++ b/lib/routing_nb_config.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "northbound.h" #include "libfrr.h" #include "vrf.h" diff --git a/lib/subdir.am b/lib/subdir.am index 98ba1cf24c..480c2938d0 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -278,13 +278,14 @@ pkginclude_HEADERS += \ lib/yang.h \ lib/yang_translator.h \ lib/yang_wrappers.h \ - lib/zassert.h \ lib/zclient.h \ lib/zebra.h \ lib/zlog.h \ lib/zlog_targets.h \ lib/pbr.h \ lib/routing_nb.h \ + \ + lib/assert/assert.h \ # end @@ -413,7 +414,7 @@ lib_grammar_sandbox_SOURCES = \ lib_grammar_sandbox_LDADD = \ lib/libfrr.la -lib_clippy_CPPFLAGS = $(AM_CPPFLAGS) -D_GNU_SOURCE -DBUILDING_CLIPPY +lib_clippy_CPPFLAGS = $(CPPFLAGS_BASE) -D_GNU_SOURCE -DBUILDING_CLIPPY lib_clippy_CFLAGS = $(AC_CFLAGS) $(PYTHON_CFLAGS) lib_clippy_LDADD = $(PYTHON_LIBS) $(UST_LIBS) -lelf lib_clippy_LDFLAGS = -export-dynamic diff --git a/lib/thread.c b/lib/thread.c index 3d8b544678..3af89fad5a 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -664,7 +664,7 @@ static int time_hhmmss(char *buf, int buf_size, long sec) long mm; int wr; - zassert(buf_size >= 8); + assert(buf_size >= 8); hh = sec / 3600; sec %= 3600; @@ -862,7 +862,10 @@ struct thread *_thread_add_read_write(const struct xref_threadsched *xref, xref->funcname, xref->xref.file, xref->xref.line, t_ptr, fd, 0, arg, 0); - assert(fd >= 0 && fd < m->fd_limit); + assert(fd >= 0); + if (fd >= m->fd_limit) + assert(!"Number of FD's open is greater than FRR currently configured to handle, aborting"); + frr_with_mutex(&m->mtx) { if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule diff --git a/lib/typerb.h b/lib/typerb.h index 60e6d09016..cbed8d4893 100644 --- a/lib/typerb.h +++ b/lib/typerb.h @@ -117,6 +117,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ typed_rb_remove(&h->rr, re); \ return container_of(re, type, field.re); \ } \ +TYPESAFE_SWAP_ALL_SIMPLE(prefix) \ macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \ { \ const struct typed_rb_entry *re; \ diff --git a/lib/typesafe.h b/lib/typesafe.h index 27e7be1286..ecac1a4381 100644 --- a/lib/typesafe.h +++ b/lib/typesafe.h @@ -78,6 +78,19 @@ macro_inline type *prefix ## _find_gteq(struct prefix##_head *h, \ } \ /* ... */ +/* SWAP_ALL_SIMPLE = for containers where the items don't point back to the + * head *AND* the head doesn'T points to itself (= everything except LIST, + * DLIST and SKIPLIST), just switch out the entire head + */ +#define TYPESAFE_SWAP_ALL_SIMPLE(prefix) \ +macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ + struct prefix##_head *b) \ +{ \ + struct prefix##_head tmp = *a; \ + *a = *b; \ + *b = tmp; \ +} \ +/* ... */ /* single-linked list, unsorted/arbitrary. * can be used as queue with add_tail / pop @@ -169,6 +182,17 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ h->sh.last_next = &h->sh.first; \ return container_of(sitem, type, field.si); \ } \ +macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ + struct prefix##_head *b) \ +{ \ + struct prefix##_head tmp = *a; \ + *a = *b; \ + *b = tmp; \ + if (a->sh.last_next == &b->sh.first) \ + a->sh.last_next = &a->sh.first; \ + if (b->sh.last_next == &a->sh.first) \ + b->sh.last_next = &b->sh.first; \ +} \ macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \ { \ return container_of_null(h->sh.first, type, field.si); \ @@ -215,6 +239,34 @@ static inline void typesafe_dlist_add(struct dlist_head *head, head->count++; } +static inline void typesafe_dlist_swap_all(struct dlist_head *a, + struct dlist_head *b) +{ + struct dlist_head tmp = *a; + + a->count = b->count; + if (a->count) { + a->hitem.next = b->hitem.next; + a->hitem.prev = b->hitem.prev; + a->hitem.next->prev = &a->hitem; + a->hitem.prev->next = &a->hitem; + } else { + a->hitem.next = &a->hitem; + a->hitem.prev = &a->hitem; + } + + b->count = tmp.count; + if (b->count) { + b->hitem.next = tmp.hitem.next; + b->hitem.prev = tmp.hitem.prev; + b->hitem.next->prev = &b->hitem; + b->hitem.prev->next = &b->hitem; + } else { + b->hitem.next = &b->hitem; + b->hitem.prev = &b->hitem; + } +} + /* double-linked list, for fast item deletion */ #define PREDECL_DLIST(prefix) \ @@ -271,6 +323,11 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ h->dh.count--; \ return container_of(ditem, type, field.di); \ } \ +macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ + struct prefix##_head *b) \ +{ \ + typesafe_dlist_swap_all(&a->dh, &b->dh); \ +} \ macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \ { \ const struct dlist_item *ditem = h->dh.hitem.next; \ @@ -380,6 +437,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ typesafe_heap_resize(&h->hh, false); \ return container_of(hitem, type, field.hi); \ } \ +TYPESAFE_SWAP_ALL_SIMPLE(prefix) \ macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \ { \ if (h->hh.count == 0) \ @@ -518,6 +576,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ h->sh.first = sitem->next; \ return container_of(sitem, type, field.si); \ } \ +TYPESAFE_SWAP_ALL_SIMPLE(prefix) \ macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \ { \ return container_of_null(h->sh.first, type, field.si); \ @@ -708,6 +767,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ } \ return NULL; \ } \ +TYPESAFE_SWAP_ALL_SIMPLE(prefix) \ macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \ { \ uint32_t i; \ @@ -824,6 +884,17 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ struct sskip_item *sitem = typesafe_skiplist_pop(&h->sh); \ return container_of_null(sitem, type, field.si); \ } \ +macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ + struct prefix##_head *b) \ +{ \ + struct prefix##_head tmp = *a; \ + *a = *b; \ + *b = tmp; \ + a->sh.hitem.next[SKIPLIST_OVERFLOW] = (struct sskip_item *) \ + ((uintptr_t)a->sh.overflow | 1); \ + b->sh.hitem.next[SKIPLIST_OVERFLOW] = (struct sskip_item *) \ + ((uintptr_t)b->sh.overflow | 1); \ +} \ macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \ { \ const struct sskip_item *first = h->sh.hitem.next[0]; \ diff --git a/lib/xref.h b/lib/xref.h index 63166b069a..949458b313 100644 --- a/lib/xref.h +++ b/lib/xref.h @@ -33,6 +33,7 @@ enum xref_type { XREFT_THREADSCHED = 0x100, XREFT_LOGMSG = 0x200, + XREFT_ASSERT = 0x280, XREFT_DEFUN = 0x300, XREFT_INSTALL_ELEMENT = 0x301, diff --git a/lib/zassert.h b/lib/zassert.h deleted file mode 100644 index 527282c4f2..0000000000 --- a/lib/zassert.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 _QUAGGA_ASSERT_H -#define _QUAGGA_ASSERT_H - -#ifdef __cplusplus -extern "C" { -#endif - -extern void _zlog_assert_failed(const char *assertion, const char *file, - unsigned int line, const char *function) - __attribute__((noreturn)); - -#undef __ASSERT_FUNCTION -#define __ASSERT_FUNCTION __func__ - -#define zassert(EX) \ - ((void)((EX) ? 0 : (_zlog_assert_failed(#EX, __FILE__, __LINE__, \ - __ASSERT_FUNCTION), \ - 0))) - -#undef assert -#define assert(EX) zassert(EX) - -#ifdef __cplusplus -} -#endif - -#endif /* _QUAGGA_ASSERT_H */ diff --git a/lib/zclient.c b/lib/zclient.c index d613906d82..b1aea55afa 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -587,7 +587,7 @@ zclient_send_router_id_update(struct zclient *zclient, enum zclient_send_status zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, struct interface *ifp, int enable, - int ra_interval) + uint32_t ra_interval) { struct stream *s; diff --git a/lib/zclient.h b/lib/zclient.h index 26fa73fc0a..e8fff4b881 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -911,7 +911,7 @@ zclient_send_router_id_update(struct zclient *zclient, extern enum zclient_send_status zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, struct interface *ifp, int enable, - int ra_interval); + uint32_t ra_interval); extern enum zclient_send_status zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id, struct interface *ifp, bool down); diff --git a/lib/zebra.h b/lib/zebra.h index 26c0fe05b5..3b624117de 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -206,7 +206,7 @@ #define __attribute__(x) #endif /* !__GNUC__ || VTYSH_EXTRACT_PL */ -#include "zassert.h" +#include <assert.h> /* * Add explicit static cast only when using a C++ compiler. diff --git a/lib/zlog.c b/lib/zlog.c index 24800c6e64..89ab9265d1 100644 --- a/lib/zlog.c +++ b/lib/zlog.c @@ -81,6 +81,11 @@ static gid_t zlog_gid = -1; DECLARE_ATOMLIST(zlog_targets, struct zlog_target, head); static struct zlog_targets_head zlog_targets; +/* Global setting for buffered vs immediate output. The default is + * per-pthread buffering. + */ +static bool default_immediate; + /* cf. zlog.h for additional comments on this struct. * * Note: you MUST NOT pass the format string + va_list to non-FRR format @@ -395,7 +400,7 @@ static void vzlog_tls(struct zlog_tls *zlog_tls, const struct xref_logmsg *xref, struct zlog_msg *msg; char *buf; bool ignoremsg = true; - bool immediate = false; + bool immediate = default_immediate; /* avoid further processing cost if no target wants this message */ rcu_read_lock(); @@ -521,6 +526,36 @@ void zlog_sigsafe(const char *text, size_t len) } } +void _zlog_assert_failed(const struct xref_assert *xref, const char *extra, ...) +{ + va_list ap; + static bool assert_in_assert; /* "global-ish" variable, init to 0 */ + + if (assert_in_assert) + abort(); + assert_in_assert = true; + + if (extra) { + struct va_format vaf; + + va_start(ap, extra); + vaf.fmt = extra; + vaf.va = ≈ + + zlog(LOG_CRIT, + "%s:%d: %s(): assertion (%s) failed, extra info: %pVA", + xref->xref.file, xref->xref.line, xref->xref.func, + xref->expr, &vaf); + + va_end(ap); + } else + zlog(LOG_CRIT, "%s:%d: %s(): assertion (%s) failed", + xref->xref.file, xref->xref.line, xref->xref.func, + xref->expr); + + /* abort() prints backtrace & memstats in SIGABRT handler */ + abort(); +} int zlog_msg_prio(struct zlog_msg *msg) { @@ -714,6 +749,14 @@ struct zlog_target *zlog_target_replace(struct zlog_target *oldzt, return oldzt; } +/* + * Enable or disable 'immediate' output - default is to buffer + * each pthread's messages. + */ +void zlog_set_immediate(bool set_p) +{ + default_immediate = set_p; +} /* common init */ diff --git a/lib/zlog.h b/lib/zlog.h index 66d8f1e5d7..c421c16f38 100644 --- a/lib/zlog.h +++ b/lib/zlog.h @@ -25,6 +25,8 @@ #include <unistd.h> #include <sys/uio.h> +#include <assert.h> + #include "atomlist.h" #include "frrcu.h" #include "memory.h" @@ -249,6 +251,9 @@ extern void zlog_tls_buffer_init(void); extern void zlog_tls_buffer_flush(void); extern void zlog_tls_buffer_fini(void); +/* Enable or disable 'immediate' output - default is to buffer messages. */ +extern void zlog_set_immediate(bool set_p); + #ifdef __cplusplus } #endif diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c index bcf0e2168c..c358baecb2 100644 --- a/nhrpd/nhrp_cache.c +++ b/nhrpd/nhrp_cache.c @@ -72,7 +72,7 @@ static void nhrp_cache_free(struct nhrp_cache *c) debugf(NHRP_DEBUG_COMMON, "Deleting cache entry"); nhrp_cache_counts[c->cur.type]--; notifier_call(&c->notifier_list, NOTIFY_CACHE_DELETE); - zassert(!notifier_active(&c->notifier_list)); + assert(!notifier_active(&c->notifier_list)); hash_release(nifp->cache_hash, c); THREAD_OFF(c->t_timeout); THREAD_OFF(c->t_auth); diff --git a/nhrpd/zbuf.c b/nhrpd/zbuf.c index 43ce974817..e191a90f2d 100644 --- a/nhrpd/zbuf.c +++ b/nhrpd/zbuf.c @@ -14,7 +14,7 @@ #include <string.h> #include <unistd.h> #include <errno.h> -#include "zassert.h" +#include <assert.h> #include "zbuf.h" #include "memory.h" #include "nhrpd.h" @@ -59,7 +59,7 @@ void zbuf_reset(struct zbuf *zb) void zbuf_reset_head(struct zbuf *zb, void *ptr) { - zassert((void *)zb->buf <= ptr && ptr <= (void *)zb->tail); + assert((void *)zb->buf <= ptr && ptr <= (void *)zb->tail); zb->head = ptr; } diff --git a/nhrpd/zbuf.h b/nhrpd/zbuf.h index d4a7c15a95..2741860bfd 100644 --- a/nhrpd/zbuf.h +++ b/nhrpd/zbuf.h @@ -15,7 +15,6 @@ #include <endian.h> #include <sys/types.h> -#include "zassert.h" #include "list.h" struct zbuf { diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index f3af8b308f..a2ddba65e9 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -474,8 +474,8 @@ void ospf6_interface_connected_route_update(struct interface *ifp) OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); } -static void ospf6_interface_state_change(uint8_t next_state, - struct ospf6_interface *oi) +static int ospf6_interface_state_change(uint8_t next_state, + struct ospf6_interface *oi) { uint8_t prev_state; struct ospf6 *ospf6; @@ -484,7 +484,7 @@ static void ospf6_interface_state_change(uint8_t next_state, oi->state = next_state; if (prev_state == next_state) - return; + return -1; /* log */ if (IS_OSPF6_DEBUG_INTERFACE) { @@ -525,6 +525,8 @@ static void ospf6_interface_state_change(uint8_t next_state, } hook_call(ospf6_interface_change, oi, next_state, prev_state); + + return 0; } @@ -1902,10 +1904,13 @@ DEFUN (ipv6_ospf6_priority, ? OSPF6_INTERFACE_PRIORITY : strtoul(argv[idx_number]->arg, NULL, 10); - if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER - || oi->state == OSPF6_INTERFACE_BDR - || oi->state == OSPF6_INTERFACE_DR)) - ospf6_interface_state_change(dr_election(oi), oi); + if (oi->area + && (oi->state == OSPF6_INTERFACE_DROTHER + || oi->state == OSPF6_INTERFACE_BDR + || oi->state == OSPF6_INTERFACE_DR)) { + if (ospf6_interface_state_change(dr_election(oi), oi) == -1) + OSPF6_LINK_LSA_SCHEDULE(oi); + } return CMD_SUCCESS; } diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 9770dd0444..2daf119c52 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -1039,7 +1039,7 @@ void ospf6_route_table_delete(struct ospf6_route_table *table) /* VTY commands */ void ospf6_route_show(struct vty *vty, struct ospf6_route *route, - json_object *json_array_routes, bool use_json) + json_object *json_routes, bool use_json) { int i; char destination[PREFIX2STR_BUFFER], nexthop[64]; @@ -1072,7 +1072,6 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route, if (use_json) { json_route = json_object_new_object(); - json_object_string_add(json_route, "destination", destination); json_object_boolean_add(json_route, "isBestRoute", ospf6_route_is_best(route)); json_object_string_add(json_route, "destinationType", @@ -1121,12 +1120,12 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route, if (use_json) { json_object_object_add(json_route, "nextHops", json_array_next_hops); - json_object_array_add(json_array_routes, json_route); + json_object_object_add(json_routes, destination, json_route); } } void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route, - json_object *json_array_routes, bool use_json) + json_object *json_routes, bool use_json) { char destination[PREFIX2STR_BUFFER], nexthop[64]; char area_id[16], id[16], adv_router[16], capa[16], options[16]; @@ -1158,7 +1157,6 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route, if (use_json) { json_route = json_object_new_object(); - json_object_string_add(json_route, "destination", destination); json_object_string_add(json_route, "destinationType", OSPF6_DEST_TYPE_NAME(route->type)); } else { @@ -1311,7 +1309,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route, if (use_json) { json_object_object_add(json_route, "nextHops", json_array_next_hops); - json_object_array_add(json_array_routes, json_route); + json_object_object_add(json_routes, destination, json_route); } else vty_out(vty, "\n"); } @@ -1377,24 +1375,23 @@ static void ospf6_route_show_table_prefix(struct vty *vty, json_object *json, bool use_json) { struct ospf6_route *route; - json_object *json_array_routes = NULL; + json_object *json_routes = NULL; route = ospf6_route_lookup(prefix, table); if (route == NULL) return; if (use_json) - json_array_routes = json_object_new_array(); + json_routes = json_object_new_object(); ospf6_route_lock(route); while (route && ospf6_route_is_prefix(prefix, route)) { /* Specifying a prefix will always display details */ - ospf6_route_show_detail(vty, route, json_array_routes, - use_json); + ospf6_route_show_detail(vty, route, json_routes, use_json); route = ospf6_route_next(route); } if (use_json) - json_object_object_add(json, "routes", json_array_routes); + json_object_object_add(json, "routes", json_routes); if (route) ospf6_route_unlock(route); } @@ -1405,24 +1402,23 @@ static void ospf6_route_show_table_address(struct vty *vty, json_object *json, bool use_json) { struct ospf6_route *route; - json_object *json_array_routes = NULL; + json_object *json_routes = NULL; route = ospf6_route_lookup_bestmatch(prefix, table); if (route == NULL) return; if (use_json) - json_array_routes = json_object_new_array(); + json_routes = json_object_new_object(); prefix = &route->prefix; ospf6_route_lock(route); while (route && ospf6_route_is_prefix(prefix, route)) { /* Specifying a prefix will always display details */ - ospf6_route_show_detail(vty, route, json_array_routes, - use_json); + ospf6_route_show_detail(vty, route, json_routes, use_json); route = ospf6_route_next(route); } if (use_json) - json_object_object_add(json, "routes", json_array_routes); + json_object_object_add(json, "routes", json_routes); if (route) ospf6_route_unlock(route); } @@ -1433,24 +1429,23 @@ static void ospf6_route_show_table_match(struct vty *vty, int detail, json_object *json, bool use_json) { struct ospf6_route *route; - json_object *json_array_routes = NULL; + json_object *json_routes = NULL; assert(prefix->family); route = ospf6_route_match_head(prefix, table); if (use_json) - json_array_routes = json_object_new_array(); + json_routes = json_object_new_object(); while (route) { if (detail) - ospf6_route_show_detail(vty, route, json_array_routes, + ospf6_route_show_detail(vty, route, json_routes, use_json); else - ospf6_route_show(vty, route, json_array_routes, - use_json); + ospf6_route_show(vty, route, json_routes, use_json); route = ospf6_route_match_next(prefix, route); } if (use_json) - json_object_object_add(json, "routes", json_array_routes); + json_object_object_add(json, "routes", json_routes); } static void ospf6_route_show_table_type(struct vty *vty, int detail, @@ -1459,25 +1454,24 @@ static void ospf6_route_show_table_type(struct vty *vty, int detail, json_object *json, bool use_json) { struct ospf6_route *route; - json_object *json_array_routes = NULL; + json_object *json_routes = NULL; route = ospf6_route_head(table); if (use_json) - json_array_routes = json_object_new_array(); + json_routes = json_object_new_object(); while (route) { if (route->path.type == type) { if (detail) - ospf6_route_show_detail(vty, route, - json_array_routes, + ospf6_route_show_detail(vty, route, json_routes, use_json); else - ospf6_route_show(vty, route, json_array_routes, + ospf6_route_show(vty, route, json_routes, use_json); } route = ospf6_route_next(route); } if (use_json) - json_object_object_add(json, "routes", json_array_routes); + json_object_object_add(json, "routes", json_routes); } static void ospf6_route_show_table(struct vty *vty, int detail, @@ -1485,22 +1479,21 @@ static void ospf6_route_show_table(struct vty *vty, int detail, json_object *json, bool use_json) { struct ospf6_route *route; - json_object *json_array_routes = NULL; + json_object *json_routes = NULL; route = ospf6_route_head(table); if (use_json) - json_array_routes = json_object_new_array(); + json_routes = json_object_new_object(); while (route) { if (detail) - ospf6_route_show_detail(vty, route, json_array_routes, + ospf6_route_show_detail(vty, route, json_routes, use_json); else - ospf6_route_show(vty, route, json_array_routes, - use_json); + ospf6_route_show(vty, route, json_routes, use_json); route = ospf6_route_next(route); } if (use_json) - json_object_object_add(json, "routes", json_array_routes); + json_object_object_add(json, "routes", json_routes); } int ospf6_route_table_show(struct vty *vty, int argc_start, int argc, diff --git a/ospf6d/ospf6_routemap_nb.c b/ospf6d/ospf6_routemap_nb.c index b710fefbdf..faa992e026 100644 --- a/ospf6d/ospf6_routemap_nb.c +++ b/ospf6d/ospf6_routemap_nb.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "lib/northbound.h" #include "lib/routemap.h" #include "ospf6_routemap_nb.h" diff --git a/ospf6d/ospf6_routemap_nb_config.c b/ospf6d/ospf6_routemap_nb_config.c index 3c7741e473..cd0a3260d5 100644 --- a/ospf6d/ospf6_routemap_nb_config.c +++ b/ospf6d/ospf6_routemap_nb_config.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "lib/command.h" #include "lib/log.h" #include "lib/northbound.h" diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index 6d80725ae6..e01cfe3e03 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -332,20 +332,29 @@ void ospf_redistribute_withdraw(struct ospf *ospf, uint8_t type, if (EXTERNAL_INFO(ext)) for (rn = route_top(EXTERNAL_INFO(ext)); rn; rn = route_next(rn)) - if ((ei = rn->info)) - if (ospf_external_info_find_lsa(ospf, &ei->p)) { - if (is_prefix_default(&ei->p) - && ospf->default_originate - != DEFAULT_ORIGINATE_NONE) - continue; + if ((ei = rn->info)) { + struct ospf_external_aggr_rt *aggr; + + if (is_prefix_default(&ei->p) + && ospf->default_originate + != DEFAULT_ORIGINATE_NONE) + continue; + + aggr = ei->aggr_route; + + if (aggr) + ospf_unlink_ei_from_aggr(ospf, aggr, + ei); + else if (ospf_external_info_find_lsa(ospf, + &ei->p)) ospf_external_lsa_flush( ospf, type, &ei->p, ei->ifindex /*, ei->nexthop */); - ospf_external_info_free(ei); - route_unlock_node(rn); - rn->info = NULL; - } + ospf_external_info_free(ei); + route_unlock_node(rn); + rn->info = NULL; + } } /* External Route Aggregator Handlers */ diff --git a/ospfd/ospf_routemap_nb.c b/ospfd/ospf_routemap_nb.c index 1f6b0ef78c..e53d009a55 100644 --- a/ospfd/ospf_routemap_nb.c +++ b/ospfd/ospf_routemap_nb.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "lib/northbound.h" #include "lib/routemap.h" #include "ospf_routemap_nb.h" diff --git a/ospfd/ospf_routemap_nb_config.c b/ospfd/ospf_routemap_nb_config.c index bfb18c5e08..9026795425 100644 --- a/ospfd/ospf_routemap_nb_config.c +++ b/ospfd/ospf_routemap_nb_config.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "lib/command.h" #include "lib/log.h" #include "lib/northbound.h" diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index f2842538a5..1929e3dea4 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -2153,6 +2153,13 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa) /* Initialize TLV browsing */ tlvh = TLV_HDR_TOP(lsa->data); + uint32_t total_len = TLV_BODY_SIZE(lsa->data) - OSPF_LSA_HEADER_SIZE; + + /* If TE Router-ID is only TLV we are done */ + if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR + && total_len == sizeof(struct te_tlv_router_addr)) + return 0; + /* Skip TE Router-ID if present */ if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR) tlvh = TLV_HDR_NEXT(tlvh); @@ -2756,7 +2763,7 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa) &lsa->data->id, &edge->attributes->standard.local); /* Initialize TLV browsing */ - len = TLV_BODY_SIZE(&ext->header); + len = TLV_BODY_SIZE(&ext->header) - EXT_TLV_LINK_SIZE; tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE + EXT_TLV_LINK_SIZE); for (; sum < len; tlvh = TLV_HDR_NEXT(tlvh)) { diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 69a3e45878..57ef6029ad 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3737,6 +3737,31 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf, vty_out(vty, " No backup designated router on this network\n"); } else { + nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi)); + if (nbr) { + if (use_json) { + json_object_string_add( + json_interface_sub, "drId", + inet_ntop(AF_INET, + &nbr->router_id, buf, + sizeof(buf))); + json_object_string_add( + json_interface_sub, "drAddress", + inet_ntop( + AF_INET, + &nbr->address.u.prefix4, + buf, sizeof(buf))); + } else { + vty_out(vty, + " Designated Router (ID) %pI4", + &nbr->router_id); + vty_out(vty, + " Interface Address %pFX\n", + &nbr->address); + } + } + nbr = NULL; + nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &BDR(oi)); if (nbr == NULL) { if (!use_json) diff --git a/pathd/path_cli.c b/pathd/path_cli.c index cf14aa8c61..ecb667f985 100644 --- a/pathd/path_cli.c +++ b/pathd/path_cli.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include <float.h> #include <math.h> #include <zebra.h> diff --git a/pathd/path_debug.c b/pathd/path_debug.c index df0550715a..eec5707396 100644 --- a/pathd/path_debug.c +++ b/pathd/path_debug.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include <string.h> #include <stdbool.h> #include <time.h> diff --git a/pathd/path_pcep_config.c b/pathd/path_pcep_config.c index 107475bec9..aacbca4ae9 100644 --- a/pathd/path_pcep_config.c +++ b/pathd/path_pcep_config.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include <northbound.h> #include <yang.h> #include <printfrr.h> diff --git a/pathd/path_pcep_debug.c b/pathd/path_pcep_debug.c index d222371bbb..370484dc1b 100644 --- a/pathd/path_pcep_debug.c +++ b/pathd/path_pcep_debug.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include <string.h> #include <stdbool.h> #include <time.h> diff --git a/pathd/path_zebra.c b/pathd/path_zebra.c index 276bc9289c..8c9357460f 100644 --- a/pathd/path_zebra.c +++ b/pathd/path_zebra.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "thread.h" #include "log.h" #include "lib_errors.h" diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index 4b73e13c27..eb41bf6043 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -50,8 +50,8 @@ struct pbr_interface *pbr_if_new(struct interface *ifp) { struct pbr_interface *pbr_ifp; - zassert(ifp); - zassert(!ifp->info); + assert(ifp); + assert(!ifp->info); pbr_ifp = XCALLOC(MTYPE_PBR_INTERFACE, sizeof(*pbr_ifp)); diff --git a/pceplib/pcep_msg_messages.c b/pceplib/pcep_msg_messages.c index ec2a237f30..9bbfc5372b 100644 --- a/pceplib/pcep_msg_messages.c +++ b/pceplib/pcep_msg_messages.c @@ -25,6 +25,10 @@ * This is the implementation of a High Level PCEP message API. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <string.h> #include <arpa/inet.h> #include <stdarg.h> diff --git a/pceplib/pcep_msg_messages_encoding.c b/pceplib/pcep_msg_messages_encoding.c index 7c8e1b3a1f..e90ca1cfd8 100644 --- a/pceplib/pcep_msg_messages_encoding.c +++ b/pceplib/pcep_msg_messages_encoding.c @@ -25,6 +25,10 @@ * Encoding and decoding for PCEP messages. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> #include <unistd.h> diff --git a/pceplib/pcep_msg_object_error_types.c b/pceplib/pcep_msg_object_error_types.c index a4fd8151cd..c72dfd7061 100644 --- a/pceplib/pcep_msg_object_error_types.c +++ b/pceplib/pcep_msg_object_error_types.c @@ -19,6 +19,10 @@ * Author : Brady Johnson <brady@voltanet.io> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include "pcep_msg_object_error_types.h" diff --git a/pceplib/pcep_msg_objects.c b/pceplib/pcep_msg_objects.c index 6c943ddc2a..e253fcc540 100644 --- a/pceplib/pcep_msg_objects.c +++ b/pceplib/pcep_msg_objects.c @@ -25,6 +25,10 @@ * This is the implementation of a High Level PCEP message object API. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <string.h> #include <arpa/inet.h> #include <stdarg.h> diff --git a/pceplib/pcep_msg_objects_encoding.c b/pceplib/pcep_msg_objects_encoding.c index c4089ba5ec..9ab96f7bce 100644 --- a/pceplib/pcep_msg_objects_encoding.c +++ b/pceplib/pcep_msg_objects_encoding.c @@ -25,6 +25,10 @@ * Encoding and decoding for PCEP Objects. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> diff --git a/pceplib/pcep_msg_tlvs.c b/pceplib/pcep_msg_tlvs.c index 9c84e71ee1..6298ed4b8d 100644 --- a/pceplib/pcep_msg_tlvs.c +++ b/pceplib/pcep_msg_tlvs.c @@ -25,6 +25,10 @@ * This is the implementation of a High Level PCEP message object TLV API. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdbool.h> #include <stdint.h> #include <string.h> diff --git a/pceplib/pcep_msg_tools.c b/pceplib/pcep_msg_tools.c index e190d2a850..8f32f2c537 100644 --- a/pceplib/pcep_msg_tools.c +++ b/pceplib/pcep_msg_tools.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <errno.h> #include <stdio.h> #include <string.h> diff --git a/pceplib/pcep_session_logic.c b/pceplib/pcep_session_logic.c index 52655914c6..2ec2fd72a8 100644 --- a/pceplib/pcep_session_logic.c +++ b/pceplib/pcep_session_logic.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <errno.h> #include <limits.h> #include <pthread.h> diff --git a/pceplib/pcep_session_logic_counters.c b/pceplib/pcep_session_logic_counters.c index a6bd41b4f1..fceb15af76 100644 --- a/pceplib/pcep_session_logic_counters.c +++ b/pceplib/pcep_session_logic_counters.c @@ -25,6 +25,10 @@ * PCEP session logic counters configuration. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <time.h> diff --git a/pceplib/pcep_session_logic_loop.c b/pceplib/pcep_session_logic_loop.c index 269aa1e07e..4b855c06cd 100644 --- a/pceplib/pcep_session_logic_loop.c +++ b/pceplib/pcep_session_logic_loop.c @@ -20,6 +20,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <pthread.h> #include <stdbool.h> #include <stdio.h> diff --git a/pceplib/pcep_session_logic_states.c b/pceplib/pcep_session_logic_states.c index 3beceefad0..3e9c701a62 100644 --- a/pceplib/pcep_session_logic_states.c +++ b/pceplib/pcep_session_logic_states.c @@ -20,6 +20,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <pthread.h> #include <stdbool.h> #include <stdio.h> diff --git a/pceplib/pcep_socket_comm_loop.c b/pceplib/pcep_socket_comm_loop.c index d58409c4f3..d9a6b9ae48 100644 --- a/pceplib/pcep_socket_comm_loop.c +++ b/pceplib/pcep_socket_comm_loop.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <errno.h> #include <stdbool.h> #include <stddef.h> diff --git a/pceplib/pcep_socket_comm_mock.c b/pceplib/pcep_socket_comm_mock.c index 069d0cf998..7a9511e315 100644 --- a/pceplib/pcep_socket_comm_mock.c +++ b/pceplib/pcep_socket_comm_mock.c @@ -27,6 +27,10 @@ * created. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <netinet/in.h> #include <stdbool.h> #include <stdlib.h> diff --git a/pceplib/pcep_timers.c b/pceplib/pcep_timers.c index d0a2349d05..4c06d2b3f7 100644 --- a/pceplib/pcep_timers.c +++ b/pceplib/pcep_timers.c @@ -25,6 +25,10 @@ * Implementation of public API timer functions. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <limits.h> #include <pthread.h> #include <stddef.h> diff --git a/pceplib/pcep_timers_event_loop.c b/pceplib/pcep_timers_event_loop.c index 932a53eb2a..8984496717 100644 --- a/pceplib/pcep_timers_event_loop.c +++ b/pceplib/pcep_timers_event_loop.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <errno.h> #include <stddef.h> #include <stdbool.h> diff --git a/pceplib/pcep_utils_double_linked_list.c b/pceplib/pcep_utils_double_linked_list.c index acdcee0598..696e46632a 100644 --- a/pceplib/pcep_utils_double_linked_list.c +++ b/pceplib/pcep_utils_double_linked_list.c @@ -20,6 +20,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stddef.h> #include <string.h> diff --git a/pceplib/pcep_utils_logging.c b/pceplib/pcep_utils_logging.c index 65e1abbc03..0286c23078 100644 --- a/pceplib/pcep_utils_logging.c +++ b/pceplib/pcep_utils_logging.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdarg.h> #include <stdio.h> #include "pcep_utils_logging.h" diff --git a/pceplib/pcep_utils_memory.c b/pceplib/pcep_utils_memory.c index 7362e3433b..c564705f66 100644 --- a/pceplib/pcep_utils_memory.c +++ b/pceplib/pcep_utils_memory.c @@ -20,6 +20,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> diff --git a/pceplib/pcep_utils_ordered_list.c b/pceplib/pcep_utils_ordered_list.c index f5c7f70240..81eb614494 100644 --- a/pceplib/pcep_utils_ordered_list.c +++ b/pceplib/pcep_utils_ordered_list.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <string.h> diff --git a/pceplib/pcep_utils_queue.c b/pceplib/pcep_utils_queue.c index e8c3f2be0e..627533d01b 100644 --- a/pceplib/pcep_utils_queue.c +++ b/pceplib/pcep_utils_queue.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdbool.h> #include <stdio.h> #include <string.h> diff --git a/pceplib/test/pcep_msg_messages_test.c b/pceplib/test/pcep_msg_messages_test.c index b8984a42bc..61fa94047b 100644 --- a/pceplib/test/pcep_msg_messages_test.c +++ b/pceplib/test/pcep_msg_messages_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <CUnit/CUnit.h> diff --git a/pceplib/test/pcep_msg_messages_tests.c b/pceplib/test/pcep_msg_messages_tests.c index bd85a16530..f24a797f77 100644 --- a/pceplib/test/pcep_msg_messages_tests.c +++ b/pceplib/test/pcep_msg_messages_tests.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <CUnit/Basic.h> #include <CUnit/CUnit.h> #include <CUnit/TestDB.h> diff --git a/pceplib/test/pcep_msg_object_error_types_test.c b/pceplib/test/pcep_msg_object_error_types_test.c index 7275eaf098..b1463751d6 100644 --- a/pceplib/test/pcep_msg_object_error_types_test.c +++ b/pceplib/test/pcep_msg_object_error_types_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <CUnit/CUnit.h> diff --git a/pceplib/test/pcep_msg_objects_test.c b/pceplib/test/pcep_msg_objects_test.c index a4c069945c..e0814de543 100644 --- a/pceplib/test/pcep_msg_objects_test.c +++ b/pceplib/test/pcep_msg_objects_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <CUnit/CUnit.h> diff --git a/pceplib/test/pcep_msg_tools_test.c b/pceplib/test/pcep_msg_tools_test.c index ff5fc62390..787df2fd7a 100644 --- a/pceplib/test/pcep_msg_tools_test.c +++ b/pceplib/test/pcep_msg_tools_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <unistd.h> diff --git a/pceplib/test/pcep_pcc_api_test.c b/pceplib/test/pcep_pcc_api_test.c index c227dc1a3d..4adbb6374e 100644 --- a/pceplib/test/pcep_pcc_api_test.c +++ b/pceplib/test/pcep_pcc_api_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <netdb.h> // gethostbyname #include <pthread.h> #include <stdlib.h> diff --git a/pceplib/test/pcep_pcc_api_tests.c b/pceplib/test/pcep_pcc_api_tests.c index 04895d6340..5d9e92c1d3 100644 --- a/pceplib/test/pcep_pcc_api_tests.c +++ b/pceplib/test/pcep_pcc_api_tests.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <CUnit/Basic.h> #include <CUnit/CUnit.h> #include <CUnit/TestDB.h> diff --git a/pceplib/test/pcep_session_logic_loop_test.c b/pceplib/test/pcep_session_logic_loop_test.c index 3a40f59bb9..d68b200549 100644 --- a/pceplib/test/pcep_session_logic_loop_test.c +++ b/pceplib/test/pcep_session_logic_loop_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <pthread.h> #include <stdlib.h> #include <string.h> diff --git a/pceplib/test/pcep_session_logic_states_test.c b/pceplib/test/pcep_session_logic_states_test.c index f75c16e397..24741fa345 100644 --- a/pceplib/test/pcep_session_logic_states_test.c +++ b/pceplib/test/pcep_session_logic_states_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> diff --git a/pceplib/test/pcep_session_logic_test.c b/pceplib/test/pcep_session_logic_test.c index 66db4fbaea..503e77c20e 100644 --- a/pceplib/test/pcep_session_logic_test.c +++ b/pceplib/test/pcep_session_logic_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> #include <time.h> diff --git a/pceplib/test/pcep_session_logic_tests.c b/pceplib/test/pcep_session_logic_tests.c index 67bf6e22ef..9a15390c1b 100644 --- a/pceplib/test/pcep_session_logic_tests.c +++ b/pceplib/test/pcep_session_logic_tests.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <CUnit/Basic.h> #include <CUnit/CUnit.h> #include <CUnit/TestDB.h> diff --git a/pceplib/test/pcep_socket_comm_loop_test.c b/pceplib/test/pcep_socket_comm_loop_test.c index 94f0983ca7..748cf433e6 100644 --- a/pceplib/test/pcep_socket_comm_loop_test.c +++ b/pceplib/test/pcep_socket_comm_loop_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <pthread.h> #include <stdlib.h> diff --git a/pceplib/test/pcep_socket_comm_test.c b/pceplib/test/pcep_socket_comm_test.c index 35afbcbb13..0ab38bf96e 100644 --- a/pceplib/test/pcep_socket_comm_test.c +++ b/pceplib/test/pcep_socket_comm_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <netinet/in.h> #include <CUnit/CUnit.h> diff --git a/pceplib/test/pcep_socket_comm_tests.c b/pceplib/test/pcep_socket_comm_tests.c index 293678f1a7..6a5839d3d0 100644 --- a/pceplib/test/pcep_socket_comm_tests.c +++ b/pceplib/test/pcep_socket_comm_tests.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <CUnit/Basic.h> #include <CUnit/CUnit.h> #include <CUnit/TestDB.h> diff --git a/pceplib/test/pcep_timers_event_loop_test.c b/pceplib/test/pcep_timers_event_loop_test.c index ae63601df2..79ed84bfeb 100644 --- a/pceplib/test/pcep_timers_event_loop_test.c +++ b/pceplib/test/pcep_timers_event_loop_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <CUnit/CUnit.h> diff --git a/pceplib/test/pcep_timers_test.c b/pceplib/test/pcep_timers_test.c index 9d9e0f6c1b..e5be90a8ed 100644 --- a/pceplib/test/pcep_timers_test.c +++ b/pceplib/test/pcep_timers_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdbool.h> #include <CUnit/CUnit.h> diff --git a/pceplib/test/pcep_timers_tests.c b/pceplib/test/pcep_timers_tests.c index adfea17e29..f3aa8307a7 100644 --- a/pceplib/test/pcep_timers_tests.c +++ b/pceplib/test/pcep_timers_tests.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <CUnit/Basic.h> #include <CUnit/CUnit.h> #include <CUnit/TestDB.h> diff --git a/pceplib/test/pcep_utils_counters_test.c b/pceplib/test/pcep_utils_counters_test.c index 6f53e4d400..bcdce36188 100644 --- a/pceplib/test/pcep_utils_counters_test.c +++ b/pceplib/test/pcep_utils_counters_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <CUnit/CUnit.h> diff --git a/pceplib/test/pcep_utils_double_linked_list_test.c b/pceplib/test/pcep_utils_double_linked_list_test.c index d2600e66c4..4eb85816b9 100644 --- a/pceplib/test/pcep_utils_double_linked_list_test.c +++ b/pceplib/test/pcep_utils_double_linked_list_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <CUnit/CUnit.h> #include "pcep_utils_double_linked_list.h" diff --git a/pceplib/test/pcep_utils_memory_test.c b/pceplib/test/pcep_utils_memory_test.c index b0b528f084..0958626a0c 100644 --- a/pceplib/test/pcep_utils_memory_test.c +++ b/pceplib/test/pcep_utils_memory_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdint.h> diff --git a/pceplib/test/pcep_utils_ordered_list_test.c b/pceplib/test/pcep_utils_ordered_list_test.c index fe9ee58825..d20f5e68af 100644 --- a/pceplib/test/pcep_utils_ordered_list_test.c +++ b/pceplib/test/pcep_utils_ordered_list_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <CUnit/CUnit.h> #include "pcep_utils_ordered_list.h" diff --git a/pceplib/test/pcep_utils_queue_test.c b/pceplib/test/pcep_utils_queue_test.c index 1731457789..061dfbf37b 100644 --- a/pceplib/test/pcep_utils_queue_test.c +++ b/pceplib/test/pcep_utils_queue_test.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <CUnit/CUnit.h> #include "pcep_utils_queue.h" diff --git a/pceplib/test/pcep_utils_tests.c b/pceplib/test/pcep_utils_tests.c index 452b9fa09c..ad9f76933a 100644 --- a/pceplib/test/pcep_utils_tests.c +++ b/pceplib/test/pcep_utils_tests.c @@ -21,6 +21,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <CUnit/Basic.h> #include <CUnit/CUnit.h> #include <CUnit/TestDB.h> diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 957f904714..0988938701 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -304,7 +304,7 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh, msg_metric.ip_address = src_addr; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); ++pim_ifp->pim_ifstat_assert_recv; return dispatch_assert(ifp, msg_source_addr.u.prefix4, sg.grp, diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c index f43a31fde2..3fbe3317ba 100644 --- a/pimd/pim_bsm.c +++ b/pimd/pim_bsm.c @@ -43,8 +43,8 @@ static inline void pim_g2rp_timer_restart(struct bsm_rpinfo *bsrp, /* Memory Types */ DEFINE_MTYPE_STATIC(PIMD, PIM_BSGRP_NODE, "PIM BSR advertised grp info"); -DEFINE_MTYPE_STATIC(PIMD, PIM_BSRP_NODE, "PIM BSR advertised RP info"); -DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_INFO, "PIM BSM Info"); +DEFINE_MTYPE_STATIC(PIMD, PIM_BSRP_INFO, "PIM BSR advertised RP info"); +DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_FRAG, "PIM BSM fragment"); DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_PKT_VAR_MEM, "PIM BSM Packet"); /* All bsm packets forwarded shall be fit within ip mtu less iphdr(max) */ @@ -63,12 +63,24 @@ void pim_bsm_write_config(struct vty *vty, struct interface *ifp) } } +static void pim_bsm_rpinfo_free(struct bsm_rpinfo *bsrp_info) +{ + THREAD_OFF(bsrp_info->g2rp_timer); + XFREE(MTYPE_PIM_BSRP_INFO, bsrp_info); +} + +void pim_bsm_rpinfos_free(struct bsm_rpinfos_head *head) +{ + struct bsm_rpinfo *bsrp_info; + + while ((bsrp_info = bsm_rpinfos_pop(head))) + pim_bsm_rpinfo_free(bsrp_info); +} + void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node) { - if (bsgrp_node->bsrp_list) - list_delete(&bsgrp_node->bsrp_list); - if (bsgrp_node->partial_bsrp_list) - list_delete(&bsgrp_node->partial_bsrp_list); + pim_bsm_rpinfos_free(bsgrp_node->bsrp_list); + pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list); XFREE(MTYPE_PIM_BSGRP_NODE, bsgrp_node); } @@ -84,14 +96,21 @@ void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp) } } -static void pim_bsm_node_free(struct bsm_info *bsm) +static void pim_bsm_frag_free(struct bsm_frag *bsfrag) { - XFREE(MTYPE_PIM_BSM_PKT_VAR_MEM, bsm->bsm); - XFREE(MTYPE_PIM_BSM_INFO, bsm); + XFREE(MTYPE_PIM_BSM_FRAG, bsfrag); } -static int pim_g2rp_list_compare(struct bsm_rpinfo *node1, - struct bsm_rpinfo *node2) +void pim_bsm_frags_free(struct bsm_scope *scope) +{ + struct bsm_frag *bsfrag; + + while ((bsfrag = bsm_frags_pop(scope->bsm_frags))) + pim_bsm_frag_free(bsfrag); +} + +int pim_bsm_rpinfo_cmp(const struct bsm_rpinfo *node1, + const struct bsm_rpinfo *node2) { /* RP election Algo : * Step-1 : Loweset Rp priority will have higher precedance. @@ -115,27 +134,6 @@ static int pim_g2rp_list_compare(struct bsm_rpinfo *node1, return 0; } -static void pim_free_bsrp_node(struct bsm_rpinfo *bsrp_info) -{ - THREAD_OFF(bsrp_info->g2rp_timer); - XFREE(MTYPE_PIM_BSRP_NODE, bsrp_info); -} - -static struct list *pim_alloc_bsrp_list(void) -{ - struct list *new_list = NULL; - - new_list = list_new(); - - if (!new_list) - return NULL; - - new_list->cmp = (int (*)(void *, void *))pim_g2rp_list_compare; - new_list->del = (void (*)(void *))pim_free_bsrp_node; - - return new_list; -} - static struct bsgrp_node *pim_bsm_new_bsgrp_node(struct route_table *rt, struct prefix *grp) { @@ -150,14 +148,8 @@ static struct bsgrp_node *pim_bsm_new_bsgrp_node(struct route_table *rt, bsgrp = XCALLOC(MTYPE_PIM_BSGRP_NODE, sizeof(struct bsgrp_node)); rn->info = bsgrp; - bsgrp->bsrp_list = pim_alloc_bsrp_list(); - bsgrp->partial_bsrp_list = pim_alloc_bsrp_list(); - - if ((!bsgrp->bsrp_list) || (!bsgrp->partial_bsrp_list)) { - route_unlock_node(rn); - pim_free_bsgrp_data(bsgrp); - return NULL; - } + bsm_rpinfos_init(bsgrp->bsrp_list); + bsm_rpinfos_init(bsgrp->partial_bsrp_list); prefix_copy(&bsgrp->group, grp); return bsgrp; @@ -197,7 +189,7 @@ static int pim_on_bs_timer(struct thread *t) scope->current_bsr_first_ts = 0; scope->current_bsr_last_ts = 0; scope->bsm_frag_tag = 0; - list_delete_all_node(scope->bsm_list); + pim_bsm_frags_free(scope); for (rn = route_top(scope->bsrp_table); rn; rn = route_next(rn)) { @@ -208,16 +200,13 @@ static int pim_on_bs_timer(struct thread *t) continue; } /* Give grace time for rp to continue for another hold time */ - if ((bsgrp_node->bsrp_list) && (bsgrp_node->bsrp_list->count)) { - bsrp = listnode_head(bsgrp_node->bsrp_list); + bsrp = bsm_rpinfos_first(bsgrp_node->bsrp_list); + if (bsrp) pim_g2rp_timer_restart(bsrp, bsrp->rp_holdtime); - } + /* clear pending list */ - if ((bsgrp_node->partial_bsrp_list) - && (bsgrp_node->partial_bsrp_list->count)) { - list_delete_all_node(bsgrp_node->partial_bsrp_list); - bsgrp_node->pend_rp_cnt = 0; - } + pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list); + bsgrp_node->pend_rp_cnt = 0; } return 0; } @@ -260,8 +249,7 @@ void pim_bsm_proc_init(struct pim_instance *pim) pim->global_scope.accept_nofwd_bsm = true; pim->global_scope.state = NO_INFO; pim->global_scope.pim = pim; - pim->global_scope.bsm_list = list_new(); - pim->global_scope.bsm_list->del = (void (*)(void *))pim_bsm_node_free; + bsm_frags_init(pim->global_scope.bsm_frags); pim_bs_timer_start(&pim->global_scope, PIM_BS_TIME); } @@ -271,9 +259,7 @@ void pim_bsm_proc_free(struct pim_instance *pim) struct bsgrp_node *bsgrp; pim_bs_timer_stop(&pim->global_scope); - - if (pim->global_scope.bsm_list) - list_delete(&pim->global_scope.bsm_list); + pim_bsm_frags_free(&pim->global_scope); for (rn = route_top(pim->global_scope.bsrp_table); rn; rn = route_next(rn)) { @@ -303,7 +289,6 @@ static int pim_on_g2rp_timer(struct thread *t) struct bsm_rpinfo *bsrp; struct bsm_rpinfo *bsrp_node; struct bsgrp_node *bsgrp_node; - struct listnode *bsrp_ln; struct pim_instance *pim; struct rp_info *rp_info; struct route_node *rn; @@ -319,14 +304,17 @@ static int pim_on_g2rp_timer(struct thread *t) bsrp_addr = bsrp->rp_address; /* update elapse for all bsrp nodes */ - for (ALL_LIST_ELEMENTS_RO(bsgrp_node->bsrp_list, bsrp_ln, bsrp_node)) + frr_each_safe (bsm_rpinfos, bsgrp_node->bsrp_list, bsrp_node) { bsrp_node->elapse_time += elapse; - /* remove the expired nodes from the list */ - list_filter_out_nodes(bsgrp_node->bsrp_list, is_hold_time_elapsed); + if (is_hold_time_elapsed(bsrp_node)) { + bsm_rpinfos_del(bsgrp_node->bsrp_list, bsrp_node); + pim_bsm_rpinfo_free(bsrp_node); + } + } /* Get the next elected rp node */ - bsrp = listnode_head(bsgrp_node->bsrp_list); + bsrp = bsm_rpinfos_first(bsgrp_node->bsrp_list); pim = bsgrp_node->scope->pim; rn = route_node_lookup(pim->rp_table, &bsgrp_node->group); @@ -356,8 +344,8 @@ static int pim_on_g2rp_timer(struct thread *t) } } - if ((!bsgrp_node->bsrp_list->count) - && (!bsgrp_node->partial_bsrp_list->count)) { + if (!bsm_rpinfos_count(bsgrp_node->bsrp_list) + && !bsm_rpinfos_count(bsgrp_node->partial_bsrp_list)) { pim_free_bsgrp_node(pim->global_scope.bsrp_table, &bsgrp_node->group); pim_free_bsgrp_data(bsgrp_node); @@ -420,7 +408,6 @@ static void pim_instate_pend_list(struct bsgrp_node *bsgrp_node) { struct bsm_rpinfo *active; struct bsm_rpinfo *pend; - struct list *temp; struct rp_info *rp_info; struct route_node *rn; struct pim_instance *pim; @@ -429,11 +416,14 @@ static void pim_instate_pend_list(struct bsgrp_node *bsgrp_node) bool had_rp_node = true; pim = bsgrp_node->scope->pim; - active = listnode_head(bsgrp_node->bsrp_list); + active = bsm_rpinfos_first(bsgrp_node->bsrp_list); /* Remove nodes with hold time 0 & check if list still has a head */ - list_filter_out_nodes(bsgrp_node->partial_bsrp_list, is_hold_time_zero); - pend = listnode_head(bsgrp_node->partial_bsrp_list); + frr_each_safe (bsm_rpinfos, bsgrp_node->partial_bsrp_list, pend) + if (is_hold_time_zero(pend)) + bsm_rpinfos_del(bsgrp_node->partial_bsrp_list, pend); + + pend = bsm_rpinfos_first(bsgrp_node->partial_bsrp_list); if (!str2prefix("224.0.0.0/4", &group_all)) return; @@ -541,14 +531,12 @@ static void pim_instate_pend_list(struct bsgrp_node *bsgrp_node) * pend is head of bsrp list * So check appriate head after swap and clean the new partial list */ - temp = bsgrp_node->bsrp_list; - bsgrp_node->bsrp_list = bsgrp_node->partial_bsrp_list; - bsgrp_node->partial_bsrp_list = temp; + bsm_rpinfos_swap_all(bsgrp_node->bsrp_list, + bsgrp_node->partial_bsrp_list); - if (active) { + if (active) pim_g2rp_timer_stop(active); - list_delete_all_node(bsgrp_node->partial_bsrp_list); - } + pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list); } static bool pim_bsr_rpf_check(struct pim_instance *pim, struct in_addr bsr, @@ -896,8 +884,7 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp) struct in_addr dst_addr; struct pim_interface *pim_ifp; struct bsm_scope *scope; - struct listnode *bsm_ln; - struct bsm_info *bsminfo; + struct bsm_frag *bsfrag; char neigh_src_str[INET_ADDRSTRLEN]; uint32_t pim_mtu; bool no_fwd = true; @@ -929,7 +916,7 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp) scope = &pim_ifp->pim->global_scope; - if (!scope->bsm_list->count) { + if (!bsm_frags_count(scope->bsm_frags)) { if (PIM_DEBUG_BSM) zlog_debug("%s: BSM list for the scope is empty", __func__); @@ -950,10 +937,10 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp) pim_mtu = ifp->mtu - MAX_IP_HDR_LEN; pim_hello_require(ifp); - for (ALL_LIST_ELEMENTS_RO(scope->bsm_list, bsm_ln, bsminfo)) { - if (pim_mtu < bsminfo->size) { - ret = pim_bsm_frag_send(bsminfo->bsm, bsminfo->size, - ifp, pim_mtu, dst_addr, no_fwd); + frr_each (bsm_frags, scope->bsm_frags, bsfrag) { + if (pim_mtu < bsfrag->size) { + ret = pim_bsm_frag_send(bsfrag->data, bsfrag->size, ifp, + pim_mtu, dst_addr, no_fwd); if (!ret) { if (PIM_DEBUG_BSM) zlog_debug( @@ -962,10 +949,10 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp) } } else { /* Pim header needs to be constructed */ - pim_msg_build_header(bsminfo->bsm, bsminfo->size, + pim_msg_build_header(bsfrag->data, bsfrag->size, PIM_MSG_TYPE_BOOTSTRAP, no_fwd); - ret = pim_bsm_send_intf(bsminfo->bsm, bsminfo->size, - ifp, dst_addr); + ret = pim_bsm_send_intf(bsfrag->data, bsfrag->size, ifp, + dst_addr); if (!ret) { if (PIM_DEBUG_BSM) zlog_debug( @@ -1035,7 +1022,7 @@ static bool pim_install_bsm_grp_rp(struct pim_instance *pim, uint8_t hashMask_len = pim->global_scope.hashMasklen; /*memory allocation for bsm_rpinfo */ - bsm_rpinfo = XCALLOC(MTYPE_PIM_BSRP_NODE, sizeof(*bsm_rpinfo)); + bsm_rpinfo = XCALLOC(MTYPE_PIM_BSRP_INFO, sizeof(*bsm_rpinfo)); bsm_rpinfo->rp_prio = rp->rp_pri; bsm_rpinfo->rp_holdtime = rp->rp_holdtime; @@ -1049,7 +1036,7 @@ static bool pim_install_bsm_grp_rp(struct pim_instance *pim, /* update hash for this rp node */ bsm_rpinfo->hash = hash_calc_on_grp_rp(grpnode->group, rp->rpaddr.addr, hashMask_len); - if (listnode_add_sort_nodup(grpnode->partial_bsrp_list, bsm_rpinfo)) { + if (bsm_rpinfos_add(grpnode->partial_bsrp_list, bsm_rpinfo) == NULL) { if (PIM_DEBUG_BSM) zlog_debug( "%s, bs_rpinfo node added to the partial bs_rplist.", @@ -1060,7 +1047,7 @@ static bool pim_install_bsm_grp_rp(struct pim_instance *pim, if (PIM_DEBUG_BSM) zlog_debug("%s: list node not added", __func__); - XFREE(MTYPE_PIM_BSRP_NODE, bsm_rpinfo); + XFREE(MTYPE_PIM_BSRP_INFO, bsm_rpinfo); return false; } @@ -1078,7 +1065,7 @@ static void pim_update_pending_rp_cnt(struct bsm_scope *sz, zlog_debug( "%s,Received a new BSM ,so clear the pending bs_rpinfo list.", __func__); - list_delete_all_node(bsgrp->partial_bsrp_list); + pim_bsm_rpinfos_free(bsgrp->partial_bsrp_list); bsgrp->pend_rp_cnt = total_rp_count; } } else @@ -1227,7 +1214,7 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf, int sz = PIM_GBL_SZ_ID; struct bsmmsg_grpinfo *msg_grp; struct pim_interface *pim_ifp = NULL; - struct bsm_info *bsminfo; + struct bsm_frag *bsfrag; struct pim_instance *pim; char bsr_str[INET_ADDRSTRLEN]; uint16_t frag_tag; @@ -1383,7 +1370,7 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf, pim_ifp->pim->global_scope.bsm_frag_tag, frag_tag); } - list_delete_all_node(pim_ifp->pim->global_scope.bsm_list); + pim_bsm_frags_free(&pim_ifp->pim->global_scope); pim_ifp->pim->global_scope.bsm_frag_tag = frag_tag; } @@ -1392,13 +1379,13 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf, if (!no_fwd) { pim_bsm_fwd_whole_sz(pim_ifp->pim, buf, buf_size, sz); - bsminfo = XCALLOC(MTYPE_PIM_BSM_INFO, sizeof(struct bsm_info)); - - bsminfo->bsm = XCALLOC(MTYPE_PIM_BSM_PKT_VAR_MEM, buf_size); + bsfrag = XCALLOC(MTYPE_PIM_BSM_FRAG, + sizeof(struct bsm_frag) + buf_size); - bsminfo->size = buf_size; - memcpy(bsminfo->bsm, buf, buf_size); - listnode_add(pim_ifp->pim->global_scope.bsm_list, bsminfo); + bsfrag->size = buf_size; + memcpy(bsfrag->data, buf, buf_size); + bsm_frags_add_tail(pim_ifp->pim->global_scope.bsm_frags, + bsfrag); } return 0; diff --git a/pimd/pim_bsm.h b/pimd/pim_bsm.h index 2829c1e05a..dbfeeceec8 100644 --- a/pimd/pim_bsm.h +++ b/pimd/pim_bsm.h @@ -25,7 +25,7 @@ #include "if.h" #include "vty.h" -#include "linklist.h" +#include "typesafe.h" #include "table.h" #include "pim_rp.h" #include "pim_msg.h" @@ -54,6 +54,8 @@ enum ncbsr_state { ACCEPT_PREFERRED }; +PREDECL_DLIST(bsm_frags); + /* BSM scope - bsm processing is per scope */ struct bsm_scope { int sz_id; /* scope zone id */ @@ -66,36 +68,49 @@ struct bsm_scope { uint16_t bsm_frag_tag; /* Last received frag tag from E-BSR */ uint8_t hashMasklen; /* Mask in hash calc RFC 7761 4.7.2 */ struct pim_instance *pim; /* Back pointer to pim instance */ - struct list *bsm_list; /* list of bsm frag for frowarding */ + + /* current set of fragments for forwarding */ + struct bsm_frags_head bsm_frags[1]; + struct route_table *bsrp_table; /* group2rp mapping rcvd from BSR */ struct thread *bs_timer; /* Boot strap timer */ - struct thread *sz_timer; }; -/* BSM packet - this is stored as list in bsm_list inside scope +/* BSM packet (= fragment) - this is stored as list in bsm_frags inside scope * This is used for forwarding to new neighbors or restarting mcast routers */ -struct bsm_info { - uint32_t size; /* size of the packet */ - unsigned char *bsm; /* Actual packet */ +struct bsm_frag { + struct bsm_frags_item item; + + uint32_t size; /* size of the packet */ + uint8_t data[0]; /* Actual packet (dyn size) */ }; +DECLARE_DLIST(bsm_frags, struct bsm_frag, item); + +PREDECL_SORTLIST_UNIQ(bsm_rpinfos); + /* This is the group node of the bsrp table in scope. * this node maintains the list of rp for the group. */ struct bsgrp_node { struct prefix group; /* Group range */ struct bsm_scope *scope; /* Back ptr to scope */ - struct list *bsrp_list; /* list of RPs adv by BSR */ - struct list *partial_bsrp_list; /* maintained until all RPs received */ + + /* RPs advertised by BSR, and temporary list while receiving new set */ + struct bsm_rpinfos_head bsrp_list[1]; + struct bsm_rpinfos_head partial_bsrp_list[1]; + int pend_rp_cnt; /* Total RP - Received RP */ uint16_t frag_tag; /* frag tag to identify the fragment */ }; -/* This is the list node of bsrp_list and partial bsrp list in - * bsgrp_node. Hold info of each RP received for the group +/* Items on [partial_]bsrp_list above. + * Holds info of each candidate RP received for the bsgrp_node's prefix. */ struct bsm_rpinfo { + struct bsm_rpinfos_item item; + uint32_t hash; /* Hash Value as per RFC 7761 4.7.2 */ uint32_t elapse_time; /* upd at expiry of elected RP node */ uint16_t rp_prio; /* RP priority */ @@ -105,6 +120,10 @@ struct bsm_rpinfo { struct thread *g2rp_timer; /* Run only for elected RP node */ }; +extern int pim_bsm_rpinfo_cmp(const struct bsm_rpinfo *a, + const struct bsm_rpinfo *b); +DECLARE_SORTLIST_UNIQ(bsm_rpinfos, struct bsm_rpinfo, item, pim_bsm_rpinfo_cmp); + /* Structures to extract Bootstrap Message header and Grp to RP Mappings * ===================================================================== * BSM Format: @@ -196,6 +215,8 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp); struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope, struct prefix *grp); void pim_bs_timer_stop(struct bsm_scope *scope); +void pim_bsm_frags_free(struct bsm_scope *scope); +void pim_bsm_rpinfos_free(struct bsm_rpinfos_head *head); void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node); void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp); #endif diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index c01cfec88e..d2f7dad820 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3000,15 +3000,14 @@ static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty) /* Display the bsm database details */ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) { - struct listnode *bsmnode; int count = 0; int fragment = 1; - struct bsm_info *bsm; + struct bsm_frag *bsfrag; json_object *json = NULL; json_object *json_group = NULL; json_object *json_row = NULL; - count = pim->global_scope.bsm_list->count; + count = bsm_frags_count(pim->global_scope.bsm_frags); if (uj) { json = json_object_new_object(); @@ -3019,7 +3018,7 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) vty_out(vty, "\n"); } - for (ALL_LIST_ELEMENTS_RO(pim->global_scope.bsm_list, bsmnode, bsm)) { + frr_each (bsm_frags, pim->global_scope.bsm_frags, bsfrag) { char grp_str[PREFIX_STRLEN]; char rp_str[INET_ADDRSTRLEN]; char bsr_str[INET_ADDRSTRLEN]; @@ -3032,8 +3031,8 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) uint32_t len = 0; uint32_t frag_rp_cnt = 0; - buf = bsm->bsm; - len = bsm->size; + buf = bsfrag->data; + len = bsfrag->size; /* skip pim header */ buf += PIM_MSG_HEADER_LEN; @@ -3160,7 +3159,6 @@ static void pim_show_group_rp_mappings_info(struct pim_instance *pim, struct vty *vty, bool uj) { struct bsgrp_node *bsgrp; - struct listnode *rpnode; struct bsm_rpinfo *bsm_rp; struct route_node *rn; char bsr_str[INET_ADDRSTRLEN]; @@ -3209,42 +3207,33 @@ static void pim_show_group_rp_mappings_info(struct pim_instance *pim, vty_out(vty, "(ACTIVE)\n"); } - if (bsgrp->bsrp_list) { - for (ALL_LIST_ELEMENTS_RO(bsgrp->bsrp_list, rpnode, - bsm_rp)) { - char rp_str[INET_ADDRSTRLEN]; + frr_each (bsm_rpinfos, bsgrp->bsrp_list, bsm_rp) { + char rp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<Rp Address?>", - bsm_rp->rp_address, rp_str, - sizeof(rp_str)); + pim_inet4_dump("<Rp Address?>", bsm_rp->rp_address, + rp_str, sizeof(rp_str)); - if (uj) { - json_row = json_object_new_object(); - json_object_string_add( - json_row, "Rp Address", rp_str); - json_object_int_add( - json_row, "Rp HoldTime", - bsm_rp->rp_holdtime); - json_object_int_add(json_row, - "Rp Priority", - bsm_rp->rp_prio); - json_object_int_add(json_row, - "Hash Val", - bsm_rp->hash); - json_object_object_add( - json_group, rp_str, json_row); + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "Rp Address", + rp_str); + json_object_int_add(json_row, "Rp HoldTime", + bsm_rp->rp_holdtime); + json_object_int_add(json_row, "Rp Priority", + bsm_rp->rp_prio); + json_object_int_add(json_row, "Hash Val", + bsm_rp->hash); + json_object_object_add(json_group, rp_str, + json_row); - } else { - vty_out(vty, - "%-15s %-15u %-15u %-15u\n", - rp_str, bsm_rp->rp_prio, - bsm_rp->rp_holdtime, - bsm_rp->hash); - } + } else { + vty_out(vty, "%-15s %-15u %-15u %-15u\n", + rp_str, bsm_rp->rp_prio, + bsm_rp->rp_holdtime, bsm_rp->hash); } - if (!bsgrp->bsrp_list->count && !uj) - vty_out(vty, "Active List is empty.\n"); } + if (!bsm_rpinfos_count(bsgrp->bsrp_list) && !uj) + vty_out(vty, "Active List is empty.\n"); if (uj) { json_object_int_add(json_group, "Pending RP count", @@ -3259,40 +3248,32 @@ static void pim_show_group_rp_mappings_info(struct pim_instance *pim, "Hash"); } - if (bsgrp->partial_bsrp_list) { - for (ALL_LIST_ELEMENTS_RO(bsgrp->partial_bsrp_list, - rpnode, bsm_rp)) { - char rp_str[INET_ADDRSTRLEN]; + frr_each (bsm_rpinfos, bsgrp->partial_bsrp_list, bsm_rp) { + char rp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<Rp Addr?>", bsm_rp->rp_address, - rp_str, sizeof(rp_str)); + pim_inet4_dump("<Rp Addr?>", bsm_rp->rp_address, rp_str, + sizeof(rp_str)); - if (uj) { - json_row = json_object_new_object(); - json_object_string_add( - json_row, "Rp Address", rp_str); - json_object_int_add( - json_row, "Rp HoldTime", - bsm_rp->rp_holdtime); - json_object_int_add(json_row, - "Rp Priority", - bsm_rp->rp_prio); - json_object_int_add(json_row, - "Hash Val", - bsm_rp->hash); - json_object_object_add( - json_group, rp_str, json_row); - } else { - vty_out(vty, - "%-15s %-15u %-15u %-15u\n", - rp_str, bsm_rp->rp_prio, - bsm_rp->rp_holdtime, - bsm_rp->hash); - } + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "Rp Address", + rp_str); + json_object_int_add(json_row, "Rp HoldTime", + bsm_rp->rp_holdtime); + json_object_int_add(json_row, "Rp Priority", + bsm_rp->rp_prio); + json_object_int_add(json_row, "Hash Val", + bsm_rp->hash); + json_object_object_add(json_group, rp_str, + json_row); + } else { + vty_out(vty, "%-15s %-15u %-15u %-15u\n", + rp_str, bsm_rp->rp_prio, + bsm_rp->rp_holdtime, bsm_rp->hash); } - if (!bsgrp->partial_bsrp_list->count && !uj) - vty_out(vty, "Partial List is empty\n"); } + if (!bsm_rpinfos_count(bsgrp->partial_bsrp_list) && !uj) + vty_out(vty, "Partial List is empty\n"); if (!uj) vty_out(vty, "\n"); @@ -3847,6 +3828,31 @@ static void clear_interfaces(struct pim_instance *pim) return CMD_WARNING_CONFIG_FAILED; \ } +/** + * Get current node VRF name. + * + * NOTE: + * In case of failure it will print error message to user. + * + * \returns name or NULL if failed to get VRF. + */ +static const char *pim_cli_get_vrf_name(struct vty *vty) +{ + const struct lyd_node *vrf_node; + + /* Not inside any VRF context. */ + if (vty->xpath_index == 0) + return VRF_DEFAULT_NAME; + + vrf_node = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (vrf_node == NULL) { + vty_out(vty, "%% Failed to get vrf dnode in configuration\n"); + return NULL; + } + + return yang_dnode_get_string(vrf_node, "./name"); +} + DEFUN (clear_ip_interfaces, clear_ip_interfaces_cmd, "clear ip interfaces [vrf NAME]", @@ -4083,7 +4089,7 @@ static void clear_pim_bsr_db(struct pim_instance *pim) pim->global_scope.current_bsr_first_ts = 0; pim->global_scope.current_bsr_last_ts = 0; pim->global_scope.bsm_frag_tag = 0; - list_delete_all_node(pim->global_scope.bsm_list); + pim_bsm_frags_free(&pim->global_scope); pim_bs_timer_stop(&pim->global_scope); @@ -6925,25 +6931,13 @@ DEFUN (ip_pim_spt_switchover_infinity, "SPT-Switchover\n" "Never switch to SPT Tree\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char spt_plist_xpath[XPATH_MAXLEN]; char spt_action_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(spt_plist_xpath, sizeof(spt_plist_xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname, @@ -6976,25 +6970,13 @@ DEFUN (ip_pim_spt_switchover_infinity_plist, "Prefix-List to control which groups to switch\n" "Prefix-List name\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char spt_plist_xpath[XPATH_MAXLEN]; char spt_action_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(spt_plist_xpath, sizeof(spt_plist_xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname, @@ -7025,25 +7007,13 @@ DEFUN (no_ip_pim_spt_switchover_infinity, "SPT_Switchover\n" "Never switch to SPT Tree\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char spt_plist_xpath[XPATH_MAXLEN]; char spt_action_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(spt_plist_xpath, sizeof(spt_plist_xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname, @@ -7075,25 +7045,13 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist, "Prefix-List to control which groups to switch\n" "Prefix-List name\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char spt_plist_xpath[XPATH_MAXLEN]; char spt_action_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(spt_plist_xpath, sizeof(spt_plist_xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname, @@ -7123,22 +7081,12 @@ DEFPY (pim_register_accept_list, "Only accept registers from a specific source prefix list\n" "Prefix-List name\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char reg_alist_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(reg_alist_xpath, sizeof(reg_alist_xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname, @@ -7233,22 +7181,12 @@ DEFUN (ip_pim_rp_keep_alive, "Keep alive Timer\n" "Seconds\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char rp_ka_timer_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath), FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname); @@ -7271,26 +7209,15 @@ DEFUN (no_ip_pim_rp_keep_alive, "Keep alive Timer\n" "Seconds\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char rp_ka_timer[5]; char rp_ka_timer_xpath[XPATH_MAXLEN]; snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%d", PIM_KEEPALIVE_PERIOD); - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; - + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath), FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname); @@ -7311,22 +7238,12 @@ DEFUN (ip_pim_keep_alive, "Keep alive Timer\n" "Seconds\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char ka_timer_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname); @@ -7347,25 +7264,15 @@ DEFUN (no_ip_pim_keep_alive, "Keep alive Timer\n" "Seconds\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char ka_timer[5]; char ka_timer_xpath[XPATH_MAXLEN]; snprintf(ka_timer, sizeof(ka_timer), "%d", PIM_KEEPALIVE_PERIOD); - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname); @@ -7447,22 +7354,12 @@ DEFUN (ip_pim_v6_secondary, "pim multicast routing\n" "Send v6 secondary addresses\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char send_v6_secondary_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(send_v6_secondary_xpath, sizeof(send_v6_secondary_xpath), FRR_PIM_AF_XPATH, @@ -7484,22 +7381,12 @@ DEFUN (no_ip_pim_v6_secondary, "pim multicast routing\n" "Send v6 secondary addresses\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char send_v6_secondary_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(send_v6_secondary_xpath, sizeof(send_v6_secondary_xpath), FRR_PIM_AF_XPATH, @@ -7522,7 +7409,6 @@ DEFUN (ip_pim_rp, "ip address of RP\n" "Group Address range to cover\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; int idx_rp = 3, idx_group = 4; char rp_group_xpath[XPATH_MAXLEN]; @@ -7558,20 +7444,9 @@ DEFUN (ip_pim_rp, return CMD_WARNING_CONFIG_FAILED; } - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(rp_group_xpath, sizeof(rp_group_xpath), FRR_PIM_STATIC_RP_XPATH, @@ -7595,24 +7470,12 @@ DEFUN (ip_pim_rp_prefix_list, "Name of a prefix-list\n") { int idx_rp = 3, idx_plist = 5; - const struct lyd_node *vrf_dnode; const char *vrfname; char rp_plist_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(rp_plist_xpath, sizeof(rp_plist_xpath), FRR_PIM_STATIC_RP_XPATH, @@ -7642,24 +7505,12 @@ DEFUN (no_ip_pim_rp, char group_list_xpath[XPATH_MAXLEN + 32]; char group_xpath[XPATH_MAXLEN + 64]; char rp_xpath[XPATH_MAXLEN]; - const struct lyd_node *vrf_dnode; const char *vrfname; const struct lyd_node *group_dnode; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", @@ -7702,23 +7553,13 @@ DEFUN (no_ip_pim_rp_prefix_list, int idx_plist = 6; char rp_xpath[XPATH_MAXLEN]; char plist_xpath[XPATH_MAXLEN]; - const struct lyd_node *vrf_dnode; const char *vrfname; const struct lyd_node *plist_dnode; const char *plist; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", @@ -7755,22 +7596,12 @@ DEFUN (ip_pim_ssm_prefix_list, "group range prefix-list filter\n" "Name of a prefix-list\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char ssm_plist_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); @@ -7790,22 +7621,12 @@ DEFUN (no_ip_pim_ssm_prefix_list, "Source Specific Multicast\n" "group range prefix-list filter\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char ssm_plist_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath), FRR_PIM_AF_XPATH, @@ -7827,27 +7648,14 @@ DEFUN (no_ip_pim_ssm_prefix_list_name, "group range prefix-list filter\n" "Name of a prefix-list\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; const struct lyd_node *ssm_plist_dnode; char ssm_plist_xpath[XPATH_MAXLEN]; const char *ssm_plist_name; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; - + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath), FRR_PIM_AF_XPATH, @@ -8001,22 +7809,12 @@ DEFUN (ip_ssmpingd, { int idx_ipv4 = 2; const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0"; - const struct lyd_node *vrf_dnode; const char *vrfname; char ssmpingd_ip_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath), FRR_PIM_AF_XPATH, @@ -8038,24 +7836,14 @@ DEFUN (no_ip_ssmpingd, CONF_SSMPINGD_STR "Source address\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; int idx_ipv4 = 3; const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0"; char ssmpingd_ip_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath), FRR_PIM_AF_XPATH, @@ -8076,22 +7864,12 @@ DEFUN (ip_pim_ecmp, "pim multicast routing\n" "Enable PIM ECMP \n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char ecmp_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname); @@ -8109,22 +7887,12 @@ DEFUN (no_ip_pim_ecmp, "pim multicast routing\n" "Disable PIM ECMP \n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char ecmp_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname); @@ -8143,23 +7911,13 @@ DEFUN (ip_pim_ecmp_rebalance, "Enable PIM ECMP \n" "Enable PIM ECMP Rebalance\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char ecmp_xpath[XPATH_MAXLEN]; char ecmp_rebalance_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname); @@ -8185,22 +7943,12 @@ DEFUN (no_ip_pim_ecmp_rebalance, "Disable PIM ECMP \n" "Disable PIM ECMP Rebalance\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char ecmp_rebalance_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(ecmp_rebalance_xpath, sizeof(ecmp_rebalance_xpath), FRR_PIM_XPATH, @@ -9882,23 +9630,13 @@ ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd, "Source address for TCP connection\n" "local ip address\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char temp_xpath[XPATH_MAXLEN]; char msdp_peer_source_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(msdp_peer_source_xpath, sizeof(msdp_peer_source_xpath), FRR_PIM_AF_XPATH, @@ -9924,23 +9662,13 @@ DEFUN (no_ip_msdp_peer, "Delete MSDP peer\n" "peer ip address\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char msdp_peer_xpath[XPATH_MAXLEN]; char temp_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(msdp_peer_xpath, sizeof(msdp_peer_xpath), FRR_PIM_AF_XPATH, @@ -9966,23 +9694,13 @@ DEFUN (ip_msdp_mesh_group_member, "mesh group member\n" "peer ip address\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char msdp_mesh_group_name_xpath[XPATH_MAXLEN]; char msdp_mesh_group_member_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(msdp_mesh_group_name_xpath, sizeof(msdp_mesh_group_name_xpath), FRR_PIM_AF_XPATH, @@ -10015,7 +9733,6 @@ DEFUN (no_ip_msdp_mesh_group_member, "mesh group member\n" "peer ip address\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char pim_af_xpath[XPATH_MAXLEN]; char mesh_group_xpath[XPATH_MAXLEN + 32]; @@ -10026,18 +9743,9 @@ DEFUN (no_ip_msdp_mesh_group_member, const char *mesh_group_name; const struct lyd_node *member_dnode; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(pim_af_xpath, sizeof(pim_af_xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); @@ -10103,23 +9811,13 @@ DEFUN (ip_msdp_mesh_group_source, "mesh group local address\n" "source ip address for the TCP connection\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char msdp_mesh_source_ip_xpath[XPATH_MAXLEN]; char msdp_mesh_group_name_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(msdp_mesh_group_name_xpath, sizeof(msdp_mesh_group_name_xpath), FRR_PIM_AF_XPATH, @@ -10152,7 +9850,6 @@ DEFUN (no_ip_msdp_mesh_group_source, "mesh group source\n" "mesh group local address\n") { - const struct lyd_node *vrf_dnode; const char *vrfname; char msdp_mesh_xpath[XPATH_MAXLEN]; char source_xpath[XPATH_MAXLEN]; @@ -10160,18 +9857,9 @@ DEFUN (no_ip_msdp_mesh_group_source, char mesh_group_name_xpath[XPATH_MAXLEN]; const char *mesh_group_name; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; snprintf(msdp_mesh_xpath, sizeof(msdp_mesh_xpath), FRR_PIM_AF_XPATH, @@ -10226,24 +9914,14 @@ DEFUN (no_ip_msdp_mesh_group, "Delete MSDP mesh-group\n" "mesh group name") { - const struct lyd_node *vrf_dnode; const char *vrfname; const char *mesh_group_name; char xpath[XPATH_MAXLEN]; char msdp_mesh_xpath[XPATH_MAXLEN]; - if (vty->xpath_index) { - vrf_dnode = - yang_dnode_get(vty->candidate_config->dnode, - VTY_CURR_XPATH); - if (!vrf_dnode) { - vty_out(vty, - "%% Failed to get vrf dnode in candidate db\n"); - return CMD_WARNING_CONFIG_FAILED; - } - vrfname = yang_dnode_get_string(vrf_dnode, "./name"); - } else - vrfname = VRF_DEFAULT_NAME; + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return CMD_WARNING_CONFIG_FAILED; if (argc == 5) { snprintf(xpath, sizeof(xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd", diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index 6f5c4174e2..e48a4bdd4d 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -141,14 +141,14 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr, on_trace(__func__, ifp, src_addr); pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); ++pim_ifp->pim_ifstat_hello_recv; /* Parse PIM hello TLVs */ - zassert(tlv_buf_size >= 0); + assert(tlv_buf_size >= 0); tlv_curr = tlv_buf; tlv_pastend = tlv_buf + tlv_buf_size; @@ -539,11 +539,11 @@ void pim_hello_require(struct interface *ifp) { struct pim_interface *pim_ifp; - zassert(ifp); + assert(ifp); pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); if (pim_ifp->pim_ifstat_hello_sent) return; diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 62d19f7619..834399053b 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -115,8 +115,8 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim, { struct pim_interface *pim_ifp; - zassert(ifp); - zassert(!ifp->info); + assert(ifp); + assert(!ifp->info); pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); @@ -145,8 +145,8 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim, The number of seconds represented by the [Query Response Interval] must be less than the [Query Interval]. */ - zassert(pim_ifp->igmp_query_max_response_time_dsec - < pim_ifp->igmp_default_query_interval); + assert(pim_ifp->igmp_query_max_response_time_dsec + < pim_ifp->igmp_default_query_interval); if (pim) PIM_IF_DO_PIM(pim_ifp->options); @@ -198,9 +198,9 @@ void pim_if_delete(struct interface *ifp) struct pim_interface *pim_ifp; struct pim_ifchannel *ch; - zassert(ifp); + assert(ifp); pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); if (pim_ifp->igmp_join_list) { pim_if_igmp_join_del_all(ifp); @@ -238,7 +238,7 @@ void pim_if_update_could_assert(struct interface *ifp) struct pim_ifchannel *ch; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { pim_ifchannel_update_could_assert(ch); @@ -251,7 +251,7 @@ static void pim_if_update_my_assert_metric(struct interface *ifp) struct pim_ifchannel *ch; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { pim_ifchannel_update_my_assert_metric(ch); @@ -263,7 +263,7 @@ static void pim_addr_change(struct interface *ifp) struct pim_interface *pim_ifp; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes -- Done TODO T30 */ @@ -507,10 +507,10 @@ void pim_if_addr_add(struct connected *ifc) struct in_addr ifaddr; bool vxlan_term; - zassert(ifc); + assert(ifc); ifp = ifc->ifp; - zassert(ifp); + assert(ifp); pim_ifp = ifp->info; if (!pim_ifp) return; @@ -708,9 +708,9 @@ void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) { struct interface *ifp; - zassert(ifc); + assert(ifc); ifp = ifc->ifp; - zassert(ifp); + assert(ifp); if (PIM_DEBUG_ZEBRA) zlog_debug("%s: %s ifindex=%d disconnected IP address %pFX %s", @@ -945,7 +945,7 @@ int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term) struct in_addr ifaddr; unsigned char flags = 0; - zassert(pim_ifp); + assert(pim_ifp); if (pim_ifp->mroute_vif_index > 0) { zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d", @@ -1063,8 +1063,8 @@ int pim_if_lan_delay_enabled(struct interface *ifp) struct pim_interface *pim_ifp; pim_ifp = ifp->info; - zassert(pim_ifp); - zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0); + assert(pim_ifp); + assert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0); return pim_ifp->pim_number_of_nonlandelay_neighbors == 0; } @@ -1128,7 +1128,7 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, struct pim_interface *pim_ifp; struct prefix p; - zassert(ifp); + assert(ifp); pim_ifp = ifp->info; if (!pim_ifp) { @@ -1171,7 +1171,7 @@ long pim_if_t_suppressed_msec(struct interface *ifp) uint32_t ramount = 0; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); /* join suppression disabled ? */ if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPPRESSION(pim_ifp->options)) @@ -1196,7 +1196,7 @@ static struct igmp_join *igmp_join_find(struct list *join_list, struct listnode *node; struct igmp_join *ij; - zassert(join_list); + assert(join_list); for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) { if ((group_addr.s_addr == ij->group_addr.s_addr) @@ -1245,7 +1245,7 @@ static struct igmp_join *igmp_join_new(struct interface *ifp, int join_fd; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, source_addr); @@ -1416,7 +1416,7 @@ void pim_if_assert_on_neighbor_down(struct interface *ifp, struct pim_ifchannel *ch; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { /* Is (S,G,I) assert loser ? */ diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index cdaf7bcdd4..579824c88d 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -498,7 +498,7 @@ void pim_ifchannel_membership_clear(struct interface *ifp) struct pim_ifchannel *ch; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); @@ -510,7 +510,7 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp) struct pim_ifchannel *ch, *ch_tmp; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); RB_FOREACH_SAFE (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch_tmp) delete_on_noinfo(ch); @@ -825,7 +825,7 @@ static int nonlocal_upstream(int is_join, struct interface *recv_ifp, int is_local; /* boolean */ recv_pim_ifp = recv_ifp->info; - zassert(recv_pim_ifp); + assert(recv_pim_ifp); is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); @@ -913,7 +913,7 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, } pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); switch (ch->ifjoin_state) { case PIM_IFJOIN_NOINFO: @@ -939,7 +939,7 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, } break; case PIM_IFJOIN_JOIN: - zassert(!ch->t_ifjoin_prune_pending_timer); + assert(!ch->t_ifjoin_prune_pending_timer); /* In the JOIN state ch->t_ifjoin_expiry_timer may be NULL due to diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 73e42e9d83..f2b909e268 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -159,7 +159,7 @@ static int pim_igmp_other_querier_expire(struct thread *t) igmp = THREAD_ARG(t); - zassert(!igmp->t_igmp_query_timer); + assert(!igmp->t_igmp_query_timer); if (PIM_DEBUG_IGMP_TRACE) { char ifaddr_str[INET_ADDRSTRLEN]; @@ -185,9 +185,9 @@ void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp) long other_querier_present_interval_msec; struct pim_interface *pim_ifp; - zassert(igmp); - zassert(igmp->interface); - zassert(igmp->interface->info); + assert(igmp); + assert(igmp->interface); + assert(igmp->interface->info); pim_ifp = igmp->interface->info; @@ -218,7 +218,7 @@ void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp) Since this socket is starting the other-querier-present timer, there should not be periodic query timer for this socket. */ - zassert(!igmp->t_igmp_query_timer); + assert(!igmp->t_igmp_query_timer); /* RFC 3376: 8.5. Other Querier Present Interval @@ -255,7 +255,7 @@ void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp) void pim_igmp_other_querier_timer_off(struct igmp_sock *igmp) { - zassert(igmp); + assert(igmp); if (PIM_DEBUG_IGMP_TRACE) { if (igmp->t_other_querier_timer) { @@ -589,9 +589,9 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp) Since this socket is starting as querier, there should not exist a timer for other-querier-present. */ - zassert(!igmp->t_other_querier_timer); + assert(!igmp->t_other_querier_timer); pim_ifp = igmp->interface->info; - zassert(pim_ifp); + assert(pim_ifp); /* RFC 3376: 8.6. Startup Query Interval @@ -638,7 +638,7 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp) void pim_igmp_general_query_off(struct igmp_sock *igmp) { - zassert(igmp); + assert(igmp); if (PIM_DEBUG_IGMP_TRACE) { if (igmp->t_igmp_query_timer) { @@ -664,8 +664,8 @@ static int pim_igmp_general_query(struct thread *t) igmp = THREAD_ARG(t); - zassert(igmp->interface); - zassert(igmp->interface->info); + assert(igmp->interface); + assert(igmp->interface->info); pim_ifp = igmp->interface->info; @@ -835,19 +835,19 @@ void igmp_group_delete(struct igmp_group *group) void igmp_group_delete_empty_include(struct igmp_group *group) { - zassert(!group->group_filtermode_isexcl); - zassert(!listcount(group->group_source_list)); + assert(!group->group_filtermode_isexcl); + assert(!listcount(group->group_source_list)); igmp_group_delete(group); } void igmp_sock_free(struct igmp_sock *igmp) { - zassert(!igmp->t_igmp_read); - zassert(!igmp->t_igmp_query_timer); - zassert(!igmp->t_other_querier_timer); - zassert(igmp->igmp_group_list); - zassert(!listcount(igmp->igmp_group_list)); + assert(!igmp->t_igmp_read); + assert(!igmp->t_igmp_query_timer); + assert(!igmp->t_other_querier_timer); + assert(igmp->igmp_group_list); + assert(!listcount(igmp->igmp_group_list)); list_delete(&igmp->igmp_group_list); hash_free(igmp->igmp_group_hash); @@ -1076,7 +1076,7 @@ static int igmp_group_timer(struct thread *t) group_str, group->group_igmp_sock->interface->name); } - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); group->group_filtermode_isexcl = 0; @@ -1085,7 +1085,7 @@ static int igmp_group_timer(struct thread *t) igmp_source_delete_expired(group->group_source_list); - zassert(!group->group_filtermode_isexcl); + assert(!group->group_filtermode_isexcl); /* RFC 3376: 6.2.2. Definition of Group Timers @@ -1137,7 +1137,7 @@ void igmp_group_timer_on(struct igmp_group *group, long interval_msec, it represents the time for the *filter-mode* of the group to expire and switch to INCLUDE mode. */ - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); thread_add_timer_msec(router->master, igmp_group_timer, group, interval_msec, &group->t_group_timer); @@ -1228,8 +1228,8 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, it represents the time for the *filter-mode* of the group to expire and switch to INCLUDE mode. */ - zassert(!group->group_filtermode_isexcl); /* INCLUDE mode */ - zassert(!group->t_group_timer); /* group timer == 0 */ + assert(!group->group_filtermode_isexcl); /* INCLUDE mode */ + assert(!group->t_group_timer); /* group timer == 0 */ /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ igmp_anysource_forward_stop(group); diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c index 7f3c7a0f8c..6eadf87c83 100644 --- a/pimd/pim_igmpv2.c +++ b/pimd/pim_igmpv2.c @@ -54,7 +54,7 @@ void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname, /* max_resp_code must be non-zero else this will look like an IGMP v1 * query */ max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); - zassert(max_resp_code > 0); + assert(max_resp_code > 0); query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; query_buf[1] = max_resp_code; diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 425adfe166..3ae7744eb0 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -103,7 +103,7 @@ void igmp_group_reset_gmi(struct igmp_group *group) it represents the time for the *filter-mode* of the group to expire and switch to INCLUDE mode. */ - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); igmp_group_timer_on(group, group_membership_interval_msec, ifp->name); } @@ -314,7 +314,7 @@ static void group_exclude_fwd_anysrc_ifempty(struct igmp_group *group) { struct pim_interface *pim_ifp = group->group_igmp_sock->interface->info; - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); if (listcount(group->group_source_list) < 1) { igmp_anysource_forward_start(pim_ifp->pim, group); @@ -324,7 +324,7 @@ static void group_exclude_fwd_anysrc_ifempty(struct igmp_group *group) void igmp_source_free(struct igmp_source *source) { /* make sure there is no source timer running */ - zassert(!source->t_source_timer); + assert(!source->t_source_timer); XFREE(MTYPE_PIM_IGMP_GROUP_SOURCE, source); } @@ -557,7 +557,7 @@ static void isex_excl(struct igmp_group *group, int num_sources, int i; /* EXCLUDE mode */ - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); /* E.1: set deletion flag for known sources (X,Y) */ source_mark_delete_flag(group); @@ -577,10 +577,10 @@ static void isex_excl(struct igmp_group *group, int num_sources, /* E.4: if not found, create source with timer=GMI: * (A-X-Y) */ source = source_new(group, *src_addr); - zassert(!source->t_source_timer); /* timer == 0 */ + assert(!source->t_source_timer); /* timer == 0 */ igmp_source_reset_gmi(group->group_igmp_sock, group, source); - zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ + assert(source->t_source_timer); /* (A-X-Y) timer > 0 */ } } /* scan received sources */ @@ -610,7 +610,7 @@ static void isex_incl(struct igmp_group *group, int num_sources, int i; /* INCLUDE mode */ - zassert(!group->group_filtermode_isexcl); + assert(!group->group_filtermode_isexcl); /* I.1: set deletion flag for known sources (A) */ source_mark_delete_flag(group); @@ -631,7 +631,7 @@ static void isex_incl(struct igmp_group *group, int num_sources, /* I.4: if not found, create source with timer=0 (B-A) */ source = source_new(group, *src_addr); - zassert(!source->t_source_timer); /* (B-A) timer=0 */ + assert(!source->t_source_timer); /* (B-A) timer=0 */ } } /* scan received sources */ @@ -641,7 +641,7 @@ static void isex_incl(struct igmp_group *group, int num_sources, group->group_filtermode_isexcl = 1; /* boolean=true */ - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); group_exclude_fwd_anysrc_ifempty(group); } @@ -675,10 +675,10 @@ void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, } else { /* INCLUDE mode */ isex_incl(group, num_sources, sources); - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); } - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); igmp_group_reset_gmi(group); } @@ -807,7 +807,7 @@ static void toex_incl(struct igmp_group *group, int num_sources, int num_sources_tosend = 0; int i; - zassert(!group->group_filtermode_isexcl); + assert(!group->group_filtermode_isexcl); /* Set DELETE flag for all known sources (A) */ source_mark_delete_flag(group); @@ -834,7 +834,7 @@ static void toex_incl(struct igmp_group *group, int num_sources, /* If source not found, create source with timer=0: * (B-A)=0 */ source = source_new(group, *src_addr); - zassert(!source->t_source_timer); /* (B-A) timer=0 */ + assert(!source->t_source_timer); /* (B-A) timer=0 */ } } /* Scan received sources (B) */ @@ -849,7 +849,7 @@ static void toex_incl(struct igmp_group *group, int num_sources, source_query_send_by_flag(group, num_sources_tosend); } - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); group_exclude_fwd_anysrc_ifempty(group); } @@ -894,17 +894,17 @@ static void toex_excl(struct igmp_group *group, int num_sources, long group_timer_msec; source = source_new(group, *src_addr); - zassert(!source->t_source_timer); /* timer == 0 */ + assert(!source->t_source_timer); /* timer == 0 */ group_timer_msec = igmp_group_timer_remain_msec(group); igmp_source_timer_on(group, source, group_timer_msec); - zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ + assert(source->t_source_timer); /* (A-X-Y) timer > 0 */ /* make sure source is created with DELETE flag unset */ - zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); + assert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); } /* make sure reported source has DELETE flag unset */ - zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); + assert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); if (source->t_source_timer) { /* if source timer>0 mark SEND flag: Q(G,A-Y) */ @@ -948,9 +948,9 @@ void igmpv3_report_toex(struct igmp_sock *igmp, struct in_addr from, } else { /* INCLUDE mode */ toex_incl(group, num_sources, sources); - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); } - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); /* Group Timer=GMI */ igmp_group_reset_gmi(group); @@ -1347,7 +1347,7 @@ static void source_query_send_by_flag(struct igmp_group *group, long lmqi_msec; /* Last Member Query Interval */ long lmqt_msec; /* Last Member Query Time */ - zassert(num_sources_tosend > 0); + assert(num_sources_tosend > 0); igmp = group->group_igmp_sock; pim_ifp = igmp->interface->info; @@ -1408,10 +1408,10 @@ static void block_excl(struct igmp_group *group, int num_sources, long group_timer_msec; source = source_new(group, *src_addr); - zassert(!source->t_source_timer); /* timer == 0 */ + assert(!source->t_source_timer); /* timer == 0 */ group_timer_msec = igmp_group_timer_remain_msec(group); igmp_source_timer_on(group, source, group_timer_msec); - zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ + assert(source->t_source_timer); /* (A-X-Y) timer > 0 */ } if (source->t_source_timer) { @@ -1523,7 +1523,7 @@ void igmp_group_timer_lower_to_lmqt(struct igmp_group *group) lmqt_msec); } - zassert(group->group_filtermode_isexcl); + assert(group->group_filtermode_isexcl); igmp_group_timer_on(group, lmqt_msec, ifname); } @@ -1581,7 +1581,7 @@ void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname, socklen_t tolen; uint16_t checksum; - zassert(num_sources >= 0); + assert(num_sources >= 0); msg_size = IGMP_V3_SOURCES_OFFSET + (num_sources << 2); if (msg_size > query_buf_size) { @@ -1593,7 +1593,7 @@ void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname, } s_flag = PIM_FORCE_BOOLEAN(s_flag); - zassert((s_flag == 0) || (s_flag == 1)); + assert((s_flag == 0) || (s_flag == 1)); max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); qqic = igmp_msg_encode16to8(querier_query_interval); diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 2766a6d2b5..c7a80ca8e0 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -71,7 +71,7 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh, } pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); ++pim_ifp->pim_ifstat_join_recv; @@ -134,7 +134,7 @@ static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh, } pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); ++pim_ifp->pim_ifstat_prune_recv; diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 7336cdfef8..9cf73c38c3 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -1562,6 +1562,26 @@ int pim_msdp_config_write(struct pim_instance *pim, struct vty *vty, return count; } +bool pim_msdp_peer_config_write(struct vty *vty, struct pim_instance *pim, + const char *spaces) +{ + struct pim_msdp_peer *mp; + struct listnode *node; + bool written = false; + + for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, node, mp)) { + /* Non meshed peers have the group name set to 'default'. */ + if (strcmp(mp->mesh_group_name, "default")) + continue; + + vty_out(vty, "%sip msdp peer %pI4 source %pI4\n", spaces, + &mp->peer, &mp->local); + written = true; + } + + return written; +} + /* Enable feature including active/periodic timers etc. on the first peer * config. Till then MSDP should just stay quiet. */ static void pim_msdp_enable(struct pim_instance *pim) diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 15a1041e21..4d01880fbf 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -234,6 +234,8 @@ char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format); int pim_msdp_config_write(struct pim_instance *pim, struct vty *vty, const char *spaces); +bool pim_msdp_peer_config_write(struct vty *vty, struct pim_instance *pim, + const char *spaces); void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp); void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp, struct prefix_sg *sg, struct in_addr rp); diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index 8e6f2ec42b..da2daea7c3 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "pimd.h" #include "pim_nb.h" #include "lib/northbound_cli.h" @@ -36,7 +38,7 @@ static void pim_if_membership_clear(struct interface *ifp) struct pim_interface *pim_ifp; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); if (PIM_IF_TEST_PIM(pim_ifp->options) && PIM_IF_TEST_IGMP(pim_ifp->options)) { @@ -62,7 +64,7 @@ static void pim_if_membership_refresh(struct interface *ifp) struct igmp_sock *igmp; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); if (!PIM_IF_TEST_PIM(pim_ifp->options)) return; @@ -576,7 +578,7 @@ static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp) struct interface *ifp; struct pim_interface *pim_ifp; - zassert(igmp); + assert(igmp); /* other querier present? */ @@ -585,8 +587,8 @@ static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp) /* this is the querier */ - zassert(igmp->interface); - zassert(igmp->interface->info); + assert(igmp->interface); + assert(igmp->interface->info); ifp = igmp->interface; pim_ifp = ifp->info; @@ -616,25 +618,25 @@ static void igmp_sock_query_reschedule(struct igmp_sock *igmp) if (igmp->t_igmp_query_timer) { /* other querier present */ - zassert(igmp->t_igmp_query_timer); - zassert(!igmp->t_other_querier_timer); + assert(igmp->t_igmp_query_timer); + assert(!igmp->t_other_querier_timer); pim_igmp_general_query_off(igmp); pim_igmp_general_query_on(igmp); - zassert(igmp->t_igmp_query_timer); - zassert(!igmp->t_other_querier_timer); + assert(igmp->t_igmp_query_timer); + assert(!igmp->t_other_querier_timer); } else { /* this is the querier */ - zassert(!igmp->t_igmp_query_timer); - zassert(igmp->t_other_querier_timer); + assert(!igmp->t_igmp_query_timer); + assert(igmp->t_other_querier_timer); pim_igmp_other_querier_timer_off(igmp); pim_igmp_other_querier_timer_on(igmp); - zassert(!igmp->t_igmp_query_timer); - zassert(igmp->t_other_querier_timer); + assert(!igmp->t_igmp_query_timer); + assert(igmp->t_other_querier_timer); } } diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 19dc469091..48b1a30f2d 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -49,7 +49,7 @@ static void dr_election_by_addr(struct interface *ifp) struct pim_neighbor *neigh; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); pim_ifp->pim_dr_addr = pim_ifp->primary_address; @@ -73,7 +73,7 @@ static void dr_election_by_pri(struct interface *ifp) uint32_t dr_pri; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); pim_ifp->pim_dr_addr = pim_ifp->primary_address; dr_pri = pim_ifp->pim_dr_priority; @@ -310,9 +310,9 @@ pim_neighbor_new(struct interface *ifp, struct in_addr source_addr, struct pim_neighbor *neigh; char src_str[INET_ADDRSTRLEN]; - zassert(ifp); + assert(ifp); pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh)); @@ -412,7 +412,7 @@ static void delete_prefix_list(struct pim_neighbor *neigh) void pim_neighbor_free(struct pim_neighbor *neigh) { - zassert(!neigh->t_expire_timer); + assert(!neigh->t_expire_timer); delete_prefix_list(neigh); @@ -503,7 +503,7 @@ pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, } pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); listnode_add(pim_ifp->pim_neighbor_list, neigh); @@ -566,7 +566,7 @@ static uint16_t find_neighbors_next_highest_propagation_delay_msec( uint16_t next_highest_delay_msec; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec; @@ -590,7 +590,7 @@ static uint16_t find_neighbors_next_highest_override_interval_msec( uint16_t next_highest_interval_msec; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); next_highest_interval_msec = pim_ifp->pim_override_interval_msec; @@ -613,7 +613,7 @@ void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh, char src_str[INET_ADDRSTRLEN]; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", src_str, @@ -637,10 +637,10 @@ void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh, --pim_ifp->pim_dr_num_nondrpri_neighbors; } - zassert(neigh->propagation_delay_msec - <= pim_ifp->pim_neighbors_highest_propagation_delay_msec); - zassert(neigh->override_interval_msec - <= pim_ifp->pim_neighbors_highest_override_interval_msec); + assert(neigh->propagation_delay_msec + <= pim_ifp->pim_neighbors_highest_propagation_delay_msec); + assert(neigh->override_interval_msec + <= pim_ifp->pim_neighbors_highest_override_interval_msec); if (pim_if_lan_delay_enabled(ifp)) { @@ -683,7 +683,7 @@ void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message) struct pim_neighbor *neigh; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, neigh_nextnode, neigh)) { @@ -728,9 +728,9 @@ static void delete_from_neigh_addr(struct interface *ifp, struct pim_interface *pim_ifp; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); - zassert(addr_list); + assert(addr_list); /* Scan secondary address list diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 3ec0720fc4..0a4e3e1a6f 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -219,8 +219,8 @@ int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif, { struct pim_interface *pim_ifp; - zassert(channel_oil); - zassert(oif); + assert(channel_oil); + assert(oif); pim_ifp = oif->info; diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 2ccff8b84a..4ba08a19d8 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -407,8 +407,8 @@ static void pim_sock_read_on(struct interface *ifp) { struct pim_interface *pim_ifp; - zassert(ifp); - zassert(ifp->info); + assert(ifp); + assert(ifp->info); pim_ifp = ifp->info; @@ -444,7 +444,7 @@ void pim_ifstat_reset(struct interface *ifp) { struct pim_interface *pim_ifp; - zassert(ifp); + assert(ifp); pim_ifp = ifp->info; if (!pim_ifp) { @@ -462,8 +462,8 @@ void pim_sock_reset(struct interface *ifp) { struct pim_interface *pim_ifp; - zassert(ifp); - zassert(ifp->info); + assert(ifp); + assert(ifp->info); pim_ifp = ifp->info; @@ -671,8 +671,8 @@ static int hello_send(struct interface *ifp, uint16_t holdtime) pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN; - zassert(pim_msg_size >= PIM_PIM_MIN_LEN); - zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE); + assert(pim_msg_size >= PIM_PIM_MIN_LEN); + assert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE); pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_HELLO, false); @@ -846,7 +846,7 @@ int pim_sock_add(struct interface *ifp) uint32_t old_genid; pim_ifp = ifp->info; - zassert(pim_ifp); + assert(pim_ifp); if (pim_ifp->pim_sock_fd >= 0) { if (PIM_DEBUG_PIM_PACKETS) diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index dbba6b66d8..feaeea929d 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -702,7 +702,7 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, bsgrp = pim_bsm_get_bsgrp_node(&pim->global_scope, &group); if (bsgrp) { - bsrp = listnode_head(bsgrp->bsrp_list); + bsrp = bsm_rpinfos_first(bsgrp->bsrp_list); if (bsrp) { if (PIM_DEBUG_PIM_TRACE) { char bsrp_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index f4d3547b3f..03e77de161 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -41,12 +41,12 @@ void pim_ssmpingd_init(struct pim_instance *pim) { int result; - zassert(!pim->ssmpingd_list); + assert(!pim->ssmpingd_list); result = inet_pton(AF_INET, PIM_SSMPINGD_REPLY_GROUP, &pim->ssmpingd_group_addr); - zassert(result > 0); + assert(result > 0); } void pim_ssmpingd_destroy(struct pim_instance *pim) @@ -197,7 +197,7 @@ static int ssmpingd_socket(struct in_addr addr, int port, int mttl) static void ssmpingd_delete(struct ssmpingd_sock *ss) { - zassert(ss); + assert(ss); THREAD_OFF(ss->t_sock_read); diff --git a/pimd/pim_time.c b/pimd/pim_time.c index 9878fcf6b4..c88ee7554b 100644 --- a/pimd/pim_time.c +++ b/pimd/pim_time.c @@ -106,7 +106,7 @@ int pim_time_mmss(char *buf, int buf_size, long sec) long mm; int wr; - zassert(buf_size >= 5); + assert(buf_size >= 5); mm = sec / 60; sec %= 60; @@ -122,7 +122,7 @@ static int pim_time_hhmmss(char *buf, int buf_size, long sec) long mm; int wr; - zassert(buf_size >= 8); + assert(buf_size >= 8); hh = sec / 3600; sec %= 3600; @@ -156,7 +156,7 @@ void pim_time_timer_to_hhmmss(char *buf, int buf_size, struct thread *t_timer) void pim_time_uptime(char *buf, int buf_size, int64_t uptime_sec) { - zassert(buf_size >= 8); + assert(buf_size >= 8); pim_time_hhmmss(buf, buf_size, uptime_sec); } diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 633bb207bd..f21c369b8d 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -662,7 +662,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, const uint8_t *addr; const uint8_t *pastend; - zassert(hello_option_addr_list); + assert(hello_option_addr_list); /* Scan addr list diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 57a0c69166..76e9c3f0aa 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -176,6 +176,7 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty) else snprintf(spaces, sizeof(spaces), "%s", " "); + writes += pim_msdp_peer_config_write(vty, pim, spaces); writes += pim_msdp_config_write(pim, vty, spaces); if (!pim->send_v6_secondary) { diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index f0eae955cc..6f933e9e72 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -471,8 +471,8 @@ void igmp_anysource_forward_start(struct pim_instance *pim, struct igmp_source *source; struct in_addr src_addr = {.s_addr = 0}; /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - zassert(group->group_filtermode_isexcl); - zassert(listcount(group->group_source_list) < 1); + assert(group->group_filtermode_isexcl); + assert(listcount(group->group_source_list) < 1); source = source_new(group, src_addr); if (!source) { diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 05c9af8734..72505a6993 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -600,7 +600,8 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil) } stream_get(&lastused, s, sizeof(lastused)); - stream_getl(s); + /* signed success value from netlink_talk; currently unused */ + (void)stream_getl(s); c_oil->cc.lastused = lastused; diff --git a/pimd/pimd.c b/pimd/pimd.c index 811dc96b56..1679480794 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -126,7 +126,7 @@ void pim_init(void) "%s %s: could not solve %s to group address: errno=%d: %s", __FILE__, __func__, PIM_ALL_PIM_ROUTERS, errno, safe_strerror(errno)); - zassert(0); + assert(0); return; } diff --git a/python/firstheader.py b/python/firstheader.py index bf50f33a33..892e9da8d6 100644 --- a/python/firstheader.py +++ b/python/firstheader.py @@ -1,30 +1,90 @@ -# # check that the first header included in C files is either # zebra.h or config.h # +# Copyright (C) 2020 David Lamparter for NetDEF, Inc. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; see the file COPYING; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import sys, os, re, subprocess +import sys +import os +import re +import subprocess +import argparse + +argp = argparse.ArgumentParser(description="include fixer") +argp.add_argument("--autofix", action="store_const", const=True) +argp.add_argument("--warn-empty", action="store_const", const=True) +argp.add_argument("--pipe", action="store_const", const=True) include_re = re.compile('^#\s*include\s+["<]([^ ">]+)[">]', re.M) -errors = 0 +ignore = [ + lambda fn: fn.startswith("tools/"), + lambda fn: fn + in [ + "lib/elf_py.c", + ], +] + + +def run(args): + out = [] + + files = subprocess.check_output(["git", "ls-files"]).decode("ASCII") + for fn in files.splitlines(): + if not fn.endswith(".c"): + continue + if max([i(fn) for i in ignore]): + continue + + with open(fn, "r") as fd: + data = fd.read() -files = subprocess.check_output(["git", "ls-files"]).decode("ASCII") -for fn in files.splitlines(): - if not fn.endswith(".c"): - continue - if fn.startswith("tools/"): - continue - with open(fn, "r") as fd: - data = fd.read() m = include_re.search(data) if m is None: - # sys.stderr.write('no #include in %s?\n' % (fn)) + if args.warn_empty: + sys.stderr.write("no #include in %s?\n" % (fn)) continue if m.group(1) in ["config.h", "zebra.h", "lib/zebra.h"]: continue - sys.stderr.write("%s: %s\n" % (fn, m.group(0))) - errors += 1 -if errors: - sys.exit(1) + if args.autofix: + sys.stderr.write("%s: %s - fixing\n" % (fn, m.group(0))) + if fn.startswith("pceplib/"): + insert = '#ifdef HAVE_CONFIG_H\n#include "config.h"\n#endif\n\n' + else: + insert = "#include <zebra.h>\n\n" + + pos = m.span()[0] + + data = data[:pos] + insert + data[pos:] + with open(fn + ".new", "w") as fd: + fd.write(data) + os.rename(fn + ".new", fn) + else: + sys.stderr.write("%s: %s\n" % (fn, m.group(0))) + out.append(fn) + + if len(out): + if args.pipe: + # for "vim `firstheader.py`" + print("\n".join(out)) + return 1 + return 0 + + +if __name__ == "__main__": + args = argp.parse_args() + sys.exit(run(args)) diff --git a/qpb/subdir.am b/qpb/subdir.am index 4f826355d9..704efc5930 100644 --- a/qpb/subdir.am +++ b/qpb/subdir.am @@ -44,6 +44,7 @@ am__v_PROTOC_C_1 = .proto.pb-c.c: $(AM_V_PROTOC_C)$(PROTOC_C) -I$(top_srcdir) --c_out=$(top_builddir) $^ + $(AM_V_GEN)$(SED) -e '1i#include "config.h"' -i $@ .pb-c.c.pb-c.h: @/bin/true diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 002336616c..8306aca9ee 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -485,7 +485,7 @@ DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd, (0-100000)$inlabel\ [nexthop-group NHGNAME$nhgname] \ [prefix A.B.C.D/M$pfx\ - " FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]", + " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]", "Sharp Routing Protocol\n" "Remove data\n" "Remove an LSP\n" @@ -494,7 +494,7 @@ DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd, "The nexthop-group name\n" "Specify a v4 prefix\n" "The v4 prefix to label\n" - FRR_IP_REDIST_HELP_STR_SHARPD + FRR_IP_REDIST_HELP_STR_ZEBRA "Routing instance\n" "Instance to use\n") { diff --git a/staticd/static_nb.c b/staticd/static_nb.c index a2a14751cf..aa9076aa88 100644 --- a/staticd/static_nb.c +++ b/staticd/static_nb.c @@ -16,6 +16,8 @@ * with this program; see the file COPYING; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "northbound.h" #include "libfrr.h" #include "static_nb.h" diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c index db154992f9..e78f5172a3 100644 --- a/staticd/static_nb_config.c +++ b/staticd/static_nb_config.c @@ -16,6 +16,8 @@ * with this program; see the file COPYING; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "northbound.h" #include "libfrr.h" #include "log.h" diff --git a/tests/.gitignore b/tests/.gitignore index ca20b0ecac..0c938beab6 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -21,6 +21,7 @@ /lib/cli/test_commands_defun.c /lib/northbound/test_oper_data /lib/cxxcompat +/lib/test_assert /lib/test_atomlist /lib/test_buffer /lib/test_checksum @@ -52,4 +53,4 @@ /lib/test_zmq /ospf6d/test_lsdb /ospf6d/test_lsdb_clippy.c -/zebra/test_lm_plugin
\ No newline at end of file +/zebra/test_lm_plugin diff --git a/tests/isisd/test_isis_spf.c b/tests/isisd/test_isis_spf.c index e06944a037..8fe1ad0b8a 100644 --- a/tests/isisd/test_isis_spf.c +++ b/tests/isisd/test_isis_spf.c @@ -556,7 +556,6 @@ int main(int argc, char **argv) /* IS-IS inits. */ yang_module_load("frr-isisd"); isis = isis_new(VRF_DEFAULT_NAME); - listnode_add(im->isis, isis); SET_FLAG(im->options, F_ISIS_UNIT_TEST); debug_spf_events |= DEBUG_SPF_EVENTS; debug_lfa |= DEBUG_LFA; diff --git a/tests/lib/cxxcompat.c b/tests/lib/cxxcompat.c index fde0d6af52..2589fca614 100644 --- a/tests/lib/cxxcompat.c +++ b/tests/lib/cxxcompat.c @@ -104,7 +104,6 @@ #include "lib/yang.h" #include "lib/yang_translator.h" #include "lib/yang_wrappers.h" -#include "lib/zassert.h" #include "lib/zclient.h" PREDECL_RBTREE_UNIQ(footree); diff --git a/tests/lib/test_assert.c b/tests/lib/test_assert.c new file mode 100644 index 0000000000..8f1f4f2bad --- /dev/null +++ b/tests/lib/test_assert.c @@ -0,0 +1,64 @@ +/* + * Quick test for assert() + * Copyright (C) 2021 David Lamparter for NetDEF, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* make sure this works with assert.h & nothing else. also check the include + * shadowing, we don't want to pick up system assert.h + */ +#include <assert.h> + +__attribute__((noinline)) +void func_for_bt(int number) +{ + assert(number > 2); + assertf(number > 3, "(A) the number was %d", number); +} + +#include <zebra.h> +#include "lib/zlog.h" +#include "lib/thread.h" +#include "lib/sigevent.h" + +int main(int argc, char **argv) +{ + int number = 10; + struct thread_master *master; + + zlog_aux_init("NONE: ", LOG_DEBUG); + + if (argc > 1) + number = atoi(argv[1]); + + assert(number > 0); + assertf(number > 1, "(B) the number was %d", number); + + /* set up SIGABRT handler */ + master = thread_master_create("test"); + signal_init(master, 0, NULL); + + func_for_bt(number); + assert(number > 4); + assertf(number > 5, "(C) the number was %d", number); + + assertf(number > 10, "(D) the number was %d", number); + return 0; +} diff --git a/tests/lib/test_assert.py b/tests/lib/test_assert.py new file mode 100644 index 0000000000..67c88e6220 --- /dev/null +++ b/tests/lib/test_assert.py @@ -0,0 +1,56 @@ +import frrtest +import os +import re +import subprocess +import inspect + +basedir = os.path.dirname(__file__) +program = os.path.join(basedir, "test_assert") + + +def check(number, rex=None): + proc = subprocess.Popen( + [frrtest.binpath(program), str(number)], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + out, err = proc.communicate() + exitcode = proc.wait() + + if rex is None: + assert exitcode == 0 + else: + assert exitcode != 0 + + text = out.decode("US-ASCII") + err.decode("US-ASCII") + rex = re.compile(rex, re.M | re.S) + m = rex.search(text) + assert m is not None, "non-matching output: %s" % text + + +def test_assert_0(): + check(0, r"test_assert\.c:\d+.*number > 0") + + +def test_assert_1(): + check(1, r"test_assert\.c:\d+.*number > 1.*\(B\) the number was 1") + + +def test_assert_2(): + check(2, r"test_assert\.c:\d+.*number > 2") + + +def test_assert_3(): + check(3, r"test_assert\.c:\d+.*number > 3.*\(A\) the number was 3") + + +def test_assert_4(): + check(4, r"test_assert\.c:\d+.*number > 4") + + +def test_assert_10(): + check(10, r"test_assert\.c:\d+.*number > 10.*\(D\) the number was 10") + + +def test_assert_11(): + check(11) diff --git a/tests/lib/test_ringbuf.c b/tests/lib/test_ringbuf.c index 7ba5a29b62..4ac62940b8 100644 --- a/tests/lib/test_ringbuf.c +++ b/tests/lib/test_ringbuf.c @@ -93,7 +93,7 @@ int main(int argc, char **argv) assert(ringbuf_get(soil, &compost, BUFSIZ) == BUFSIZ); validate_state(soil, BUFSIZ, 0); - assert(soil->empty = true); + assert(soil->empty == true); assert(soil->start == soil->end); assert(soil->start == 15); diff --git a/tests/lib/test_seqlock.c b/tests/lib/test_seqlock.c index 639c2bdc2b..768307d56d 100644 --- a/tests/lib/test_seqlock.c +++ b/tests/lib/test_seqlock.c @@ -32,6 +32,7 @@ #include "monotime.h" #include "seqlock.h" +#include "printfrr.h" static struct seqlock sqlo; static pthread_t thr1; @@ -43,7 +44,7 @@ static void writestr(const char *str) char buf[32]; int64_t usec = monotime_since(&start, NULL); - snprintf(buf, sizeof(buf), "[%02"PRId64"] ", usec / 100000); + snprintfrr(buf, sizeof(buf), "[%02" PRId64 "] ", usec / 100000); iov[0].iov_base = buf; iov[0].iov_len = strlen(buf); diff --git a/tests/lib/test_typelist.h b/tests/lib/test_typelist.h index 32331c14a0..379a2396b4 100644 --- a/tests/lib/test_typelist.h +++ b/tests/lib/test_typelist.h @@ -17,6 +17,7 @@ /* C++ called, they want their templates back */ #define item concat(item_, TYPE) #define itm concat(itm_, TYPE) +#define itmswap concat(itmswap_, TYPE) #define head concat(head_, TYPE) #define list concat(TYPE, ) #define list_head concat(TYPE, _head) @@ -40,8 +41,9 @@ #define list_find_gteq concat(TYPE, _find_gteq) #define list_del concat(TYPE, _del) #define list_pop concat(TYPE, _pop) +#define list_swap_all concat(TYPE, _swap_all) -#define ts_hash concat(ts_hash_, TYPE) +#define ts_hash_head concat(ts_hash_head_, TYPE) #ifndef REALTYPE #define REALTYPE TYPE @@ -89,10 +91,12 @@ DECLARE(REALTYPE, list, struct item, itm); #endif #define NITEM 10000 -struct item itm[NITEM]; +#define NITEM_SWAP 100 /* other container for swap */ +struct item itm[NITEM], itmswap[NITEM_SWAP]; static struct list_head head = concat(INIT_, REALTYPE)(head); -static void ts_hash(const char *text, const char *expect) +static void ts_hash_head(struct list_head *h, const char *text, + const char *expect) { int64_t us = monotime_since(&ref, NULL); SHA256_CTX ctx; @@ -102,13 +106,13 @@ static void ts_hash(const char *text, const char *expect) char hashtext[65]; uint32_t swap_count, count; - count = list_count(&head); + count = list_count(h); swap_count = htonl(count); SHA256_Init(&ctx); SHA256_Update(&ctx, &swap_count, sizeof(swap_count)); - frr_each (list, &head, item) { + frr_each (list, h, item) { struct { uint32_t val_upper, val_lower, index; } hashitem = { @@ -135,15 +139,20 @@ static void ts_hash(const char *text, const char *expect) } /* hashes will have different item ordering */ #if IS_HASH(REALTYPE) || IS_HEAP(REALTYPE) -#define ts_hashx(pos, csum) ts_hash(pos, NULL) +#define ts_hash(pos, csum) ts_hash_head(&head, pos, NULL) +#define ts_hashx(pos, csum) ts_hash_head(&head, pos, NULL) +#define ts_hash_headx(head, pos, csum) ts_hash_head(head, pos, NULL) #else -#define ts_hashx(pos, csum) ts_hash(pos, csum) +#define ts_hash(pos, csum) ts_hash_head(&head, pos, csum) +#define ts_hashx(pos, csum) ts_hash_head(&head, pos, csum) +#define ts_hash_headx(head, pos, csum) ts_hash_head(head, pos, csum) #endif static void concat(test_, TYPE)(void) { size_t i, j, k, l; struct prng *prng; + struct prng *prng_swap __attribute__((unused)); struct item *item, *prev __attribute__((unused)); struct item dummy __attribute__((unused)); @@ -151,6 +160,10 @@ static void concat(test_, TYPE)(void) for (i = 0; i < NITEM; i++) itm[i].val = i; + memset(itmswap, 0, sizeof(itmswap)); + for (i = 0; i < NITEM_SWAP; i++) + itmswap[i].val = i; + printfrr("%s start\n", str(TYPE)); ts_start(); @@ -178,6 +191,56 @@ static void concat(test_, TYPE)(void) assert(list_first(&head) != NULL); ts_hashx("fill", "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838"); +#if !IS_ATOMIC(REALTYPE) + struct list_head other; + + list_init(&other); + list_swap_all(&head, &other); + + assert(list_count(&head) == 0); + assert(!list_first(&head)); + assert(list_count(&other) == k); + assert(list_first(&other) != NULL); + ts_hash_headx( + &other, "swap1", + "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838"); + + prng_swap = prng_new(0x1234dead); + l = 0; + for (i = 0; i < NITEM_SWAP; i++) { + j = prng_rand(prng_swap) % NITEM_SWAP; + if (itmswap[j].scratchpad == 0) { + list_add(&head, &itmswap[j]); + itmswap[j].scratchpad = 1; + l++; + } +#if !IS_HEAP(REALTYPE) + else { + struct item *rv = list_add(&head, &itmswap[j]); + assert(rv == &itmswap[j]); + } +#endif + } + assert(list_count(&head) == l); + assert(list_first(&head) != NULL); + ts_hash_headx( + &head, "swap-fill", + "26df437174051cf305d1bbb62d779ee450ca764167a1e7a94be1aece420008e6"); + + list_swap_all(&head, &other); + + assert(list_count(&other) == l); + assert(list_first(&other)); + ts_hash_headx( + &other, "swap2a", + "26df437174051cf305d1bbb62d779ee450ca764167a1e7a94be1aece420008e6"); + assert(list_count(&head) == k); + assert(list_first(&head) != NULL); + ts_hash_headx( + &head, "swap2b", + "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838"); +#endif /* !IS_ATOMIC */ + k = 0; #if IS_ATOMIC(REALTYPE) @@ -344,6 +407,50 @@ static void concat(test_, TYPE)(void) assert(list_first(&head) != NULL); ts_hash("fill / add_tail", "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19"); +#if !IS_ATOMIC(REALTYPE) + struct list_head other; + + list_init(&other); + list_swap_all(&head, &other); + + assert(list_count(&head) == 0); + assert(!list_first(&head)); + assert(list_count(&other) == k); + assert(list_first(&other) != NULL); + ts_hash_head( + &other, "swap1", + "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19"); + + prng_swap = prng_new(0x1234dead); + l = 0; + for (i = 0; i < NITEM_SWAP; i++) { + j = prng_rand(prng_swap) % NITEM_SWAP; + if (itmswap[j].scratchpad == 0) { + list_add_tail(&head, &itmswap[j]); + itmswap[j].scratchpad = 1; + l++; + } + } + assert(list_count(&head) == l); + assert(list_first(&head) != NULL); + ts_hash_head( + &head, "swap-fill", + "833e6ae437e322dfbd36eda8cfc33a61109be735b43f15d256c05e52d1b01909"); + + list_swap_all(&head, &other); + + assert(list_count(&other) == l); + assert(list_first(&other)); + ts_hash_head( + &other, "swap2a", + "833e6ae437e322dfbd36eda8cfc33a61109be735b43f15d256c05e52d1b01909"); + assert(list_count(&head) == k); + assert(list_first(&head) != NULL); + ts_hash_head( + &head, "swap2b", + "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19"); +#endif + for (i = 0; i < NITEM / 2; i++) { j = prng_rand(prng) % NITEM; if (itm[j].scratchpad == 1) { @@ -546,10 +653,14 @@ static void concat(test_, TYPE)(void) printfrr("%s end\n", str(TYPE)); } +#undef ts_hash #undef ts_hashx +#undef ts_hash_head +#undef ts_hash_headx #undef item #undef itm +#undef itmswap #undef head #undef list #undef list_head @@ -571,6 +682,7 @@ static void concat(test_, TYPE)(void) #undef list_find_gteq #undef list_del #undef list_pop +#undef list_swap_all #undef REALTYPE #undef TYPE diff --git a/tests/subdir.am b/tests/subdir.am index ec0a154a2d..139f4878c8 100644 --- a/tests/subdir.am +++ b/tests/subdir.am @@ -66,6 +66,7 @@ clippy_scan += \ check_PROGRAMS = \ tests/lib/cxxcompat \ + tests/lib/test_assert \ tests/lib/test_atomlist \ tests/lib/test_buffer \ tests/lib/test_checksum \ @@ -249,6 +250,10 @@ tests_lib_northbound_test_oper_data_CPPFLAGS = $(TESTS_CPPFLAGS) tests_lib_northbound_test_oper_data_LDADD = $(ALL_TESTS_LDADD) tests_lib_northbound_test_oper_data_SOURCES = tests/lib/northbound/test_oper_data.c nodist_tests_lib_northbound_test_oper_data_SOURCES = yang/frr-test-module.yang.c +tests_lib_test_assert_CFLAGS = $(TESTS_CFLAGS) +tests_lib_test_assert_CPPFLAGS = $(TESTS_CPPFLAGS) +tests_lib_test_assert_LDADD = $(ALL_TESTS_LDADD) +tests_lib_test_assert_SOURCES = tests/lib/test_assert.c tests_lib_test_atomlist_CFLAGS = $(TESTS_CFLAGS) tests_lib_test_atomlist_CPPFLAGS = $(TESTS_CPPFLAGS) tests_lib_test_atomlist_LDADD = $(ALL_TESTS_LDADD) @@ -289,7 +294,7 @@ tests_lib_test_nexthop_iter_CPPFLAGS = $(TESTS_CPPFLAGS) tests_lib_test_nexthop_iter_LDADD = $(ALL_TESTS_LDADD) tests_lib_test_nexthop_iter_SOURCES = tests/lib/test_nexthop_iter.c tests/helpers/c/prng.c tests_lib_test_ntop_CFLAGS = $(TESTS_CFLAGS) -tests_lib_test_ntop_CPPFLAGS = $(TESTS_CPPFLAGS) +tests_lib_test_ntop_CPPFLAGS = $(CPPFLAGS_BASE) # no assert override tests_lib_test_ntop_LDADD = # none tests_lib_test_ntop_SOURCES = tests/lib/test_ntop.c tests/helpers/c/prng.c tests_lib_test_prefix2str_CFLAGS = $(TESTS_CFLAGS) @@ -404,6 +409,7 @@ EXTRA_DIST += \ tests/lib/northbound/test_oper_data.in \ tests/lib/northbound/test_oper_data.py \ tests/lib/northbound/test_oper_data.refout \ + tests/lib/test_assert.py \ tests/lib/test_atomlist.py \ tests/lib/test_nexthop_iter.py \ tests/lib/test_ntop.py \ diff --git a/tests/topotests/Dockerfile b/tests/topotests/Dockerfile index c9110d2db9..1503e67d31 100644 --- a/tests/topotests/Dockerfile +++ b/tests/topotests/Dockerfile @@ -44,6 +44,7 @@ RUN export DEBIAN_FRONTEND=noninteractive \ xterm \ && pip install \ exabgp==3.4.17 \ + "scapy>=2.4.2" \ ipaddr \ pytest \ && rm -rf /var/lib/apt/lists/* diff --git a/tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref b/tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref index 1e8f67f3f9..ff85679256 100644 --- a/tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref +++ b/tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref @@ -4,6 +4,7 @@ r1-eth0 is up MTU mismatch detection: enabled Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10 Transmit Delay is 1 sec, State DR, Priority 1 + Designated Router (ID) 192.168.0.1 Interface Address 192.168.0.1/24 No backup designated router on this network Multicast group memberships: OSPFAllRouters OSPFDesignatedRouters Timer intervals configured, Hello 10s, Dead 40s, Wait 40s, Retransmit 5 @@ -15,6 +16,7 @@ r1-eth3 is up MTU mismatch detection: enabled Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10 Transmit Delay is 1 sec, State DR, Priority 1 + Designated Router (ID) 192.168.0.1 Interface Address 192.168.3.1/26 No backup designated router on this network Multicast group memberships: OSPFAllRouters OSPFDesignatedRouters Timer intervals configured, Hello 10s, Dead 40s, Wait 40s, Retransmit 5 diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py b/tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py index c1dbf0ebec..f9aa94fd14 100644 --- a/tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py +++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py @@ -34,6 +34,8 @@ import json import pytest import functools +pytestmark = [pytest.mark.bgpd] + CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) diff --git a/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py index 19c4c5f87d..3b99065fe0 100644 --- a/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py +++ b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py @@ -40,6 +40,8 @@ import time import pytest import functools +pytestmark = [pytest.mark.bgpd] + CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py index cf64956bfd..de5c584e91 100755 --- a/tests/topotests/conftest.py +++ b/tests/topotests/conftest.py @@ -62,6 +62,7 @@ def pytest_addoption(parser): parser.addoption( "--topology-only", action="store_true", + default=False, help="Only set up this topology, don't run tests", ) diff --git a/tests/topotests/isis-snmp/test_isis_snmp.py b/tests/topotests/isis-snmp/test_isis_snmp.py index 07f3335e23..04e043847d 100755 --- a/tests/topotests/isis-snmp/test_isis_snmp.py +++ b/tests/topotests/isis-snmp/test_isis_snmp.py @@ -243,15 +243,15 @@ def test_r1_scalar_snmp(): circtable_test = { - "isisCircAdminState": ["on(1)", "on(1)", "on(1)"], - "isisCircExistState": ["active(1)", "active(1)", "active(1)"], - "isisCircType": ["broadcast(1)", "ptToPt(2)", "staticIn(3)"], - "isisCircExtDomain": ["false(2)", "false(2)", "false(2)"], - "isisCircLevelType": ["level1(1)", "level1(1)", "level1and2(3)"], - "isisCircPassiveCircuit": ["false(2)", "false(2)", "true(1)"], - "isisCircMeshGroupEnabled": ["inactive(1)", "inactive(1)", "inactive(1)"], - "isisCircSmallHellos": ["false(2)", "false(2)", "false(2)"], - "isisCirc3WayEnabled": ["false(2)", "false(2)", "false(2)"], + "isisCircAdminState": ["on(1)", "on(1)"], + "isisCircExistState": ["active(1)", "active(1)"], + "isisCircType": ["broadcast(1)", "ptToPt(2)"], + "isisCircExtDomain": ["false(2)", "false(2)"], + "isisCircLevelType": ["level1(1)", "level1(1)"], + "isisCircPassiveCircuit": ["false(2)", "false(2)"], + "isisCircMeshGroupEnabled": ["inactive(1)", "inactive(1)"], + "isisCircSmallHellos": ["false(2)", "false(2)"], + "isisCirc3WayEnabled": ["false(2)", "false(2)"], } @@ -266,7 +266,6 @@ def test_r1_isisCircTable(): oids = [] oids.append(generate_oid(1, 1, 0)) oids.append(generate_oid(1, 2, 0)) - oids.append(generate_oid(1, 3, 0)) # check items for item in circtable_test.keys(): @@ -277,21 +276,17 @@ def test_r1_isisCircTable(): circleveltable_test = { - "isisCircLevelMetric": ["10", "10", "10", "10"], - "isisCircLevelWideMetric": ["10", "10", "0", "0"], - "isisCircLevelISPriority": ["64", "64", "64", "64"], - "isisCircLevelHelloMultiplier": ["10", "10", "10", "10"], + "isisCircLevelMetric": ["10", "10"], + "isisCircLevelWideMetric": ["10", "10"], + "isisCircLevelISPriority": ["64", "64"], + "isisCircLevelHelloMultiplier": ["10", "10"], "isisCircLevelHelloTimer": [ "3000 milliseconds", "3000 milliseconds", - "3000 milliseconds", - "3000 milliseconds", ], "isisCircLevelMinLSPRetransInt": [ "1 seconds", "1 seconds", - "0 seconds", - "0 seconds", ], } @@ -307,8 +302,6 @@ def test_r1_isislevelCircTable(): oids = [] oids.append(generate_oid(2, 1, "area")) oids.append(generate_oid(2, 2, "area")) - oids.append(generate_oid(2, 3, "area")) - oids.append(generate_oid(2, 3, "domain")) # check items for item in circleveltable_test.keys(): diff --git a/tests/topotests/isis-sr-topo1/test_isis_sr_topo1.py b/tests/topotests/isis-sr-topo1/test_isis_sr_topo1.py index 148a89474e..c22bd65d2d 100644 --- a/tests/topotests/isis-sr-topo1/test_isis_sr_topo1.py +++ b/tests/topotests/isis-sr-topo1/test_isis_sr_topo1.py @@ -1002,6 +1002,12 @@ def test_isis_adjacencies_step12(): tgen.net["rt4"].cmd( 'vtysh -c "conf t" -c "interface eth-rt5" -c "ipv6 router isis 1"' ) + tgen.net["rt4"].cmd( + 'vtysh -c "conf t" -c "interface eth-rt5" -c "isis network point-to-point"' + ) + tgen.net["rt4"].cmd( + 'vtysh -c "conf t" -c "interface eth-rt5" -c "isis hello-multiplier 3"' + ) tgen.net["rt6"].cmd( 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing global-block 16000 23999"' ) diff --git a/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync.ref b/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync.ref index 9cb70a4758..7180f84d1a 100644 --- a/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync.ref +++ b/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync.ref @@ -1,7 +1,7 @@ { "r3-eth1":{ "ldpIgpSyncEnabled":false, - "holdDownTimeInSec":50, + "holdDownTimeInSec":0, "ldpIgpSyncState":"Sync not required" }, "r3-eth2":{ diff --git a/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync_r1_eth1_shutdown.ref b/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync_r1_eth1_shutdown.ref index 9cb70a4758..7180f84d1a 100644 --- a/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync_r1_eth1_shutdown.ref +++ b/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync_r1_eth1_shutdown.ref @@ -1,7 +1,7 @@ { "r3-eth1":{ "ldpIgpSyncEnabled":false, - "holdDownTimeInSec":50, + "holdDownTimeInSec":0, "ldpIgpSyncState":"Sync not required" }, "r3-eth2":{ diff --git a/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync_r2_eth1_shutdown.ref b/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync_r2_eth1_shutdown.ref index 9cb70a4758..7180f84d1a 100644 --- a/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync_r2_eth1_shutdown.ref +++ b/tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync_r2_eth1_shutdown.ref @@ -1,7 +1,7 @@ { "r3-eth1":{ "ldpIgpSyncEnabled":false, - "holdDownTimeInSec":50, + "holdDownTimeInSec":0, "ldpIgpSyncState":"Sync not required" }, "r3-eth2":{ diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py index d07b58a774..61a5705a5d 100644 --- a/tests/topotests/lib/pim.py +++ b/tests/topotests/lib/pim.py @@ -384,50 +384,6 @@ def _enable_disable_pim(tgen, topo, input_dict, router, build=False): return result -def add_rp_interfaces_and_pim_config(tgen, topo, interface, rp, rp_mapping): - """ - Add physical interfaces tp RP for all the RPs - - Parameters - ---------- - * `tgen` : Topogen object - * `topo` : json file data - * `interface` : RP interface - * `rp` : rp for given topology - * `rp_mapping` : dictionary of all groups and RPs - - Returns - ------- - True or False - """ - result = False - logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) - - try: - config_data = [] - - for group, rp_list in rp_mapping.items(): - for _rp in rp_list: - config_data.append("interface {}".format(interface)) - config_data.append("ip address {}".format(_rp)) - config_data.append("ip pim") - - result = create_common_configuration( - tgen, rp, config_data, "interface_config" - ) - if result is not True: - return False - - except InvalidCLIError: - # Traceback - errormsg = traceback.format_exc() - logger.error(errormsg) - return errormsg - - logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) - return result - - def find_rp_details(tgen, topo): """ Find who is RP in topology and returns list of RPs @@ -1444,14 +1400,10 @@ def verify_pim_state( errormsg = ( "[DUT %s]: Verifying pim state for group" " %s, [FAILED]!! Expected: " - "(iif: %s, oil: %s, installed: %s) ", + "(iif: %s, oil: %s, installed: %s) " + % (dut, grp_addr, iif, oil, "1"), "Found: (iif: %s, oil: %s, installed: %s)" % ( - dut, - grp_addr, - iif, - oil, - "1", data["inboundInterface"], data["outboundInterface"], data["installed"], @@ -2080,7 +2032,7 @@ def add_rp_interfaces_and_pim_config(tgen, topo, interface, rp, rp_mapping): logger.error(errormsg) return errormsg - logger.debug("Exiting lib API: add_rp_interfaces_and_pim_config()") + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) return result @@ -2425,8 +2377,7 @@ def verify_ip_pim_upstream_rpf(tgen, topo, dut, interface, group_addresses, rp=N if rp is None: rp_details = find_rp_details(tgen, topo) else: - rp_details = {dut: ip} - rp_details[dut] = rp + rp_details = {dut: rp} if dut in rp_details: pim_nh_intf_ip = topo["routers"][dut]["links"]["lo"]["ipv4"].split( @@ -2732,7 +2683,7 @@ def verify_igmp_config(tgen, input_dict, stats_return=False): if statistics and report: show_ip_igmp_intf_json = run_frr_cmd( - rnode, "{} json".format(cmd, interface), isjson=True + rnode, "{} json".format(cmd), isjson=True ) intf_detail_json = show_ip_igmp_intf_json["global"] else: @@ -2808,7 +2759,6 @@ def verify_igmp_config(tgen, input_dict, stats_return=False): dut, interface, value, - intf_detail_json["reportV2"], ) ) return errormsg diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 2a46115850..2a5bd17361 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -351,8 +351,8 @@ def run_and_expect(func, what, count=20, wait=3): func_name = func.__name__ logger.info( - "'{}' polling started (interval {} secs, maximum wait {} secs)".format( - func_name, wait, int(wait * count) + "'{}' polling started (interval {} secs, maximum {} tries)".format( + func_name, wait, count ) ) diff --git a/tools/subdir.am b/tools/subdir.am index e159d82d4c..6a03a23baa 100644 --- a/tools/subdir.am +++ b/tools/subdir.am @@ -34,9 +34,11 @@ tools_gen_yang_deviations_SOURCES = tools/gen_yang_deviations.c tools_gen_yang_deviations_LDADD = lib/libfrr.la $(LIBYANG_LIBS) tools_ssd_SOURCES = tools/start-stop-daemon.c +tools_ssd_CPPFLAGS = # don't bother autoconf'ing these for a simple optional tool llvm_version = $(shell echo __clang_major__ | $(CC) -xc -P -E -) +tools_frr_llvm_cg_CPPFLAGS = $(CPPFLAGS_BASE) tools_frr_llvm_cg_CFLAGS = $(AM_CFLAGS) `llvm-config-$(llvm_version) --cflags` tools_frr_llvm_cg_LDFLAGS = `llvm-config-$(llvm_version) --ldflags --libs` tools_frr_llvm_cg_SOURCES = \ diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index 7c820c9611..4653e6f009 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -493,6 +493,13 @@ module frr-isisd { description "Node protection is provided by the alternate."; } + leaf link-fallback { + type boolean; + must ". = 'false' or ../enable = 'true'"; + default false; + description + "Fallback to link protection."; + } } } @@ -506,13 +513,6 @@ module frr-isisd { "Area-tag associated to this circuit."; } - leaf vrf { - type frr-vrf:vrf-ref; - default "default"; - description - "VRF NAME."; - } - leaf ipv4-routing { type boolean; default "false"; @@ -791,10 +791,10 @@ module frr-isisd { leaf holddown { type uint16 { range "0..10000"; - } - units "seconds"; - description - "Time to wait for LDP-Sync to occur before restoring interface metric."; + } + units "seconds"; + description + "Time to wait for LDP-Sync to occur before restoring interface metric."; } } diff --git a/zebra/connected.c b/zebra/connected.c index 6f405ca1bb..1e03f8b639 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -208,6 +208,9 @@ void connected_up(struct interface *ifp, struct connected *ifc) struct zebra_vrf *zvrf; uint32_t metric; uint32_t flags = 0; + uint32_t count = 0; + struct listnode *cnode; + struct connected *c; zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); if (!zvrf) { @@ -263,6 +266,27 @@ void connected_up(struct interface *ifp, struct connected *ifc) if (zrouter.asic_offloaded) flags |= ZEBRA_FLAG_OFFLOADED; + /* + * It's possible to add the same network and mask + * to an interface over and over. This would + * result in an equivalent number of connected + * routes. Just add one connected route in + * for all the addresses on an interface that + * resolve to the same network and mask + */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + struct prefix cp; + + PREFIX_COPY(&cp, CONNECTED_PREFIX(c)); + apply_mask(&cp); + + if (prefix_same(&cp, &p)) + count++; + + if (count >= 2) + return; + } + rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0); @@ -358,6 +382,9 @@ void connected_down(struct interface *ifp, struct connected *ifc) .vrf_id = ifp->vrf_id, }; struct zebra_vrf *zvrf; + uint32_t count = 0; + struct listnode *cnode; + struct connected *c; zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); if (!zvrf) { @@ -397,6 +424,26 @@ void connected_down(struct interface *ifp, struct connected *ifc) } /* + * It's possible to have X number of addresses + * on a interface that all resolve to the same + * network and mask. Find them and just + * allow the deletion when are removing the last + * one. + */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + struct prefix cp; + + PREFIX_COPY(&cp, CONNECTED_PREFIX(c)); + apply_mask(&cp); + + if (prefix_same(&p, &cp)) + count++; + + if (count >= 2) + return; + } + + /* * Same logic as for connected_up(): push the changes into the * head. */ diff --git a/zebra/debug.c b/zebra/debug.c index 05eed0d26e..a8ddf6ba64 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -241,12 +241,6 @@ DEFUN (debug_zebra_kernel, { SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL); - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) - UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); - - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) - UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); - return CMD_SUCCESS; } @@ -262,21 +256,11 @@ DEFUN (debug_zebra_kernel_msgdump, { int idx = 0; - if (argv_find(argv, argc, "recv", &idx)) { + if (argv_find(argv, argc, "recv", &idx)) SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); - - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) - UNSET_FLAG(zebra_debug_kernel, - ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); - - } else if (argv_find(argv, argc, "send", &idx)) { + else if (argv_find(argv, argc, "send", &idx)) SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); - - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) - UNSET_FLAG(zebra_debug_kernel, - ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); - - } else { + else { SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); } @@ -476,7 +460,8 @@ DEFUN (no_debug_zebra_kernel, "Zebra configuration\n" "Debug option set for zebra between kernel interface\n") { - zebra_debug_kernel = 0; + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL); + return CMD_SUCCESS; } @@ -491,7 +476,17 @@ DEFUN (no_debug_zebra_kernel_msgdump, "Dump raw netlink messages received\n" "Dump raw netlink messages sent\n") { - zebra_debug_kernel = 0; + int idx = 0; + + if (argv_find(argv, argc, "recv", &idx)) + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); + else if (argv_find(argv, argc, "send", &idx)) + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); + else { + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); + } + return CMD_SUCCESS; } @@ -599,21 +594,21 @@ static int config_write_debug(struct vty *vty) } } + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND + && IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) { + vty_out(vty, "debug zebra kernel msgdump\n"); + write++; + } else if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) { + vty_out(vty, "debug zebra kernel msgdump recv\n"); + write++; + } else if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) { + vty_out(vty, "debug zebra kernel msgdump send\n"); + write++; + } + if (IS_ZEBRA_DEBUG_KERNEL) { - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND - && IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) { - vty_out(vty, "debug zebra kernel msgdump\n"); - write++; - } else if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) { - vty_out(vty, "debug zebra kernel msgdump recv\n"); - write++; - } else if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) { - vty_out(vty, "debug zebra kernel msgdump send\n"); - write++; - } else { - vty_out(vty, "debug zebra kernel\n"); - write++; - } + vty_out(vty, "debug zebra kernel\n"); + write++; } if (CHECK_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED)) { diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 6aaf9d94f3..e7d8b318e0 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -974,7 +974,7 @@ int interface_lookup_netlink(struct zebra_ns *zns) return ret; /* fixup linkages */ - zebra_if_update_all_links(); + zebra_if_update_all_links(zns); return 0; } @@ -1550,6 +1550,9 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) memcpy(old_hw_addr, ifp->hw_addr, INTERFACE_HWADDR_MAX); + /* Update link. */ + zebra_if_update_link(ifp, link_ifindex, ns_id); + netlink_interface_update_hw_addr(tb, ifp); if (if_is_no_ptm_operative(ifp)) { diff --git a/zebra/interface.c b/zebra/interface.c index 4b708496a1..e7357cb302 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1074,6 +1074,9 @@ void if_up(struct interface *ifp) if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK) zebra_evpn_mh_uplink_oper_update(zif); + + thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 0, + &zif->speed_update); } /* Interface goes down. We have to manage different behavior of based @@ -1148,18 +1151,16 @@ void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex, * during initial link dump kernel does not order lower devices before * upper devices so we need to fixup link dependencies at the end of dump */ -void zebra_if_update_all_links(void) +void zebra_if_update_all_links(struct zebra_ns *zns) { struct route_node *rn; struct interface *ifp; struct zebra_if *zif; - struct zebra_ns *ns; if (IS_ZEBRA_DEBUG_KERNEL) zlog_info("fixup link dependencies"); - ns = zebra_ns_lookup(NS_DEFAULT); - for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) { + for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { ifp = (struct interface *)rn->info; if (!ifp) continue; @@ -1177,8 +1178,8 @@ void zebra_if_update_all_links(void) /* update SVI linkages */ if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) { - zif->link = if_lookup_by_index_per_ns(ns, - zif->link_ifindex); + zif->link = if_lookup_by_index_per_ns( + zns, zif->link_ifindex); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("interface %s/%d's lower fixup to %s/%d", ifp->name, ifp->ifindex, diff --git a/zebra/interface.h b/zebra/interface.h index 67eb1176b9..24bc70cb9b 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -482,7 +482,7 @@ extern int ipv6_address_configured(struct interface *ifp); extern void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id); extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex, ns_id_t ns_id); -extern void zebra_if_update_all_links(void); +extern void zebra_if_update_all_links(struct zebra_ns *zns); extern void zebra_if_set_protodown(struct interface *ifp, bool down); extern int if_ip_address_install(struct interface *ifp, struct prefix *prefix, const char *label, struct prefix *pp); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 6f24ec4225..7cb426359d 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -91,8 +91,7 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id) continue; RNODE_FOREACH_RE (rn, newre) { - if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED) - && newre->distance != DISTANCE_INFINITY) + if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)) zsend_redistribute_route( ZEBRA_REDISTRIBUTE_ROUTE_ADD, client, &rn->p, NULL, newre); @@ -138,8 +137,6 @@ static void zebra_redistribute(struct zserv *client, int type, && (newre->type != type || newre->instance != instance))) continue; - if (newre->distance == DISTANCE_INFINITY) - continue; if (!zebra_check_addr(dst_p)) continue; @@ -265,13 +262,6 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p, new_re ? zebra_route_string(new_re->type) : "None"); } - /* Add DISTANCE_INFINITY check. */ - if (old_re && (old_re->distance == DISTANCE_INFINITY)) { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug(" Skipping due to Infinite Distance"); - return; - } - afi = family2afi(p->family); if (!afi) { flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF, diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 8ffb3870fa..1e06b3e0e9 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -1063,22 +1063,13 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable) ifindex_t ifindex; struct interface *ifp; struct zebra_if *zif; - int ra_interval_rxd; + uint32_t ra_interval; s = msg; /* Get interface index and RA interval. */ STREAM_GETL(s, ifindex); - STREAM_GETL(s, ra_interval_rxd); - - if (ra_interval_rxd < 0) { - zlog_warn( - "Requested RA interval %d is garbage; ignoring request", - ra_interval_rxd); - return; - } - - unsigned int ra_interval = ra_interval_rxd; + STREAM_GETL(s, ra_interval); if (IS_ZEBRA_DEBUG_EVENT) { struct vrf *vrf = zvrf->vrf; diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index cabba707a0..0038689e85 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -2484,8 +2484,8 @@ void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS) memset(&esi, 0, sizeof(esi_t)); s = msg; - stream_get(&esi, s, sizeof(esi_t)); - vtep_ip.s_addr = stream_get_ipv4(s); + STREAM_GET(&esi, s, sizeof(esi_t)); + STREAM_GET(&vtep_ip.s_addr, s, sizeof(vtep_ip.s_addr)); if (hdr->command == ZEBRA_REMOTE_ES_VTEP_ADD) { uint32_t zapi_flags; @@ -2493,16 +2493,19 @@ void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS) uint16_t df_pref; bool esr_rxed; - zapi_flags = stream_getl(s); + STREAM_GETL(s, zapi_flags); esr_rxed = (zapi_flags & ZAPI_ES_VTEP_FLAG_ESR_RXED) ? true : false; - df_alg = stream_getc(s); - df_pref = stream_getw(s); + STREAM_GETC(s, df_alg); + STREAM_GETW(s, df_pref); zebra_evpn_remote_es_add(&esi, vtep_ip, esr_rxed, df_alg, df_pref); } else { zebra_evpn_remote_es_del(&esi, vtep_ip); } + +stream_failure: + return; } void zebra_evpn_es_mac_deref_entry(zebra_mac_t *mac) diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index 3af805558d..ef0f2d8924 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -65,7 +65,7 @@ stream_failure: stream_put_in_addr(s, &mroute.sg.src); stream_put_in_addr(s, &mroute.sg.grp); stream_put(s, &mroute.lastused, sizeof(mroute.lastused)); - stream_putl(s, suc); + stream_putl(s, (uint32_t)suc); stream_putw_at(s, 0, stream_get_endp(s)); zserv_send_message(client, s); diff --git a/zebra/zebra_routemap_nb.c b/zebra/zebra_routemap_nb.c index c82c34dd53..9da4589501 100644 --- a/zebra/zebra_routemap_nb.c +++ b/zebra/zebra_routemap_nb.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include "northbound.h" #include "libfrr.h" #include "zebra_routemap_nb.h" diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 4cd3b60a0f..3ac7ee8f4f 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -3749,7 +3749,7 @@ zebra_vxlan_remote_macip_helper(bool add, struct stream *s, vni_t *vni, memset(ip, 0, sizeof(*ip)); STREAM_GETL(s, *vni); STREAM_GET(macaddr->octet, s, ETH_ALEN); - STREAM_GETL(s, *ipa_len); + STREAM_GETW(s, *ipa_len); if (*ipa_len) { if (*ipa_len == IPV4_MAX_BYTELEN) diff --git a/zebra/zserv.c b/zebra/zserv.c index f89b6fe478..0bf4d8ece2 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -50,7 +50,6 @@ #include "lib/thread.h" /* for thread (ptr only), THREAD_ARG, ... */ #include "lib/vrf.h" /* for vrf_info_lookup, VRF_DEFAULT */ #include "lib/vty.h" /* for vty_out, vty (ptr only) */ -#include "lib/zassert.h" /* for assert */ #include "lib/zclient.h" /* for zmsghdr, ZEBRA_HEADER_SIZE, ZEBRA... */ #include "lib/frr_pthread.h" /* for frr_pthread_new, frr_pthread_stop... */ #include "lib/frratomic.h" /* for atomic_load_explicit, atomic_stor... */ |
