summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/bfdd_cli.c52
-rw-r--r--bgpd/bgp_bmp.c24
-rw-r--r--bgpd/bgp_main.c32
-rw-r--r--bgpd/bgp_mpath.c465
-rw-r--r--bgpd/bgp_mpath.h29
-rw-r--r--bgpd/bgp_pbr.c175
-rw-r--r--bgpd/bgp_route.c25
-rw-r--r--bgpd/bgp_route.h14
-rw-r--r--bgpd/bgp_routemap.c2
-rw-r--r--bgpd/bgpd.c6
-rw-r--r--doc/user/bgp.rst2
-rw-r--r--isisd/isis_nb_config.c8
-rw-r--r--lib/bfd.h6
-rw-r--r--lib/grammar_sandbox_main.c2
-rw-r--r--lib/libfrr.c3
-rw-r--r--lib/libfrr.h5
-rw-r--r--lib/log.c1
-rw-r--r--lib/nexthop_group.c21
-rw-r--r--lib/nexthop_group.h5
-rw-r--r--lib/northbound.c4
-rw-r--r--lib/northbound.h8
-rw-r--r--lib/yang.c10
-rw-r--r--lib/yang.h10
-rw-r--r--lib/yang_translator.c4
-rw-r--r--lib/zclient.h1
-rw-r--r--mgmtd/mgmt.c3
-rw-r--r--mgmtd/mgmt_main.c2
-rw-r--r--pimd/pim_autorp.c4
-rw-r--r--pimd/pim_iface.c107
-rw-r--r--tests/bgpd/subdir.am11
-rw-r--r--tests/bgpd/test_mpath.c482
-rw-r--r--tests/bgpd/test_mpath.py10
-rw-r--r--tests/bgpd/test_peer_attr.c2
-rw-r--r--tests/helpers/c/main.c2
-rw-r--r--tests/isisd/test_isis_spf.c2
-rw-r--r--tests/lib/cli/common_cli.c2
-rw-r--r--tests/lib/cli/test_commands.c2
-rw-r--r--tests/lib/northbound/test_oper_data.c2
-rw-r--r--tests/lib/test_grpc.cpp3
-rw-r--r--tests/topotests/bgp_default_originate/test_bgp_default_originate_2links.py11
-rw-r--r--tests/topotests/bgp_default_originate/test_default_orginate_vrf.py8
-rw-r--r--tests/topotests/lib/common_config.py2
-rw-r--r--tests/topotests/lib/topogen.py11
-rwxr-xr-xtools/frr-reload.py25
-rw-r--r--tools/gen_northbound_callbacks.c2
-rw-r--r--tools/gen_yang_deviations.c2
-rw-r--r--vrrpd/vrrp_packet.c2
-rw-r--r--zebra/dplane_fpm_nl.c2
-rw-r--r--zebra/if_netlink.c206
-rw-r--r--zebra/if_netlink.h3
-rw-r--r--zebra/rib.h7
-rw-r--r--zebra/tc_netlink.c40
-rw-r--r--zebra/tc_netlink.h2
-rw-r--r--zebra/zapi_msg.c17
-rw-r--r--zebra/zebra_nhg.c175
-rw-r--r--zebra/zebra_nhg.h3
-rw-r--r--zebra/zebra_rib.c50
-rw-r--r--zebra/zebra_trace.h14
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;
diff --git a/lib/bfd.h b/lib/bfd.h
index 48929a9564..99790f96a5 100644
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -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 {
diff --git a/lib/log.c b/lib/log.c
index 880180ae5a..04b789b5da 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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,