diff options
58 files changed, 613 insertions, 1517 deletions
diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index 75034d220c..2e213a2237 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -338,11 +338,12 @@ void bfd_cli_show_minimum_ttl(struct vty *vty, const struct lyd_node *dnode, DEFPY_YANG( bfd_peer_mult, bfd_peer_mult_cmd, - "detect-multiplier (2-255)$multiplier", + "[no] detect-multiplier ![(2-255)$multiplier]", + NO_STR "Configure peer detection multiplier\n" "Configure peer detection multiplier value\n") { - nb_cli_enqueue_change(vty, "./detection-multiplier", NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./detection-multiplier", no ? NB_OP_DESTROY : NB_OP_MODIFY, multiplier_str); return nb_cli_apply_changes(vty, NULL); } @@ -356,14 +357,15 @@ void bfd_cli_show_mult(struct vty *vty, const struct lyd_node *dnode, DEFPY_YANG( bfd_peer_rx, bfd_peer_rx_cmd, - "receive-interval (10-60000)$interval", + "[no] receive-interval ![(10-60000)$interval]", + NO_STR "Configure peer receive interval\n" "Configure peer receive interval value in milliseconds\n") { char value[32]; snprintf(value, sizeof(value), "%ld", interval * 1000); - nb_cli_enqueue_change(vty, "./required-receive-interval", NB_OP_MODIFY, + nb_cli_enqueue_change(vty, "./required-receive-interval", no ? NB_OP_DESTROY : NB_OP_MODIFY, value); return nb_cli_apply_changes(vty, NULL); @@ -379,7 +381,8 @@ void bfd_cli_show_rx(struct vty *vty, const struct lyd_node *dnode, DEFPY_YANG( bfd_peer_tx, bfd_peer_tx_cmd, - "transmit-interval (10-60000)$interval", + "[no] transmit-interval ![(10-60000)$interval]", + NO_STR "Configure peer transmit interval\n" "Configure peer transmit interval value in milliseconds\n") { @@ -387,7 +390,7 @@ DEFPY_YANG( snprintf(value, sizeof(value), "%ld", interval * 1000); nb_cli_enqueue_change(vty, "./desired-transmission-interval", - NB_OP_MODIFY, value); + no ? NB_OP_DESTROY : NB_OP_MODIFY, value); return nb_cli_apply_changes(vty, NULL); } @@ -436,7 +439,8 @@ void bfd_cli_show_echo(struct vty *vty, const struct lyd_node *dnode, DEFPY_YANG( bfd_peer_echo_interval, bfd_peer_echo_interval_cmd, - "echo-interval (10-60000)$interval", + "[no] echo-interval ![(10-60000)$interval]", + NO_STR "Configure peer echo intervals\n" "Configure peer echo rx/tx intervals value in milliseconds\n") { @@ -449,16 +453,17 @@ DEFPY_YANG( snprintf(value, sizeof(value), "%ld", interval * 1000); nb_cli_enqueue_change(vty, "./desired-echo-transmission-interval", - NB_OP_MODIFY, value); + no ? NB_OP_DESTROY : NB_OP_MODIFY, value); nb_cli_enqueue_change(vty, "./required-echo-receive-interval", - NB_OP_MODIFY, value); + no ? NB_OP_DESTROY : NB_OP_MODIFY, value); return nb_cli_apply_changes(vty, NULL); } DEFPY_YANG( bfd_peer_echo_transmit_interval, bfd_peer_echo_transmit_interval_cmd, - "echo transmit-interval (10-60000)$interval", + "[no] echo transmit-interval ![(10-60000)$interval]", + NO_STR "Configure peer echo intervals\n" "Configure desired transmit interval\n" "Configure interval value in milliseconds\n") @@ -472,7 +477,7 @@ DEFPY_YANG( snprintf(value, sizeof(value), "%ld", interval * 1000); nb_cli_enqueue_change(vty, "./desired-echo-transmission-interval", - NB_OP_MODIFY, value); + no ? NB_OP_DESTROY : NB_OP_MODIFY, value); return nb_cli_apply_changes(vty, NULL); } @@ -487,7 +492,8 @@ void bfd_cli_show_desired_echo_transmission_interval( DEFPY_YANG( bfd_peer_echo_receive_interval, bfd_peer_echo_receive_interval_cmd, - "echo receive-interval <disabled$disabled|(10-60000)$interval>", + "[no] echo receive-interval ![<disabled$disabled|(10-60000)$interval>]", + NO_STR "Configure peer echo intervals\n" "Configure required receive interval\n" "Disable echo packets receive\n" @@ -504,9 +510,9 @@ DEFPY_YANG( snprintf(value, sizeof(value), "0"); else snprintf(value, sizeof(value), "%ld", interval * 1000); - + nb_cli_enqueue_change(vty, "./required-echo-receive-interval", - NB_OP_MODIFY, value); + no ? NB_OP_DESTROY : NB_OP_MODIFY, value); return nb_cli_apply_changes(vty, NULL); } @@ -571,17 +577,20 @@ void bfd_cli_show_profile(struct vty *vty, const struct lyd_node *dnode, } ALIAS_YANG(bfd_peer_mult, bfd_profile_mult_cmd, - "detect-multiplier (2-255)$multiplier", + "[no] detect-multiplier ![(2-255)$multiplier]", + NO_STR "Configure peer detection multiplier\n" "Configure peer detection multiplier value\n") ALIAS_YANG(bfd_peer_tx, bfd_profile_tx_cmd, - "transmit-interval (10-60000)$interval", + "[no] transmit-interval ![(10-60000)$interval]", + NO_STR "Configure peer transmit interval\n" "Configure peer transmit interval value in milliseconds\n") ALIAS_YANG(bfd_peer_rx, bfd_profile_rx_cmd, - "receive-interval (10-60000)$interval", + "[no] receive-interval ![(10-60000)$interval]", + NO_STR "Configure peer receive interval\n" "Configure peer receive interval value in milliseconds\n") @@ -612,20 +621,23 @@ ALIAS_YANG(bfd_peer_echo, bfd_profile_echo_cmd, "Configure echo mode\n") ALIAS_YANG(bfd_peer_echo_interval, bfd_profile_echo_interval_cmd, - "echo-interval (10-60000)$interval", + "[no] echo-interval ![(10-60000)$interval]", + NO_STR "Configure peer echo interval\n" "Configure peer echo interval value in milliseconds\n") ALIAS_YANG( bfd_peer_echo_transmit_interval, bfd_profile_echo_transmit_interval_cmd, - "echo transmit-interval (10-60000)$interval", + "[no] echo transmit-interval ![(10-60000)$interval]", + NO_STR "Configure peer echo intervals\n" "Configure desired transmit interval\n" "Configure interval value in milliseconds\n") ALIAS_YANG( bfd_peer_echo_receive_interval, bfd_profile_echo_receive_interval_cmd, - "echo receive-interval <disabled$disabled|(10-60000)$interval>", + "[no] echo receive-interval ![<disabled$disabled|(10-60000)$interval>]", + NO_STR "Configure peer echo intervals\n" "Configure required receive interval\n" "Disable echo packets receive\n" diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index 556738a606..9d99c2c7fd 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -1047,7 +1047,7 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags, static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr) { - uint8_t bpi_num_labels; + uint8_t bpi_num_labels, adjin_num_labels; afi_t afi; safi_t safi; @@ -1241,11 +1241,12 @@ afibreak: bpi_num_labels ? bpi->extra->labels->label : NULL, bpi_num_labels); - if (adjin) - /* TODO: set label here when adjin supports labels */ - bmp_monitor(bmp, adjin->peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE, - bn_p, prd, adjin->attr, afi, safi, adjin->uptime, - NULL, 0); + if (adjin) { + adjin_num_labels = adjin->labels ? adjin->labels->num_labels : 0; + bmp_monitor(bmp, adjin->peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE, bn_p, prd, + adjin->attr, afi, safi, adjin->uptime, + adjin_num_labels ? &adjin->labels->label[0] : NULL, adjin_num_labels); + } if (bn) bgp_dest_unlock_node(bn); @@ -1382,7 +1383,7 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr) struct peer *peer; struct bgp_dest *bn = NULL; bool written = false; - uint8_t bpi_num_labels; + uint8_t bpi_num_labels, adjin_num_labels; bqe = bmp_pull(bmp); if (!bqe) @@ -1453,10 +1454,11 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr) if (adjin->peer == peer) break; } - /* TODO: set label here when adjin supports labels */ - bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE, - &bqe->p, prd, adjin ? adjin->attr : NULL, afi, safi, - adjin ? adjin->uptime : monotime(NULL), NULL, 0); + adjin_num_labels = adjin && adjin->labels ? adjin->labels->num_labels : 0; + bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE, &bqe->p, prd, + adjin ? adjin->attr : NULL, afi, safi, + adjin ? adjin->uptime : monotime(NULL), + adjin_num_labels ? &adjin->labels->label[0] : NULL, adjin_num_labels); written = true; } diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 5e6a62c9b9..535d2fc5f4 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -63,18 +63,16 @@ DEFINE_HOOK(bgp_hook_vrf_update, (struct vrf *vrf, bool enabled), (vrf, enabled)); /* bgpd options, we use GNU getopt library. */ -static const struct option longopts[] = { - { "bgp_port", required_argument, NULL, 'p' }, - { "listenon", required_argument, NULL, 'l' }, - { "no_kernel", no_argument, NULL, 'n' }, - { "skip_runas", no_argument, NULL, 'S' }, - { "ecmp", required_argument, NULL, 'e' }, - { "int_num", required_argument, NULL, 'I' }, - { "no_zebra", no_argument, NULL, 'Z' }, - { "socket_size", required_argument, NULL, 's' }, - { "v6-with-v4-nexthops", no_argument, NULL, 'v' }, - { 0 } -}; +static const struct option longopts[] = { { "bgp_port", required_argument, NULL, 'p' }, + { "listenon", required_argument, NULL, 'l' }, + { "no_kernel", no_argument, NULL, 'n' }, + { "skip_runas", no_argument, NULL, 'S' }, + { "ecmp", required_argument, NULL, 'e' }, + { "int_num", required_argument, NULL, 'I' }, + { "no_zebra", no_argument, NULL, 'Z' }, + { "socket_size", required_argument, NULL, 's' }, + { "v6-with-v4-nexthops", no_argument, NULL, 'x' }, + { 0 } }; /* signal definitions */ void sighup(void); @@ -424,11 +422,12 @@ int main(int argc, char **argv) int buffer_size = BGP_SOCKET_SNDBUF_SIZE; char *address; struct listnode *node; + bool v6_with_v4_nexthops = false; addresses->cmp = (int (*)(void *, void *))strcmp; frr_preinit(&bgpd_di, argc, argv); - frr_opt_add("p:l:SnZe:I:s:" DEPRECATED_OPTIONS, longopts, + frr_opt_add("p:l:SnZe:I:s:x" DEPRECATED_OPTIONS, longopts, " -p, --bgp_port Set BGP listen port number (0 means do not listen).\n" " -l, --listenon Listen on specified address (implies -n)\n" " -n, --no_kernel Do not install route to kernel.\n" @@ -437,7 +436,7 @@ int main(int argc, char **argv) " -e, --ecmp Specify ECMP to use.\n" " -I, --int_num Set instance number (label-manager)\n" " -s, --socket_size Set BGP peer socket send buffer size\n" - " , --v6-with-v4-nexthop Allow BGP to form v6 neighbors using v4 nexthops\n"); + " -x, --v6-with-v4-nexthop Allow BGP to form v6 neighbors using v4 nexthops\n"); /* Command line argument treatment. */ while (1) { @@ -499,8 +498,8 @@ int main(int argc, char **argv) case 's': buffer_size = atoi(optarg); break; - case 'v': - bm->v6_with_v4_nexthops = true; + case 'x': + v6_with_v4_nexthops = true; break; default: frr_help_exit(1); @@ -513,6 +512,7 @@ int main(int argc, char **argv) bgp_master_init(frr_init(), buffer_size, addresses); bm->startup_time = monotime(NULL); bm->port = bgp_port; + bm->v6_with_v4_nexthops = v6_with_v4_nexthops; if (bgp_port == 0) bgp_option_set(BGP_OPT_NO_LISTEN); if (no_fib_flag || no_zebra_flag) diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index eadd52b8e0..609afa4245 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -2,8 +2,10 @@ /* * BGP Multipath * Copyright (C) 2010 Google Inc. + * 2024 Nvidia Corporation + * Donald Sharp * - * This file is part of Quagga + * This file is part of FRR */ #include <zebra.h> @@ -191,78 +193,6 @@ int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1, } /* - * bgp_path_info_mpath_cmp - * - * This function determines our multipath list ordering. By ordering - * the list we can deterministically select which paths are included - * in the multipath set. The ordering also helps in detecting changes - * in the multipath selection so we can detect whether to send an - * update to zebra. - * - * The order of paths is determined first by received nexthop, and then - * by peer address if the nexthops are the same. - */ -static int bgp_path_info_mpath_cmp(void *val1, void *val2) -{ - struct bgp_path_info *bpi1, *bpi2; - int compare; - - bpi1 = val1; - bpi2 = val2; - - compare = bgp_path_info_nexthop_cmp(bpi1, bpi2); - - if (!compare) { - if (!bpi1->peer->su_remote && !bpi2->peer->su_remote) - compare = 0; - else if (!bpi1->peer->su_remote) - compare = 1; - else if (!bpi2->peer->su_remote) - compare = -1; - else - compare = sockunion_cmp(bpi1->peer->su_remote, - bpi2->peer->su_remote); - } - - return compare; -} - -/* - * bgp_mp_list_init - * - * Initialize the mp_list, which holds the list of multipaths - * selected by bgp_best_selection - */ -void bgp_mp_list_init(struct list *mp_list) -{ - assert(mp_list); - memset(mp_list, 0, sizeof(struct list)); - mp_list->cmp = bgp_path_info_mpath_cmp; -} - -/* - * bgp_mp_list_clear - * - * Clears all entries out of the mp_list - */ -void bgp_mp_list_clear(struct list *mp_list) -{ - assert(mp_list); - list_delete_all_node(mp_list); -} - -/* - * bgp_mp_list_add - * - * Adds a multipath entry to the mp_list - */ -void bgp_mp_list_add(struct list *mp_list, struct bgp_path_info *mpinfo) -{ - assert(mp_list && mpinfo); - listnode_add_sort(mp_list, mpinfo); -} - -/* * bgp_path_info_mpath_new * * Allocate and zero memory for a new bgp_path_info_mpath element @@ -274,6 +204,7 @@ static struct bgp_path_info_mpath *bgp_path_info_mpath_new(void) new_mpath = XCALLOC(MTYPE_BGP_MPATH_INFO, sizeof(struct bgp_path_info_mpath)); + new_mpath->mp_count = 1; return new_mpath; } @@ -287,6 +218,8 @@ void bgp_path_info_mpath_free(struct bgp_path_info_mpath **mpath) if (mpath && *mpath) { if ((*mpath)->mp_attr) bgp_attr_unintern(&(*mpath)->mp_attr); + (*mpath)->mp_attr = NULL; + XFREE(MTYPE_BGP_MPATH_INFO, *mpath); } } @@ -314,58 +247,22 @@ bgp_path_info_mpath_get(struct bgp_path_info *path) } /* - * bgp_path_info_mpath_enqueue - * - * Enqueue a path onto the multipath list given the previous multipath - * list entry - */ -static void bgp_path_info_mpath_enqueue(struct bgp_path_info *prev_info, - struct bgp_path_info *path) -{ - struct bgp_path_info_mpath *prev, *mpath; - - prev = bgp_path_info_mpath_get(prev_info); - mpath = bgp_path_info_mpath_get(path); - if (!prev || !mpath) - return; - - mpath->mp_next = prev->mp_next; - mpath->mp_prev = prev; - if (prev->mp_next) - prev->mp_next->mp_prev = mpath; - prev->mp_next = mpath; - - SET_FLAG(path->flags, BGP_PATH_MULTIPATH); -} - -/* - * bgp_path_info_mpath_dequeue - * - * Remove a path from the multipath list - */ -void bgp_path_info_mpath_dequeue(struct bgp_path_info *path) -{ - struct bgp_path_info_mpath *mpath = path->mpath; - if (!mpath) - return; - if (mpath->mp_prev) - mpath->mp_prev->mp_next = mpath->mp_next; - if (mpath->mp_next) - mpath->mp_next->mp_prev = mpath->mp_prev; - mpath->mp_next = mpath->mp_prev = NULL; - UNSET_FLAG(path->flags, BGP_PATH_MULTIPATH); -} - -/* * bgp_path_info_mpath_next * * Given a bgp_path_info, return the next multipath entry */ struct bgp_path_info *bgp_path_info_mpath_next(struct bgp_path_info *path) { - if (!path->mpath || !path->mpath->mp_next) - return NULL; - return path->mpath->mp_next->mp_info; + path = path->next; + + while (path) { + if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)) + return path; + + path = path->next; + } + + return NULL; } /* @@ -386,7 +283,8 @@ struct bgp_path_info *bgp_path_info_mpath_first(struct bgp_path_info *path) uint32_t bgp_path_info_mpath_count(struct bgp_path_info *path) { if (!path->mpath) - return 0; + return 1; + return path->mpath->mp_count; } @@ -411,6 +309,10 @@ static void bgp_path_info_mpath_count_set(struct bgp_path_info *path, * bgp_path_info_mpath_lb_update * * Update cumulative info related to link-bandwidth + * + * This is only set on the first mpath of the list + * as such we should UNSET the flags when removing + * to ensure nothing accidently happens */ static void bgp_path_info_mpath_lb_update(struct bgp_path_info *path, bool set, bool all_paths_lb, uint64_t cum_bw) @@ -472,10 +374,10 @@ bool bgp_path_info_mpath_chkwtd(struct bgp *bgp, struct bgp_path_info *path) */ if (bgp->lb_handling != BGP_LINK_BW_SKIP_MISSING && bgp->lb_handling != BGP_LINK_BW_DEFWT_4_MISSING) - return (path->mpath->mp_flags & BGP_MP_LB_ALL); + return CHECK_FLAG(path->mpath->mp_flags, BGP_MP_LB_ALL); /* At least one path should have bandwidth. */ - return (path->mpath->mp_flags & BGP_MP_LB_PRESENT); + return CHECK_FLAG(path->mpath->mp_flags, BGP_MP_LB_PRESENT); } /* @@ -511,58 +413,51 @@ static void bgp_path_info_mpath_attr_set(struct bgp_path_info *path, /* * bgp_path_info_mpath_update * - * Compare and sync up the multipath list with the mp_list generated by - * bgp_best_selection + * Compare and sync up the multipath flags with what was choosen + * in best selection */ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, - struct bgp_path_info *new_best, - struct bgp_path_info *old_best, - struct list *mp_list, - struct bgp_maxpaths_cfg *mpath_cfg) + struct bgp_path_info *new_best, struct bgp_path_info *old_best, + uint32_t num_candidates, struct bgp_maxpaths_cfg *mpath_cfg) { uint16_t maxpaths, mpath_count, old_mpath_count; uint64_t bwval; uint64_t cum_bw, old_cum_bw; - struct listnode *mp_node, *mp_next_node; - struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath; - int mpath_changed, debug; + struct bgp_path_info *cur_iterator = NULL; + bool mpath_changed, debug; bool all_paths_lb; char path_buf[PATH_ADDPATH_STR_BUFFER]; + bool old_mpath, new_mpath; - mpath_changed = 0; + mpath_changed = false; maxpaths = multipath_num; mpath_count = 0; - cur_mpath = NULL; old_mpath_count = 0; old_cum_bw = cum_bw = 0; - prev_mpath = new_best; - mp_node = listhead(mp_list); debug = bgp_debug_bestpath(dest); - if (new_best) { - mpath_count++; - if (new_best != old_best) - bgp_path_info_mpath_dequeue(new_best); - maxpaths = (new_best->peer->sort == BGP_PEER_IBGP) - ? mpath_cfg->maxpaths_ibgp - : mpath_cfg->maxpaths_ebgp; - } - if (old_best) { - cur_mpath = bgp_path_info_mpath_first(old_best); old_mpath_count = bgp_path_info_mpath_count(old_best); + if (old_mpath_count == 1) + SET_FLAG(old_best->flags, BGP_PATH_MULTIPATH); old_cum_bw = bgp_path_info_mpath_cumbw(old_best); bgp_path_info_mpath_count_set(old_best, 0); bgp_path_info_mpath_lb_update(old_best, false, false, 0); - bgp_path_info_mpath_dequeue(old_best); + bgp_path_info_mpath_free(&old_best->mpath); + old_best->mpath = NULL; + } + + if (new_best) { + maxpaths = (new_best->peer->sort == BGP_PEER_IBGP) ? mpath_cfg->maxpaths_ibgp + : mpath_cfg->maxpaths_ebgp; + cur_iterator = new_best; } if (debug) - zlog_debug("%pBD(%s): starting mpath update, newbest %s num candidates %d old-mpath-count %d old-cum-bw %" PRIu64, - dest, bgp->name_pretty, - new_best ? new_best->peer->host : "NONE", - mp_list ? listcount(mp_list) : 0, old_mpath_count, - old_cum_bw); + zlog_debug("%pBD(%s): starting mpath update, newbest %s num candidates %d old-mpath-count %d old-cum-bw %" PRIu64 + " maxpaths set %u", + dest, bgp->name_pretty, new_best ? new_best->peer->host : "NONE", + num_candidates, old_mpath_count, old_cum_bw, maxpaths); /* * We perform an ordered walk through both lists in parallel. @@ -576,240 +471,106 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, * to skip over it */ all_paths_lb = true; /* We'll reset if any path doesn't have LB. */ - while (mp_node || cur_mpath) { - struct bgp_path_info *tmp_info; + while (cur_iterator) { + old_mpath = CHECK_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH); + new_mpath = CHECK_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH_NEW); + + UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH_NEW); /* - * We can bail out of this loop if all existing paths on the - * multipath list have been visited (for cleanup purposes) and - * the maxpath requirement is fulfulled + * If the current mpath count is equal to the number of + * maxpaths that can be used then we can bail, after + * we clean up the flags associated with the rest of the + * bestpaths */ - if (!cur_mpath && (mpath_count >= maxpaths)) - break; + if (mpath_count >= maxpaths) { + while (cur_iterator) { + UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH); + UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH_NEW); + + cur_iterator = cur_iterator->next; + } - mp_next_node = mp_node ? listnextnode(mp_node) : NULL; - next_mpath = - cur_mpath ? bgp_path_info_mpath_next(cur_mpath) : NULL; - tmp_info = mp_node ? listgetdata(mp_node) : NULL; + if (debug) + zlog_debug("%pBD(%s): Mpath count %u is equal to maximum paths allowed, finished comparision for MPATHS", + dest, bgp->name_pretty, mpath_count); - if (debug) - zlog_debug("%pBD(%s): comparing candidate %s with existing mpath %s", - dest, bgp->name_pretty, - tmp_info ? tmp_info->peer->host : "NONE", - cur_mpath ? cur_mpath->peer->host : "NONE"); + break; + } + if (debug) + zlog_debug("%pBD(%s): Candidate %s old_mpath: %u new_mpath: %u, Nexthop %pI4 current mpath count: %u", + dest, bgp->name_pretty, cur_iterator->peer->host, old_mpath, + new_mpath, &cur_iterator->attr->nexthop, mpath_count); /* - * If equal, the path was a multipath and is still a multipath. - * Insert onto new multipath list if maxpaths allows. + * There is nothing to do if the cur_iterator is neither a old path + * or a new path */ - if (mp_node && (listgetdata(mp_node) == cur_mpath)) { - list_delete_node(mp_list, mp_node); - bgp_path_info_mpath_dequeue(cur_mpath); - if ((mpath_count < maxpaths) && prev_mpath) { - mpath_count++; - if (bgp_path_info_nexthop_cmp(prev_mpath, - cur_mpath)) { - if (ecommunity_linkbw_present( - bgp_attr_get_ecommunity( - cur_mpath->attr), - &bwval) || - ecommunity_linkbw_present( - bgp_attr_get_ipv6_ecommunity( - cur_mpath->attr), - &bwval)) - cum_bw += bwval; - else - all_paths_lb = false; - if (debug) { - bgp_path_info_path_with_addpath_rx_str( - cur_mpath, path_buf, - sizeof(path_buf)); - zlog_debug("%pBD: %s is still multipath, cur count %d", - dest, path_buf, - mpath_count); - } - } else { - if (debug) { - bgp_path_info_path_with_addpath_rx_str( - cur_mpath, path_buf, - sizeof(path_buf)); - zlog_debug("%pBD: nexthop equal, however add mpath %s nexthop %pI4, cur count %d", - dest, path_buf, - &cur_mpath->attr->nexthop, - mpath_count); - } - } - bgp_path_info_mpath_enqueue(prev_mpath, - cur_mpath); - prev_mpath = cur_mpath; - } else { - mpath_changed = 1; - if (debug) { - bgp_path_info_path_with_addpath_rx_str( - cur_mpath, path_buf, - sizeof(path_buf)); - zlog_debug("%pBD: remove mpath %s nexthop %pI4, cur count %d", - dest, path_buf, - &cur_mpath->attr->nexthop, - mpath_count); - } - } - mp_node = mp_next_node; - cur_mpath = next_mpath; + if (!old_mpath && !new_mpath) { + UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH); + cur_iterator = cur_iterator->next; continue; } - if (cur_mpath - && (!mp_node - || (bgp_path_info_mpath_cmp(cur_mpath, - listgetdata(mp_node)) - < 0))) { - /* - * If here, we have an old multipath and either the - * mp_list - * is finished or the next mp_node points to a later - * multipath, so we need to purge this path from the - * multipath list - */ - bgp_path_info_mpath_dequeue(cur_mpath); - mpath_changed = 1; + if (new_mpath) { + mpath_count++; + + if (cur_iterator != new_best) + SET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH); + + if (!old_mpath) + mpath_changed = true; + + if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(cur_iterator->attr), + &bwval) || + ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity( + cur_iterator->attr), + &bwval)) + cum_bw += bwval; + else + all_paths_lb = false; + if (debug) { - bgp_path_info_path_with_addpath_rx_str( - cur_mpath, path_buf, sizeof(path_buf)); - zlog_debug("%pBD: remove mpath %s nexthop %pI4, cur count %d", - dest, path_buf, - &cur_mpath->attr->nexthop, - mpath_count); + bgp_path_info_path_with_addpath_rx_str(cur_iterator, path_buf, + sizeof(path_buf)); + zlog_debug("%pBD: add mpath %s nexthop %pI4, cur count %d cum_bw: %" PRIu64 + " all_paths_lb: %u", + dest, path_buf, &cur_iterator->attr->nexthop, + mpath_count, cum_bw, all_paths_lb); } - cur_mpath = next_mpath; } else { /* - * If here, we have a path on the mp_list that was not - * previously - * a multipath (due to non-equivalance or maxpaths - * exceeded), - * or the matching multipath is sorted later in the - * multipath - * list. Before we enqueue the path on the new multipath - * list, - * make sure its not on the old_best multipath list or - * referenced - * via next_mpath: - * - If next_mpath points to this new path, update - * next_mpath to - * point to the multipath after this one - * - Dequeue the path from the multipath list just to - * make sure + * We know that old_mpath is true and new_mpath is false in this path */ - new_mpath = listgetdata(mp_node); - list_delete_node(mp_list, mp_node); - assert(new_mpath); - assert(prev_mpath); - if ((mpath_count < maxpaths) && (new_mpath != new_best)) { - /* keep duplicate nexthop */ - bgp_path_info_mpath_dequeue(new_mpath); - - bgp_path_info_mpath_enqueue(prev_mpath, - new_mpath); - mpath_changed = 1; - mpath_count++; - if (bgp_path_info_nexthop_cmp(prev_mpath, - new_mpath)) { - if (ecommunity_linkbw_present( - bgp_attr_get_ecommunity( - new_mpath->attr), - &bwval) || - ecommunity_linkbw_present( - bgp_attr_get_ipv6_ecommunity( - new_mpath->attr), - &bwval)) - cum_bw += bwval; - else - all_paths_lb = false; - if (debug) { - bgp_path_info_path_with_addpath_rx_str( - new_mpath, path_buf, - sizeof(path_buf)); - zlog_debug("%pBD: add mpath %s nexthop %pI4, cur count %d", - dest, path_buf, - &new_mpath->attr - ->nexthop, - mpath_count); - } - } else { - if (debug) { - bgp_path_info_path_with_addpath_rx_str( - new_mpath, path_buf, - sizeof(path_buf)); - zlog_debug("%pBD: nexthop equal, however add mpath %s nexthop %pI4, cur count %d", - dest, path_buf, - &new_mpath->attr - ->nexthop, - mpath_count); - } - } - prev_mpath = new_mpath; - } - mp_node = mp_next_node; + mpath_changed = true; + UNSET_FLAG(cur_iterator->flags, BGP_PATH_MULTIPATH); } + + cur_iterator = cur_iterator->next; } if (new_best) { - bgp_path_info_mpath_count_set(new_best, mpath_count - 1); - if (mpath_count <= 1 || - (!ecommunity_linkbw_present(bgp_attr_get_ecommunity( - new_best->attr), - &bwval) && - !ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity( - new_best->attr), - &bwval))) - all_paths_lb = false; - else - cum_bw += bwval; - bgp_path_info_mpath_lb_update(new_best, true, - all_paths_lb, cum_bw); - + if (mpath_count > 1 || new_best->mpath) { + bgp_path_info_mpath_count_set(new_best, mpath_count); + bgp_path_info_mpath_lb_update(new_best, true, all_paths_lb, cum_bw); + } if (debug) zlog_debug("%pBD(%s): New mpath count (incl newbest) %d mpath-change %s all_paths_lb %d cum_bw %" PRIu64, dest, bgp->name_pretty, mpath_count, mpath_changed ? "YES" : "NO", all_paths_lb, cum_bw); + if (mpath_count == 1) + UNSET_FLAG(new_best->flags, BGP_PATH_MULTIPATH); if (mpath_changed || (bgp_path_info_mpath_count(new_best) != old_mpath_count)) SET_FLAG(new_best->flags, BGP_PATH_MULTIPATH_CHG); - if ((mpath_count - 1) != old_mpath_count || - old_cum_bw != cum_bw) + if ((mpath_count) != old_mpath_count || old_cum_bw != cum_bw) SET_FLAG(new_best->flags, BGP_PATH_LINK_BW_CHG); } } /* - * bgp_mp_dmed_deselect - * - * Clean up multipath information for BGP_PATH_DMED_SELECTED path that - * is not selected as best path - */ -void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best) -{ - struct bgp_path_info *mpinfo, *mpnext; - - if (!dmed_best) - return; - - for (mpinfo = bgp_path_info_mpath_first(dmed_best); mpinfo; - mpinfo = mpnext) { - mpnext = bgp_path_info_mpath_next(mpinfo); - bgp_path_info_mpath_dequeue(mpinfo); - } - - bgp_path_info_mpath_count_set(dmed_best, 0); - UNSET_FLAG(dmed_best->flags, BGP_PATH_MULTIPATH_CHG); - UNSET_FLAG(dmed_best->flags, BGP_PATH_LINK_BW_CHG); - assert(bgp_path_info_mpath_first(dmed_best) == NULL); -} - -/* * bgp_path_info_mpath_aggregate_update * * Set the multipath aggregate attribute. We need to see if the @@ -843,7 +604,7 @@ void bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best, if (!new_best) return; - if (!bgp_path_info_mpath_count(new_best)) { + if (bgp_path_info_mpath_count(new_best) == 1) { if ((new_attr = bgp_path_info_mpath_attr(new_best))) { bgp_attr_unintern(&new_attr); bgp_path_info_mpath_attr_set(new_best, NULL); diff --git a/bgpd/bgp_mpath.h b/bgpd/bgp_mpath.h index 129682d1dc..c5a009a4c8 100644 --- a/bgpd/bgp_mpath.h +++ b/bgpd/bgp_mpath.h @@ -2,8 +2,9 @@ /* * BGP Multipath * Copyright (C) 2010 Google Inc. + * 2024 Nvidia Corporation * - * This file is part of Quagga + * This file is part of FRR */ #ifndef _FRR_BGP_MPATH_H @@ -13,27 +14,24 @@ * multipath selections, lazily allocated to save memory */ struct bgp_path_info_mpath { - /* Points to the first multipath (on bestpath) or the next multipath */ - struct bgp_path_info_mpath *mp_next; - - /* Points to the previous multipath or NULL on bestpath */ - struct bgp_path_info_mpath *mp_prev; - /* Points to bgp_path_info associated with this multipath info */ struct bgp_path_info *mp_info; /* When attached to best path, the number of selected multipaths */ uint16_t mp_count; - /* Flags - relevant as noted. */ + /* Flags - relevant as noted, attached to bestpath. */ uint16_t mp_flags; #define BGP_MP_LB_PRESENT 0x1 /* Link-bandwidth present for >= 1 path */ #define BGP_MP_LB_ALL 0x2 /* Link-bandwidth present for all multipaths */ - /* Aggregated attribute for advertising multipath route */ + /* + * Aggregated attribute for advertising multipath route, + * attached to bestpath + */ struct attr *mp_attr; - /* Cumulative bandiwdth of all multipaths - attached to best path. */ + /* Cumulative bandiwdth of all multipaths - attached to bestpath. */ uint64_t cum_bw; }; @@ -47,23 +45,16 @@ extern int bgp_maximum_paths_unset(struct bgp *bgp, afi_t afi, safi_t safi, /* Functions used by bgp_best_selection to record current * multipath selections */ -extern int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1, - struct bgp_path_info *bpi2); -extern void bgp_mp_list_init(struct list *mp_list); -extern void bgp_mp_list_clear(struct list *mp_list); -extern void bgp_mp_list_add(struct list *mp_list, struct bgp_path_info *mpinfo); -extern void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best); +extern int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1, struct bgp_path_info *bpi2); extern void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info *new_best, - struct bgp_path_info *old_best, - struct list *mp_list, + struct bgp_path_info *old_best, uint32_t num_candidates, struct bgp_maxpaths_cfg *mpath_cfg); extern void bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best, struct bgp_path_info *old_best); /* Unlink and free multipath information associated with a bgp_path_info */ -extern void bgp_path_info_mpath_dequeue(struct bgp_path_info *path); extern void bgp_path_info_mpath_free(struct bgp_path_info_mpath **mpath); /* Walk list of multipaths associated with a best path */ diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index ec5b50a08f..2d61c0f00a 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -173,33 +173,33 @@ static int snprintf_bgp_pbr_match_val(char *str, int len, ptr += delta; len -= delta; } else { - if (mval->unary_operator & OPERATOR_UNARY_OR) { + if (CHECK_FLAG(mval->unary_operator, OPERATOR_UNARY_OR)) { delta = snprintf(ptr, len, ", or "); ptr += delta; len -= delta; } - if (mval->unary_operator & OPERATOR_UNARY_AND) { + if (CHECK_FLAG(mval->unary_operator, OPERATOR_UNARY_AND)) { delta = snprintf(ptr, len, ", and "); ptr += delta; len -= delta; } } - if (mval->compare_operator & OPERATOR_COMPARE_LESS_THAN) { + if (CHECK_FLAG(mval->compare_operator, OPERATOR_COMPARE_LESS_THAN)) { delta = snprintf(ptr, len, "<"); ptr += delta; len -= delta; } - if (mval->compare_operator & OPERATOR_COMPARE_GREATER_THAN) { + if (CHECK_FLAG(mval->compare_operator, OPERATOR_COMPARE_GREATER_THAN)) { delta = snprintf(ptr, len, ">"); ptr += delta; len -= delta; } - if (mval->compare_operator & OPERATOR_COMPARE_EQUAL_TO) { + if (CHECK_FLAG(mval->compare_operator, OPERATOR_COMPARE_EQUAL_TO)) { delta = snprintf(ptr, len, "="); ptr += delta; len -= delta; } - if (mval->compare_operator & OPERATOR_COMPARE_EXACT_MATCH) { + if (CHECK_FLAG(mval->compare_operator, OPERATOR_COMPARE_EXACT_MATCH)) { delta = snprintf(ptr, len, "match"); ptr += delta; len -= delta; @@ -287,9 +287,7 @@ static bool bgp_pbr_extract_enumerate_unary_opposite( { if (unary_operator == OPERATOR_UNARY_AND && and_valmask) { if (type_entry == FLOWSPEC_TCP_FLAGS) { - and_valmask->mask |= - TCP_HEADER_ALL_FLAGS & - ~(value); + SET_FLAG(and_valmask->mask, CHECK_FLAG(TCP_HEADER_ALL_FLAGS, ~(value))); } else if (type_entry == FLOWSPEC_DSCP || type_entry == FLOWSPEC_FLOW_LABEL || type_entry == FLOWSPEC_PKT_LEN || @@ -302,9 +300,7 @@ static bool bgp_pbr_extract_enumerate_unary_opposite( sizeof(struct bgp_pbr_val_mask)); if (type_entry == FLOWSPEC_TCP_FLAGS) { and_valmask->val = TCP_HEADER_ALL_FLAGS; - and_valmask->mask |= - TCP_HEADER_ALL_FLAGS & - ~(value); + SET_FLAG(and_valmask->mask, CHECK_FLAG(TCP_HEADER_ALL_FLAGS, ~(value))); } else if (type_entry == FLOWSPEC_DSCP || type_entry == FLOWSPEC_FLOW_LABEL || type_entry == FLOWSPEC_FRAGMENT || @@ -346,14 +342,10 @@ static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[], if (i != 0 && list[i].unary_operator != unary_operator) return false; - if (!(list[i].compare_operator & - OPERATOR_COMPARE_EQUAL_TO) && - !(list[i].compare_operator & - OPERATOR_COMPARE_EXACT_MATCH)) { - if ((list[i].compare_operator & - OPERATOR_COMPARE_LESS_THAN) && - (list[i].compare_operator & - OPERATOR_COMPARE_GREATER_THAN)) { + if (!CHECK_FLAG(list[i].compare_operator, OPERATOR_COMPARE_EQUAL_TO) && + !CHECK_FLAG(list[i].compare_operator, OPERATOR_COMPARE_EXACT_MATCH)) { + if (CHECK_FLAG(list[i].compare_operator, OPERATOR_COMPARE_LESS_THAN) && + CHECK_FLAG(list[i].compare_operator, OPERATOR_COMPARE_GREATER_THAN)) { ret = bgp_pbr_extract_enumerate_unary_opposite( unary_operator, and_valmask, or_valmask, list[i].value, @@ -366,15 +358,15 @@ static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[], } if (unary_operator == OPERATOR_UNARY_AND && and_valmask) { if (type_entry == FLOWSPEC_TCP_FLAGS) - and_valmask->mask |= - TCP_HEADER_ALL_FLAGS & list[i].value; + SET_FLAG(and_valmask->mask, + CHECK_FLAG(TCP_HEADER_ALL_FLAGS, list[i].value)); } else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) { and_valmask = XCALLOC(MTYPE_PBR_VALMASK, sizeof(struct bgp_pbr_val_mask)); if (type_entry == FLOWSPEC_TCP_FLAGS) { and_valmask->val = TCP_HEADER_ALL_FLAGS; - and_valmask->mask |= - TCP_HEADER_ALL_FLAGS & list[i].value; + SET_FLAG(and_valmask->mask, + CHECK_FLAG(TCP_HEADER_ALL_FLAGS, list[i].value)); } else if (type_entry == FLOWSPEC_DSCP || type_entry == FLOWSPEC_FLOW_LABEL || type_entry == FLOWSPEC_ICMP_TYPE || @@ -402,8 +394,8 @@ static bool bgp_pbr_extract_enumerate(struct bgp_pbr_match_val list[], uint8_t unary_operator_val; bool double_check = false; - if ((unary_operator & OPERATOR_UNARY_OR) && - (unary_operator & OPERATOR_UNARY_AND)) { + if (CHECK_FLAG(unary_operator, OPERATOR_UNARY_OR) && + CHECK_FLAG(unary_operator, OPERATOR_UNARY_AND)) { unary_operator_val = OPERATOR_UNARY_AND; double_check = true; } else @@ -431,12 +423,12 @@ static uint8_t bgp_pbr_match_val_get_operator(struct bgp_pbr_match_val list[], for (i = 0; i < num; i++) { if (i == 0) continue; - if (list[i].unary_operator & OPERATOR_UNARY_OR) + if (CHECK_FLAG(list[i].unary_operator, OPERATOR_UNARY_OR)) unary_operator = OPERATOR_UNARY_OR; - if ((list[i].unary_operator & OPERATOR_UNARY_AND - && unary_operator == OPERATOR_UNARY_OR) || - (list[i].unary_operator & OPERATOR_UNARY_OR - && unary_operator == OPERATOR_UNARY_AND)) + if ((CHECK_FLAG(list[i].unary_operator, OPERATOR_UNARY_AND) && + unary_operator == OPERATOR_UNARY_OR) || + (CHECK_FLAG(list[i].unary_operator, OPERATOR_UNARY_OR) && + unary_operator == OPERATOR_UNARY_AND)) return 0; } return unary_operator; @@ -723,8 +715,8 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) } } - } else if (!(api->match_bitmask & PREFIX_SRC_PRESENT) && - !(api->match_bitmask & PREFIX_DST_PRESENT)) { + } else if (!CHECK_FLAG(api->match_bitmask, PREFIX_SRC_PRESENT) && + !CHECK_FLAG(api->match_bitmask, PREFIX_DST_PRESENT)) { if (BGP_DEBUG(pbr, PBR)) { bgp_pbr_print_policy_route(api); zlog_debug("BGP: match actions without src or dst address can not operate. ignoring."); @@ -786,8 +778,7 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p, memcpy(&ecom_copy, ecom_eval, sizeof(struct ecommunity_val)); - ecom_copy.val[0] &= - ~ECOMMUNITY_ENCODE_TRANS_EXP; + UNSET_FLAG(ecom_copy.val[0], ECOMMUNITY_ENCODE_TRANS_EXP); ecom_copy.val[1] = ECOMMUNITY_ROUTE_TARGET; ecommunity_add_val(eckey, &ecom_copy, false, false); @@ -955,12 +946,12 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p, return -1; /* check inconsistency in the match rule */ - if (api->match_bitmask & PREFIX_SRC_PRESENT) { + if (CHECK_FLAG(api->match_bitmask, PREFIX_SRC_PRESENT)) { src = &api->src_prefix; afi = family2afi(src->family); valid_prefix = 1; } - if (api->match_bitmask & PREFIX_DST_PRESENT) { + if (CHECK_FLAG(api->match_bitmask, PREFIX_DST_PRESENT)) { dst = &api->dst_prefix; if (valid_prefix && afi != family2afi(dst->family)) { if (BGP_DEBUG(pbr, PBR)) { @@ -1204,12 +1195,10 @@ bool bgp_pbr_rule_hash_equal(const void *arg1, const void *arg2) if (r1->action != r2->action) return false; - if ((r1->flags & MATCH_IP_SRC_SET) && - !prefix_same(&r1->src, &r2->src)) + if (CHECK_FLAG(r1->flags, MATCH_IP_SRC_SET) && !prefix_same(&r1->src, &r2->src)) return false; - if ((r1->flags & MATCH_IP_DST_SET) && - !prefix_same(&r1->dst, &r2->dst)) + if (CHECK_FLAG(r1->flags, MATCH_IP_DST_SET) && !prefix_same(&r1->dst, &r2->dst)) return false; return true; @@ -1426,7 +1415,7 @@ void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api) delta = snprintf(ptr, sizeof(return_string), "MATCH : "); len -= delta; ptr += delta; - if (api->match_bitmask & PREFIX_SRC_PRESENT) { + if (CHECK_FLAG(api->match_bitmask, PREFIX_SRC_PRESENT)) { struct prefix *p = &(api->src_prefix); if (api->src_prefix_offset) @@ -1438,7 +1427,7 @@ void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api) ptr += delta; INCREMENT_DISPLAY(ptr, nb_items, len); } - if (api->match_bitmask & PREFIX_DST_PRESENT) { + if (CHECK_FLAG(api->match_bitmask, PREFIX_DST_PRESENT)) { struct prefix *p = &(api->dst_prefix); INCREMENT_DISPLAY(ptr, nb_items, len); @@ -1581,21 +1570,18 @@ void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api) delta = snprintf(ptr, len, "@action "); len -= delta; ptr += delta; - if (api->actions[i].u.za.filter - & TRAFFIC_ACTION_TERMINATE) { + if (CHECK_FLAG(api->actions[i].u.za.filter, TRAFFIC_ACTION_TERMINATE)) { delta = snprintf(ptr, len, " terminate (apply filter(s))"); len -= delta; ptr += delta; } - if (api->actions[i].u.za.filter - & TRAFFIC_ACTION_DISTRIBUTE) { + if (CHECK_FLAG(api->actions[i].u.za.filter, TRAFFIC_ACTION_DISTRIBUTE)) { delta = snprintf(ptr, len, " distribute"); len -= delta; ptr += delta; } - if (api->actions[i].u.za.filter - & TRAFFIC_ACTION_SAMPLE) { + if (CHECK_FLAG(api->actions[i].u.za.filter, TRAFFIC_ACTION_SAMPLE)) { delta = snprintf(ptr, len, " sample"); len -= delta; ptr += delta; @@ -1746,12 +1732,10 @@ static int bgp_pbr_get_same_rule(struct hash_bucket *bucket, void *arg) if (r1->flags != r2->flags) return HASHWALK_CONTINUE; - if ((r1->flags & MATCH_IP_SRC_SET) && - !prefix_same(&r1->src, &r2->src)) + if (CHECK_FLAG(r1->flags, MATCH_IP_SRC_SET) && !prefix_same(&r1->src, &r2->src)) return HASHWALK_CONTINUE; - if ((r1->flags & MATCH_IP_DST_SET) && - !prefix_same(&r1->dst, &r2->dst)) + if (CHECK_FLAG(r1->flags, MATCH_IP_DST_SET) && !prefix_same(&r1->dst, &r2->dst)) return HASHWALK_CONTINUE; /* this function is used for two cases: @@ -1840,11 +1824,11 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit( pbr_rule.vrf_id = bpf->vrf_id; if (bpf->src) { prefix_copy(&pbr_rule.src, bpf->src); - pbr_rule.flags |= MATCH_IP_SRC_SET; + SET_FLAG(pbr_rule.flags, MATCH_IP_SRC_SET); } if (bpf->dst) { prefix_copy(&pbr_rule.dst, bpf->dst); - pbr_rule.flags |= MATCH_IP_DST_SET; + SET_FLAG(pbr_rule.flags, MATCH_IP_DST_SET); } bpr = &pbr_rule; /* A previous entry may already exist @@ -1867,32 +1851,32 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit( temp.family = bpf->family; if (bpf->src) { - temp.flags |= MATCH_IP_SRC_SET; + SET_FLAG(temp.flags, MATCH_IP_SRC_SET); prefix_copy(&temp2.src, bpf->src); } else temp2.src.family = bpf->family; if (bpf->dst) { - temp.flags |= MATCH_IP_DST_SET; + SET_FLAG(temp.flags, MATCH_IP_DST_SET); prefix_copy(&temp2.dst, bpf->dst); } else temp2.dst.family = bpf->family; if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) { if (bpf->protocol == IPPROTO_ICMP) - temp.flags |= MATCH_ICMP_SET; - temp.flags |= MATCH_PORT_SRC_SET; + SET_FLAG(temp.flags, MATCH_ICMP_SET); + SET_FLAG(temp.flags, MATCH_PORT_SRC_SET); temp2.src_port_min = src_port->min_port; if (src_port->max_port) { - temp.flags |= MATCH_PORT_SRC_RANGE_SET; + SET_FLAG(temp.flags, MATCH_PORT_SRC_RANGE_SET); temp2.src_port_max = src_port->max_port; } } if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) { if (bpf->protocol == IPPROTO_ICMP) - temp.flags |= MATCH_ICMP_SET; - temp.flags |= MATCH_PORT_DST_SET; + SET_FLAG(temp.flags, MATCH_ICMP_SET); + SET_FLAG(temp.flags, MATCH_PORT_DST_SET); temp2.dst_port_min = dst_port->min_port; if (dst_port->max_port) { - temp.flags |= MATCH_PORT_DST_RANGE_SET; + SET_FLAG(temp.flags, MATCH_PORT_DST_RANGE_SET); temp2.dst_port_max = dst_port->max_port; } } @@ -1904,7 +1888,7 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit( temp.pkt_len_max = pkt_len->max_port; } else if (bpf->pkt_len_val) { if (bpf->pkt_len_val->mask) - temp.flags |= MATCH_PKT_LEN_INVERSE_SET; + SET_FLAG(temp.flags, MATCH_PKT_LEN_INVERSE_SET); temp.pkt_len_min = bpf->pkt_len_val->val; } if (bpf->tcp_flags) { @@ -1913,32 +1897,32 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit( } if (bpf->dscp) { if (bpf->dscp->mask) - temp.flags |= MATCH_DSCP_INVERSE_SET; + SET_FLAG(temp.flags, MATCH_DSCP_INVERSE_SET); else - temp.flags |= MATCH_DSCP_SET; + SET_FLAG(temp.flags, MATCH_DSCP_SET); temp.dscp_value = bpf->dscp->val; } if (bpf->flow_label) { if (bpf->flow_label->mask) - temp.flags |= MATCH_FLOW_LABEL_INVERSE_SET; + SET_FLAG(temp.flags, MATCH_FLOW_LABEL_INVERSE_SET); else - temp.flags |= MATCH_FLOW_LABEL_SET; + SET_FLAG(temp.flags, MATCH_FLOW_LABEL_SET); temp.flow_label = bpf->flow_label->val; } if (bpf->fragment) { if (bpf->fragment->mask) - temp.flags |= MATCH_FRAGMENT_INVERSE_SET; + SET_FLAG(temp.flags, MATCH_FRAGMENT_INVERSE_SET); temp.fragment = bpf->fragment->val; } if (bpf->src == NULL || bpf->dst == NULL) { - if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET)) + if (CHECK_FLAG(temp.flags, (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))) temp.type = IPSET_NET_PORT; else temp.type = IPSET_NET; } else { - if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET)) + if (CHECK_FLAG(temp.flags, (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))) temp.type = IPSET_NET_PORT_NET; else temp.type = IPSET_NET_NET; @@ -2316,11 +2300,11 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, pbr_rule.vrf_id = bpf->vrf_id; pbr_rule.priority = 20; if (bpf->src) { - pbr_rule.flags |= MATCH_IP_SRC_SET; + SET_FLAG(pbr_rule.flags, MATCH_IP_SRC_SET); prefix_copy(&pbr_rule.src, bpf->src); } if (bpf->dst) { - pbr_rule.flags |= MATCH_IP_DST_SET; + SET_FLAG(pbr_rule.flags, MATCH_IP_DST_SET); prefix_copy(&pbr_rule.dst, bpf->dst); } pbr_rule.action = bpa; @@ -2377,32 +2361,32 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, temp.vrf_id = bpf->vrf_id; temp.family = bpf->family; if (bpf->src) - temp.flags |= MATCH_IP_SRC_SET; + SET_FLAG(temp.flags, MATCH_IP_SRC_SET); if (bpf->dst) - temp.flags |= MATCH_IP_DST_SET; + SET_FLAG(temp.flags, MATCH_IP_DST_SET); if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) { if (bpf->protocol == IPPROTO_ICMP) - temp.flags |= MATCH_ICMP_SET; - temp.flags |= MATCH_PORT_SRC_SET; + SET_FLAG(temp.flags, MATCH_ICMP_SET); + SET_FLAG(temp.flags, MATCH_PORT_SRC_SET); } if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) { if (bpf->protocol == IPPROTO_ICMP) - temp.flags |= MATCH_ICMP_SET; - temp.flags |= MATCH_PORT_DST_SET; + SET_FLAG(temp.flags, MATCH_ICMP_SET); + SET_FLAG(temp.flags, MATCH_PORT_DST_SET); } if (src_port && src_port->max_port) - temp.flags |= MATCH_PORT_SRC_RANGE_SET; + SET_FLAG(temp.flags, MATCH_PORT_SRC_RANGE_SET); if (dst_port && dst_port->max_port) - temp.flags |= MATCH_PORT_DST_RANGE_SET; + SET_FLAG(temp.flags, MATCH_PORT_DST_RANGE_SET); if (bpf->src == NULL || bpf->dst == NULL) { - if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET)) + if (CHECK_FLAG(temp.flags, (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))) temp.type = IPSET_NET_PORT; else temp.type = IPSET_NET; } else { - if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET)) + if (CHECK_FLAG(temp.flags, (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))) temp.type = IPSET_NET_PORT_NET; else temp.type = IPSET_NET_NET; @@ -2413,7 +2397,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, temp.pkt_len_max = pkt_len->max_port; } else if (bpf->pkt_len_val) { if (bpf->pkt_len_val->mask) - temp.flags |= MATCH_PKT_LEN_INVERSE_SET; + SET_FLAG(temp.flags, MATCH_PKT_LEN_INVERSE_SET); temp.pkt_len_min = bpf->pkt_len_val->val; } if (bpf->tcp_flags) { @@ -2422,26 +2406,26 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, } if (bpf->dscp) { if (bpf->dscp->mask) - temp.flags |= MATCH_DSCP_INVERSE_SET; + SET_FLAG(temp.flags, MATCH_DSCP_INVERSE_SET); else - temp.flags |= MATCH_DSCP_SET; + SET_FLAG(temp.flags, MATCH_DSCP_SET); temp.dscp_value = bpf->dscp->val; } if (bpf->flow_label) { if (bpf->flow_label->mask) - temp.flags |= MATCH_FLOW_LABEL_INVERSE_SET; + SET_FLAG(temp.flags, MATCH_FLOW_LABEL_INVERSE_SET); else - temp.flags |= MATCH_FLOW_LABEL_SET; + SET_FLAG(temp.flags, MATCH_FLOW_LABEL_SET); temp.flow_label = bpf->flow_label->val; } if (bpf->fragment) { if (bpf->fragment->mask) - temp.flags |= MATCH_FRAGMENT_INVERSE_SET; + SET_FLAG(temp.flags, MATCH_FRAGMENT_INVERSE_SET); temp.fragment = bpf->fragment->val; } if (bpf->protocol) { temp.protocol = bpf->protocol; - temp.flags |= MATCH_PROTOCOL_SET; + SET_FLAG(temp.flags, MATCH_PROTOCOL_SET); } temp.action = bpa; bpm = hash_get(bgp->pbr_match_hash, &temp, @@ -2658,13 +2642,13 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path, memset(&nh, 0, sizeof(nh)); memset(&bpf, 0, sizeof(bpf)); memset(&bpof, 0, sizeof(bpof)); - if (api->match_bitmask & PREFIX_SRC_PRESENT || + if (CHECK_FLAG(api->match_bitmask, PREFIX_SRC_PRESENT) || (api->type == BGP_PBR_IPRULE && - api->match_bitmask_iprule & PREFIX_SRC_PRESENT)) + CHECK_FLAG(api->match_bitmask_iprule, PREFIX_SRC_PRESENT))) src = &api->src_prefix; - if (api->match_bitmask & PREFIX_DST_PRESENT || + if (CHECK_FLAG(api->match_bitmask, PREFIX_DST_PRESENT) || (api->type == BGP_PBR_IPRULE && - api->match_bitmask_iprule & PREFIX_DST_PRESENT)) + CHECK_FLAG(api->match_bitmask_iprule, PREFIX_DST_PRESENT))) dst = &api->dst_prefix; if (api->type == BGP_PBR_IPRULE) bpf.type = api->type; @@ -2809,8 +2793,7 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path, } break; case ACTION_TRAFFIC_ACTION: - if (api->actions[i].u.za.filter - & TRAFFIC_ACTION_SAMPLE) { + if (CHECK_FLAG(api->actions[i].u.za.filter, TRAFFIC_ACTION_SAMPLE)) { if (BGP_DEBUG(pbr, PBR)) { bgp_pbr_print_policy_route(api); zlog_warn("PBR: Sample action Ignored"); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f28c9adda2..8dbb4e3b04 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -525,8 +525,6 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest, else bgp_dest_set_bgp_path_info(dest, pi->next); - bgp_path_info_mpath_dequeue(pi); - pi->next = NULL; pi->prev = NULL; @@ -541,8 +539,6 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest, static struct bgp_dest *bgp_path_info_reap_unsorted(struct bgp_dest *dest, struct bgp_path_info *pi) { - bgp_path_info_mpath_dequeue(pi); - pi->next = NULL; pi->prev = NULL; @@ -2173,8 +2169,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, from = pi->peer; filter = &peer->filter[afi][safi]; bgp = SUBGRP_INST(subgrp); - piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi) - : pi->attr; + piattr = bgp_path_info_mpath_count(pi) > 1 ? bgp_path_info_mpath_attr(pi) : pi->attr; if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) && peer->pmax_out[afi][safi] != 0 && @@ -2854,13 +2849,12 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info *pi2; int paths_eq, do_mpath; bool debug, any_comparisons; - struct list mp_list; char pfx_buf[PREFIX2STR_BUFFER] = {}; char path_buf[PATH_ADDPATH_STR_BUFFER]; enum bgp_path_selection_reason reason = bgp_path_selection_none; bool unsorted_items = true; + uint32_t num_candidates = 0; - bgp_mp_list_init(&mp_list); do_mpath = (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1); @@ -3235,7 +3229,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, "%pBD(%s): %s is the bestpath, add to the multipath list", dest, bgp->name_pretty, path_buf); - bgp_mp_list_add(&mp_list, pi); + SET_FLAG(pi->flags, BGP_PATH_MULTIPATH_NEW); + num_candidates++; continue; } @@ -3258,15 +3253,14 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, "%pBD(%s): %s is equivalent to the bestpath, add to the multipath list", dest, bgp->name_pretty, path_buf); - bgp_mp_list_add(&mp_list, pi); + SET_FLAG(pi->flags, BGP_PATH_MULTIPATH_NEW); + num_candidates++; } } } - bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list, - mpath_cfg); + bgp_path_info_mpath_update(bgp, dest, new_select, old_select, num_candidates, mpath_cfg); bgp_path_info_mpath_aggregate_update(new_select, old_select); - bgp_mp_list_clear(&mp_list); bgp_addpath_update_ids(bgp, dest, afi, safi); @@ -11189,9 +11183,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, vty_out(vty, ", otc %u", attr->otc); } - if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH) - || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED) - && bgp_path_info_mpath_count(path))) { + if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH) || + (CHECK_FLAG(path->flags, BGP_PATH_SELECTED) && bgp_path_info_mpath_count(path) > 1)) { if (json_paths) json_object_boolean_true_add(json_path, "multipath"); else diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index b6df241181..d71bfd3ebc 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -313,6 +313,11 @@ struct bgp_path_info { #define BGP_PATH_STALE (1 << 8) #define BGP_PATH_REMOVED (1 << 9) #define BGP_PATH_COUNTED (1 << 10) +/* + * A BGP_PATH_MULTIPATH flag is not set on the best path + * it is set on every other node that is part of ECMP + * for that particular dest + */ #define BGP_PATH_MULTIPATH (1 << 11) #define BGP_PATH_MULTIPATH_CHG (1 << 12) #define BGP_PATH_RIB_ATTR_CHG (1 << 13) @@ -322,6 +327,15 @@ struct bgp_path_info { #define BGP_PATH_MPLSVPN_LABEL_NH (1 << 17) #define BGP_PATH_MPLSVPN_NH_LABEL_BIND (1 << 18) #define BGP_PATH_UNSORTED (1 << 19) +/* + * BGP_PATH_MULTIPATH_NEW is set on those bgp_path_info + * nodes that we have decided should possibly be in the + * ecmp path for a particular dest. This flag is + * removed when the bgp_path_info's are looked at to + * decide on whether or not a bgp_path_info is on + * the actual ecmp path. + */ +#define BGP_PATH_MULTIPATH_NEW (1 << 20) /* BGP route type. This can be static, RIP, OSPF, BGP etc. */ uint8_t type; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index ec60e5db86..583b9e7980 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3220,7 +3220,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object) return RMAP_OKAY; bw_bytes = (peer->bgp->lb_ref_bw * 1000 * 1000) / 8; - mpath_count = bgp_path_info_mpath_count(path) + 1; + mpath_count = bgp_path_info_mpath_count(path); bw_bytes *= mpath_count; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index a3caa5a806..80b1ae39d4 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -8901,6 +8901,12 @@ static ssize_t printfrr_bp(struct fbuf *buf, struct printfrr_eargs *ea, if (!peer) return bputs(buf, "(null)"); + if (!peer->host) { + if (peer->conf_if) + return bprintfrr(buf, "%s", peer->conf_if); + return bprintfrr(buf, "%pSU", &peer->connection->su); + } + return bprintfrr(buf, "%s(%s)", peer->host, peer->hostname ? peer->hostname : "Unknown"); } diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 438c60a3f6..4632c70d53 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -83,7 +83,7 @@ be specified (:ref:`common-invocation-options`). be done to see if this is helping or not at the scale you are running at. -.. option:: --v6-with-v4-nexthops +.. option:: -x, --v6-with-v4-nexthops Allow BGP to peer in the V6 afi, when the interface only has v4 addresses. This allows bgp to install the v6 routes with a v6 nexthop that has the diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index 7286a692f5..0f0c900ec2 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -4297,14 +4297,6 @@ static int lib_interface_isis_multi_topology_common( switch (event) { case NB_EV_VALIDATE: - circuit = nb_running_get_entry(dnode, NULL, false); - if (circuit && circuit->area && circuit->area->oldmetric) { - snprintf( - errmsg, errmsg_len, - "Multi topology IS-IS can only be used with wide metrics"); - return NB_ERR_VALIDATION; - } - break; case NB_EV_PREPARE: case NB_EV_ABORT: break; @@ -16,14 +16,8 @@ extern "C" { #endif #define BFD_DEF_MIN_RX 300 -#define BFD_MIN_MIN_RX 50 -#define BFD_MAX_MIN_RX 60000 #define BFD_DEF_MIN_TX 300 -#define BFD_MIN_MIN_TX 50 -#define BFD_MAX_MIN_TX 60000 #define BFD_DEF_DETECT_MULT 3 -#define BFD_MIN_DETECT_MULT 2 -#define BFD_MAX_DETECT_MULT 255 #define BFD_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */ #define BFD_STATUS_DOWN (1 << 1) /* BFD session status is down */ diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c index abd42f359f..05088d52d1 100644 --- a/lib/grammar_sandbox_main.c +++ b/lib/grammar_sandbox_main.c @@ -40,7 +40,7 @@ int main(int argc, char **argv) vty_init(master, true); lib_cmd_init(); - nb_init(master, NULL, 0, false); + nb_init(master, NULL, 0, false, false); vty_stdio(vty_do_exit); diff --git a/lib/libfrr.c b/lib/libfrr.c index a1982841d3..f2247a48e5 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -820,7 +820,8 @@ struct event_loop *frr_init(void) log_ref_vty_init(); lib_error_init(); - nb_init(master, di->yang_modules, di->n_yang_modules, true); + nb_init(master, di->yang_modules, di->n_yang_modules, true, + (di->flags & FRR_LOAD_YANG_LIBRARY) != 0); if (nb_db_init() != NB_OK) flog_warn(EC_LIB_NB_DATABASE, "%s: failed to initialize northbound database", diff --git a/lib/libfrr.h b/lib/libfrr.h index 7ed7be4d98..df537e2e3b 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -46,6 +46,11 @@ extern "C" { * is responsible for calling frr_vty_serv() itself. */ #define FRR_MANUAL_VTY_START (1 << 7) +/* If FRR_LOAD_YANG_LIBRARY is set then libyang will be told to load and + * implement it's internal ietf-yang-library implementation. This should + * normally only be done from mgmtd. + */ +#define FRR_LOAD_YANG_LIBRARY (1 << 8) PREDECL_DLIST(log_args); struct log_arg { @@ -351,7 +351,6 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY), DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_ADD), DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_DEL), - DESC_ENTRY(ZEBRA_VRF_UNREGISTER), DESC_ENTRY(ZEBRA_VRF_ADD), DESC_ENTRY(ZEBRA_VRF_DELETE), DESC_ENTRY(ZEBRA_VRF_LABEL), diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 3f408e0a71..cb1ebb5d09 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -70,10 +70,10 @@ static struct nexthop *nexthop_group_tail(const struct nexthop_group *nhg) return nexthop; } -uint8_t nexthop_group_nexthop_num(const struct nexthop_group *nhg) +uint16_t nexthop_group_nexthop_num(const struct nexthop_group *nhg) { struct nexthop *nhop; - uint8_t num = 0; + uint16_t num = 0; for (ALL_NEXTHOPS_PTR(nhg, nhop)) num++; @@ -81,11 +81,10 @@ uint8_t nexthop_group_nexthop_num(const struct nexthop_group *nhg) return num; } -static uint8_t -nexthop_group_nexthop_num_no_recurse(const struct nexthop_group *nhg) +static uint16_t nexthop_group_nexthop_num_no_recurse(const struct nexthop_group *nhg) { struct nexthop *nhop; - uint8_t num = 0; + uint16_t num = 0; for (nhop = nhg->nexthop; nhop; nhop = nhop->next) num++; @@ -93,10 +92,10 @@ nexthop_group_nexthop_num_no_recurse(const struct nexthop_group *nhg) return num; } -uint8_t nexthop_group_active_nexthop_num(const struct nexthop_group *nhg) +uint16_t nexthop_group_active_nexthop_num(const struct nexthop_group *nhg) { struct nexthop *nhop; - uint8_t num = 0; + uint16_t num = 0; for (ALL_NEXTHOPS_PTR(nhg, nhop)) { if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_ACTIVE)) @@ -184,11 +183,9 @@ static struct nexthop *nhg_nh_find(const struct nexthop_group *nhg, return NULL; } -static bool -nexthop_group_equal_common(const struct nexthop_group *nhg1, - const struct nexthop_group *nhg2, - uint8_t (*nexthop_group_nexthop_num_func)( - const struct nexthop_group *nhg)) +static bool nexthop_group_equal_common( + const struct nexthop_group *nhg1, const struct nexthop_group *nhg2, + uint16_t (*nexthop_group_nexthop_num_func)(const struct nexthop_group *nhg)) { if (nhg1 && !nhg2) return false; diff --git a/lib/nexthop_group.h b/lib/nexthop_group.h index 822a35439c..9103299418 100644 --- a/lib/nexthop_group.h +++ b/lib/nexthop_group.h @@ -149,9 +149,8 @@ extern void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh); /* Return the number of nexthops in this nhg */ -extern uint8_t nexthop_group_nexthop_num(const struct nexthop_group *nhg); -extern uint8_t -nexthop_group_active_nexthop_num(const struct nexthop_group *nhg); +extern uint16_t nexthop_group_nexthop_num(const struct nexthop_group *nhg); +extern uint16_t nexthop_group_active_nexthop_num(const struct nexthop_group *nhg); extern bool nexthop_group_has_label(const struct nexthop_group *nhg); diff --git a/lib/northbound.c b/lib/northbound.c index 2dae21341e..a385cc9ece 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -2701,7 +2701,7 @@ void nb_validate_callbacks(void) void nb_init(struct event_loop *tm, const struct frr_yang_module_info *const modules[], - size_t nmodules, bool db_enabled) + size_t nmodules, bool db_enabled, bool load_library) { struct yang_module *loaded[nmodules], **loadedp = loaded; @@ -2717,7 +2717,7 @@ void nb_init(struct event_loop *tm, nb_db_enabled = db_enabled; - yang_init(true, explicit_compile); + yang_init(true, explicit_compile, load_library); /* Load YANG modules and their corresponding northbound callbacks. */ for (size_t i = 0; i < nmodules; i++) { diff --git a/lib/northbound.h b/lib/northbound.h index dd3fbf8f73..97a1d31e57 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -1703,10 +1703,12 @@ void nb_validate_callbacks(void); * * db_enabled * Set this to record the transactions in the transaction log. + * + * load_library + * Set this to have libyang to load/implement the ietf-yang-library. */ -extern void nb_init(struct event_loop *tm, - const struct frr_yang_module_info *const modules[], - size_t nmodules, bool db_enabled); +extern void nb_init(struct event_loop *tm, const struct frr_yang_module_info *const modules[], + size_t nmodules, bool db_enabled, bool load_library); /* * Finish the northbound layer gracefully. Should be called only when the daemon diff --git a/lib/yang.c b/lib/yang.c index 14d5b118c6..b847b8b77b 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -976,7 +976,7 @@ void yang_debugging_set(bool enable) } } -struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile) +struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile, bool load_library) { struct ly_ctx *ctx = NULL; const char *yang_models_path = YANG_MODELS_PATH; @@ -994,7 +994,9 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile) YANG_MODELS_PATH); } - options = LY_CTX_NO_YANGLIBRARY | LY_CTX_DISABLE_SEARCHDIR_CWD; + options = LY_CTX_DISABLE_SEARCHDIR_CWD; + if (!load_library) + options |= LY_CTX_NO_YANGLIBRARY; if (explicit_compile) options |= LY_CTX_EXPLICIT_COMPILE; err = ly_ctx_new(yang_models_path, options, &ctx); @@ -1007,7 +1009,7 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile) return ctx; } -void yang_init(bool embedded_modules, bool defer_compile) +void yang_init(bool embedded_modules, bool defer_compile, bool load_library) { /* Initialize libyang global parameters that affect all containers. */ ly_set_log_clb(ly_zlog_cb @@ -1019,7 +1021,7 @@ void yang_init(bool embedded_modules, bool defer_compile) ly_log_options(LY_LOLOG | LY_LOSTORE); /* Initialize libyang container for native models. */ - ly_native_ctx = yang_ctx_new_setup(embedded_modules, defer_compile); + ly_native_ctx = yang_ctx_new_setup(embedded_modules, defer_compile, load_library); if (!ly_native_ctx) { flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__); exit(1); diff --git a/lib/yang.h b/lib/yang.h index c4fc78b8ae..52857ecf00 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -607,9 +607,11 @@ extern struct yang_data *yang_data_list_find(const struct list *list, * explicit_compile * True if the caller will later call ly_ctx_compile to compile all loaded * modules at once. + * load_library + * Set this to have libyang to load/implement the ietf-yang-library. */ -extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, - bool explicit_compile); +extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile, + bool load_library); /* * Enable or disable libyang verbose debugging. @@ -727,8 +729,10 @@ extern const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, * Specify whether libyang should attempt to look for embedded YANG modules. * defer_compile * Hold off on compiling modules until yang_init_loading_complete is called. + * load_library + * Set this to have libyang to load/implement the ietf-yang-library. */ -extern void yang_init(bool embedded_modules, bool defer_compile); +extern void yang_init(bool embedded_modules, bool defer_compile, bool load_library); /* * Should be called after yang_init and all yang_module_load()s have been done, diff --git a/lib/yang_translator.c b/lib/yang_translator.c index 005f6422f3..b7599e0a71 100644 --- a/lib/yang_translator.c +++ b/lib/yang_translator.c @@ -166,7 +166,7 @@ struct yang_translator *yang_translator_load(const char *path) RB_INSERT(yang_translators, &yang_translators, translator); /* Initialize the translator libyang context. */ - translator->ly_ctx = yang_ctx_new_setup(false, false); + translator->ly_ctx = yang_ctx_new_setup(false, false, false); if (!translator->ly_ctx) { flog_warn(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__); goto error; @@ -512,7 +512,7 @@ static unsigned int yang_module_nodes_count(const struct lys_module *module) void yang_translator_init(void) { - ly_translator_ctx = yang_ctx_new_setup(true, false); + ly_translator_ctx = yang_ctx_new_setup(true, false, false); if (!ly_translator_ctx) { flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__); exit(1); diff --git a/lib/zclient.h b/lib/zclient.h index 2877b347d8..91c0c9ed6d 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -124,7 +124,6 @@ typedef enum { ZEBRA_BFD_DEST_REPLAY, ZEBRA_REDISTRIBUTE_ROUTE_ADD, ZEBRA_REDISTRIBUTE_ROUTE_DEL, - ZEBRA_VRF_UNREGISTER, ZEBRA_VRF_ADD, ZEBRA_VRF_DELETE, ZEBRA_VRF_LABEL, diff --git a/mgmtd/mgmt.c b/mgmtd/mgmt.c index 02c54b9215..cfadad4829 100644 --- a/mgmtd/mgmt.c +++ b/mgmtd/mgmt.c @@ -57,9 +57,6 @@ void mgmt_init(void) /* Initialize MGMTD Transaction module */ mgmt_txn_init(mm, mm->master); - /* Add yang-library module */ - yang_module_load("ietf-yang-library", NULL); - /* Initialize the MGMTD Frontend Adapter Module */ mgmt_fe_adapter_init(mm->master); diff --git a/mgmtd/mgmt_main.c b/mgmtd/mgmt_main.c index e181d0da5e..1880d94415 100644 --- a/mgmtd/mgmt_main.c +++ b/mgmtd/mgmt_main.c @@ -214,7 +214,7 @@ FRR_DAEMON_INFO(mgmtd, MGMTD, .n_yang_modules = array_size(mgmt_yang_modules), /* avoid libfrr trying to read our config file for us */ - .flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG, + .flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG | FRR_LOAD_YANG_LIBRARY, ); /* clang-format on */ diff --git a/pimd/pim_autorp.c b/pimd/pim_autorp.c index 1f4d0c65af..35347a2790 100644 --- a/pimd/pim_autorp.c +++ b/pimd/pim_autorp.c @@ -290,8 +290,8 @@ static bool pim_autorp_add_rp(struct pim_autorp *autorp, pim_addr rpaddr, event_add_timer(router->master, autorp_rp_holdtime, trp, holdtime, &(trp->hold_timer)); if (PIM_DEBUG_AUTORP) - zlog_debug("%s: Started %u second hold timer for RP %pI4", - __func__, holdtime, &rp->addr); + zlog_debug("%s: Started %u second hold timer for RP %pI4", __func__, + holdtime, &trp->addr); } else { /* If hold time is zero, make sure there doesn't exist a hold timer for it already */ event_cancel(&trp->hold_timer); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 1dc9307e4f..20e3ba184b 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -527,77 +527,66 @@ void pim_if_addr_add(struct connected *ifc) detect_address_change(ifp, 0, __func__); - // if (ifc->address->family != AF_INET) - // return; - #if PIM_IPV == 4 - struct in_addr ifaddr = ifc->address->u.prefix4; + if (ifc->address->family == AF_INET) { + struct in_addr ifaddr = ifc->address->u.prefix4; - if (pim_ifp->gm_enable) { - struct gm_sock *igmp; + if (pim_ifp->gm_enable) { + struct gm_sock *igmp; - /* lookup IGMP socket */ - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, - ifaddr); - if (!igmp) { - /* if addr new, add IGMP socket */ - if (ifc->address->family == AF_INET) + /* lookup IGMP socket */ + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, ifaddr); + if (!igmp) { + /* if addr new, add IGMP socket */ pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp, false); - } else if (igmp->mtrace_only) { - igmp_sock_delete(igmp); - pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp, - false); - } + } else if (igmp->mtrace_only) { + igmp_sock_delete(igmp); + pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp, false); + } - /* Replay Static IGMP groups */ - if (pim_ifp->gm_join_list) { - struct listnode *node; - struct listnode *nextnode; - struct gm_join *ij; - int join_fd; - - for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node, - nextnode, ij)) { - /* Close socket and reopen with Source and Group - */ - close(ij->sock_fd); - join_fd = gm_join_sock( - ifp->name, ifp->ifindex, ij->group_addr, - ij->source_addr, pim_ifp); - if (join_fd < 0) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", ij->group_addr, - group_str, - sizeof(group_str)); - pim_inet4_dump( - "<src?>", ij->source_addr, - source_str, sizeof(source_str)); - zlog_warn( - "%s: gm_join_sock() failure for IGMP group %s source %s on interface %s", - __func__, group_str, source_str, - ifp->name); - /* warning only */ - } else - ij->sock_fd = join_fd; + /* Replay Static IGMP groups */ + if (pim_ifp->gm_join_list) { + struct listnode *node; + struct listnode *nextnode; + struct gm_join *ij; + int join_fd; + + for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node, nextnode, ij)) { + /* Close socket and reopen with Source and Group + */ + close(ij->sock_fd); + join_fd = gm_join_sock(ifp->name, ifp->ifindex, + ij->group_addr, ij->source_addr, + pim_ifp); + if (join_fd < 0) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("<grp?>", ij->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("<src?>", ij->source_addr, + source_str, sizeof(source_str)); + zlog_warn("%s: gm_join_sock() failure for IGMP group %s source %s on interface %s", + __func__, group_str, source_str, + ifp->name); + /* warning only */ + } else + ij->sock_fd = join_fd; + } } - } - } /* igmp */ - else { - struct gm_sock *igmp; - - /* lookup IGMP socket */ - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, - ifaddr); - if (ifc->address->family == AF_INET) { + } /* igmp */ + else { + struct gm_sock *igmp; + + /* lookup IGMP socket */ + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, ifaddr); if (igmp) igmp_sock_delete(igmp); /* if addr new, add IGMP socket */ pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp, true); - } - } /* igmp mtrace only */ + } /* igmp mtrace only */ + } #endif if (pim_ifp->pim_enable) { diff --git a/tests/bgpd/subdir.am b/tests/bgpd/subdir.am index 5148e7e440..97845ec1aa 100644 --- a/tests/bgpd/subdir.am +++ b/tests/bgpd/subdir.am @@ -52,17 +52,6 @@ tests_bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD) tests_bgpd_test_mp_attr_SOURCES = tests/bgpd/test_mp_attr.c EXTRA_DIST += tests/bgpd/test_mp_attr.py - -if BGPD -check_PROGRAMS += tests/bgpd/test_mpath -endif -tests_bgpd_test_mpath_CFLAGS = $(TESTS_CFLAGS) -tests_bgpd_test_mpath_CPPFLAGS = $(TESTS_CPPFLAGS) -tests_bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD) -tests_bgpd_test_mpath_SOURCES = tests/bgpd/test_mpath.c -EXTRA_DIST += tests/bgpd/test_mpath.py - - if BGPD check_PROGRAMS += tests/bgpd/test_packet endif diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c deleted file mode 100644 index ebbe3ac3e2..0000000000 --- a/tests/bgpd/test_mpath.c +++ /dev/null @@ -1,482 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * BGP Multipath Unit Test - * Copyright (C) 2010 Google Inc. - * - * This file is part of Quagga - */ - -#include <zebra.h> - -#include "qobj.h" -#include "vty.h" -#include "stream.h" -#include "privs.h" -#include "linklist.h" -#include "memory.h" -#include "zclient.h" -#include "queue.h" -#include "filter.h" - -#include "bgpd/bgpd.h" -#include "bgpd/bgp_table.h" -#include "bgpd/bgp_route.h" -#include "bgpd/bgp_attr.h" -#include "bgpd/bgp_nexthop.h" -#include "bgpd/bgp_mpath.h" -#include "bgpd/bgp_evpn.h" -#include "bgpd/bgp_network.h" - -#define VT100_RESET "\x1b[0m" -#define VT100_RED "\x1b[31m" -#define VT100_GREEN "\x1b[32m" -#define VT100_YELLOW "\x1b[33m" -#define OK VT100_GREEN "OK" VT100_RESET -#define FAILED VT100_RED "failed" VT100_RESET - -#define TEST_PASSED 0 -#define TEST_FAILED -1 - -#define EXPECT_TRUE(expr, res) \ - if (!(expr)) { \ - printf("Test failure in %s line %u: %s\n", __func__, __LINE__, \ - #expr); \ - (res) = TEST_FAILED; \ - } - -typedef struct testcase_t__ testcase_t; - -typedef int (*test_setup_func)(testcase_t *); -typedef int (*test_run_func)(testcase_t *); -typedef int (*test_cleanup_func)(testcase_t *); - -struct testcase_t__ { - const char *desc; - void *test_data; - void *verify_data; - void *tmp_data; - test_setup_func setup; - test_run_func run; - test_cleanup_func cleanup; -}; - -/* need these to link in libbgp */ -struct event_loop *master = NULL; -extern struct zclient *zclient; -struct zebra_privs_t bgpd_privs = { - .user = NULL, - .group = NULL, - .vty_group = NULL, -}; - -static int tty = 0; - -/* Create fake bgp instance */ -static struct bgp *bgp_create_fake(as_t *as, const char *name) -{ - struct bgp *bgp; - afi_t afi; - safi_t safi; - - if ((bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp))) == NULL) - return NULL; - - bgp_lock(bgp); - // bgp->peer_self = peer_new (bgp); - // bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static - // announcement"); - - bgp->peer = list_new(); - // bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp; - - bgp->group = list_new(); - // bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp; - - bgp_evpn_init(bgp); - FOREACH_AFI_SAFI (afi, safi) { - bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi); - bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi, safi); - bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi); - bgp->maxpaths[afi][safi].maxpaths_ebgp = MULTIPATH_NUM; - bgp->maxpaths[afi][safi].maxpaths_ibgp = MULTIPATH_NUM; - } - - bgp_scan_init(bgp); - bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; - bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; - bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; - bgp->restart_time = BGP_DEFAULT_RESTART_TIME; - bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; - - bgp->as = *as; - - if (name) - bgp->name = strdup(name); - - return bgp; -} - -/*========================================================= - * Testcase for maximum-paths configuration - */ -static int setup_bgp_cfg_maximum_paths(testcase_t *t) -{ - as_t asn = 1; - t->tmp_data = bgp_create_fake(&asn, NULL); - if (!t->tmp_data) - return -1; - return 0; -} - -static int run_bgp_cfg_maximum_paths(testcase_t *t) -{ - afi_t afi; - safi_t safi; - struct bgp *bgp; - int api_result; - int test_result = TEST_PASSED; - - bgp = t->tmp_data; - FOREACH_AFI_SAFI (afi, safi) { - /* test bgp_maximum_paths_set */ - api_result = bgp_maximum_paths_set(bgp, afi, safi, - BGP_PEER_EBGP, 10, 0); - EXPECT_TRUE(api_result == 0, test_result); - api_result = bgp_maximum_paths_set(bgp, afi, safi, - BGP_PEER_IBGP, 10, 0); - EXPECT_TRUE(api_result == 0, test_result); - EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ebgp == 10, - test_result); - EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ibgp == 10, - test_result); - - /* test bgp_maximum_paths_unset */ - api_result = - bgp_maximum_paths_unset(bgp, afi, safi, BGP_PEER_EBGP); - EXPECT_TRUE(api_result == 0, test_result); - api_result = - bgp_maximum_paths_unset(bgp, afi, safi, BGP_PEER_IBGP); - EXPECT_TRUE(api_result == 0, test_result); - EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ebgp - == MULTIPATH_NUM), - test_result); - EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ibgp - == MULTIPATH_NUM), - test_result); - } - - return test_result; -} - -static int cleanup_bgp_cfg_maximum_paths(testcase_t *t) -{ - return bgp_delete((struct bgp *)t->tmp_data); -} - -testcase_t test_bgp_cfg_maximum_paths = { - .desc = "Test bgp maximum-paths config", - .setup = setup_bgp_cfg_maximum_paths, - .run = run_bgp_cfg_maximum_paths, - .cleanup = cleanup_bgp_cfg_maximum_paths, -}; - -/*========================================================= - * Testcase for bgp_mp_list - */ -struct peer test_mp_list_peer[] = { - {.local_as = 1, .as = 2}, {.local_as = 1, .as = 2}, - {.local_as = 1, .as = 2}, {.local_as = 1, .as = 2}, - {.local_as = 1, .as = 2}, -}; -int test_mp_list_peer_count = array_size(test_mp_list_peer); -struct attr test_mp_list_attr[4]; -struct bgp_path_info test_mp_list_info[] = { - {.peer = &test_mp_list_peer[0], .attr = &test_mp_list_attr[0]}, - {.peer = &test_mp_list_peer[1], .attr = &test_mp_list_attr[1]}, - {.peer = &test_mp_list_peer[2], .attr = &test_mp_list_attr[1]}, - {.peer = &test_mp_list_peer[3], .attr = &test_mp_list_attr[2]}, - {.peer = &test_mp_list_peer[4], .attr = &test_mp_list_attr[3]}, -}; -int test_mp_list_info_count = array_size(test_mp_list_info); - -static int setup_bgp_mp_list(testcase_t *t) -{ - test_mp_list_attr[0].nexthop.s_addr = 0x01010101; - test_mp_list_attr[1].nexthop.s_addr = 0x02020202; - test_mp_list_attr[2].nexthop.s_addr = 0x03030303; - test_mp_list_attr[3].nexthop.s_addr = 0x04040404; - - if ((test_mp_list_peer[0].su_remote = sockunion_str2su("1.1.1.1")) - == NULL) - return -1; - if ((test_mp_list_peer[1].su_remote = sockunion_str2su("2.2.2.2")) - == NULL) - return -1; - if ((test_mp_list_peer[2].su_remote = sockunion_str2su("3.3.3.3")) - == NULL) - return -1; - if ((test_mp_list_peer[3].su_remote = sockunion_str2su("4.4.4.4")) - == NULL) - return -1; - if ((test_mp_list_peer[4].su_remote = sockunion_str2su("5.5.5.5")) - == NULL) - return -1; - - return 0; -} - -static int run_bgp_mp_list(testcase_t *t) -{ - struct list mp_list; - struct listnode *mp_node; - struct bgp_path_info *info; - int i; - int test_result = TEST_PASSED; - bgp_mp_list_init(&mp_list); - EXPECT_TRUE(listcount(&mp_list) == 0, test_result); - - bgp_mp_list_add(&mp_list, &test_mp_list_info[1]); - bgp_mp_list_add(&mp_list, &test_mp_list_info[4]); - bgp_mp_list_add(&mp_list, &test_mp_list_info[2]); - bgp_mp_list_add(&mp_list, &test_mp_list_info[3]); - bgp_mp_list_add(&mp_list, &test_mp_list_info[0]); - - for (i = 0, mp_node = mp_list.head; i < test_mp_list_info_count; - i++, mp_node = listnextnode(mp_node)) { - info = listgetdata(mp_node); - info->lock++; - EXPECT_TRUE(info == &test_mp_list_info[i], test_result); - } - - bgp_mp_list_clear(&mp_list); - EXPECT_TRUE(listcount(&mp_list) == 0, test_result); - - return test_result; -} - -static int cleanup_bgp_mp_list(testcase_t *t) -{ - int i; - - for (i = 0; i < test_mp_list_peer_count; i++) - sockunion_free(test_mp_list_peer[i].su_remote); - - return 0; -} - -testcase_t test_bgp_mp_list = { - .desc = "Test bgp_mp_list", - .setup = setup_bgp_mp_list, - .run = run_bgp_mp_list, - .cleanup = cleanup_bgp_mp_list, -}; - -/*========================================================= - * Testcase for bgp_path_info_mpath_update - */ - -static struct bgp_dest *dest; - -static int setup_bgp_path_info_mpath_update(testcase_t *t) -{ - int i; - struct bgp *bgp; - struct bgp_table *rt; - struct prefix p; - as_t asn = 1; - - t->tmp_data = bgp_create_fake(&asn, NULL); - if (!t->tmp_data) - return -1; - - bgp = t->tmp_data; - rt = bgp->rib[AFI_IP][SAFI_UNICAST]; - - if (!rt) - return -1; - - str2prefix("42.1.1.0/24", &p); - dest = bgp_node_get(rt, &p); - - setup_bgp_mp_list(t); - for (i = 0; i < test_mp_list_info_count; i++) - bgp_path_info_add(dest, &test_mp_list_info[i]); - return 0; -} - -static int run_bgp_path_info_mpath_update(testcase_t *t) -{ - struct bgp_path_info *new_best, *old_best, *mpath; - struct list mp_list; - struct bgp_maxpaths_cfg mp_cfg = {3, 3}; - - int test_result = TEST_PASSED; - bgp_mp_list_init(&mp_list); - bgp_mp_list_add(&mp_list, &test_mp_list_info[4]); - bgp_mp_list_add(&mp_list, &test_mp_list_info[3]); - bgp_mp_list_add(&mp_list, &test_mp_list_info[0]); - bgp_mp_list_add(&mp_list, &test_mp_list_info[1]); - new_best = &test_mp_list_info[3]; - old_best = NULL; - bgp_path_info_mpath_update(NULL, dest, new_best, old_best, &mp_list, - &mp_cfg); - bgp_mp_list_clear(&mp_list); - EXPECT_TRUE(bgp_path_info_mpath_count(new_best) == 2, test_result); - mpath = bgp_path_info_mpath_first(new_best); - EXPECT_TRUE(mpath == &test_mp_list_info[0], test_result); - EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_PATH_MULTIPATH), test_result); - mpath = bgp_path_info_mpath_next(mpath); - EXPECT_TRUE(mpath == &test_mp_list_info[1], test_result); - EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_PATH_MULTIPATH), test_result); - - bgp_mp_list_add(&mp_list, &test_mp_list_info[0]); - bgp_mp_list_add(&mp_list, &test_mp_list_info[1]); - new_best = &test_mp_list_info[0]; - old_best = &test_mp_list_info[3]; - bgp_path_info_mpath_update(NULL, dest, new_best, old_best, &mp_list, - &mp_cfg); - bgp_mp_list_clear(&mp_list); - EXPECT_TRUE(bgp_path_info_mpath_count(new_best) == 1, test_result); - mpath = bgp_path_info_mpath_first(new_best); - EXPECT_TRUE(mpath == &test_mp_list_info[1], test_result); - EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_PATH_MULTIPATH), test_result); - EXPECT_TRUE(!CHECK_FLAG(test_mp_list_info[0].flags, BGP_PATH_MULTIPATH), - test_result); - - return test_result; -} - -static int cleanup_bgp_path_info_mpath_update(testcase_t *t) -{ - int i; - - for (i = 0; i < test_mp_list_peer_count; i++) - sockunion_free(test_mp_list_peer[i].su_remote); - - return bgp_delete((struct bgp *)t->tmp_data); -} - -testcase_t test_bgp_path_info_mpath_update = { - .desc = "Test bgp_path_info_mpath_update", - .setup = setup_bgp_path_info_mpath_update, - .run = run_bgp_path_info_mpath_update, - .cleanup = cleanup_bgp_path_info_mpath_update, -}; - -/*========================================================= - * Set up testcase vector - */ -testcase_t *all_tests[] = { - &test_bgp_cfg_maximum_paths, &test_bgp_mp_list, - &test_bgp_path_info_mpath_update, -}; - -int all_tests_count = array_size(all_tests); - -/*========================================================= - * Test Driver Functions - */ -static int global_test_init(void) -{ - qobj_init(); - master = event_master_create(NULL); - zclient = zclient_new(master, &zclient_options_default, NULL, 0); - bgp_master_init(master, BGP_SOCKET_SNDBUF_SIZE, list_new()); - vrf_init(NULL, NULL, NULL, NULL); - bgp_option_set(BGP_OPT_NO_LISTEN); - - if (fileno(stdout) >= 0) - tty = isatty(fileno(stdout)); - return 0; -} - -static int global_test_cleanup(void) -{ - if (zclient != NULL) - zclient_free(zclient); - event_master_free(master); - return 0; -} - -static void display_result(testcase_t *test, int result) -{ - if (tty) - printf("%s: %s\n", test->desc, - result == TEST_PASSED ? OK : FAILED); - else - printf("%s: %s\n", test->desc, - result == TEST_PASSED ? "OK" : "FAILED"); -} - -static int setup_test(testcase_t *t) -{ - int res = 0; - if (t->setup) - res = t->setup(t); - return res; -} - -static int cleanup_test(testcase_t *t) -{ - int res = 0; - if (t->cleanup) - res = t->cleanup(t); - return res; -} - -static void run_tests(testcase_t *tests[], int num_tests, int *pass_count, - int *fail_count) -{ - int test_index, result; - testcase_t *cur_test; - - *pass_count = *fail_count = 0; - - for (test_index = 0; test_index < num_tests; test_index++) { - cur_test = tests[test_index]; - if (!cur_test->desc) { - printf("error: test %d has no description!\n", - test_index); - continue; - } - if (!cur_test->run) { - printf("error: test %s has no run function!\n", - cur_test->desc); - continue; - } - if (setup_test(cur_test) != 0) { - printf("error: setup failed for test %s\n", - cur_test->desc); - continue; - } - result = cur_test->run(cur_test); - if (result == TEST_PASSED) - *pass_count += 1; - else - *fail_count += 1; - display_result(cur_test, result); - if (cleanup_test(cur_test) != 0) { - printf("error: cleanup failed for test %s\n", - cur_test->desc); - continue; - } - } -} - -int main(void) -{ - int pass_count, fail_count; - time_t cur_time; - char buf[32]; - - time(&cur_time); - printf("BGP Multipath Tests Run at %s", ctime_r(&cur_time, buf)); - if (global_test_init() != 0) { - printf("Global init failed. Terminating.\n"); - exit(1); - } - run_tests(all_tests, all_tests_count, &pass_count, &fail_count); - global_test_cleanup(); - printf("Total pass/fail: %d/%d\n", pass_count, fail_count); - return fail_count; -} diff --git a/tests/bgpd/test_mpath.py b/tests/bgpd/test_mpath.py deleted file mode 100644 index 582fd25c20..0000000000 --- a/tests/bgpd/test_mpath.py +++ /dev/null @@ -1,10 +0,0 @@ -import frrtest - - -class TestMpath(frrtest.TestMultiOut): - program = "./test_mpath" - - -TestMpath.okfail("bgp maximum-paths config") -TestMpath.okfail("bgp_mp_list") -TestMpath.okfail("bgp_path_info_mpath_update") diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c index d5faa33ca8..17002464e1 100644 --- a/tests/bgpd/test_peer_attr.c +++ b/tests/bgpd/test_peer_attr.c @@ -1355,7 +1355,7 @@ static void bgp_startup(void) zprivs_init(&bgpd_privs); master = event_master_create(NULL); - nb_init(master, NULL, 0, false); + nb_init(master, NULL, 0, false, false); bgp_master_init(master, BGP_SOCKET_SNDBUF_SIZE, list_new()); bgp_option_set(BGP_OPT_NO_LISTEN); vrf_init(NULL, NULL, NULL, NULL); diff --git a/tests/helpers/c/main.c b/tests/helpers/c/main.c index 9cb395bb1f..344af82fca 100644 --- a/tests/helpers/c/main.c +++ b/tests/helpers/c/main.c @@ -143,7 +143,7 @@ int main(int argc, char **argv) vty_init(master, false); lib_cmd_init(); debug_init(); - nb_init(master, NULL, 0, false); + nb_init(master, NULL, 0, false, false); /* OSPF vty inits. */ test_vty_init(); diff --git a/tests/isisd/test_isis_spf.c b/tests/isisd/test_isis_spf.c index 93009a1b84..e5a8f7a513 100644 --- a/tests/isisd/test_isis_spf.c +++ b/tests/isisd/test_isis_spf.c @@ -546,7 +546,7 @@ int main(int argc, char **argv) cmd_init(1); cmd_hostname_set("test"); vty_init(master, false); - yang_init(true, false); + yang_init(true, false, false); if (debug) zlog_aux_init("NONE: ", LOG_DEBUG); else diff --git a/tests/lib/cli/common_cli.c b/tests/lib/cli/common_cli.c index 6401971435..342a91cc79 100644 --- a/tests/lib/cli/common_cli.c +++ b/tests/lib/cli/common_cli.c @@ -77,7 +77,7 @@ int main(int argc, char **argv) for (yangcount = 0; test_yang_modules && test_yang_modules[yangcount]; yangcount++) ; - nb_init(master, test_yang_modules, yangcount, false); + nb_init(master, test_yang_modules, yangcount, false, false); test_init(argc, argv); diff --git a/tests/lib/cli/test_commands.c b/tests/lib/cli/test_commands.c index 0034c2af89..9873383fdc 100644 --- a/tests/lib/cli/test_commands.c +++ b/tests/lib/cli/test_commands.c @@ -197,7 +197,7 @@ static void test_init(void) cmd_init(1); debug_init(); - nb_init(master, NULL, 0, false); + nb_init(master, NULL, 0, false, false); install_node(&bgp_node); install_node(&rip_node); diff --git a/tests/lib/northbound/test_oper_data.c b/tests/lib/northbound/test_oper_data.c index 74a0dfe6cc..fdc9e53ca3 100644 --- a/tests/lib/northbound/test_oper_data.c +++ b/tests/lib/northbound/test_oper_data.c @@ -461,7 +461,7 @@ int main(int argc, char **argv) vty_init(master, false); lib_cmd_init(); debug_init(); - nb_init(master, modules, array_size(modules), false); + nb_init(master, modules, array_size(modules), false, false); install_element(ENABLE_NODE, &test_rpc_cmd); diff --git a/tests/lib/test_grpc.cpp b/tests/lib/test_grpc.cpp index 2f0282704e..379a8688a7 100644 --- a/tests/lib/test_grpc.cpp +++ b/tests/lib/test_grpc.cpp @@ -111,8 +111,7 @@ static void static_startup(void) static_debug_init(); master = event_master_create(NULL); - nb_init(master, staticd_yang_modules, array_size(staticd_yang_modules), - false); + nb_init(master, staticd_yang_modules, array_size(staticd_yang_modules), false, false); static_zebra_init(); vty_init(master, true); diff --git a/tests/topotests/bgp_default_originate/test_bgp_default_originate_2links.py b/tests/topotests/bgp_default_originate/test_bgp_default_originate_2links.py index f4f874f942..bcdd987889 100644 --- a/tests/topotests/bgp_default_originate/test_bgp_default_originate_2links.py +++ b/tests/topotests/bgp_default_originate/test_bgp_default_originate_2links.py @@ -266,21 +266,21 @@ def verify_the_uptime(time_stamp_before, time_stamp_after, incremented=None): if incremented == True: if uptime_before < uptime_after: logger.info( - " The Uptime [{}] is incremented than [{}].......PASSED ".format( + " The Uptime before [{}] is less than [{}].......PASSED ".format( time_stamp_before, time_stamp_after ) ) return True else: logger.error( - " The Uptime [{}] is expected to be incremented than [{}].......FAILED ".format( + " The Uptime before [{}] is greater than the uptime after [{}].......FAILED ".format( time_stamp_before, time_stamp_after ) ) return False else: logger.info( - " The Uptime [{}] is not incremented than [{}] ".format( + " The Uptime before [{}] the same as after [{}] ".format( time_stamp_before, time_stamp_after ) ) @@ -1027,7 +1027,7 @@ def test_verify_bgp_default_originate_with_default_static_route_p1(request): result = verify_the_uptime(uptime_before_ipv6, uptime_after_ipv6, incremented=False) assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) - step("Taking uptime snapshot before removing redisctribute static ") + step("Taking uptime snapshot before removing redistribute static") uptime_before_ipv4 = get_rib_route_uptime(tgen, "ipv4", "r2", ipv4_uptime_dict) uptime_before_ipv6 = get_rib_route_uptime(tgen, "ipv6", "r2", ipv6_uptime_dict) sleep(1) @@ -1074,6 +1074,7 @@ def test_verify_bgp_default_originate_with_default_static_route_p1(request): ) assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + step("Now look that the route is not pointed at link2") result = verify_rib_default_route( tgen, topo, @@ -1093,7 +1094,7 @@ def test_verify_bgp_default_originate_with_default_static_route_p1(request): ) assert result is not True, "Testcase {} : Failed Error: {}".format(tc_name, result) - step("Taking uptime snapshot before removing redisctribute static ") + step("Taking uptime snapshot after removing redistribute static") uptime_after_ipv4 = get_rib_route_uptime(tgen, "ipv4", "r2", ipv4_uptime_dict) uptime_after_ipv6 = get_rib_route_uptime(tgen, "ipv6", "r2", ipv6_uptime_dict) diff --git a/tests/topotests/bgp_default_originate/test_default_orginate_vrf.py b/tests/topotests/bgp_default_originate/test_default_orginate_vrf.py index 1506b02e5d..905c3e2b66 100644 --- a/tests/topotests/bgp_default_originate/test_default_orginate_vrf.py +++ b/tests/topotests/bgp_default_originate/test_default_orginate_vrf.py @@ -546,13 +546,7 @@ def test_verify_default_originate_route_with_non_default_VRF_p1(request): tc_name, result ) - result = verify_rib( - tgen, - addr_type, - "r2", - static_routes_input, - next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], - ) + result = verify_rib(tgen, addr_type, "r2", static_routes_input) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index cb71112af3..f34c48b890 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -3371,7 +3371,7 @@ def verify_rib( found_hops = [ rib_r["ip"] for rib_r in rib_routes_json[st_rt][0]["nexthops"] - if "ip" in rib_r + if "ip" in rib_r and "active" in rib_r ] # If somehow key "ip" is not found in nexthops JSON diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index 7941e5c1d2..14dd61b077 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -492,7 +492,16 @@ class Topogen(object): "Errors found post shutdown - details follow: {}".format(errors) ) - self.net.stop() + try: + self.net.stop() + + except OSError as error: + # OSError exception is raised when mininet tries to stop switch + # though switch is stopped once but mininet tries to stop same + # switch again, where it ended up with exception + + logger.info(error) + logger.info("Exception ignored: switch is already stopped") def get_exabgp_cmd(self): if not self.exabgp_cmd: diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 9dae348b8e..08a1f1e07e 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -1140,14 +1140,14 @@ def pim_delete_move_lines(lines_to_add, lines_to_del): # they are implicitly deleted by 'no ip pim'. # Remove all such depdendent options from delete # pending list. - pim_disable = False + pim_disable = [] lines_to_del_to_del = [] index = -1 for ctx_keys, line in lines_to_del: index = index + 1 if ctx_keys[0].startswith("interface") and line and line == "ip pim": - pim_disable = True + pim_disable.append(ctx_keys[0]) # no ip msdp peer <> does not accept source so strip it off. if line and line.startswith("ip msdp peer "): @@ -1158,14 +1158,19 @@ def pim_delete_move_lines(lines_to_add, lines_to_del): lines_to_del.remove((ctx_keys, line)) lines_to_del.insert(index, (ctx_keys, new_line)) - if pim_disable: - for ctx_keys, line in lines_to_del: - if ( - ctx_keys[0].startswith("interface") - and line - and (line.startswith("ip pim ") or line.startswith("ip multicast ")) - ): - lines_to_del_to_del.append((ctx_keys, line)) + for ctx_keys, line in lines_to_del: + if ( + ctx_keys[0] in pim_disable + and ctx_keys[0].startswith("interface") + and line + and ( + line.startswith("ip pim ") + or line.startswith("no ip pim ") + or line.startswith("ip multicast ") + or line.startswith("no ip multicast ") + ) + ): + lines_to_del_to_del.append((ctx_keys, line)) for ctx_keys, line in lines_to_del_to_del: lines_to_del.remove((ctx_keys, line)) diff --git a/tools/gen_northbound_callbacks.c b/tools/gen_northbound_callbacks.c index a879811363..046dc9e99e 100644 --- a/tools/gen_northbound_callbacks.c +++ b/tools/gen_northbound_callbacks.c @@ -448,7 +448,7 @@ int main(int argc, char *argv[]) if (argc != 1) usage(EXIT_FAILURE); - yang_init(false, true); + yang_init(false, true, false); if (search_path) ly_ctx_set_searchdir(ly_native_ctx, search_path); diff --git a/tools/gen_yang_deviations.c b/tools/gen_yang_deviations.c index 251643c69e..c2e7fd91c6 100644 --- a/tools/gen_yang_deviations.c +++ b/tools/gen_yang_deviations.c @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) if (argc != 1) usage(EXIT_FAILURE); - yang_init(false, false); + yang_init(false, false, false); /* Load YANG module. */ module = yang_module_load(argv[0], NULL); diff --git a/vrrpd/vrrp_packet.c b/vrrpd/vrrp_packet.c index 36494c7df8..a2fb2bc321 100644 --- a/vrrpd/vrrp_packet.c +++ b/vrrpd/vrrp_packet.c @@ -234,7 +234,7 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, bool ipv4_ph, } else if (family == AF_INET6) { struct cmsghdr *c; - for (c = CMSG_FIRSTHDR(m); c != NULL; CMSG_NXTHDR(m, c)) { + for (c = CMSG_FIRSTHDR(m); c != NULL; c = CMSG_NXTHDR(m, c)) { if (c->cmsg_level == IPPROTO_IPV6 && c->cmsg_type == IPV6_HOPLIMIT) break; diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c index 1d2f9e695f..d594fc2c86 100644 --- a/zebra/dplane_fpm_nl.c +++ b/zebra/dplane_fpm_nl.c @@ -1336,7 +1336,7 @@ static void fpm_enqueue_l3vni_table(struct hash_bucket *bucket, void *arg) struct zebra_l3vni *zl3vni = bucket->data; fra->zl3vni = zl3vni; - hash_iterate(zl3vni->rmac_table, fpm_enqueue_rmac_table, zl3vni); + hash_iterate(zl3vni->rmac_table, fpm_enqueue_rmac_table, fra); } static void fpm_rmac_send(struct event *t) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 5fb908eb0d..8beae125d2 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1032,212 +1032,6 @@ netlink_put_intf_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx) return netlink_batch_add_msg(bth, ctx, netlink_intf_msg_encoder, false); } -int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) -{ - int len; - struct ifaddrmsg *ifa; - struct rtattr *tb[IFA_MAX + 1]; - struct interface *ifp; - void *addr; - void *broad; - uint8_t flags = 0; - char *label = NULL; - struct zebra_ns *zns; - uint32_t metric = METRIC_MAX; - uint32_t kernel_flags = 0; - - frrtrace(3, frr_zebra, netlink_interface_addr, h, ns_id, startup); - - zns = zebra_ns_lookup(ns_id); - ifa = NLMSG_DATA(h); - - if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) { - flog_warn( - EC_ZEBRA_UNKNOWN_FAMILY, - "Invalid address family: %u received from kernel interface addr change: %s", - ifa->ifa_family, nl_msg_type_to_str(h->nlmsg_type)); - return 0; - } - - if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) - return 0; - - len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg)); - if (len < 0) { - zlog_err( - "%s: Message received from netlink is of a broken size: %d %zu", - __func__, h->nlmsg_len, - (size_t)NLMSG_LENGTH(sizeof(struct ifaddrmsg))); - return -1; - } - - netlink_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len); - - ifp = if_lookup_by_index_per_ns(zns, ifa->ifa_index); - if (ifp == NULL) { - if (startup) { - /* During startup, failure to lookup the referenced - * interface should not be an error, so we have - * downgraded this condition to warning, and we permit - * the startup interface state retrieval to continue. - */ - flog_warn(EC_LIB_INTERFACE, - "%s: can't find interface by index %d", - __func__, ifa->ifa_index); - return 0; - } else { - flog_err(EC_LIB_INTERFACE, - "%s: can't find interface by index %d", - __func__, ifa->ifa_index); - return -1; - } - } - - /* Flags passed through */ - if (tb[IFA_FLAGS]) - kernel_flags = *(int *)RTA_DATA(tb[IFA_FLAGS]); - else - kernel_flags = ifa->ifa_flags; - - if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ - { - char buf[BUFSIZ]; - zlog_debug("%s %s %s flags 0x%x:", __func__, - nl_msg_type_to_str(h->nlmsg_type), ifp->name, - kernel_flags); - if (tb[IFA_LOCAL]) - zlog_debug(" IFA_LOCAL %s/%d", - inet_ntop(ifa->ifa_family, - RTA_DATA(tb[IFA_LOCAL]), buf, - BUFSIZ), - ifa->ifa_prefixlen); - if (tb[IFA_ADDRESS]) - zlog_debug(" IFA_ADDRESS %s/%d", - inet_ntop(ifa->ifa_family, - RTA_DATA(tb[IFA_ADDRESS]), buf, - BUFSIZ), - ifa->ifa_prefixlen); - if (tb[IFA_BROADCAST]) - zlog_debug(" IFA_BROADCAST %s/%d", - inet_ntop(ifa->ifa_family, - RTA_DATA(tb[IFA_BROADCAST]), buf, - BUFSIZ), - ifa->ifa_prefixlen); - if (tb[IFA_LABEL] && strcmp(ifp->name, RTA_DATA(tb[IFA_LABEL]))) - zlog_debug(" IFA_LABEL %s", - (char *)RTA_DATA(tb[IFA_LABEL])); - - if (tb[IFA_CACHEINFO]) { - struct ifa_cacheinfo *ci = RTA_DATA(tb[IFA_CACHEINFO]); - zlog_debug(" IFA_CACHEINFO pref %d, valid %d", - ci->ifa_prefered, ci->ifa_valid); - } - } - - /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */ - if (tb[IFA_LOCAL] == NULL) - tb[IFA_LOCAL] = tb[IFA_ADDRESS]; - if (tb[IFA_ADDRESS] == NULL) - tb[IFA_ADDRESS] = tb[IFA_LOCAL]; - - /* local interface address */ - addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL); - - /* is there a peer address? */ - if (tb[IFA_ADDRESS] - && memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), - RTA_PAYLOAD(tb[IFA_ADDRESS]))) { - broad = RTA_DATA(tb[IFA_ADDRESS]); - SET_FLAG(flags, ZEBRA_IFA_PEER); - } else - /* seeking a broadcast address */ - broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) - : NULL); - - /* addr is primary key, SOL if we don't have one */ - if (addr == NULL) { - zlog_debug("%s: Local Interface Address is NULL for %s", - __func__, ifp->name); - return -1; - } - - /* Flags. */ - if (kernel_flags & IFA_F_SECONDARY) - SET_FLAG(flags, ZEBRA_IFA_SECONDARY); - - /* Label */ - if (tb[IFA_LABEL]) - label = (char *)RTA_DATA(tb[IFA_LABEL]); - - if (label && strcmp(ifp->name, label) == 0) - label = NULL; - - if (tb[IFA_RT_PRIORITY]) - metric = *(uint32_t *)RTA_DATA(tb[IFA_RT_PRIORITY]); - - /* Register interface address to the interface. */ - if (ifa->ifa_family == AF_INET) { - if (ifa->ifa_prefixlen > IPV4_MAX_BITLEN) { - zlog_err( - "Invalid prefix length: %u received from kernel interface addr change: %s", - ifa->ifa_prefixlen, - nl_msg_type_to_str(h->nlmsg_type)); - return -1; - } - - if (h->nlmsg_type == RTM_NEWADDR) - connected_add_ipv4(ifp, flags, (struct in_addr *)addr, - ifa->ifa_prefixlen, - (struct in_addr *)broad, label, - metric); - else if (CHECK_FLAG(flags, ZEBRA_IFA_PEER)) { - /* Delete with a peer address */ - connected_delete_ipv4( - ifp, flags, (struct in_addr *)addr, - ifa->ifa_prefixlen, broad); - } else - connected_delete_ipv4( - ifp, flags, (struct in_addr *)addr, - ifa->ifa_prefixlen, NULL); - } - - if (ifa->ifa_family == AF_INET6) { - if (ifa->ifa_prefixlen > IPV6_MAX_BITLEN) { - zlog_err( - "Invalid prefix length: %u received from kernel interface addr change: %s", - ifa->ifa_prefixlen, - nl_msg_type_to_str(h->nlmsg_type)); - return -1; - } - if (h->nlmsg_type == RTM_NEWADDR) { - /* Only consider valid addresses; we'll not get a - * notification from - * the kernel till IPv6 DAD has completed, but at init - * time, Quagga - * does query for and will receive all addresses. - */ - if (!(kernel_flags - & (IFA_F_DADFAILED | IFA_F_TENTATIVE))) - connected_add_ipv6(ifp, flags, - (struct in6_addr *)addr, - (struct in6_addr *)broad, - ifa->ifa_prefixlen, label, - metric); - } else - connected_delete_ipv6(ifp, (struct in6_addr *)addr, - NULL, ifa->ifa_prefixlen); - } - - /* - * Linux kernel does not send route delete on interface down/addr del - * so we have to re-process routes it owns (i.e. kernel routes) - */ - if (h->nlmsg_type != RTM_NEWADDR) - rib_update(RIB_UPDATE_KERNEL); - - return 0; -} - /* * Parse and validate an incoming interface address change message, * generating a dplane context object. diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h index 9b31906a17..dc1f71cb77 100644 --- a/zebra/if_netlink.h +++ b/zebra/if_netlink.h @@ -12,9 +12,6 @@ extern "C" { #endif -extern int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, - int startup); - /* * Parse an incoming interface address change message, generate a dplane * context object for processing. diff --git a/zebra/rib.h b/zebra/rib.h index 4293b5f240..5fedb07335 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -408,9 +408,6 @@ extern struct route_entry *rib_match_multicast(afi_t afi, vrf_id_t vrf_id, union g_addr *gaddr, struct route_node **rn_out); -extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, - vrf_id_t vrf_id); - extern void rib_update(enum rib_update_event event); extern void rib_update_table(struct route_table *table, enum rib_update_event event, int rtype); @@ -637,6 +634,10 @@ extern pid_t pid; extern uint32_t rt_table_main_id; +void route_entry_dump_nh(const struct route_entry *re, const char *straddr, + const struct vrf *re_vrf, + const struct nexthop *nexthop); + /* Name of hook calls */ #define ZEBRA_ON_RIB_PROCESS_HOOK_CALL "on_rib_process_dplane_results" diff --git a/zebra/tc_netlink.c b/zebra/tc_netlink.c index 19667e66ac..3c4db0090c 100644 --- a/zebra/tc_netlink.c +++ b/zebra/tc_netlink.c @@ -661,27 +661,6 @@ netlink_put_tc_filter_update_msg(struct nl_batch *bth, } /* - * Request filters from the kernel - */ -static int netlink_request_filters(struct zebra_ns *zns, int family, int type, - ifindex_t ifindex) -{ - struct { - struct nlmsghdr n; - struct tcmsg tc; - } req; - - memset(&req, 0, sizeof(req)); - req.n.nlmsg_type = type; - req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)); - req.tc.tcm_family = family; - req.tc.tcm_ifindex = ifindex; - - return netlink_request(&zns->netlink_cmd, &req); -} - -/* * Request queue discipline from the kernel */ static int netlink_request_qdiscs(struct zebra_ns *zns, int family, int type) @@ -852,23 +831,4 @@ int netlink_qdisc_read(struct zebra_ns *zns) return 0; } -int netlink_tfilter_read_for_interface(struct zebra_ns *zns, ifindex_t ifindex) -{ - int ret; - struct zebra_dplane_info dp_info; - - zebra_dplane_info_from_zns(&dp_info, zns, true); - - ret = netlink_request_filters(zns, AF_UNSPEC, RTM_GETTFILTER, ifindex); - if (ret < 0) - return ret; - - ret = netlink_parse_info(netlink_tfilter_change, &zns->netlink_cmd, - &dp_info, 0, true); - if (ret < 0) - return ret; - - return 0; -} - #endif /* HAVE_NETLINK */ diff --git a/zebra/tc_netlink.h b/zebra/tc_netlink.h index 5e95e6c1d8..300c53b6f5 100644 --- a/zebra/tc_netlink.h +++ b/zebra/tc_netlink.h @@ -50,8 +50,6 @@ netlink_put_tc_filter_update_msg(struct nl_batch *bth, */ extern int netlink_qdisc_read(struct zebra_ns *zns); -extern int netlink_tfilter_read_for_interface(struct zebra_ns *zns, - ifindex_t ifindex); extern int netlink_tfilter_change(struct nlmsghdr *h, ns_id_t ns_id, int startup); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index c45c61a208..b13d58f99d 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -2477,22 +2477,6 @@ stream_failure: return; } -/* Unregister all information in a VRF. */ -static void zread_vrf_unregister(ZAPI_HANDLER_ARGS) -{ - int i; - afi_t afi; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - vrf_bitmap_unset(&client->redist[afi][i], - zvrf_id(zvrf)); - vrf_bitmap_unset(&client->redist_default[afi], zvrf_id(zvrf)); - vrf_bitmap_unset(&client->ridinfo[afi], zvrf_id(zvrf)); - vrf_bitmap_unset(&client->neighinfo[afi], zvrf_id(zvrf)); - } -} - /* * Validate incoming zapi mpls lsp / labels message */ @@ -4055,7 +4039,6 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { #if HAVE_BFDD > 0 [ZEBRA_BFD_DEST_REPLAY] = zebra_ptm_bfd_dst_replay, #endif /* HAVE_BFDD */ - [ZEBRA_VRF_UNREGISTER] = zread_vrf_unregister, [ZEBRA_VRF_LABEL] = zread_vrf_label, [ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register, [ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable, diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 4ee9dc5fcf..81f1411ee5 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -1101,11 +1101,15 @@ void zebra_nhg_check_valid(struct nhg_hash_entry *nhe) bool valid = false; /* - * If I have other nhe's depending on me, then this is a + * If I have other nhe's depending on me, or I have nothing + * I am depending on then this is a * singleton nhe so set this nexthops flag as appropriate. */ - if (nhg_connected_tree_count(&nhe->nhg_depends)) + if (nhg_connected_tree_count(&nhe->nhg_depends) || + nhg_connected_tree_count(&nhe->nhg_dependents) == 0) { + UNSET_FLAG(nhe->nhg.nexthop->flags, NEXTHOP_FLAG_FIB); UNSET_FLAG(nhe->nhg.nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } /* If anthing else in the group is valid, the group is valid */ frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) { @@ -2922,13 +2926,162 @@ static uint32_t proto_nhg_nexthop_active_update(struct nexthop_group *nhg) } /* + * This function takes the start of two comparable nexthops from two different + * nexthop groups and walks them to see if they can be considered the same + * or not. This is being used to determine if zebra should reuse a nhg + * from the old_re to the new_re, when an interface goes down and the + * new nhg sent down from the upper level protocol would resolve to it + */ +static bool zebra_nhg_nexthop_compare(const struct nexthop *nhop, + const struct nexthop *old_nhop, + const struct route_node *rn) +{ + bool same = true; + + while (nhop && old_nhop) { + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: %pRN Comparing %pNHvv(%u) to old: %pNHvv(%u)", + __func__, rn, nhop, nhop->flags, old_nhop, + old_nhop->flags); + if (!CHECK_FLAG(old_nhop->flags, NEXTHOP_FLAG_ACTIVE)) { + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: %pRN Old is not active going to the next one", + __func__, rn); + old_nhop = old_nhop->next; + continue; + } + + if (nexthop_same(nhop, old_nhop)) { + struct nexthop *new_recursive, *old_recursive; + + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s: %pRN New and old are same, continuing search", + __func__, rn); + + new_recursive = nhop->resolved; + old_recursive = old_nhop->resolved; + + while (new_recursive && old_recursive) { + if (!nexthop_same(new_recursive, old_recursive)) { + same = false; + break; + } + + new_recursive = new_recursive->next; + old_recursive = old_recursive->next; + } + + if (new_recursive) + same = false; + else if (old_recursive) { + while (old_recursive) { + if (CHECK_FLAG(old_recursive->flags, + NEXTHOP_FLAG_ACTIVE)) + break; + old_recursive = old_recursive->next; + } + + if (old_recursive) + same = false; + } + + if (!same) + break; + + nhop = nhop->next; + old_nhop = old_nhop->next; + continue; + } else { + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s:%pRN They are not the same, stopping using new nexthop entry", + __func__, rn); + same = false; + break; + } + } + + if (nhop) + same = false; + else if (old_nhop) { + while (old_nhop) { + if (CHECK_FLAG(old_nhop->flags, NEXTHOP_FLAG_ACTIVE)) + break; + old_nhop = old_nhop->next; + } + + if (old_nhop) + same = false; + } + + return same; +} + +static struct nhg_hash_entry *zebra_nhg_rib_compare_old_nhe( + const struct route_node *rn, const struct route_entry *re, + struct nhg_hash_entry *new_nhe, struct nhg_hash_entry *old_nhe) +{ + struct nexthop *nhop, *old_nhop; + bool same = true; + struct vrf *vrf = vrf_lookup_by_id(re->vrf_id); + + if (IS_ZEBRA_DEBUG_NHG_DETAIL) { + char straddr[PREFIX_STRLEN]; + + prefix2str(&rn->p, straddr, sizeof(straddr)); + zlog_debug("%s: %pRN new id: %u old id: %u", __func__, rn, + new_nhe->id, old_nhe->id); + zlog_debug("%s: %pRN NEW", __func__, rn); + for (ALL_NEXTHOPS(new_nhe->nhg, nhop)) + route_entry_dump_nh(re, straddr, vrf, nhop); + + zlog_debug("%s: %pRN OLD", __func__, rn); + for (ALL_NEXTHOPS(old_nhe->nhg, nhop)) + route_entry_dump_nh(re, straddr, vrf, nhop); + } + + nhop = new_nhe->nhg.nexthop; + old_nhop = old_nhe->nhg.nexthop; + + same = zebra_nhg_nexthop_compare(nhop, old_nhop, rn); + + if (same) { + struct nexthop_group *bnhg, *old_bnhg; + + bnhg = zebra_nhg_get_backup_nhg(new_nhe); + old_bnhg = zebra_nhg_get_backup_nhg(old_nhe); + + if (bnhg || old_bnhg) { + if (bnhg && !old_bnhg) + same = false; + else if (!bnhg && old_bnhg) + same = false; + else + same = zebra_nhg_nexthop_compare(bnhg->nexthop, + old_bnhg->nexthop, + rn); + } + } + + if (IS_ZEBRA_DEBUG_NHG_DETAIL) + zlog_debug("%s:%pRN They are %sthe same, using the %s nhg entry", + __func__, rn, same ? "" : "not ", + same ? "old" : "new"); + + if (same) + return old_nhe; + else + return new_nhe; +} + +/* * Iterate over all nexthops of the given RIB entry and refresh their * ACTIVE flag. If any nexthop is found to toggle the ACTIVE flag, * the whole re structure is flagged with ROUTE_ENTRY_CHANGED. * * Return value is the new number of active nexthops. */ -int nexthop_active_update(struct route_node *rn, struct route_entry *re) +int nexthop_active_update(struct route_node *rn, struct route_entry *re, + struct route_entry *old_re) { struct nhg_hash_entry *curr_nhe; uint32_t curr_active = 0, backup_active = 0; @@ -2984,6 +3137,11 @@ backups_done: new_nhe = zebra_nhg_rib_find_nhe(curr_nhe, rt_afi); + if (old_re && old_re->type == re->type && + old_re->instance == re->instance) + new_nhe = zebra_nhg_rib_compare_old_nhe(rn, re, new_nhe, + old_re->nhe); + if (IS_ZEBRA_DEBUG_NHG_DETAIL) zlog_debug( "%s: re %p CHANGED: nhe %p (%pNG) => new_nhe %p (%pNG)", @@ -3779,6 +3937,17 @@ void zebra_interface_nhg_reinstall(struct interface *ifp) frr_each_safe (nhg_connected_tree, &rb_node_dep->nhe->nhg_dependents, rb_node_dependent) { + struct nexthop *nhop_dependent = + rb_node_dependent->nhe->nhg.nexthop; + + while (nhop_dependent && + !nexthop_same(nhop_dependent, nh)) + nhop_dependent = nhop_dependent->next; + + if (nhop_dependent) + SET_FLAG(nhop_dependent->flags, + NEXTHOP_FLAG_ACTIVE); + if (IS_ZEBRA_DEBUG_NHG) zlog_debug("%s dependent nhe %pNG Setting Reinstall flag", __func__, diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h index 712c1057a1..435ccb0d01 100644 --- a/zebra/zebra_nhg.h +++ b/zebra/zebra_nhg.h @@ -404,7 +404,8 @@ extern void zebra_nhg_mark_keep(void); /* Nexthop resolution processing */ struct route_entry; /* Forward ref to avoid circular includes */ -extern int nexthop_active_update(struct route_node *rn, struct route_entry *re); +extern int nexthop_active_update(struct route_node *rn, struct route_entry *re, + struct route_entry *old_re); #ifdef _FRR_ATTRIBUTE_PRINTFRR #pragma FRR printfrr_ext "%pNG" (const struct nhg_hash_entry *) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 402a3104b9..2d2be4fc78 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -611,45 +611,6 @@ struct route_entry *rib_match_multicast(afi_t afi, vrf_id_t vrf_id, return re; } -struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *match = NULL; - rib_dest_t *dest; - - /* Lookup table. */ - table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); - if (!table) - return 0; - - rn = route_node_lookup(table, (struct prefix *)p); - - /* No route for this prefix. */ - if (!rn) - return NULL; - - /* Unlock node. */ - route_unlock_node(rn); - dest = rib_dest_from_rnode(rn); - - if (dest && dest->selected_fib - && !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED)) - match = dest->selected_fib; - - if (!match) - return NULL; - - if (match->type == ZEBRA_ROUTE_CONNECT || - match->type == ZEBRA_ROUTE_LOCAL) - return match; - - if (CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED)) - return match; - - return NULL; -} - /* * Is this RIB labeled-unicast? It must be of type BGP and all paths * (nexthops) must have a label. @@ -1313,7 +1274,7 @@ static void rib_process(struct route_node *rn) */ if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) { proto_re_changed = re; - if (!nexthop_active_update(rn, re)) { + if (!nexthop_active_update(rn, re, old_fib)) { const struct prefix *p; struct rib_table_info *info; @@ -4118,9 +4079,8 @@ void rib_delnode(struct route_node *rn, struct route_entry *re) /* * Helper that debugs a single nexthop within a route-entry */ -static void _route_entry_dump_nh(const struct route_entry *re, - const char *straddr, const struct vrf *re_vrf, - const struct nexthop *nexthop) +void route_entry_dump_nh(const struct route_entry *re, const char *straddr, + const struct vrf *re_vrf, const struct nexthop *nexthop) { char nhname[PREFIX_STRLEN]; char backup_str[50]; @@ -4243,7 +4203,7 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, /* Dump nexthops */ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) - _route_entry_dump_nh(re, straddr, vrf, nexthop); + route_entry_dump_nh(re, straddr, vrf, nexthop); if (zebra_nhg_get_backup_nhg(re->nhe)) { zlog_debug("%s(%s): backup nexthops:", straddr, @@ -4251,7 +4211,7 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, nhg = zebra_nhg_get_backup_nhg(re->nhe); for (ALL_NEXTHOPS_PTR(nhg, nexthop)) - _route_entry_dump_nh(re, straddr, vrf, nexthop); + route_entry_dump_nh(re, straddr, vrf, nexthop); } zlog_debug("%s(%s): dump complete", straddr, VRF_LOGNAME(vrf)); diff --git a/zebra/zebra_trace.h b/zebra/zebra_trace.h index 17528c4bf1..6451562466 100644 --- a/zebra/zebra_trace.h +++ b/zebra/zebra_trace.h @@ -70,20 +70,6 @@ TRACEPOINT_EVENT( TRACEPOINT_EVENT( frr_zebra, - netlink_interface_addr, - TP_ARGS( - struct nlmsghdr *, header, - ns_id_t, ns_id, - int, startup), - TP_FIELDS( - ctf_integer_hex(intptr_t, header, header) - ctf_integer(uint32_t, ns_id, ns_id) - ctf_integer(uint32_t, startup, startup) - ) - ) - -TRACEPOINT_EVENT( - frr_zebra, netlink_route_change_read_unicast, TP_ARGS( struct nlmsghdr *, header, |
