diff options
205 files changed, 3796 insertions, 2805 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/babeld/babeld.c b/babeld/babeld.c index 72080bd7eb..4d4dd2e194 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -712,6 +712,92 @@ DEFUN (babel_set_smoothing_half_life, return CMD_SUCCESS; } +DEFUN (babel_distribute_list, + babel_distribute_list_cmd, + "distribute-list [prefix] WORD <in|out> [WORD]", + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_parser(prefix, true, argv[2 + prefix]->text, + argv[1 + prefix]->arg, ifname); +} + +DEFUN (babel_no_distribute_list, + babel_no_distribute_list_cmd, + "no distribute-list [prefix] WORD <in|out> [WORD]", + NO_STR + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_no_parser(vty, prefix, true, + argv[3 + prefix]->text, + argv[2 + prefix]->arg, ifname); +} + +DEFUN (babel_ipv6_distribute_list, + babel_ipv6_distribute_list_cmd, + "ipv6 distribute-list [prefix] WORD <in|out> [WORD]", + "IPv6\n" + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_parser(prefix, false, argv[3 + prefix]->text, + argv[2 + prefix]->arg, ifname); +} + +DEFUN (babel_no_ipv6_distribute_list, + babel_no_ipv6_distribute_list_cmd, + "no ipv6 distribute-list [prefix] WORD <in|out> [WORD]", + NO_STR + "IPv6\n" + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_no_parser(vty, prefix, false, + argv[4 + prefix]->text, + argv[3 + prefix]->arg, ifname); +} + void babeld_quagga_init(void) { @@ -728,6 +814,11 @@ babeld_quagga_init(void) install_element(BABEL_NODE, &babel_set_resend_delay_cmd); install_element(BABEL_NODE, &babel_set_smoothing_half_life_cmd); + install_element(BABEL_NODE, &babel_distribute_list_cmd); + install_element(BABEL_NODE, &babel_no_distribute_list_cmd); + install_element(BABEL_NODE, &babel_ipv6_distribute_list_cmd); + install_element(BABEL_NODE, &babel_no_ipv6_distribute_list_cmd); + babel_if_init(); /* Access list install. */ @@ -739,9 +830,6 @@ babeld_quagga_init(void) prefix_list_init (); prefix_list_add_hook (babel_distribute_update_all); prefix_list_delete_hook (babel_distribute_update_all); - - /* Distribute list install. */ - distribute_list_init(BABEL_NODE); } /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */ diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index e17cce3ff6..50122ad7da 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -1117,9 +1117,6 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name, } if (str) { - if (!lcommunity_list_valid(str, style)) - return COMMUNITY_LIST_ERR_MALFORMED_VAL; - if (style == LARGE_COMMUNITY_LIST_STANDARD) lcom = lcommunity_str2com(str); else 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 047b9742ee..fae3f1000f 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1670,8 +1670,9 @@ static inline bool bgp_evpn_route_add_l3_ecomm_ok(struct bgpevpn *vpn, { return p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE && (is_evpn_prefix_ipaddr_v4(p) - || !IN6_IS_ADDR_LINKLOCAL( - &p->prefix.macip_addr.ip.ipaddr_v6)) + || (is_evpn_prefix_ipaddr_v6(p) + && !IN6_IS_ADDR_LINKLOCAL( + &p->prefix.macip_addr.ip.ipaddr_v6))) && CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS) && bgpevpn_get_l3vni(vpn) && bgp_evpn_es_add_l3_ecomm_ok(esi); } diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c index 99d0344c9f..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 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..f3857162c3 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); @@ -443,6 +442,11 @@ static int bgp_accept(struct thread *thread) if (peer1) { /* Dynamic neighbor has been created, let it proceed */ peer1->fd = bgp_sock; + + /* Set the user configured MSS to TCP socket */ + if (CHECK_FLAG(peer1->flags, PEER_FLAG_TCP_MSS)) + sockopt_tcp_mss_set(bgp_sock, peer1->tcp_mss); + bgp_fsm_change_status(peer1, Active); BGP_TIMER_OFF( peer1->t_start); /* created in peer_create() */ @@ -714,6 +718,10 @@ int bgp_connect(struct peer *peer) set_nonblocking(peer->fd); + /* Set the user configured MSS to TCP socket */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_TCP_MSS)) + sockopt_tcp_mss_set(peer->fd, peer->tcp_mss); + bgp_socket_set_buffer_size(peer->fd); if (bgp_set_socket_ttl(peer, peer->fd) < 0) @@ -838,7 +846,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_vty.c b/bgpd/bgp_vty.c index 1e465d2620..0347f49cb8 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -22,6 +22,7 @@ #include "command.h" #include "lib/json.h" +#include "lib/sockopt.h" #include "lib_errors.h" #include "lib/zclient.h" #include "lib/printfrr.h" @@ -840,9 +841,6 @@ int bgp_vty_return(struct vty *vty, int ret) case BGP_ERR_GR_OPERATION_FAILED: str = "The Graceful Restart Operation failed due to an err."; break; - case BGP_GR_NO_OPERATION: - str = GR_NO_OPER; - break; } if (str) { vty_out(vty, "%% %s\n", str); @@ -12597,6 +12595,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, uint8_t *msg; json_object *json_neigh = NULL; time_t epoch_tbuf; + uint32_t sync_tcp_mss; bgp = p->bgp; @@ -12858,6 +12857,15 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, p->v_delayopen * 1000); } + /* Configured and Synced tcp-mss value for peer */ + if (CHECK_FLAG(p->flags, PEER_FLAG_TCP_MSS)) { + sync_tcp_mss = sockopt_tcp_mss_get(p->fd); + json_object_int_add(json_neigh, "bgpTcpMssConfigured", + p->tcp_mss); + json_object_int_add(json_neigh, "bgpTcpMssSynced", + sync_tcp_mss); + } + if (CHECK_FLAG(p->flags, PEER_FLAG_TIMER)) { json_object_int_add(json_neigh, "bgpTimerConfiguredHoldTimeMsecs", @@ -12941,6 +12949,13 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, vty_out(vty, " Configured DelayOpenTime is %d seconds\n", p->delayopen); + + /* Configured and synced tcp-mss value for peer */ + if (CHECK_FLAG(p->flags, PEER_FLAG_TCP_MSS)) { + sync_tcp_mss = sockopt_tcp_mss_get(p->fd); + vty_out(vty, " Configured tcp-mss is %d", p->tcp_mss); + vty_out(vty, ", synced tcp-mss is %d\n", sync_tcp_mss); + } } /* Capability. */ if (p->status == Established) { @@ -16360,6 +16375,55 @@ void cli_show_bgp_global_afi_safi_ip_unicast_redistribution_list( vty_out(vty, "\n"); } +/* Neighbor update tcp-mss. */ +static int peer_tcp_mss_vty(struct vty *vty, const char *peer_str, + const char *tcp_mss_str) +{ + struct peer *peer; + uint32_t tcp_mss_val = 0; + + peer = peer_and_group_lookup_vty(vty, peer_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + if (tcp_mss_str) { + tcp_mss_val = strtoul(tcp_mss_str, NULL, 10); + peer_tcp_mss_set(peer, tcp_mss_val); + } else { + peer_tcp_mss_unset(peer); + } + + return CMD_SUCCESS; +} + +DEFUN(neighbor_tcp_mss, neighbor_tcp_mss_cmd, + "neighbor <A.B.C.D|X:X::X:X|WORD> tcp-mss (1-65535)", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "TCP max segment size\n" + "TCP MSS value\n") +{ + int peer_index = 1; + int mss_index = 3; + + vty_out(vty, + " Warning: Reset BGP session for tcp-mss value to take effect\n"); + return peer_tcp_mss_vty(vty, argv[peer_index]->arg, + argv[mss_index]->arg); +} + +DEFUN(no_neighbor_tcp_mss, no_neighbor_tcp_mss_cmd, + "no neighbor <A.B.C.D|X:X::X:X|WORD> tcp-mss [(1-65535)]", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "TCP max segment size\n" + "TCP MSS value\n") +{ + int peer_index = 2; + + vty_out(vty, + " Warning: Reset BGP session for tcp-mss value to take effect\n"); + return peer_tcp_mss_vty(vty, argv[peer_index]->arg, NULL); +} + static void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) { @@ -16809,6 +16873,10 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, vty_out(vty, " neighbor %s interface %s\n", addr, peer->ifname); } + /* TCP max segment size */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_TCP_MSS)) + vty_out(vty, " neighbor %s tcp-mss %d\n", addr, peer->tcp_mss); + /* passive */ if (peergroup_flag_check(peer, PEER_FLAG_PASSIVE)) vty_out(vty, " neighbor %s passive\n", addr); @@ -17234,6 +17302,9 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, : ""); } } + + if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_CONFIG_DAMPENING)) + bgp_config_write_peer_damp(vty, peer, afi, safi); } /* Address family based peer configuration display. */ @@ -17287,23 +17358,11 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, /* BGP flag dampening. */ if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) bgp_config_write_damp(vty, bgp, afi, safi); - for (ALL_LIST_ELEMENTS_RO(bgp->group, node, group)) - if (peer_af_flag_check(group->conf, afi, safi, - PEER_FLAG_CONFIG_DAMPENING)) - bgp_config_write_peer_damp(vty, group->conf, afi, safi); - for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) - if (peer_af_flag_check(peer, afi, safi, - PEER_FLAG_CONFIG_DAMPENING)) - bgp_config_write_peer_damp(vty, peer, afi, safi); for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi); for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { - /* Skip dynamic neighbors. */ - if (peer_dynamic_neighbor(peer)) - continue; - /* Do not display doppelganger peers */ if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) bgp_config_write_peer_af(vty, bgp, peer, afi, safi); @@ -19229,6 +19288,10 @@ void bgp_vty_init(void) install_element(BGP_IPV6_NODE, &af_no_route_map_vpn_imexport_cmd); install_element(BGP_IPV4_NODE, &af_no_import_vrf_route_map_cmd); install_element(BGP_IPV6_NODE, &af_no_import_vrf_route_map_cmd); + + /* tcp-mss command */ + install_element(BGP_NODE, &neighbor_tcp_mss_cmd); + install_element(BGP_NODE, &no_neighbor_tcp_mss_cmd); } #include "memory.h" diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 20bb5e5320..2c9aad5d21 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -43,6 +43,7 @@ #include "jhash.h" #include "table.h" #include "lib/json.h" +#include "lib/sockopt.h" #include "frr_pthread.h" #include "bitfield.h" @@ -1439,6 +1440,8 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src) peer_dst->local_as = peer_src->local_as; peer_dst->port = peer_src->port; + /* copy tcp_mss value */ + peer_dst->tcp_mss = peer_src->tcp_mss; (void)peer_sort(peer_dst); peer_dst->rmap_type = peer_src->rmap_type; @@ -5116,6 +5119,26 @@ void peer_port_unset(struct peer *peer) peer->port = BGP_PORT_DEFAULT; } +/* Set the TCP-MSS value in the peer structure, + * This gets applied only after connection reset + * So this value will be used in bgp_connect. + */ +void peer_tcp_mss_set(struct peer *peer, uint32_t tcp_mss) +{ + peer->tcp_mss = tcp_mss; + SET_FLAG(peer->flags, PEER_FLAG_TCP_MSS); +} + +/* Reset the TCP-MSS value in the peer structure, + * This gets applied only after connection reset + * So this value will be used in bgp_connect. + */ +void peer_tcp_mss_unset(struct peer *peer) +{ + UNSET_FLAG(peer->flags, PEER_FLAG_TCP_MSS); + peer->tcp_mss = 0; +} + /* * Helper function that is called after the name of the policy * being used by a peer has changed (AF specific). Automatically diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 88588952ba..3343b332f4 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1241,6 +1241,8 @@ struct peer { #define PEER_FLAG_GRACEFUL_RESTART (1U << 24) /* Graceful Restart */ #define PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT (1U << 25) /* Global-Inherit */ #define PEER_FLAG_RTT_SHUTDOWN (1U << 26) /* shutdown rtt */ +#define PEER_FLAG_TIMER_DELAYOPEN (1U << 27) /* delayopen timer */ +#define PEER_FLAG_TCP_MSS (1U << 28) /* tcp-mss */ /* *GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART @@ -1248,8 +1250,6 @@ struct peer { *and PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT */ -#define PEER_FLAG_TIMER_DELAYOPEN (1 << 27) /* delayopen timer */ - struct bgp_peer_gr PEER_GR_FSM[BGP_PEER_GR_MODE][BGP_PEER_GR_EVENT_CMD]; enum peer_mode peer_gr_present_state; /* Non stop forwarding afi-safi count for BGP gr feature*/ @@ -1606,6 +1606,9 @@ struct peer { bool advmap_config_change[AFI_MAX][SAFI_MAX]; bool advmap_table_change; + /* set TCP max segment size */ + uint32_t tcp_mss; + QOBJ_FIELDS; }; DECLARE_QOBJ_TYPE(peer); @@ -2409,4 +2412,6 @@ DECLARE_HOOK(bgp_rpki_prefix_status, void peer_nsf_stop(struct peer *peer); +void peer_tcp_mss_set(struct peer *peer, uint32_t tcp_mss); +void peer_tcp_mss_unset(struct peer *peer); #endif /* _QUAGGA_BGPD_H */ 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/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..314873640d 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 ^^^^^^^^^^^^^^^^ @@ -3877,6 +3908,147 @@ Example of how to set up a 6-Bone connection. log file bgpd.log ! +.. _bgp-tcp-mss: + +BGP tcp-mss support +=================== +TCP provides a mechanism for the user to specify the max segment size. +setsockopt API is used to set the max segment size for TCP session. We +can configure this as part of BGP neighbor configuration. + +This document explains how to avoid ICMP vulnerability issues by limiting +TCP max segment size when you are using MTU discovery. Using MTU discovery +on TCP paths is one method of avoiding BGP packet fragmentation. + +TCP negotiates a maximum segment size (MSS) value during session connection +establishment between two peers. The MSS value negotiated is primarily based +on the maximum transmission unit (MTU) of the interfaces to which the +communicating peers are directly connected. However, due to variations in +link MTU on the path taken by the TCP packets, some packets in the network +that are well within the MSS value might be fragmented when the packet size +exceeds the link's MTU. + +This feature is supported with TCP over IPv4 and TCP over IPv6. + +CLI Configuration: +------------------ +Below configuration can be done in router bgp mode and allows the user to +configure the tcp-mss value per neighbor. The configuration gets applied +only after hard reset is performed on that neighbor. If we configure tcp-mss +on both the neighbors then both neighbors need to be reset. + +The configuration takes effect based on below rules, so there is a configured +tcp-mss and a synced tcp-mss value per TCP session. + +By default if the configuration is not done then the TCP max segment size is +set to the Maximum Transmission unit (MTU) – (IP/IP6 header size + TCP header +size + ethernet header). For IPv4 its MTU – (20 bytes IP header + 20 bytes TCP +header + 12 bytes ethernet header) and for IPv6 its MTU – (40 bytes IPv6 header ++ 20 bytes TCP header + 12 bytes ethernet header). + +If the config is done then it reduces 12-14 bytes for the ether header and +uses it after synchronizing in TCP handshake. + +.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> tcp-mss (1-65535) + +When tcp-mss is configured kernel reduces 12-14 bytes for ethernet header. +E.g. if tcp-mss is configured as 150 the synced value will be 138. + +Note: configured and synced value is different since TCP module will reduce +12 bytes for ethernet header. + +Running config: +--------------- + +.. code-block:: frr + + frr# show running-config + Building configuration... + + Current configuration: + ! + router bgp 100 + bgp router-id 192.0.2.1 + neighbor 198.51.100.2 remote-as 100 + neighbor 198.51.100.2 tcp-mss 150 => new entry + neighbor 2001:DB8::2 remote-as 100 + neighbor 2001:DB8::2 tcp-mss 400 => new entry + +Show command: +------------- + +.. code-block:: frr + + frr# show bgp neighbors 198.51.100.2 + BGP neighbor is 198.51.100.2, remote AS 100, local AS 100, internal link + Hostname: frr + BGP version 4, remote router ID 192.0.2.2, local router ID 192.0.2.1 + BGP state = Established, up for 02:15:28 + Last read 00:00:28, Last write 00:00:28 + Hold time is 180, keepalive interval is 60 seconds + Configured tcp-mss is 150, synced tcp-mss is 138 => new display + +.. code-block:: frr + + frr# show bgp neighbors 2001:DB8::2 + BGP neighbor is 2001:DB8::2, remote AS 100, local AS 100, internal link + Hostname: frr + BGP version 4, remote router ID 192.0.2.2, local router ID 192.0.2.1 + BGP state = Established, up for 02:16:34 + Last read 00:00:34, Last write 00:00:34 + Hold time is 180, keepalive interval is 60 seconds + Configured tcp-mss is 400, synced tcp-mss is 388 => new display + +Show command json output: +------------------------- + +.. code-block:: frr + + frr# show bgp neighbors 2001:DB8::2 json + { + "2001:DB8::2":{ + "remoteAs":100, + "localAs":100, + "nbrInternalLink":true, + "hostname":"frr", + "bgpVersion":4, + "remoteRouterId":"192.0.2.2", + "localRouterId":"192.0.2.1", + "bgpState":"Established", + "bgpTimerUpMsec":8349000, + "bgpTimerUpString":"02:19:09", + "bgpTimerUpEstablishedEpoch":1613054251, + "bgpTimerLastRead":9000, + "bgpTimerLastWrite":9000, + "bgpInUpdateElapsedTimeMsecs":8347000, + "bgpTimerHoldTimeMsecs":180000, + "bgpTimerKeepAliveIntervalMsecs":60000, + "bgpTcpMssConfigured":400, => new entry + "bgpTcpMssSynced":388, => new entry + +.. code-block:: frr + + frr# show bgp neighbors 198.51.100.2 json + { + "198.51.100.2":{ + "remoteAs":100, + "localAs":100, + "nbrInternalLink":true, + "hostname":"frr", + "bgpVersion":4, + "remoteRouterId":"192.0.2.2", + "localRouterId":"192.0.2.1", + "bgpState":"Established", + "bgpTimerUpMsec":8370000, + "bgpTimerUpString":"02:19:30", + "bgpTimerUpEstablishedEpoch":1613054251, + "bgpTimerLastRead":30000, + "bgpTimerLastWrite":30000, + "bgpInUpdateElapsedTimeMsecs":8368000, + "bgpTimerHoldTimeMsecs":180000, + "bgpTimerKeepAliveIntervalMsecs":60000, + "bgpTcpMssConfigured":150, => new entry + "bgpTcpMssSynced":138, => new entry .. include:: routeserver.rst 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/doc/user/ripd.rst b/doc/user/ripd.rst index 83c8c93b1c..0a155bf489 100644 --- a/doc/user/ripd.rst +++ b/doc/user/ripd.rst @@ -236,11 +236,13 @@ Filtering RIP Routes RIP routes can be filtered by a distribute-list. -.. clicmd:: distribute-list ACCESS_LIST DIRECT IFNAME +.. clicmd:: distribute-list [prefix] LIST <in|out> IFNAME You can apply access lists to the interface with a `distribute-list` command. - ACCESS_LIST is the access list name. DIRECT is ``in`` or ``out``. If DIRECT - is ``in`` the access list is applied to input packets. + If prefix is specified LIST is a prefix-list. If prefix is not specified + then LIST is the access list name. `in` specifies packets being received, + and `out` specifies outgoing packets. Finally if an interface is specified + it will be applied against a specific interface. The `distribute-list` command can be used to filter the RIP path. `distribute-list` can apply access-lists to a chosen interface. First, one @@ -261,13 +263,6 @@ RIP routes can be filtered by a distribute-list. `distribute-list` can be applied to both incoming and outgoing data. -.. clicmd:: distribute-list prefix PREFIX_LIST (in|out) IFNAME - - You can apply prefix lists to the interface with a `distribute-list` - command. PREFIX_LIST is the prefix list name. Next is the direction of - ``in`` or ``out``. If DIRECT is ``in`` the access list is applied to input - packets. - .. _rip-metric-manipulation: RIP Metric Manipulation diff --git a/doc/user/ripngd.rst b/doc/user/ripngd.rst index b273eb3bfa..c7ca22bf95 100644 --- a/doc/user/ripngd.rst +++ b/doc/user/ripngd.rst @@ -62,14 +62,34 @@ ripngd Terminal Mode Commands ripngd Filtering Commands ========================= -.. clicmd:: distribute-list ACCESS_LIST (in|out) IFNAME +RIPng routes can be filtered by a distribute-list. - You can apply an access-list to the interface using the `distribute-list` - command. ACCESS_LIST is an access-list name. `direct` is ``in`` or - ``out``. If `direct` is ``in``, the access-list is applied only to incoming - packets.:: +.. clicmd:: distribute-list [prefix] LIST <in|out> IFNAME - distribute-list local-only out sit1 + You can apply access lists to the interface with a `distribute-list` command. + If prefix is specified LIST is a prefix-list. If prefix is not specified + then LIST is the access list name. `in` specifies packets being received, + and `out` specifies outgoing packets. Finally if an interface is specified + it will be applied against a specific interface. + + The ``distribute-list`` command can be used to filter the RIPNG path. + ``distribute-list`` can apply access-lists to a chosen interface. First, one + should specify the access-list. Next, the name of the access-list is used in + the distribute-list command. For example, in the following configuration + ``eth0`` will permit only the paths that match the route 10.0.0.0/8 + + .. code-block:: frr + + ! + router ripng + distribute-list private in eth0 + ! + access-list private permit 10 10.0.0.0/8 + access-list private deny any + ! + + + `distribute-list` can be applied to both incoming and outgoing data. Sample configuration diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index 0ed7e94968..b775c841f0 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -227,8 +227,6 @@ int main(int argc, char **argv, char **envp) route_map_add_hook (eigrp_rmap_update); route_map_delete_hook (eigrp_rmap_update);*/ /*if_rmap_init (EIGRP_NODE); */ - /* Distribute list install. */ - distribute_list_init(EIGRP_NODE); frr_config_fork(); frr_run(master); 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/eigrpd/eigrp_routemap.c b/eigrpd/eigrp_routemap.c index 5183e645e5..90913a5b28 100644 --- a/eigrpd/eigrp_routemap.c +++ b/eigrpd/eigrp_routemap.c @@ -1130,6 +1130,48 @@ ALIAS(no_set_tag, no_set_tag_val_cmd, "no set tag (0-65535)", NO_STR SET_STR "Tag value for routing protocol\n" "Tag value\n") +DEFUN (eigrp_distribute_list, + eigrp_distribute_list_cmd, + "distribute-list [prefix] WORD <in|out> [WORD]", + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_parser(prefix, true, argv[2 + prefix]->text, + argv[1 + prefix]->arg, ifname); +} + +DEFUN (eigrp_no_distribute_list, + eigrp_no_distribute_list_cmd, + "no distribute-list [prefix] WORD <in|out> [WORD]", + NO_STR + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_no_parser(vty, prefix, true, + argv[3 + prefix]->text, + argv[2 + prefix]->arg, ifname); +} + /* Route-map init */ void eigrp_route_map_init() @@ -1139,6 +1181,9 @@ void eigrp_route_map_init() route_map_add_hook(eigrp_route_map_update); route_map_delete_hook(eigrp_route_map_update); + install_element(EIGRP_NODE, &eigrp_distribute_list_cmd); + install_element(EIGRP_NODE, &eigrp_no_distribute_list_cmd); + /*route_map_install_match (&route_match_metric_cmd); route_map_install_match (&route_match_interface_cmd);*/ /*route_map_install_match (&route_match_ip_next_hop_cmd); 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 fd51625bbd..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; 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 cb7ac85d96..616c390e50 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -590,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/distribute.c b/lib/distribute.c index 60bd0a47bb..0f503d2ab9 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -240,150 +240,59 @@ static int distribute_list_prefix_unset(struct distribute_ctx *ctx, return 1; } -DEFUN (distribute_list, - distribute_list_cmd, - "distribute-list [prefix] WORD <in|out> [WORD]", - "Filter networks in routing updates\n" - "Specify a prefix\n" - "Access-list name\n" - "Filter incoming routing updates\n" - "Filter outgoing routing updates\n" - "Interface name\n") +static enum distribute_type distribute_direction(const char *dir, bool v4) { - int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0; - /* Check of distribute list type. */ - enum distribute_type type = argv[2 + prefix]->arg[0] == 'i' - ? DISTRIBUTE_V4_IN - : DISTRIBUTE_V4_OUT; - - /* Set appropriate function call */ - void (*distfn)(struct distribute_ctx *, const char *, - enum distribute_type, const char *) = - prefix ? &distribute_list_prefix_set : &distribute_list_set; - struct distribute_ctx *ctx = - (struct distribute_ctx *)listnode_head(dist_ctx_list); - - /* if interface is present, get name */ - const char *ifname = NULL; - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; + if (dir[0] == 'i') { + if (v4) + return DISTRIBUTE_V4_IN; + else + return DISTRIBUTE_V6_IN; + } else if (dir[0] == 'o') { + if (v4) + return DISTRIBUTE_V4_OUT; + else + return DISTRIBUTE_V6_OUT; + } - /* Get interface name corresponding distribute list. */ - distfn(ctx, ifname, type, argv[1 + prefix]->arg); + assert(!"Expecting in or out only, fix your code"); - return CMD_SUCCESS; + __builtin_unreachable(); } -DEFUN (ipv6_distribute_list, - ipv6_distribute_list_cmd, - "ipv6 distribute-list [prefix] WORD <in|out> [WORD]", - "IPv6\n" - "Filter networks in routing updates\n" - "Specify a prefix\n" - "Access-list name\n" - "Filter incoming routing updates\n" - "Filter outgoing routing updates\n" - "Interface name\n") +int distribute_list_parser(bool prefix, bool v4, const char *dir, + const char *list, const char *ifname) { - int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; - /* Check of distribute list type. */ - enum distribute_type type = argv[3 + prefix]->arg[0] == 'i' - ? DISTRIBUTE_V6_IN - : DISTRIBUTE_V6_OUT; + enum distribute_type type = distribute_direction(dir, v4); + struct distribute_ctx *ctx = listnode_head(dist_ctx_list); - /* Set appropriate function call */ void (*distfn)(struct distribute_ctx *, const char *, enum distribute_type, const char *) = prefix ? &distribute_list_prefix_set : &distribute_list_set; - struct distribute_ctx *ctx = listnode_head(dist_ctx_list); - /* if interface is present, get name */ - const char *ifname = NULL; - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; - - /* Get interface name corresponding distribute list. */ - distfn(ctx, ifname, type, argv[2 + prefix]->arg); + distfn(ctx, ifname, type, list); return CMD_SUCCESS; } -DEFUN (no_distribute_list, - no_distribute_list_cmd, - "no distribute-list [prefix] WORD <in|out> [WORD]", - NO_STR - "Filter networks in routing updates\n" - "Specify a prefix\n" - "Access-list name\n" - "Filter incoming routing updates\n" - "Filter outgoing routing updates\n" - "Interface name\n") +int distribute_list_no_parser(struct vty *vty, bool prefix, bool v4, + const char *dir, const char *list, + const char *ifname) { - int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; - int idx_alname = 2 + prefix; - int idx_disttype = idx_alname + 1; - enum distribute_type type = - argv[idx_disttype]->arg[0] == 'i' ? - DISTRIBUTE_V4_IN : DISTRIBUTE_V4_OUT; - - /* Set appropriate function call */ - int (*distfn)(struct distribute_ctx *, const char *, - enum distribute_type, const char *) = - prefix ? &distribute_list_prefix_unset : &distribute_list_unset; + enum distribute_type type = distribute_direction(dir, v4); struct distribute_ctx *ctx = listnode_head(dist_ctx_list); + int ret; - /* if interface is present, get name */ - const char *ifname = NULL; - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; - /* Get interface name corresponding distribute list. */ - int ret = distfn(ctx, ifname, type, argv[2 + prefix]->arg); - - if (!ret) { - vty_out(vty, "distribute list doesn't exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; -} - -DEFUN (no_ipv6_distribute_list, - no_ipv6_distribute_list_cmd, - "no ipv6 distribute-list [prefix] WORD <in|out> [WORD]", - NO_STR - "IPv6\n" - "Filter networks in routing updates\n" - "Specify a prefix\n" - "Access-list name\n" - "Filter incoming routing updates\n" - "Filter outgoing routing updates\n" - "Interface name\n") -{ - int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0; - int idx_alname = 3 + prefix; - int idx_disttype = idx_alname + 1; - - enum distribute_type type = - argv[idx_disttype]->arg[0] == 'i' ? - DISTRIBUTE_V6_IN : DISTRIBUTE_V6_OUT; - struct distribute_ctx *ctx = listnode_head(dist_ctx_list); - - /* Set appropriate function call */ int (*distfn)(struct distribute_ctx *, const char *, - enum distribute_type, const char *) = + enum distribute_type, const char *) = prefix ? &distribute_list_prefix_unset : &distribute_list_unset; - /* if interface is present, get name */ - const char *ifname = NULL; - - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; - /* Get interface name corresponding distribute list. */ - int ret = distfn(ctx, ifname, type, argv[3 + prefix]->arg); + ret = distfn(ctx, ifname, type, list); if (!ret) { vty_out(vty, "distribute list doesn't exist\n"); return CMD_WARNING_CONFIG_FAILED; } + return CMD_SUCCESS; } @@ -577,32 +486,3 @@ struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf) listnode_add(dist_ctx_list, ctx); return ctx; } - -/* Initialize distribute list vty commands */ -void distribute_list_init(int node) -{ - /* vtysh command-extraction doesn't grok install_element(node, ) */ - if (node == RIP_NODE) { - install_element(RIP_NODE, &distribute_list_cmd); - install_element(RIP_NODE, &no_distribute_list_cmd); - } else if (node == RIPNG_NODE) { - install_element(RIPNG_NODE, &distribute_list_cmd); - install_element(RIPNG_NODE, &no_distribute_list_cmd); - /* install v6 */ - install_element(RIPNG_NODE, &ipv6_distribute_list_cmd); - install_element(RIPNG_NODE, &no_ipv6_distribute_list_cmd); - } - - /* TODO: install v4 syntax command for v6 only protocols. */ - /* if (node == RIPNG_NODE) { - * install_element (node, &ipv6_as_v4_distribute_list_all_cmd); - * install_element (node, &no_ipv6_as_v4_distribute_list_all_cmd); - * install_element (node, &ipv6_as_v4_distribute_list_cmd); - * install_element (node, &no_ipv6_as_v4_distribute_list_cmd); - * install_element (node, &ipv6_as_v4_distribute_list_prefix_all_cmd); - * install_element (node, - &no_ipv6_as_v4_distribute_list_prefix_all_cmd); - * install_element (node, &ipv6_as_v4_distribute_list_prefix_cmd); - * install_element (node, &no_ipv6_as_v4_distribute_list_prefix_cmd); - }*/ -} diff --git a/lib/distribute.h b/lib/distribute.h index 4016d3b133..83682dea6a 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -64,7 +64,6 @@ struct distribute_ctx { }; /* Prototypes for distribute-list. */ -extern void distribute_list_init(int node); extern struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf); extern void distribute_list_delete(struct distribute_ctx **ctx); extern void distribute_list_add_hook(struct distribute_ctx *ctx, @@ -85,6 +84,11 @@ extern enum filter_type distribute_apply_in(struct interface *, extern enum filter_type distribute_apply_out(struct interface *, struct prefix *); +extern int distribute_list_parser(bool prefix, bool v4, const char *dir, + const char *list, const char *ifname); +extern int distribute_list_no_parser(struct vty *vty, bool prefix, bool v4, + const char *dir, const char *list, + const char *ifname); #ifdef __cplusplus } #endif 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/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/sockopt.c b/lib/sockopt.c index b624fe2230..98bfda5079 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -667,3 +667,39 @@ int sockopt_tcp_signature(int sock, union sockunion *su, const char *password) { return sockopt_tcp_signature_ext(sock, su, 0, password); } + +/* set TCP mss value to socket */ +int sockopt_tcp_mss_set(int sock, int tcp_maxseg) +{ + int ret = 0; + socklen_t tcp_maxseg_len = sizeof(tcp_maxseg); + + ret = setsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, &tcp_maxseg, + tcp_maxseg_len); + if (ret != 0) { + flog_err_sys(EC_LIB_SYSTEM_CALL, + "%s failed: setsockopt(%d): %s", __func__, sock, + safe_strerror(errno)); + } + + return ret; +} + +/* get TCP mss value synced by socket */ +int sockopt_tcp_mss_get(int sock) +{ + int ret = 0; + int tcp_maxseg = 0; + socklen_t tcp_maxseg_len = sizeof(tcp_maxseg); + + ret = getsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, &tcp_maxseg, + &tcp_maxseg_len); + if (ret != 0) { + flog_err_sys(EC_LIB_SYSTEM_CALL, + "%s failed: getsockopt(%d): %s", __func__, sock, + safe_strerror(errno)); + return 0; + } + + return tcp_maxseg; +} diff --git a/lib/sockopt.h b/lib/sockopt.h index 545abe631f..6c80841e3c 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -133,6 +133,26 @@ extern int sockopt_tcp_signature(int sock, union sockunion *su, extern int sockopt_tcp_signature_ext(int sock, union sockunion *su, uint16_t prefixlen, const char *password); +/* + * set TCP max segment size. This option allows user to configure + * max segment size for TCP session + * + * sock + * Socket to enable option on. + * + * tcp_maxseg + * value used for TCP segment size negotiation during SYN + */ +extern int sockopt_tcp_mss_set(int sock, int tcp_maxseg); + +/* + * get TCP max segment size. This option allows user to get + * the segment size for TCP session + * + * sock + * Socket to get max segement size. + */ +extern int sockopt_tcp_mss_get(int sock); #ifdef __cplusplus } #endif 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/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_message.c b/ospf6d/ospf6_message.c index 7aedd3df45..d2dcfd81d4 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -94,7 +94,7 @@ static void ospf6_header_print(struct ospf6_header *oh) ntohs(oh->checksum), oh->instance_id); } -void ospf6_hello_print(struct ospf6_header *oh) +void ospf6_hello_print(struct ospf6_header *oh, int action) { struct ospf6_hello *hello; char options[16]; @@ -115,15 +115,21 @@ void ospf6_hello_print(struct ospf6_header *oh) ntohs(hello->hello_interval), ntohs(hello->dead_interval)); zlog_debug(" DR:%pI4 BDR:%pI4", &hello->drouter, &hello->bdrouter); - for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello)); - p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh); - p += sizeof(uint32_t)) - zlog_debug(" Neighbor: %pI4", (in_addr_t *)p); + if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV) + && action == OSPF6_ACTION_RECV) + || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND) + && action == OSPF6_ACTION_SEND)) { - assert(p == OSPF6_MESSAGE_END(oh)); + for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello)); + p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh); + p += sizeof(uint32_t)) + zlog_debug(" Neighbor: %pI4", (in_addr_t *)p); + + assert(p == OSPF6_MESSAGE_END(oh)); + } } -void ospf6_dbdesc_print(struct ospf6_header *oh) +void ospf6_dbdesc_print(struct ospf6_header *oh, int action) { struct ospf6_dbdesc *dbdesc; char options[16]; @@ -145,34 +151,52 @@ void ospf6_dbdesc_print(struct ospf6_header *oh) (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"), (unsigned long)ntohl(dbdesc->seqnum)); - for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc)); - p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh); - p += sizeof(struct ospf6_lsa_header)) - ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p); + if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV) + && action == OSPF6_ACTION_RECV) + || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND) + && action == OSPF6_ACTION_SEND)) { - assert(p == OSPF6_MESSAGE_END(oh)); + for (p = (char *)((caddr_t)dbdesc + + sizeof(struct ospf6_dbdesc)); + p + sizeof(struct ospf6_lsa_header) + <= OSPF6_MESSAGE_END(oh); + p += sizeof(struct ospf6_lsa_header)) + ospf6_lsa_header_print_raw( + (struct ospf6_lsa_header *)p); + + assert(p == OSPF6_MESSAGE_END(oh)); + } } -void ospf6_lsreq_print(struct ospf6_header *oh) +void ospf6_lsreq_print(struct ospf6_header *oh, int action) { char *p; ospf6_header_print(oh); assert(oh->type == OSPF6_MESSAGE_TYPE_LSREQ); - for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header)); - p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh); - p += sizeof(struct ospf6_lsreq_entry)) { - struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *)p; + if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV) + && action == OSPF6_ACTION_RECV) + || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND) + && action == OSPF6_ACTION_SEND)) { + + for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header)); + p + sizeof(struct ospf6_lsreq_entry) + <= OSPF6_MESSAGE_END(oh); + p += sizeof(struct ospf6_lsreq_entry)) { + struct ospf6_lsreq_entry *e = + (struct ospf6_lsreq_entry *)p; + + zlog_debug(" [%s Id:%pI4 Adv:%pI4]", + ospf6_lstype_name(e->type), &e->id, + &e->adv_router); + } - zlog_debug(" [%s Id:%pI4 Adv:%pI4]", - ospf6_lstype_name(e->type), &e->id, &e->adv_router); + assert(p == OSPF6_MESSAGE_END(oh)); } - - assert(p == OSPF6_MESSAGE_END(oh)); } -void ospf6_lsupdate_print(struct ospf6_header *oh) +void ospf6_lsupdate_print(struct ospf6_header *oh, int action) { struct ospf6_lsupdate *lsupdate; unsigned long num; @@ -187,29 +211,45 @@ void ospf6_lsupdate_print(struct ospf6_header *oh) num = ntohl(lsupdate->lsa_number); zlog_debug(" Number of LSA: %ld", num); - for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate)); - p < OSPF6_MESSAGE_END(oh) - && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh); - p += OSPF6_LSA_SIZE(p)) { - ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p); - } + if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV) + && action == OSPF6_ACTION_RECV) + || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND) + && action == OSPF6_ACTION_SEND)) { + + for (p = (char *)((caddr_t)lsupdate + + sizeof(struct ospf6_lsupdate)); + p < OSPF6_MESSAGE_END(oh) + && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh); + p += OSPF6_LSA_SIZE(p)) { + ospf6_lsa_header_print_raw( + (struct ospf6_lsa_header *)p); + } - assert(p == OSPF6_MESSAGE_END(oh)); + assert(p == OSPF6_MESSAGE_END(oh)); + } } -void ospf6_lsack_print(struct ospf6_header *oh) +void ospf6_lsack_print(struct ospf6_header *oh, int action) { char *p; ospf6_header_print(oh); assert(oh->type == OSPF6_MESSAGE_TYPE_LSACK); - for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header)); - p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh); - p += sizeof(struct ospf6_lsa_header)) - ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p); + if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV) + && action == OSPF6_ACTION_RECV) + || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND) + && action == OSPF6_ACTION_SEND)) { - assert(p == OSPF6_MESSAGE_END(oh)); + for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header)); + p + sizeof(struct ospf6_lsa_header) + <= OSPF6_MESSAGE_END(oh); + p += sizeof(struct ospf6_lsa_header)) + ospf6_lsa_header_print_raw( + (struct ospf6_lsa_header *)p); + + assert(p == OSPF6_MESSAGE_END(oh)); + } } static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst, @@ -348,21 +388,21 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, + sizeof(struct ospf6_header)); if (on->state < OSPF6_NEIGHBOR_INIT) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor state less than Init, ignore"); return; } switch (on->state) { case OSPF6_NEIGHBOR_TWOWAY: - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor state is 2-Way, ignore"); return; case OSPF6_NEIGHBOR_INIT: thread_execute(master, twoway_received, on, 0); if (on->state != OSPF6_NEIGHBOR_EXSTART) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug( "Neighbor state is not ExStart, ignore"); return; @@ -395,14 +435,14 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, sizeof(struct ospf6_dbdesc))) { /* Duplicated DatabaseDescription is dropped by master */ - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug( "Duplicated dbdesc discarded by Master, ignore"); return; } if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Master/Slave bit mismatch"); thread_add_event(master, seqnumber_mismatch, on, 0, NULL); @@ -410,7 +450,7 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, } if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Initialize bit mismatch"); thread_add_event(master, seqnumber_mismatch, on, 0, NULL); @@ -418,7 +458,7 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, } if (memcmp(on->options, dbdesc->options, sizeof(on->options))) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Option field mismatch"); thread_add_event(master, seqnumber_mismatch, on, 0, NULL); @@ -426,7 +466,7 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, } if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug( "Sequence number mismatch (%#lx expected)", (unsigned long)on->dbdesc_seqnum); @@ -442,13 +482,13 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, sizeof(struct ospf6_dbdesc))) { /* Duplicated DatabaseDescription is dropped by master */ - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug( "Duplicated dbdesc discarded by Master, ignore"); return; } - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Not duplicate dbdesc in state %s", ospf6_neighbor_state_str[on->state]); thread_add_event(master, seqnumber_mismatch, on, 0, NULL); @@ -553,21 +593,21 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, + sizeof(struct ospf6_header)); if (on->state < OSPF6_NEIGHBOR_INIT) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor state less than Init, ignore"); return; } switch (on->state) { case OSPF6_NEIGHBOR_TWOWAY: - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor state is 2-Way, ignore"); return; case OSPF6_NEIGHBOR_INIT: thread_execute(master, twoway_received, on, 0); if (on->state != OSPF6_NEIGHBOR_EXSTART) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug( "Neighbor state is not ExStart, ignore"); return; @@ -611,7 +651,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, sizeof(struct ospf6_dbdesc))) { /* Duplicated DatabaseDescription causes slave to * retransmit */ - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug( "Duplicated dbdesc causes retransmit"); THREAD_OFF(on->thread_send_dbdesc); @@ -622,7 +662,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, } if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Master/Slave bit mismatch"); thread_add_event(master, seqnumber_mismatch, on, 0, NULL); @@ -630,7 +670,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, } if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Initialize bit mismatch"); thread_add_event(master, seqnumber_mismatch, on, 0, NULL); @@ -638,7 +678,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, } if (memcmp(on->options, dbdesc->options, sizeof(on->options))) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Option field mismatch"); thread_add_event(master, seqnumber_mismatch, on, 0, NULL); @@ -646,7 +686,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, } if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum + 1) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug( "Sequence number mismatch (%#lx expected)", (unsigned long)on->dbdesc_seqnum + 1); @@ -662,7 +702,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, sizeof(struct ospf6_dbdesc))) { /* Duplicated DatabaseDescription causes slave to * retransmit */ - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug( "Duplicated dbdesc causes retransmit"); THREAD_OFF(on->thread_send_dbdesc); @@ -671,7 +711,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, return; } - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Not duplicate dbdesc in state %s", ospf6_neighbor_state_str[on->state]); thread_add_event(master, seqnumber_mismatch, on, 0, NULL); @@ -756,7 +796,7 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst, on = ospf6_neighbor_lookup(oh->router_id, oi); if (on == NULL) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor not found, ignore"); return; } @@ -773,7 +813,7 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst, } if (dbdesc->reserved1 || dbdesc->reserved2) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug( "Non-0 reserved field in %s's DbDesc, correct", on->name); @@ -788,7 +828,7 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst, else if (ntohl(oi->area->ospf6->router_id) < ntohl(oh->router_id)) ospf6_dbdesc_recv_slave(oh, on); else { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Can't decide which is master, ignore"); } } @@ -805,7 +845,7 @@ static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst, on = ospf6_neighbor_lookup(oh->router_id, oi); if (on == NULL) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor not found, ignore"); return; } @@ -813,7 +853,7 @@ static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst, if (on->state != OSPF6_NEIGHBOR_EXCHANGE && on->state != OSPF6_NEIGHBOR_LOADING && on->state != OSPF6_NEIGHBOR_FULL) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor state less than Exchange, ignore"); return; } @@ -882,7 +922,7 @@ static unsigned ospf6_prefixes_examin( while (length) { if (length < OSPF6_PREFIX_MIN_SIZE) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, - RECV)) + RECV_HDR)) zlog_debug("%s: undersized IPv6 prefix header", __func__); return MSG_NG; @@ -890,7 +930,7 @@ static unsigned ospf6_prefixes_examin( /* safe to look deeper */ if (current->prefix_length > IPV6_MAX_BITLEN) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, - RECV)) + RECV_HDR)) zlog_debug("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length); return MSG_NG; @@ -901,7 +941,7 @@ static unsigned ospf6_prefixes_examin( + OSPF6_PREFIX_SPACE(current->prefix_length); if (requested_pfx_bytes > length) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, - RECV)) + RECV_HDR)) zlog_debug("%s: undersized IPv6 prefix", __func__); return MSG_NG; @@ -913,7 +953,8 @@ static unsigned ospf6_prefixes_examin( real_num_pfxs++; } if (real_num_pfxs != req_num_pfxs) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug( "%s: IPv6 prefix number mismatch (%u required, %u real)", __func__, req_num_pfxs, real_num_pfxs); @@ -945,7 +986,8 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah, ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK; if (ltindex < OSPF6_LSTYPE_SIZE && ospf6_lsa_minlen[ltindex] && lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug("%s: undersized (%u B) LSA", __func__, lsalen); return MSG_NG; @@ -958,7 +1000,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah, if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, - RECV)) + RECV_HDR)) zlog_debug( "%s: interface description alignment error", __func__); @@ -972,7 +1014,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah, - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, - RECV)) + RECV_HDR)) zlog_debug( "%s: router description alignment error", __func__); @@ -997,7 +1039,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah, if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, - RECV)) + RECV_HDR)) zlog_debug("%s: oversized (%u B) LSA", __func__, lsalen); return MSG_NG; @@ -1026,7 +1068,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah, prefix before ospf6_prefix_examin() confirms its sizing. */ if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, - RECV)) + RECV_HDR)) zlog_debug("%s: undersized (%u B) LSA header", __func__, lsalen); return MSG_NG; @@ -1045,7 +1087,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah, this check does not include any IPv6 prefix fields. */ if (exp_length > lsalen) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, - RECV)) + RECV_HDR)) zlog_debug("%s: undersized (%u B) LSA header", __func__, lsalen); return MSG_NG; @@ -1114,7 +1156,7 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */ uint16_t lsalen; if (length < OSPF6_LSA_HEADER_SIZE) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, - RECV)) + RECV_HDR)) zlog_debug( "%s: undersized (%zu B) trailing (#%u) LSA header", __func__, length, counted_lsas); @@ -1124,7 +1166,7 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */ lsalen = OSPF6_LSA_SIZE(lsah); if (lsalen < OSPF6_LSA_HEADER_SIZE) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, - RECV)) + RECV_HDR)) zlog_debug( "%s: malformed LSA header #%u, declared length is %u B", __func__, counted_lsas, lsalen); @@ -1134,7 +1176,8 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */ /* less checks here and in ospf6_lsa_examin() */ if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 1)) { if (IS_OSPF6_DEBUG_MESSAGE( - OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug( "%s: anomaly in header-only %s LSA #%u", __func__, @@ -1151,7 +1194,8 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */ * further checks */ if (lsalen > length) { if (IS_OSPF6_DEBUG_MESSAGE( - OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug( "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B", __func__, @@ -1161,7 +1205,8 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */ } if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 0)) { if (IS_OSPF6_DEBUG_MESSAGE( - OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug( "%s: anomaly in %s LSA #%u", __func__, @@ -1177,7 +1222,8 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */ } if (declared_num_lsas && counted_lsas != declared_num_lsas) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug( "%s: #LSAs declared (%u) does not match actual (%u)", __func__, declared_num_lsas, counted_lsas); @@ -1195,14 +1241,16 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh, /* length, 1st approximation */ if (bytesonwire < OSPF6_HEADER_SIZE) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug("%s: undersized (%u B) packet", __func__, bytesonwire); return MSG_NG; } /* Now it is safe to access header fields. */ if (bytesonwire != ntohs(oh->length)) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug( "%s: %s packet length error (%u real, %u declared)", __func__, lookup_msg(ospf6_message_type_str, @@ -1212,7 +1260,8 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh, } /* version check */ if (oh->version != OSPFV3_VERSION) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug("%s: invalid (%u) protocol version", __func__, oh->version); return MSG_NG; @@ -1221,7 +1270,8 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh, if (oh->type < OSPF6_MESSAGE_TYPE_ALL && ospf6_packet_minlen[oh->type] && bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug("%s: undersized (%u B) %s packet", __func__, bytesonwire, lookup_msg(ospf6_message_type_str, oh->type, @@ -1238,7 +1288,8 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh, == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4) return MSG_OK; - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug("%s: alignment error in %s packet", __func__, lookup_msg(ospf6_message_type_str, oh->type, NULL)); @@ -1261,7 +1312,8 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh, == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE) return MSG_OK; - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug("%s: alignment error in %s packet", __func__, lookup_msg(ospf6_message_type_str, oh->type, NULL)); @@ -1289,13 +1341,14 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh, 1, 0); break; default: - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug("%s: invalid (%u) message type", __func__, oh->type); return MSG_NG; } if (test != MSG_OK - && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV_HDR)) zlog_debug("%s: anomaly in %s packet", __func__, lookup_msg(ospf6_message_type_str, oh->type, NULL)); return test; @@ -1356,7 +1409,7 @@ static void ospf6_lsupdate_recv(struct in6_addr *src, struct in6_addr *dst, on = ospf6_neighbor_lookup(oh->router_id, oi); if (on == NULL) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor not found, ignore"); return; } @@ -1364,7 +1417,7 @@ static void ospf6_lsupdate_recv(struct in6_addr *src, struct in6_addr *dst, if (on->state != OSPF6_NEIGHBOR_EXCHANGE && on->state != OSPF6_NEIGHBOR_LOADING && on->state != OSPF6_NEIGHBOR_FULL) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor state less than Exchange, ignore"); return; } @@ -1398,7 +1451,7 @@ static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst, on = ospf6_neighbor_lookup(oh->router_id, oi); if (on == NULL) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor not found, ignore"); return; } @@ -1406,7 +1459,7 @@ static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst, if (on->state != OSPF6_NEIGHBOR_EXCHANGE && on->state != OSPF6_NEIGHBOR_LOADING && on->state != OSPF6_NEIGHBOR_FULL) { - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) zlog_debug("Neighbor state less than Exchange, ignore"); return; } @@ -1555,12 +1608,14 @@ int ospf6_receive(struct thread *thread) oi = ospf6_interface_lookup_by_ifindex(ifindex, ospf6->vrf_id); if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug("Message received on disabled interface"); return 0; } if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV_HDR)) zlog_debug("%s: Ignore message on passive interface %s", __func__, oi->interface->name); return 0; @@ -1576,7 +1631,7 @@ int ospf6_receive(struct thread *thread) which can be dismissed in a cleanup-focused review round later. */ /* Log */ - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) { zlog_debug("%s received on %s", lookup_msg(ospf6_message_type_str, oh->type, NULL), oi->interface->name); @@ -1585,19 +1640,19 @@ int ospf6_receive(struct thread *thread) switch (oh->type) { case OSPF6_MESSAGE_TYPE_HELLO: - ospf6_hello_print(oh); + ospf6_hello_print(oh, OSPF6_ACTION_RECV); break; case OSPF6_MESSAGE_TYPE_DBDESC: - ospf6_dbdesc_print(oh); + ospf6_dbdesc_print(oh, OSPF6_ACTION_RECV); break; case OSPF6_MESSAGE_TYPE_LSREQ: - ospf6_lsreq_print(oh); + ospf6_lsreq_print(oh, OSPF6_ACTION_RECV); break; case OSPF6_MESSAGE_TYPE_LSUPDATE: - ospf6_lsupdate_print(oh); + ospf6_lsupdate_print(oh, OSPF6_ACTION_RECV); break; case OSPF6_MESSAGE_TYPE_LSACK: - ospf6_lsack_print(oh); + ospf6_lsack_print(oh, OSPF6_ACTION_RECV); break; default: assert(0); @@ -1656,7 +1711,7 @@ static void ospf6_send(struct in6_addr *src, struct in6_addr *dst, oh->reserved = 0; /* Log */ - if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) { if (src) inet_ntop(AF_INET6, src, srcname, sizeof(srcname)); else @@ -1669,19 +1724,19 @@ static void ospf6_send(struct in6_addr *src, struct in6_addr *dst, switch (oh->type) { case OSPF6_MESSAGE_TYPE_HELLO: - ospf6_hello_print(oh); + ospf6_hello_print(oh, OSPF6_ACTION_RECV); break; case OSPF6_MESSAGE_TYPE_DBDESC: - ospf6_dbdesc_print(oh); + ospf6_dbdesc_print(oh, OSPF6_ACTION_RECV); break; case OSPF6_MESSAGE_TYPE_LSREQ: - ospf6_lsreq_print(oh); + ospf6_lsreq_print(oh, OSPF6_ACTION_RECV); break; case OSPF6_MESSAGE_TYPE_LSUPDATE: - ospf6_lsupdate_print(oh); + ospf6_lsupdate_print(oh, OSPF6_ACTION_RECV); break; case OSPF6_MESSAGE_TYPE_LSACK: - ospf6_lsack_print(oh); + ospf6_lsack_print(oh, OSPF6_ACTION_RECV); break; default: zlog_debug("Unknown message"); @@ -1719,7 +1774,7 @@ int ospf6_hello_send(struct thread *thread) oi->thread_send_hello = (struct thread *)NULL; if (oi->state <= OSPF6_INTERFACE_DOWN) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, SEND)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, SEND_HDR)) zlog_debug("Unable to send Hello on down interface %s", oi->interface->name); return 0; @@ -1758,7 +1813,7 @@ int ospf6_hello_send(struct thread *thread) if (p - sendbuf + sizeof(uint32_t) > ospf6_packet_max(oi)) { if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, - SEND)) + SEND_HDR)) zlog_debug( "sending Hello message: exceeds I/F MTU"); break; @@ -1790,7 +1845,7 @@ int ospf6_dbdesc_send(struct thread *thread) on->thread_send_dbdesc = (struct thread *)NULL; if (on->state < OSPF6_NEIGHBOR_EXSTART) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC, SEND)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC, SEND_HDR)) zlog_debug( "Quit to send DbDesc to neighbor %s state %s", on->name, ospf6_neighbor_state_str[on->state]); @@ -1918,7 +1973,7 @@ int ospf6_lsreq_send(struct thread *thread) /* LSReq will be sent only in ExStart or Loading */ if (on->state != OSPF6_NEIGHBOR_EXCHANGE && on->state != OSPF6_NEIGHBOR_LOADING) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ, SEND)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ, SEND_HDR)) zlog_debug("Quit to send LSReq to neighbor %s state %s", on->name, ospf6_neighbor_state_str[on->state]); @@ -2029,11 +2084,12 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread) on = (struct ospf6_neighbor *)THREAD_ARG(thread); on->thread_send_lsupdate = (struct thread *)NULL; - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND_HDR)) zlog_debug("LSUpdate to neighbor %s", on->name); if (on->state < OSPF6_NEIGHBOR_EXCHANGE) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, + SEND_HDR)) zlog_debug("Quit to send (neighbor state %s)", ospf6_neighbor_state_str[on->state]); return 0; @@ -2190,7 +2246,7 @@ int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on, lsupdate->lsa_number = htonl(lsa_cnt); if (IS_OSPF6_DEBUG_FLOODING - || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND_HDR)) zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__, lsa->name, ntohs(lsa->header->age)); @@ -2212,7 +2268,8 @@ int ospf6_lsupdate_send_interface(struct thread *thread) oi->thread_send_lsupdate = (struct thread *)NULL; if (oi->state <= OSPF6_INTERFACE_WAITING) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, + SEND_HDR)) zlog_debug( "Quit to send LSUpdate to interface %s state %s", oi->interface->name, @@ -2299,7 +2356,7 @@ int ospf6_lsack_send_neighbor(struct thread *thread) on->thread_send_lsack = (struct thread *)NULL; if (on->state < OSPF6_NEIGHBOR_EXCHANGE) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND_HDR)) zlog_debug("Quit to send LSAck to neighbor %s state %s", on->name, ospf6_neighbor_state_str[on->state]); @@ -2377,7 +2434,7 @@ int ospf6_lsack_send_interface(struct thread *thread) oi->thread_send_lsack = (struct thread *)NULL; if (oi->state <= OSPF6_INTERFACE_WAITING) { - if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND)) + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND_HDR)) zlog_debug( "Quit to send LSAck to interface %s state %s", oi->interface->name, @@ -2440,21 +2497,21 @@ int ospf6_lsack_send_interface(struct thread *thread) /* Commands */ -DEFUN (debug_ospf6_message, - debug_ospf6_message_cmd, - "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]", - DEBUG_STR - OSPF6_STR - "Debug OSPFv3 message\n" - "Debug Unknown message\n" - "Debug Hello message\n" - "Debug Database Description message\n" - "Debug Link State Request message\n" - "Debug Link State Update message\n" - "Debug Link State Acknowledgement message\n" - "Debug All message\n" - "Debug only sending message\n" - "Debug only receiving message\n") +DEFUN(debug_ospf6_message, debug_ospf6_message_cmd, + "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]", + DEBUG_STR OSPF6_STR + "Debug OSPFv3 message\n" + "Debug Unknown message\n" + "Debug Hello message\n" + "Debug Database Description message\n" + "Debug Link State Request message\n" + "Debug Link State Update message\n" + "Debug Link State Acknowledgement message\n" + "Debug All message\n" + "Debug only sending message, entire packet\n" + "Debug only receiving message, entire packet\n" + "Debug only sending message, header only\n" + "Debug only receiving message, header only\n") { int idx_packet = 3; int idx_send_recv = 4; @@ -2480,8 +2537,12 @@ DEFUN (debug_ospf6_message, if (argc == 4) level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV; + else if (!strncmp(argv[idx_send_recv]->arg, "send-h", 6)) + level = OSPF6_DEBUG_MESSAGE_SEND_HDR; else if (!strncmp(argv[idx_send_recv]->arg, "s", 1)) level = OSPF6_DEBUG_MESSAGE_SEND; + else if (!strncmp(argv[idx_send_recv]->arg, "recv-h", 6)) + level = OSPF6_DEBUG_MESSAGE_RECV_HDR; else if (!strncmp(argv[idx_send_recv]->arg, "r", 1)) level = OSPF6_DEBUG_MESSAGE_RECV; @@ -2494,22 +2555,21 @@ DEFUN (debug_ospf6_message, return CMD_SUCCESS; } -DEFUN (no_debug_ospf6_message, - no_debug_ospf6_message_cmd, - "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]", - NO_STR - DEBUG_STR - OSPF6_STR - "Debug OSPFv3 message\n" - "Debug Unknown message\n" - "Debug Hello message\n" - "Debug Database Description message\n" - "Debug Link State Request message\n" - "Debug Link State Update message\n" - "Debug Link State Acknowledgement message\n" - "Debug All message\n" - "Debug only sending message\n" - "Debug only receiving message\n") +DEFUN(no_debug_ospf6_message, no_debug_ospf6_message_cmd, + "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]", + NO_STR DEBUG_STR OSPF6_STR + "Debug OSPFv3 message\n" + "Debug Unknown message\n" + "Debug Hello message\n" + "Debug Database Description message\n" + "Debug Link State Request message\n" + "Debug Link State Update message\n" + "Debug Link State Acknowledgement message\n" + "Debug All message\n" + "Debug only sending message, entire pkt\n" + "Debug only receiving message, entire pkt\n" + "Debug only sending message, header only\n" + "Debug only receiving message, header only\n") { int idx_packet = 4; int idx_send_recv = 5; @@ -2534,9 +2594,15 @@ DEFUN (no_debug_ospf6_message, type = OSPF6_MESSAGE_TYPE_ALL; if (argc == 5) - level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV; + level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV + | OSPF6_DEBUG_MESSAGE_SEND_HDR + | OSPF6_DEBUG_MESSAGE_RECV_HDR; + else if (!strncmp(argv[idx_send_recv]->arg, "send-h", 6)) + level = OSPF6_DEBUG_MESSAGE_SEND_HDR; else if (!strncmp(argv[idx_send_recv]->arg, "s", 1)) level = OSPF6_DEBUG_MESSAGE_SEND; + else if (!strncmp(argv[idx_send_recv]->arg, "recv-h", 6)) + level = OSPF6_DEBUG_MESSAGE_RECV_HDR; else if (!strncmp(argv[idx_send_recv]->arg, "r", 1)) level = OSPF6_DEBUG_MESSAGE_RECV; @@ -2554,16 +2620,23 @@ int config_write_ospf6_debug_message(struct vty *vty) { const char *type_str[] = {"unknown", "hello", "dbdesc", "lsreq", "lsupdate", "lsack"}; - unsigned char s = 0, r = 0; + unsigned char s = 0, r = 0, sh = 0, rh = 0; int i; for (i = 0; i < 6; i++) { - if (IS_OSPF6_DEBUG_MESSAGE(i, SEND)) + if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND)) s |= 1 << i; - if (IS_OSPF6_DEBUG_MESSAGE(i, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV)) r |= 1 << i; } + for (i = 0; i < 6; i++) { + if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR)) + sh |= 1 << i; + if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR)) + rh |= 1 << i; + } + if (s == 0x3f && r == 0x3f) { vty_out(vty, "debug ospf6 message all\n"); return 0; @@ -2577,6 +2650,14 @@ int config_write_ospf6_debug_message(struct vty *vty) return 0; } + if (sh == 0x3f && rh == 0) { + vty_out(vty, "debug ospf6 message all send-hdr\n"); + return 0; + } else if (sh == 0 && rh == 0x3f) { + vty_out(vty, "debug ospf6 message all recv-hdr\n"); + return 0; + } + /* Unknown message is logged by default */ if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) @@ -2587,15 +2668,25 @@ int config_write_ospf6_debug_message(struct vty *vty) vty_out(vty, "no debug ospf6 message unknown recv\n"); for (i = 1; i < 6; i++) { - if (IS_OSPF6_DEBUG_MESSAGE(i, SEND) - && IS_OSPF6_DEBUG_MESSAGE(i, RECV)) + if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND) + && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV)) vty_out(vty, "debug ospf6 message %s\n", type_str[i]); - else if (IS_OSPF6_DEBUG_MESSAGE(i, SEND)) + else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND)) vty_out(vty, "debug ospf6 message %s send\n", type_str[i]); - else if (IS_OSPF6_DEBUG_MESSAGE(i, RECV)) + else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV)) vty_out(vty, "debug ospf6 message %s recv\n", type_str[i]); + else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR) + && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR)) + vty_out(vty, "debug ospf6 message %s; header only\n", + type_str[i]); + else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR)) + vty_out(vty, "debug ospf6 message %s recv-hdr\n", + type_str[i]); + else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR)) + vty_out(vty, "debug ospf6 message %s send-hdr\n", + type_str[i]); } return 0; diff --git a/ospf6d/ospf6_message.h b/ospf6d/ospf6_message.h index 7ec8cb785f..c4cdbd52f4 100644 --- a/ospf6d/ospf6_message.h +++ b/ospf6d/ospf6_message.h @@ -25,14 +25,34 @@ /* Debug option */ extern unsigned char conf_debug_ospf6_message[]; +#define OSPF6_ACTION_SEND 0x01 +#define OSPF6_ACTION_RECV 0x02 #define OSPF6_DEBUG_MESSAGE_SEND 0x01 #define OSPF6_DEBUG_MESSAGE_RECV 0x02 +#define OSPF6_DEBUG_MESSAGE_SEND_HDR 0x04 +#define OSPF6_DEBUG_MESSAGE_RECV_HDR 0x08 +#define OSPF6_DEBUG_MESSAGE_SEND_BOTH \ + OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_SEND_HDR +#define OSPF6_DEBUG_MESSAGE_RECV_BOTH \ + OSPF6_DEBUG_MESSAGE_RECV | OSPF6_DEBUG_MESSAGE_RECV_HDR + #define OSPF6_DEBUG_MESSAGE_ON(type, level) \ (conf_debug_ospf6_message[type] |= (level)) #define OSPF6_DEBUG_MESSAGE_OFF(type, level) \ (conf_debug_ospf6_message[type] &= ~(level)) + #define IS_OSPF6_DEBUG_MESSAGE(t, e) \ - (conf_debug_ospf6_message[t] & OSPF6_DEBUG_MESSAGE_##e) + ((OSPF6_DEBUG_MESSAGE_##e) == OSPF6_DEBUG_MESSAGE_RECV_HDR) \ + ? (conf_debug_ospf6_message[t] \ + & (OSPF6_DEBUG_MESSAGE_RECV_BOTH)) \ + : (((OSPF6_DEBUG_MESSAGE_##e) == OSPF6_DEBUG_MESSAGE_SEND_HDR) \ + ? (conf_debug_ospf6_message[t] \ + & (OSPF6_DEBUG_MESSAGE_SEND_BOTH)) \ + : (conf_debug_ospf6_message[t] \ + & (OSPF6_DEBUG_MESSAGE_##e))) + +#define IS_OSPF6_DEBUG_MESSAGE_ENABLED(type, e) \ + (conf_debug_ospf6_message[type] & (OSPF6_DEBUG_MESSAGE_##e)) /* Type */ #define OSPF6_MESSAGE_TYPE_UNKNOWN 0x0 @@ -110,11 +130,11 @@ struct ospf6_lsupdate { /* It is just a sequence of LSA Headers */ /* Function definition */ -extern void ospf6_hello_print(struct ospf6_header *); -extern void ospf6_dbdesc_print(struct ospf6_header *); -extern void ospf6_lsreq_print(struct ospf6_header *); -extern void ospf6_lsupdate_print(struct ospf6_header *); -extern void ospf6_lsack_print(struct ospf6_header *); +extern void ospf6_hello_print(struct ospf6_header *, int action); +extern void ospf6_dbdesc_print(struct ospf6_header *, int action); +extern void ospf6_lsreq_print(struct ospf6_header *, int action); +extern void ospf6_lsupdate_print(struct ospf6_header *, int action); +extern void ospf6_lsack_print(struct ospf6_header *, int action); extern int ospf6_iobuf_size(unsigned int size); extern void ospf6_message_terminate(void); 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 e01cfe3e03..b022133dcd 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -113,7 +113,6 @@ ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance, struct external_info *new; struct route_node *rn; struct ospf_external *ext; - char inetbuf[INET6_BUFSIZ]; ext = ospf_external_lookup(ospf, type, instance); if (!ext) @@ -121,26 +120,23 @@ ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance, rn = route_node_get(EXTERNAL_INFO(ext), (struct prefix *)&p); /* If old info exists, -- discard new one or overwrite with new one? */ - if (rn) - if (rn->info) { - new = rn->info; - if ((new->ifindex == ifindex) - && (new->nexthop.s_addr == nexthop.s_addr) - && (new->tag == tag)) { - route_unlock_node(rn); - return NULL; /* NULL => no LSA to refresh */ - } - - inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf, - sizeof(inetbuf)); - if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) - zlog_debug( - "Redistribute[%s][%d][%u]: %pFX discarding old info with NH %s.", - ospf_redist_string(type), instance, - ospf->vrf_id, &p, inetbuf); - XFREE(MTYPE_OSPF_EXTERNAL_INFO, rn->info); + if (rn && rn->info) { + new = rn->info; + if ((new->ifindex == ifindex) + && (new->nexthop.s_addr == nexthop.s_addr) + && (new->tag == tag)) { + route_unlock_node(rn); + return NULL; /* NULL => no LSA to refresh */ } + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "Redistribute[%s][%d][%u]: %pFX discarding old info with NH %pI4.", + ospf_redist_string(type), instance, + ospf->vrf_id, &p, &nexthop.s_addr); + XFREE(MTYPE_OSPF_EXTERNAL_INFO, rn->info); + } + /* Create new External info instance. */ new = ospf_external_info_new(type, instance); new->p = p; @@ -155,12 +151,10 @@ ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance, rn->info = new; if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { - inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf, - sizeof(inetbuf)); zlog_debug( - "Redistribute[%s][%u]: %pFX external info created, with NH %s", - ospf_redist_string(type), ospf->vrf_id, - &p, inetbuf); + "Redistribute[%s][%u]: %pFX external info created, with NH %pI4", + ospf_redist_string(type), ospf->vrf_id, &p, + &nexthop.s_addr); } return new; } @@ -329,34 +323,36 @@ void ospf_redistribute_withdraw(struct ospf *ospf, uint8_t type, return; /* Delete external info for specified type. */ - if (EXTERNAL_INFO(ext)) - for (rn = route_top(EXTERNAL_INFO(ext)); rn; - rn = route_next(rn)) - if ((ei = rn->info)) { - struct ospf_external_aggr_rt *aggr; - - if (is_prefix_default(&ei->p) - && ospf->default_originate - != DEFAULT_ORIGINATE_NONE) - continue; + if (!EXTERNAL_INFO(ext)) + return; + + for (rn = route_top(EXTERNAL_INFO(ext)); rn; rn = route_next(rn)) { + ei = rn->info; - aggr = ei->aggr_route; + if (!ei) + continue; + + 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, + 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 */ bool is_valid_summary_addr(struct prefix_ipv4 *p) { 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_sr.c b/ospfd/ospf_sr.c index a7a2e03632..d003f3bf7c 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -1689,7 +1689,8 @@ void ospf_sr_ext_itf_add(struct ext_itf *exti) else srl->nhlfe[1].nexthop = exti->rmt_itf_addr.value; break; - default: + case PREF_SID: + case LOCAL_SID: /* Wrong SID Type. Abort! */ XFREE(MTYPE_OSPF_SR_PARAMS, srl); return; 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_zebra.c b/ospfd/ospf_zebra.c index a2ce4d1ce7..f198995dfa 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -637,7 +637,8 @@ void ospf_zebra_update_prefix_sid(const struct sr_prefix *srp) } } break; - default: + case ADJ_SID: + case LAN_ADJ_SID: return; } @@ -765,12 +766,12 @@ int ospf_is_type_redistributed(struct ospf *ospf, int type, ospf->vrf_id) : ((instance && redist_check_instance( - &zclient->mi_redist[AFI_IP][type], - instance)) + &zclient->mi_redist[AFI_IP][type], + instance)) || (!instance && vrf_bitmap_check( - zclient->redist[AFI_IP][type], - ospf->vrf_id)))); + zclient->redist[AFI_IP][type], + ospf->vrf_id)))); } int ospf_redistribute_set(struct ospf *ospf, int type, unsigned short instance, @@ -1262,104 +1263,92 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS) return 0; } if (ospf->router_id.s_addr != INADDR_ANY) { - if (ei) { - if (is_prefix_default(&p)) - ospf_external_lsa_refresh_default(ospf); - else { - struct ospf_external_aggr_rt *aggr; - struct as_external_lsa *al; - struct ospf_lsa *lsa = NULL; - struct in_addr mask; - - aggr = ospf_external_aggr_match(ospf, - &ei->p); + if (is_prefix_default(&p)) + ospf_external_lsa_refresh_default(ospf); + else { + struct ospf_external_aggr_rt *aggr; + struct as_external_lsa *al; + struct ospf_lsa *lsa = NULL; + struct in_addr mask; + + aggr = ospf_external_aggr_match(ospf, &ei->p); + + if (aggr) { + /* Check the AS-external-LSA + * should be originated. + */ + if (!ospf_redistribute_check(ospf, ei, + NULL)) + return 0; + + if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Send Aggreate LSA (%pI4/%d)", + __func__, + &aggr->p.prefix, + aggr->p.prefixlen); + + ospf_originate_summary_lsa(ospf, aggr, + ei); + + /* Handling the case where the + * external route prefix + * and aggegate prefix is same + * If same dont flush the + * originated + * external LSA. + */ + if (prefix_same( + (struct prefix *)&aggr->p, + (struct prefix *)&ei->p)) + return 0; + + lsa = ospf_external_info_find_lsa( + ospf, &ei->p); + + if (lsa) { + al = (struct as_external_lsa *) + lsa->data; + masklen2ip(ei->p.prefixlen, + &mask); + + if (mask.s_addr + != al->mask.s_addr) + return 0; - if (aggr) { - /* Check the AS-external-LSA - * should be originated. + ospf_external_lsa_flush( + ospf, ei->type, &ei->p, + 0); + } + } else { + struct ospf_lsa *current; + + current = ospf_external_info_find_lsa( + ospf, &ei->p); + if (!current) { + /* Check the + * AS-external-LSA + * should be + * originated. */ if (!ospf_redistribute_check( ospf, ei, NULL)) return 0; + ospf_external_lsa_originate( + ospf, ei); + } else { if (IS_DEBUG_OSPF( - lsa, - EXTNL_LSA_AGGR)) + zebra, + ZEBRA_REDISTRIBUTE)) zlog_debug( - "%s: Send Aggreate LSA (%pI4/%d)", + "%s: %pI4 refreshing LSA", __func__, - &aggr->p.prefix, - aggr->p.prefixlen); - - ospf_originate_summary_lsa( - ospf, aggr, ei); - - /* Handling the case where the - * external route prefix - * and aggegate prefix is same - * If same dont flush the - * originated - * external LSA. - */ - if (prefix_same( - (struct prefix - *)&aggr->p, - (struct prefix *)&ei - ->p)) - return 0; - - lsa = ospf_external_info_find_lsa( - ospf, &ei->p); - - if (lsa) { - al = (struct - as_external_lsa *) - lsa->data; - masklen2ip( - ei->p.prefixlen, - &mask); - - if (mask.s_addr - != al->mask.s_addr) - return 0; - - ospf_external_lsa_flush( - ospf, ei->type, - &ei->p, 0); - } - } else { - struct ospf_lsa *current; - - current = - ospf_external_info_find_lsa( - ospf, &ei->p); - if (!current) { - /* Check the - * AS-external-LSA - * should be - * originated. - */ - if (!ospf_redistribute_check( - ospf, ei, - NULL)) - return 0; - - ospf_external_lsa_originate( - ospf, ei); - } else { - if (IS_DEBUG_OSPF( - zebra, - ZEBRA_REDISTRIBUTE)) - zlog_debug( - "%s: %pI4 refreshing LSA", - __func__, - &p.prefix); - ospf_external_lsa_refresh( - ospf, current, - ei, - LSA_REFRESH_FORCE, - false); - } + &p.prefix); + ospf_external_lsa_refresh( + ospf, current, ei, + LSA_REFRESH_FORCE, + false); } } } @@ -1371,20 +1360,19 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS) */ ospf_external_lsa_default_routemap_apply(ospf, ei, cmd); - } else /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ - { + } else { /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ struct ospf_external_aggr_rt *aggr; ei = ospf_external_info_lookup(ospf, rt_type, api.instance, &p); if (ei == NULL) return 0; - else - /* - * Check if default-information originate i - * with some routemap prefix/access list match. - * Apply before ei is deleted. - */ - ospf_external_lsa_default_routemap_apply(ospf, ei, cmd); + + /* + * Check if default-information originate i + * with some routemap prefix/access list match. + * Apply before ei is deleted. + */ + ospf_external_lsa_default_routemap_apply(ospf, ei, cmd); aggr = ospf_external_aggr_match(ospf, &ei->p); @@ -1405,7 +1393,6 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS) } } - return 0; } @@ -1490,85 +1477,83 @@ static int ospf_distribute_list_update_timer(struct thread *thread) rt = ext->external_info; if (!rt) continue; - for (rn = route_top(rt); rn; rn = route_next(rn)) - if ((ei = rn->info) != NULL) { - if (is_prefix_default(&ei->p)) - default_refresh = 1; - else { - struct ospf_external_aggr_rt - *aggr; - aggr = ospf_external_aggr_match( - ospf, &ei->p); - if (aggr) { - /* Check the - * AS-external-LSA - * should be originated. - */ - if (!ospf_redistribute_check( - ospf, ei, - NULL)) { - - ospf_unlink_ei_from_aggr( - ospf, - aggr, - ei); - continue; - } - - if (IS_DEBUG_OSPF( - lsa, - EXTNL_LSA_AGGR)) - zlog_debug( - "%s: Send Aggregate LSA (%pI4/%d)", - __func__, - &aggr->p.prefix, - aggr->p.prefixlen); - - /* Originate Aggregate - * LSA - */ - ospf_originate_summary_lsa( + for (rn = route_top(rt); rn; rn = route_next(rn)) { + ei = rn->info; + if (!ei) + continue; + + if (is_prefix_default(&ei->p)) + default_refresh = 1; + else { + struct ospf_external_aggr_rt *aggr; + + aggr = ospf_external_aggr_match(ospf, + &ei->p); + if (aggr) { + /* Check the + * AS-external-LSA + * should be originated. + */ + if (!ospf_redistribute_check( + ospf, ei, NULL)) { + + ospf_unlink_ei_from_aggr( ospf, aggr, ei); - } else if ( - (lsa = ospf_external_info_find_lsa( - ospf, - &ei->p))) { - int force = - LSA_REFRESH_IF_CHANGED; - /* If this is a MaxAge - * LSA, we need to - * force refresh it - * because distribute - * settings might have - * changed and now, - * this LSA needs to be - * originated, not be - * removed. - * If we don't force - * refresh it, it will - * remain a MaxAge LSA - * because it will look - * like it hasn't - * changed. Neighbors - * will not receive - * updates for this LSA. - */ - if (IS_LSA_MAXAGE(lsa)) - force = LSA_REFRESH_FORCE; - - ospf_external_lsa_refresh( - ospf, lsa, ei, - force, false); - } else { - if (!ospf_redistribute_check( - ospf, ei, - NULL)) - continue; - ospf_external_lsa_originate( - ospf, ei); + continue; } + + if (IS_DEBUG_OSPF( + lsa, + EXTNL_LSA_AGGR)) + zlog_debug( + "%s: Send Aggregate LSA (%pI4/%d)", + __func__, + &aggr->p.prefix, + aggr->p.prefixlen); + + /* Originate Aggregate + * LSA + */ + ospf_originate_summary_lsa( + ospf, aggr, ei); + } else if ( + (lsa = ospf_external_info_find_lsa( + ospf, &ei->p))) { + int force = + LSA_REFRESH_IF_CHANGED; + /* If this is a MaxAge + * LSA, we need to + * force refresh it + * because distribute + * settings might have + * changed and now, + * this LSA needs to be + * originated, not be + * removed. + * If we don't force + * refresh it, it will + * remain a MaxAge LSA + * because it will look + * like it hasn't + * changed. Neighbors + * will not receive + * updates for this LSA. + */ + if (IS_LSA_MAXAGE(lsa)) + force = LSA_REFRESH_FORCE; + + ospf_external_lsa_refresh( + ospf, lsa, ei, force, + false); + } else { + if (!ospf_redistribute_check( + ospf, ei, NULL)) + continue; + ospf_external_lsa_originate( + ospf, ei); } } + } } } if (default_refresh) @@ -1718,17 +1703,16 @@ void ospf_prefix_list_update(struct prefix_list *plist) struct ospf_redist *red; red_list = ospf->redist[type]; - if (red_list) { - for (ALL_LIST_ELEMENTS_RO(red_list, node, - red)) { - if (ROUTEMAP(red)) { - /* if route-map is not NULL - * it may be using - * this prefix list */ - ospf_distribute_list_update( - ospf, type, - red->instance); - } + if (!red_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + if (ROUTEMAP(red)) { + /* if route-map is not NULL + * it may be using + * this prefix list */ + ospf_distribute_list_update( + ospf, type, red->instance); } } } @@ -1736,28 +1720,24 @@ void ospf_prefix_list_update(struct prefix_list *plist) /* Update area filter-lists. */ for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { /* Update filter-list in. */ - if (PREFIX_NAME_IN(area)) - if (strcmp(PREFIX_NAME_IN(area), - prefix_list_name(plist)) - == 0) { - PREFIX_LIST_IN(area) = - prefix_list_lookup( - AFI_IP, - PREFIX_NAME_IN(area)); - abr_inv++; - } + if (PREFIX_NAME_IN(area) + && strcmp(PREFIX_NAME_IN(area), + prefix_list_name(plist)) + == 0) { + PREFIX_LIST_IN(area) = prefix_list_lookup( + AFI_IP, PREFIX_NAME_IN(area)); + abr_inv++; + } /* Update filter-list out. */ - if (PREFIX_NAME_OUT(area)) - if (strcmp(PREFIX_NAME_OUT(area), - prefix_list_name(plist)) - == 0) { - PREFIX_LIST_IN(area) = - prefix_list_lookup( - AFI_IP, - PREFIX_NAME_OUT(area)); - abr_inv++; - } + if (PREFIX_NAME_OUT(area) + && strcmp(PREFIX_NAME_OUT(area), + prefix_list_name(plist)) + == 0) { + PREFIX_LIST_IN(area) = prefix_list_lookup( + AFI_IP, PREFIX_NAME_OUT(area)); + abr_inv++; + } } /* Schedule ABR task. */ @@ -1857,14 +1837,17 @@ void ospf_distance_reset(struct ospf *ospf) struct route_node *rn; struct ospf_distance *odistance; - for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn)) - if ((odistance = rn->info) != NULL) { - if (odistance->access_list) - free(odistance->access_list); - ospf_distance_free(odistance); - rn->info = NULL; - route_unlock_node(rn); - } + for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn)) { + odistance = rn->info; + if (!odistance) + continue; + + if (odistance->access_list) + free(odistance->access_list); + ospf_distance_free(odistance); + rn->info = NULL; + route_unlock_node(rn); + } } uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *p, @@ -1874,18 +1857,16 @@ uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *p, if (ospf == NULL) return 0; - if (ospf->distance_intra) - if (or->path_type == OSPF_PATH_INTRA_AREA) - return ospf->distance_intra; + if (ospf->distance_intra && or->path_type == OSPF_PATH_INTRA_AREA) + return ospf->distance_intra; - if (ospf->distance_inter) - if (or->path_type == OSPF_PATH_INTER_AREA) - return ospf->distance_inter; + if (ospf->distance_inter && or->path_type == OSPF_PATH_INTER_AREA) + return ospf->distance_inter; - if (ospf->distance_external) - if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL || - or->path_type == OSPF_PATH_TYPE2_EXTERNAL) - return ospf->distance_external; + if (ospf->distance_external + && (or->path_type == OSPF_PATH_TYPE1_EXTERNAL || + or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) + return ospf->distance_external; if (ospf->distance_all) return ospf->distance_all; 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/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/ripd/rip_cli.c b/ripd/rip_cli.c index 87098ece64..43e5b21fa1 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -1019,11 +1019,56 @@ DEFPY_YANG (clear_ip_rip, return ret; } +DEFUN (rip_distribute_list, + rip_distribute_list_cmd, + "distribute-list [prefix] WORD <in|out> [WORD]", + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_parser(prefix, true, argv[2 + prefix]->text, + argv[1 + prefix]->arg, ifname); +} + +DEFUN (rip_no_distribute_list, + rip_no_distribute_list_cmd, + "no distribute-list [prefix] WORD <in|out> [WORD]", + NO_STR + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_no_parser(vty, prefix, true, + argv[3 + prefix]->text, + argv[2 + prefix]->arg, ifname); +} + void rip_cli_init(void) { install_element(CONFIG_NODE, &router_rip_cmd); install_element(CONFIG_NODE, &no_router_rip_cmd); + install_element(RIP_NODE, &rip_distribute_list_cmd); + install_element(RIP_NODE, &rip_no_distribute_list_cmd); + install_element(RIP_NODE, &rip_allow_ecmp_cmd); install_element(RIP_NODE, &rip_default_information_originate_cmd); install_element(RIP_NODE, &rip_default_metric_cmd); diff --git a/ripd/ripd.c b/ripd/ripd.c index 1c23575bf3..9832c7c52a 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -3722,9 +3722,6 @@ void rip_init(void) prefix_list_add_hook(rip_distribute_update_all); prefix_list_delete_hook(rip_distribute_update_all); - /* Distribute list install. */ - distribute_list_init(RIP_NODE); - /* Route-map */ rip_route_map_init(); diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c index 365082f806..7e0d014086 100644 --- a/ripngd/ripng_cli.c +++ b/ripngd/ripng_cli.c @@ -503,11 +503,58 @@ DEFPY_YANG (clear_ipv6_rip, return ret; } +DEFUN (ripng_ipv6_distribute_list, + ripng_ipv6_distribute_list_cmd, + "ipv6 distribute-list [prefix] WORD <in|out> [WORD]", + "IPv6\n" + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_parser(prefix, false, argv[3 + prefix]->text, + argv[2 + prefix]->arg, ifname); +} + +DEFUN (ripng_no_ipv6_distribute_list, + ripng_no_ipv6_distribute_list_cmd, + "no ipv6 distribute-list [prefix] WORD <in|out> [WORD]", + NO_STR + "IPv6\n" + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_no_parser(vty, prefix, false, + argv[4 + prefix]->text, + argv[3 + prefix]->arg, ifname); +} + void ripng_cli_init(void) { install_element(CONFIG_NODE, &router_ripng_cmd); install_element(CONFIG_NODE, &no_router_ripng_cmd); + install_element(RIPNG_NODE, &ripng_ipv6_distribute_list_cmd); + install_element(RIPNG_NODE, &ripng_no_ipv6_distribute_list_cmd); + install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd); install_element(RIPNG_NODE, &ripng_default_information_originate_cmd); install_element(RIPNG_NODE, &ripng_default_metric_cmd); diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 0e83140149..5a71928fbd 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -2723,9 +2723,6 @@ void ripng_init(void) prefix_list_add_hook(ripng_distribute_update_all); prefix_list_delete_hook(ripng_distribute_update_all); - /* Distribute list install. */ - distribute_list_init(RIPNG_NODE); - /* Route-map for interface. */ ripng_route_map_init(); 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/bgp_tcp_mss/__init__.py b/tests/topotests/bgp_tcp_mss/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_tcp_mss/__init__.py diff --git a/tests/topotests/bgp_tcp_mss/r1/bgpd.conf b/tests/topotests/bgp_tcp_mss/r1/bgpd.conf new file mode 100644 index 0000000000..07cfe2e2f1 --- /dev/null +++ b/tests/topotests/bgp_tcp_mss/r1/bgpd.conf @@ -0,0 +1,6 @@ +router bgp 65000 + no bgp ebgp-requires-policy + neighbor 192.168.255.2 remote-as 65001 + neighbor 192.168.255.2 timers 3 10 + exit-address-family +! diff --git a/tests/topotests/bgp_tcp_mss/r1/zebra.conf b/tests/topotests/bgp_tcp_mss/r1/zebra.conf new file mode 100644 index 0000000000..6e9b0b4a7e --- /dev/null +++ b/tests/topotests/bgp_tcp_mss/r1/zebra.conf @@ -0,0 +1,6 @@ +! +interface r1-eth0 + ip address 192.168.255.1/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_tcp_mss/r2/bgpd.conf b/tests/topotests/bgp_tcp_mss/r2/bgpd.conf new file mode 100644 index 0000000000..b2d945583c --- /dev/null +++ b/tests/topotests/bgp_tcp_mss/r2/bgpd.conf @@ -0,0 +1,6 @@ +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 192.168.255.1 remote-as 65000 + neighbor 192.168.255.1 timers 3 10 + exit-address-family +! diff --git a/tests/topotests/bgp_tcp_mss/r2/zebra.conf b/tests/topotests/bgp_tcp_mss/r2/zebra.conf new file mode 100644 index 0000000000..6c14de583b --- /dev/null +++ b/tests/topotests/bgp_tcp_mss/r2/zebra.conf @@ -0,0 +1,6 @@ +! +interface r2-eth0 + ip address 192.168.255.2/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py new file mode 100644 index 0000000000..7500c3b3ad --- /dev/null +++ b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python + +# +# bgp_tcp_mss.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2021 by +# Abhinay Ramesh <rabhinay@vmware.com> +# +# Permission to use, copy, modify, and/or 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 NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF 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. +# + +""" +bgp_tcp_mss.py: + +Test if works the following commands: +router bgp 65000 + neighbor 192.168.255.2 tcp-mss 500 + +Need to verify if the tcp-mss value is reflected in the TCP session. +""" + +import os +import sys +import json +import time +import pytest +import functools + +# add after imports, before defining classes or functions: +pytestmark = [pytest.mark.bgpd] + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from mininet.topo import Topo + + +class TemplateTopo(Topo): + def build(self, *_args, **_opts): + tgen = get_topogen(self) + + for routern in range(1, 3): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + +def setup_module(mod): + tgen = Topogen(TemplateTopo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_tcp_mss(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + router1 = tgen.gears["r1"] + router2 = tgen.gears["r2"] + + def _bgp_converge(router): + output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.2 json")) + expected = { + "192.168.255.2": { + "bgpState": "Established", + "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 0}}, + } + } + return topotest.json_cmp(output, expected) + + def _bgp_conf_tcp_mss(router, as_num, neigh): + router.vtysh_cmd( + """configure terminal + router bgp {0} + neighbor {1} tcp-mss 500""".format( + as_num, neigh + ) + ) + + def _bgp_clear_session(router): + router.vtysh_cmd("clear bgp *") + + def _bgp_check_neighbor_tcp_mss(router, neigh): + output = json.loads(router.vtysh_cmd("show bgp neighbor {} json".format(neigh))) + expected = { + "{}".format(neigh): {"bgpTcpMssConfigured": 500, "bgpTcpMssSynced": 488} + } + return topotest.json_cmp(output, expected) + + logger.info("Check if neighbor sessions are up in {}".format(router1.name)) + test_func = functools.partial(_bgp_converge, router1) + success, result = topotest.run_and_expect(test_func, None, count=15, wait=0.5) + assert result is None, 'Failed to see BGP convergence in "{}"'.format(router1.name) + + logger.info("BGP neighbor session is up in {}".format(router1.name)) + + logger.info( + "Configure tcp-mss 500 on {} and reset the session".format(router1.name) + ) + _bgp_conf_tcp_mss(router1, "65000", "192.168.255.2") + _bgp_clear_session(router1) + + logger.info( + "Configure tcp-mss 500 on {} and reset the session".format(router2.name) + ) + _bgp_conf_tcp_mss(router2, "65001", "192.168.255.1") + _bgp_clear_session(router2) + + logger.info( + "Check if neighbor session is up after reset in {}".format(router1.name) + ) + test_func = functools.partial(_bgp_converge, router1) + success, result = topotest.run_and_expect(test_func, None, count=15, wait=0.5) + assert result is None, 'Failed to see BGP convergence after reset in "{}"'.format( + router1.name + ) + + logger.info( + "Verify if TCP MSS value is synced with neighbor in {}".format(router1.name) + ) + test_func = functools.partial(_bgp_check_neighbor_tcp_mss, router1, "192.168.255.2") + success, result = topotest.run_and_expect(test_func, None, count=3, wait=0.5) + assert ( + result is None + ), 'Failed to sync TCP MSS value over BGP session in "{}"'.format(router1.name) + logger.info("TCP MSS value is synced with neighbor in {}".format(router1.name)) + + logger.info( + "Verify if TCP MSS value is synced with neighbor in {}".format(router2.name) + ) + test_func = functools.partial(_bgp_check_neighbor_tcp_mss, router2, "192.168.255.1") + success, result = topotest.run_and_expect(test_func, None, count=3, wait=0.5) + assert ( + result is None + ), 'Failed to sync TCP MSS value over BGP session in "{}"'.format(router2.name) + logger.info("TCP MSS value is synced with neighbor in {}".format(router2.name)) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) 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/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/vtysh/extract.pl.in b/vtysh/extract.pl.in index af974771cc..37ae0ab189 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -119,13 +119,6 @@ sub scan_file { $protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_ISISD|VTYSH_FABRICD"; } } - elsif ($file =~ /lib\/distribute\.c$/) { - if ($defun_array[1] =~ m/ipv6/) { - $protocol = "VTYSH_RIPNGD"; - } else { - $protocol = "VTYSH_RIPD"; - } - } elsif ($file =~ /lib\/if_rmap\.c$/) { if ($defun_array[1] =~ m/ipv6/) { $protocol = "VTYSH_RIPNGD"; 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/if_netlink.c b/zebra/if_netlink.c index b1e0f21f68..fbf64439e3 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1119,7 +1119,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; } @@ -1695,6 +1695,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 5f3ee9428c..7fd967dd8b 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1075,6 +1075,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 @@ -1150,18 +1153,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; @@ -1179,8 +1180,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 753eb6b58f..df4872d48e 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -486,7 +486,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/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/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... */ |
