summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.h6
-rw-r--r--bgpd/bgp_damp.c6
-rw-r--r--bgpd/bgp_ecommunity.h6
-rw-r--r--bgpd/bgp_evpn.c144
-rw-r--r--bgpd/bgp_evpn_mh.c21
-rw-r--r--bgpd/bgp_evpn_private.h3
-rw-r--r--bgpd/bgp_fsm.c18
-rw-r--r--bgpd/bgp_label.c2
-rw-r--r--bgpd/bgp_mplsvpn.c33
-rw-r--r--bgpd/bgp_network.c4
-rw-r--r--bgpd/bgp_nht.c2
-rw-r--r--bgpd/bgp_route.c596
-rw-r--r--bgpd/bgp_route.h16
-rw-r--r--bgpd/bgp_updgrp_adv.c13
-rw-r--r--bgpd/bgp_vpn.c2
-rw-r--r--bgpd/bgp_vty.c159
-rw-r--r--bgpd/bgp_zebra.c4
-rw-r--r--bgpd/bgpd.c38
-rw-r--r--bgpd/rfapi/rfapi.c6
-rw-r--r--doc/user/bgp.rst5
-rw-r--r--isisd/isis_spf.c2
-rw-r--r--ospf6d/ospf6_gr_helper.c9
-rw-r--r--ospfd/ospf_sr.c4
-rw-r--r--ospfd/ospf_vty.c9
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref2
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref2
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref2
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref2
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref2
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref2
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref2
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/__init__.py0
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf4
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf4
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf30
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf25
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py92
-rw-r--r--tests/topotests/bgp_evpn_mh/leaf1/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/leaf2/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/spine1/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/spine2/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/torm11/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/torm12/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/torm21/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/torm22/evpn.conf1
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py2
-rw-r--r--zebra/rt_netlink.c2
-rw-r--r--zebra/zebra_nb_config.c1
-rw-r--r--zebra/zebra_neigh.c12
-rw-r--r--zebra/zebra_netns_id.c4
-rw-r--r--zebra/zebra_netns_notify.c4
-rw-r--r--zebra/zebra_nhg.c4
52 files changed, 919 insertions, 395 deletions
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 5386f24a0b..164aa5ae79 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -517,9 +517,11 @@ static inline void bgp_attr_set_ecommunity(struct attr *attr,
{
attr->ecommunity = ecomm;
- if (ecomm)
+ if (ecomm) {
SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
- else
+ if (ecommunity_select_color(ecomm))
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR));
+ } else
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
}
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index 80425ebe7a..6b6387b1b5 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -150,7 +150,7 @@ static void bgp_reuse_timer(struct event *t)
bgp_aggregate_increment(
bgp, bgp_dest_get_prefix(bdi->dest),
bdi->path, bdi->afi, bdi->safi);
- bgp_process(bgp, bdi->dest, bdi->afi,
+ bgp_process(bgp, bdi->dest, bdi->path, bdi->afi,
bdi->safi);
}
@@ -306,8 +306,10 @@ void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi,
bgp_path_info_unset_flag(bdi->dest, path,
BGP_PATH_HISTORY | BGP_PATH_DAMPED);
- if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
+ if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) {
bgp_path_info_delete(bdi->dest, path);
+ bgp_process(path->peer->bgp, bdi->dest, path, afi, safi);
+ }
XFREE(MTYPE_BGP_DAMP_INFO, bdi);
}
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index d20ad01c35..794c5a3975 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -52,10 +52,8 @@
* 0x0c Flow-spec Redirect to IPv4 - draft-ietf-idr-flowspec-redirect
*/
#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4 0x0c
-/* from draft-ietf-idr-flow-spec-v6-09
- * 0x0b Flow-spec Redirect to IPv6
- */
-#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0b
+/* RFC 8956 */
+#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0d
/* Low-order octet of the Extended Communities type field for EVPN types */
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index e142ff6a34..1c3b4e05c6 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -1429,7 +1429,7 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -1443,14 +1443,29 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
* Note: vpn is NULL for local EAD-ES routes.
*/
int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
- struct bgp_dest *dest)
+ struct bgp_dest *dest, struct bgp_path_info *pi)
{
- struct bgp_path_info *old_select, *new_select;
+ struct bgp_path_info *old_select, *new_select, *first;
struct bgp_path_info_pair old_and_new;
afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN;
int ret = 0;
+ first = bgp_dest_get_bgp_path_info(dest);
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
+ if (pi != first) {
+ if (pi->next)
+ pi->next->prev = pi->prev;
+ if (pi->prev)
+ pi->prev->next = pi->next;
+
+ if (first)
+ first->prev = pi;
+ pi->next = first;
+ pi->prev = NULL;
+ bgp_dest_set_bgp_path_info(dest, pi);
+ }
+
/* Compute the best path. */
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
afi, safi);
@@ -1582,7 +1597,8 @@ static struct bgp_path_info *bgp_evpn_route_get_local_path(
static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
struct bgp *bgp_vrf, afi_t afi,
safi_t safi, struct bgp_dest *dest,
- struct attr *attr, int *route_changed)
+ struct attr *attr, int *route_changed,
+ struct bgp_path_info **entry)
{
struct attr *attr_new = NULL;
struct bgp_path_info *pi = NULL;
@@ -1620,8 +1636,8 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
/* add the route entry to route node*/
bgp_path_info_add(dest, pi);
+ *entry = pi;
} else {
-
tmp_pi = local_pi;
if (!attrhash_cmp(tmp_pi->attr, attr)) {
@@ -1643,6 +1659,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
tmp_pi->attr = attr_new;
tmp_pi->uptime = monotime(NULL);
}
+ *entry = local_pi;
}
return 0;
}
@@ -1658,6 +1675,7 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
struct bgp_dest *dest = NULL;
struct bgp *bgp_evpn = NULL;
int route_changed = 0;
+ struct bgp_path_info *pi = NULL;
bgp_evpn = bgp_get_evpn();
if (!bgp_evpn)
@@ -1739,11 +1757,11 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
/* create or update the route entry within the route node */
update_evpn_type5_route_entry(bgp_evpn, bgp_vrf, afi, safi, dest, &attr,
- &route_changed);
+ &route_changed, &pi);
/* schedule for processing and unlock node */
if (route_changed) {
- bgp_process(bgp_evpn, dest, afi, safi);
+ bgp_process(bgp_evpn, dest, pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -2253,7 +2271,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* route would win, and we should evict the defunct local route
* and (re)install the remote route into zebra.
*/
- evpn_route_select_install(bgp, vpn, dest);
+ evpn_route_select_install(bgp, vpn, dest, pi);
/*
* If the new local route was not selected evict it and tell zebra
* to re-add the best remote dest. BGP doesn't retain non-best local
@@ -2309,7 +2327,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
false /* setup_sync */, NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, global_pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -2369,7 +2387,7 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp)
delete_evpn_route_entry(bgp_evpn, afi, safi, dest, &pi);
if (pi)
- bgp_process(bgp_evpn, dest, afi, safi);
+ bgp_process(bgp_evpn, dest, pi, afi, safi);
bgp_dest_unlock_node(dest);
return 0;
}
@@ -2409,7 +2427,7 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -2417,9 +2435,8 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
*/
delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
if (pi) {
- dest = bgp_path_info_reap(dest, pi);
- assert(dest);
- evpn_route_select_install(bgp, vpn, dest);
+ bgp_path_info_delete(dest, pi);
+ evpn_route_select_install(bgp, vpn, dest, pi);
}
/* dest should still exist due to locking make coverity happy */
@@ -2533,7 +2550,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* advertised to peers; otherwise, ensure it is evicted and
* (re)install the remote route into zebra.
*/
- evpn_route_select_install(bgp, vpn, dest);
+ evpn_route_select_install(bgp, vpn, dest, pi);
if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
route_change = 0;
@@ -2581,7 +2598,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, global_pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -2666,7 +2683,7 @@ static void delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
if (pi)
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
/* Unlock RD node. */
@@ -3135,7 +3152,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
safi);
/* Perform route selection and update zebra, if required. */
- bgp_process(bgp_vrf, dest, afi, safi);
+ bgp_process(bgp_vrf, dest, pi, afi, safi);
/* Process for route leaking. */
vpn_leak_from_vrf_update(bgp_get_default(), bgp_vrf, pi);
@@ -3247,7 +3264,7 @@ static int install_evpn_route_entry_in_vni_common(
bgp_evpn_remote_ip_hash_add(vpn, pi);
/* Perform route selection and update zebra, if required. */
- ret = evpn_route_select_install(bgp, vpn, dest);
+ ret = evpn_route_select_install(bgp, vpn, dest, pi);
/* if the best path is a local path with a non-zero ES
* sync info against the local path may need to be updated
@@ -3289,7 +3306,7 @@ static int uninstall_evpn_route_entry_in_vni_common(
bgp_path_info_delete(dest, pi);
/* Perform route selection and update zebra, if required. */
- ret = evpn_route_select_install(bgp, vpn, dest);
+ ret = evpn_route_select_install(bgp, vpn, dest, pi);
/* if the best path is a local path with a non-zero ES
* sync info against the local path may need to be updated
@@ -3497,7 +3514,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
bgp_evpn_path_nh_del(bgp_vrf, pi);
/* Perform route selection and update zebra, if required. */
- bgp_process(bgp_vrf, dest, afi, safi);
+ bgp_process(bgp_vrf, dest, pi, afi, safi);
/* Unlock route node. */
bgp_dest_unlock_node(dest);
@@ -3862,7 +3879,7 @@ int bgp_evpn_route_entry_install_if_vrf_match(struct bgp *bgp_vrf,
* Install or uninstall mac-ip routes are appropriate for this
* particular VRF.
*/
-static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
+static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, bool install)
{
afi_t afi;
safi_t safi;
@@ -3926,9 +3943,7 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
* particular VNI.
*/
static int install_uninstall_routes_for_vni(struct bgp *bgp,
- struct bgpevpn *vpn,
- bgp_evpn_route_type rtype,
- int install)
+ struct bgpevpn *vpn, bool install)
{
afi_t afi;
safi_t safi;
@@ -3959,7 +3974,9 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
(const struct prefix_evpn *)bgp_dest_get_prefix(
dest);
- if (evp->prefix.route_type != rtype)
+ if (evp->prefix.route_type != BGP_EVPN_IMET_ROUTE &&
+ evp->prefix.route_type != BGP_EVPN_AD_ROUTE &&
+ evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
continue;
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
@@ -3986,16 +4003,16 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
bgp, vpn, evp, pi);
if (ret) {
- flog_err(
- EC_BGP_EVPN_FAIL,
- "%u: Failed to %s EVPN %s route in VNI %u",
- bgp->vrf_id,
- install ? "install"
- : "uninstall",
- rtype == BGP_EVPN_MAC_IP_ROUTE
- ? "MACIP"
- : "IMET",
- vpn->vni);
+ flog_err(EC_BGP_EVPN_FAIL,
+ "%u: Failed to %s EVPN %s route in VNI %u",
+ bgp->vrf_id,
+ install ? "install"
+ : "uninstall",
+ evp->prefix.route_type ==
+ BGP_EVPN_MAC_IP_ROUTE
+ ? "MACIP"
+ : "IMET",
+ vpn->vni);
bgp_dest_unlock_node(rd_dest);
bgp_dest_unlock_node(dest);
@@ -4013,7 +4030,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
*/
static int install_routes_for_vrf(struct bgp *bgp_vrf)
{
- install_uninstall_routes_for_vrf(bgp_vrf, 1);
+ install_uninstall_routes_for_vrf(bgp_vrf, true);
return 0;
}
@@ -4024,29 +4041,17 @@ static int install_routes_for_vrf(struct bgp *bgp_vrf)
*/
static int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
{
- int ret;
-
- /* Install type-3 routes followed by type-2 routes - the ones applicable
+ /*
+ * Install type-3 routes followed by type-2 routes - the ones applicable
* for this VNI.
*/
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE,
- 1);
- if (ret)
- return ret;
-
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE,
- 1);
- if (ret)
- return ret;
-
- return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE,
- 1);
+ return install_uninstall_routes_for_vni(bgp, vpn, true);
}
/* uninstall routes from l3vni vrf. */
static int uninstall_routes_for_vrf(struct bgp *bgp_vrf)
{
- install_uninstall_routes_for_vrf(bgp_vrf, 0);
+ install_uninstall_routes_for_vrf(bgp_vrf, false);
return 0;
}
@@ -4056,25 +4061,11 @@ static int uninstall_routes_for_vrf(struct bgp *bgp_vrf)
*/
static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
{
- int ret;
-
- /* Uninstall type-2 routes followed by type-3 routes - the ones
- * applicable
- * for this VNI.
+ /*
+ * Uninstall type-2 routes followed by type-3 routes - the ones
+ * applicable for this VNI.
*/
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE,
- 0);
- if (ret)
- return ret;
-
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE,
- 0);
- if (ret)
- return ret;
-
-
- return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE,
- 0);
+ return install_uninstall_routes_for_vni(bgp, vpn, false);
}
/*
@@ -4494,7 +4485,7 @@ static void update_advertise_vni_route(struct bgp *bgp, struct bgpevpn *vpn,
}
/* Schedule for processing and unlock node. */
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, global_pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -4544,7 +4535,7 @@ static void update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
false /* setup_sync */, NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -4589,7 +4580,7 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -6499,9 +6490,10 @@ void bgp_filter_evpn_routes_upon_martian_change(
for (dest = bgp_table_top(table); dest;
dest = bgp_route_next(dest)) {
+ struct bgp_path_info *next;
- for (pi = bgp_dest_get_bgp_path_info(dest); pi;
- pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next) {
bool affected = false;
const struct prefix *p;
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 601b8e91ba..d63e011560 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -92,7 +92,8 @@ static void bgp_evpn_path_nh_unlink(struct bgp_path_evpn_nh_info *nh_info);
*/
static int bgp_evpn_es_route_select_install(struct bgp *bgp,
struct bgp_evpn_es *es,
- struct bgp_dest *dest)
+ struct bgp_dest *dest,
+ struct bgp_path_info *pi)
{
int ret = 0;
int zret = 0;
@@ -102,6 +103,8 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp,
struct bgp_path_info *new_select; /* new best */
struct bgp_path_info_pair old_and_new;
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
+
/* Compute the best path. */
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
afi, safi);
@@ -233,7 +236,7 @@ static int bgp_evpn_es_route_install(struct bgp *bgp,
}
/* Perform route selection and update zebra, if required. */
- ret = bgp_evpn_es_route_select_install(bgp, es, dest);
+ ret = bgp_evpn_es_route_select_install(bgp, es, dest, pi);
bgp_dest_unlock_node(dest);
@@ -274,7 +277,7 @@ static int bgp_evpn_es_route_uninstall(struct bgp *bgp, struct bgp_evpn_es *es,
bgp_path_info_delete(dest, pi);
/* Perform route selection and update zebra, if required. */
- ret = bgp_evpn_es_route_select_install(bgp, es, dest);
+ ret = bgp_evpn_es_route_select_install(bgp, es, dest, pi);
/* Unlock route node. */
bgp_dest_unlock_node(dest);
@@ -513,7 +516,7 @@ static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es,
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -564,7 +567,7 @@ int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn)
delete_evpn_route_entry(bgp, afi, safi, bd, &pi);
if (pi)
- bgp_process(bgp, bd, afi, safi);
+ bgp_process(bgp, bd, pi, afi, safi);
}
}
@@ -670,7 +673,7 @@ static int bgp_evpn_type4_route_update(struct bgp *bgp,
* this is just to set the flags correctly
* as local route in the ES always wins.
*/
- bgp_evpn_es_route_select_install(bgp, es, dest);
+ bgp_evpn_es_route_select_install(bgp, es, dest, pi);
bgp_dest_unlock_node(dest);
/* If this is a new route or some attribute has changed, export the
@@ -688,7 +691,7 @@ static int bgp_evpn_type4_route_update(struct bgp *bgp,
attr_new, &global_pi, &route_changed);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, global_pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -1010,7 +1013,7 @@ static int bgp_evpn_type1_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
* this is just to set the flags correctly as local route in
* the ES always wins.
*/
- evpn_route_select_install(bgp, vpn, dest);
+ evpn_route_select_install(bgp, vpn, dest, pi);
bgp_dest_unlock_node(dest);
/* If this is a new route or some attribute has changed, export the
@@ -1027,7 +1030,7 @@ static int bgp_evpn_type1_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
attr_new, &global_pi, &route_changed);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, global_pi, afi, safi);
bgp_dest_unlock_node(dest);
}
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index 5af99afa34..07bba9b426 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -716,7 +716,8 @@ extern void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_path_info **pi);
int vni_list_cmp(void *p1, void *p2);
extern int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
- struct bgp_dest *dest);
+ struct bgp_dest *dest,
+ struct bgp_path_info *pi);
extern struct bgp_dest *
bgp_evpn_global_node_get(struct bgp_table *table, afi_t afi, safi_t safi,
const struct prefix_evpn *evp, struct prefix_rd *prd,
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index a2d3172882..7866adbdcd 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -1796,6 +1796,22 @@ bgp_connect_fail(struct peer_connection *connection)
return bgp_stop(connection);
}
+/* after connect is called(), getpeername is able to return
+ * port and address on non established streams
+ */
+static void bgp_connect_in_progress_update_connection(struct peer *peer)
+{
+ bgp_getsockname(peer);
+ if (!peer->su_remote && !BGP_CONNECTION_SU_UNSPEC(peer->connection)) {
+ /* if connect initiated, then dest port and dest addresses are well known */
+ peer->su_remote = sockunion_dup(&peer->connection->su);
+ if (sockunion_family(peer->su_remote) == AF_INET)
+ peer->su_remote->sin.sin_port = htons(peer->port);
+ else if (sockunion_family(peer->su_remote) == AF_INET6)
+ peer->su_remote->sin6.sin6_port = htons(peer->port);
+ }
+}
+
/* This function is the first starting point of all BGP connection. It
* try to connect to remote peer with non-blocking IO.
*/
@@ -1892,6 +1908,8 @@ static enum bgp_fsm_state_progress bgp_start(struct peer_connection *connection)
__func__, peer->connection->fd);
return BGP_FSM_FAILURE;
}
+ bgp_connect_in_progress_update_connection(peer);
+
/*
* - when the socket becomes ready, poll() will signify POLLOUT
* - if it fails to connect, poll() will signify POLLHUP
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index 7327ab5182..68104967b2 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -74,7 +74,7 @@ int bgp_parse_fec_update(void)
bgp_set_valid_label(&dest->local_label);
}
SET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, NULL, afi, safi);
bgp_dest_unlock_node(dest);
return 1;
}
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 985af84ea9..2404ceffb1 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -1208,7 +1208,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
/* Process change. */
bgp_aggregate_increment(to_bgp, p, bpi, afi, safi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
if (debug)
zlog_debug("%s: ->%s: %pBD Found route, changed attr",
@@ -1270,7 +1270,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
bgp_aggregate_increment(to_bgp, p, new, afi, safi);
bgp_path_info_add(bn, new);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, new, afi, safi);
if (debug)
zlog_debug("%s: ->%s: %pBD: Added new route", __func__,
@@ -1956,7 +1956,7 @@ void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, /* to */
bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
}
bgp_dest_unlock_node(bn);
}
@@ -1976,7 +1976,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
struct bgp_table *table;
struct bgp_dest *bn;
- struct bgp_path_info *bpi;
+ struct bgp_path_info *bpi, *next;
/* This is the per-RD table of prefixes */
table = bgp_dest_get_bgp_table_info(pdest);
@@ -1991,7 +1991,8 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
__func__, bn);
}
- for (; bpi; bpi = bpi->next) {
+ for (; (bpi != NULL) && (next = bpi->next, 1);
+ bpi = next) {
if (debug)
zlog_debug("%s: type %d, sub_type %d",
__func__, bpi->type,
@@ -2012,7 +2013,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
to_bgp, bgp_dest_get_prefix(bn),
bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
bgp_mplsvpn_path_nh_label_unlink(
bpi->extra->vrfleak->parent);
}
@@ -2506,7 +2507,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn)
bpi);
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, bpi, afi, safi);
}
bgp_dest_unlock_node(bn);
}
@@ -2515,7 +2516,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn)
void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
{
struct bgp_dest *bn;
- struct bgp_path_info *bpi;
+ struct bgp_path_info *bpi, *next;
safi_t safi = SAFI_UNICAST;
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
@@ -2526,9 +2527,8 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
*/
for (bn = bgp_table_top(to_bgp->rib[afi][safi]); bn;
bn = bgp_route_next(bn)) {
-
- for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
- bpi = bpi->next) {
+ for (bpi = bgp_dest_get_bgp_path_info(bn);
+ (bpi != NULL) && (next = bpi->next, 1); bpi = next) {
if (bpi->extra && bpi->extra->vrfleak &&
bpi->extra->vrfleak->bgp_orig != to_bgp &&
bpi->extra->vrfleak->parent &&
@@ -2538,7 +2538,7 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
bgp_dest_get_prefix(bn),
bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
}
}
}
@@ -2567,8 +2567,11 @@ void vpn_leak_no_retain(struct bgp *to_bgp, struct bgp *vpn_from, afi_t afi)
continue;
for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
- for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
- bpi = bpi->next) {
+ struct bgp_path_info *next;
+
+ for (bpi = bgp_dest_get_bgp_path_info(bn);
+ (bpi != NULL) && (next = bpi->next, 1);
+ bpi = next) {
if (bpi->extra && bpi->extra->vrfleak &&
bpi->extra->vrfleak->bgp_orig == to_bgp)
continue;
@@ -4189,7 +4192,7 @@ static int bgp_mplsvpn_nh_label_bind_get_local_label_cb(mpls_label_t label,
if (!table)
continue;
SET_FLAG(pi->net->flags, BGP_NODE_LABEL_CHANGED);
- bgp_process(table->bgp, pi->net, table->afi, table->safi);
+ bgp_process(table->bgp, pi->net, pi, table->afi, table->safi);
}
return 0;
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index dbb34b048f..b409cbe706 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -875,11 +875,7 @@ int bgp_getsockname(struct peer *peer)
}
peer->su_local = sockunion_getsockname(peer->connection->fd);
- if (!peer->su_local)
- return -1;
peer->su_remote = sockunion_getpeername(peer->connection->fd);
- if (!peer->su_remote)
- return -1;
if (!bgp_zebra_nexthop_set(peer->su_local, peer->su_remote,
&peer->nexthop, peer)) {
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 20a285b9d9..80ec9bcf77 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -1435,7 +1435,7 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
}
}
- bgp_process(bgp_path, dest, afi, safi);
+ bgp_process(bgp_path, dest, path, afi, safi);
}
if (peer) {
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index e2b1687e99..848e8ffd8d 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -114,6 +114,46 @@ static const struct message bgp_pmsi_tnltype_str[] = {
#define VRFID_NONE_STR "-"
#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
+static inline char *bgp_route_dump_path_info_flags(struct bgp_path_info *pi,
+ char *buf, size_t len)
+{
+ uint32_t flags = pi->flags;
+
+ if (flags == 0) {
+ snprintfrr(buf, len, "None ");
+ return buf;
+ }
+
+ snprintfrr(buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ CHECK_FLAG(flags, BGP_PATH_IGP_CHANGED) ? "IGP Changed " : "",
+ CHECK_FLAG(flags, BGP_PATH_DAMPED) ? "Damped" : "",
+ CHECK_FLAG(flags, BGP_PATH_HISTORY) ? "History " : "",
+ CHECK_FLAG(flags, BGP_PATH_SELECTED) ? "Selected " : "",
+ CHECK_FLAG(flags, BGP_PATH_VALID) ? "Valid " : "",
+ CHECK_FLAG(flags, BGP_PATH_ATTR_CHANGED) ? "Attr Changed "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_DMED_CHECK) ? "Dmed Check " : "",
+ CHECK_FLAG(flags, BGP_PATH_DMED_SELECTED) ? "Dmed Selected "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_STALE) ? "Stale " : "",
+ CHECK_FLAG(flags, BGP_PATH_REMOVED) ? "Removed " : "",
+ CHECK_FLAG(flags, BGP_PATH_COUNTED) ? "Counted " : "",
+ CHECK_FLAG(flags, BGP_PATH_MULTIPATH) ? "Mpath " : "",
+ CHECK_FLAG(flags, BGP_PATH_MULTIPATH_CHG) ? "Mpath Chg " : "",
+ CHECK_FLAG(flags, BGP_PATH_RIB_ATTR_CHG) ? "Rib Chg " : "",
+ CHECK_FLAG(flags, BGP_PATH_ANNC_NH_SELF) ? "NH Self " : "",
+ CHECK_FLAG(flags, BGP_PATH_LINK_BW_CHG) ? "LinkBW Chg " : "",
+ CHECK_FLAG(flags, BGP_PATH_ACCEPT_OWN) ? "Accept Own " : "",
+ CHECK_FLAG(flags, BGP_PATH_MPLSVPN_LABEL_NH) ? "MPLS Label "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_MPLSVPN_NH_LABEL_BIND)
+ ? "MPLS Label Bind "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_UNSORTED) ? "Unsorted " : "");
+
+ return buf;
+}
+
DEFINE_HOOK(bgp_process,
(struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
struct peer *peer, bool withdraw),
@@ -442,6 +482,7 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
top->prev = pi;
bgp_dest_set_bgp_path_info(dest, pi);
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
bgp_path_info_lock(pi);
bgp_dest_lock_node(dest);
peer_lock(pi->peer); /* bgp_path_info peer reference */
@@ -462,8 +503,26 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
bgp_dest_set_bgp_path_info(dest, pi->next);
bgp_path_info_mpath_dequeue(pi);
+
+ pi->next = NULL;
+ pi->prev = NULL;
+
+ hook_call(bgp_snmp_update_stats, dest, pi, false);
+
bgp_path_info_unlock(pi);
+ return bgp_dest_unlock_node(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;
+
hook_call(bgp_snmp_update_stats, dest, pi, false);
+ bgp_path_info_unlock(pi);
return bgp_dest_unlock_node(dest);
}
@@ -553,6 +612,15 @@ void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
bgp_pcount_adjust(dest, pi);
}
+static bool use_bgp_med_value(struct attr *attr, struct bgp *bgp)
+{
+ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC) ||
+ CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
+ return true;
+
+ return false;
+}
+
/* Get MED value. If MED value is missing and "bgp bestpath
missing-as-worst" is specified, treat it as the worst value. */
static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
@@ -679,12 +747,18 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
if (debug) {
+ char buf1[256], buf2[256];
+
bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
sizeof(exist_buf));
- zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
- pfx_buf, bgp->name_pretty, new_buf, new->flags,
- exist_buf, exist->flags);
+ zlog_debug("%s(%s): Comparing %s flags %s with %s flags %s",
+ pfx_buf, bgp->name_pretty, new_buf,
+ bgp_route_dump_path_info_flags(new, buf1,
+ sizeof(buf1)),
+ exist_buf,
+ bgp_route_dump_path_info_flags(exist, buf2,
+ sizeof(buf2)));
}
newattr = new->attr;
@@ -2736,17 +2810,18 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info_pair *result, afi_t afi,
safi_t safi)
{
- struct bgp_path_info *new_select;
- struct bgp_path_info *old_select;
+ struct bgp_path_info *new_select, *look_thru;
+ struct bgp_path_info *old_select, *worse, *first;
struct bgp_path_info *pi;
struct bgp_path_info *pi1;
struct bgp_path_info *pi2;
- struct bgp_path_info *nextpi = NULL;
int paths_eq, do_mpath;
- bool debug;
+ 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;
bgp_mp_list_init(&mp_list);
do_mpath =
@@ -2757,16 +2832,16 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (debug)
prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
- dest->reason = bgp_path_selection_none;
/* bgp deterministic-med */
new_select = NULL;
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
-
/* Clear BGP_PATH_DMED_SELECTED for all paths */
for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
- pi1 = pi1->next)
+ pi1 = pi1->next) {
bgp_path_info_unset_flag(dest, pi1,
BGP_PATH_DMED_SELECTED);
+ UNSET_FLAG(pi1->flags, BGP_PATH_DMED_CHECK);
+ }
for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
pi1 = pi1->next) {
@@ -2829,68 +2904,273 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
}
}
- /* Check old selected route and new selected route. */
+ /*
+ * Let's grab the unsorted items from the list
+ */
+ struct bgp_path_info *unsorted_list = NULL;
+ struct bgp_path_info *unsorted_list_spot = NULL;
+ struct bgp_path_info *unsorted_holddown = NULL;
+
old_select = NULL;
- new_select = NULL;
- for (pi = bgp_dest_get_bgp_path_info(dest);
- (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
- enum bgp_path_selection_reason reason;
+ pi = bgp_dest_get_bgp_path_info(dest);
+ while (pi && CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED)) {
+ struct bgp_path_info *next = pi->next;
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
old_select = pi;
- if (BGP_PATH_HOLDDOWN(pi)) {
- /* reap REMOVED routes, if needs be
+ /*
+ * Pull off pi off the list
+ */
+ if (pi->next)
+ pi->next->prev = NULL;
+
+ bgp_dest_set_bgp_path_info(dest, pi->next);
+ pi->next = NULL;
+ pi->prev = NULL;
+
+ /*
+ * Place it on the unsorted list
+ */
+ if (unsorted_list_spot) {
+ unsorted_list_spot->next = pi;
+ pi->prev = unsorted_list_spot;
+ pi->next = NULL;
+ } else {
+ unsorted_list = pi;
+
+ pi->next = NULL;
+ pi->prev = NULL;
+ }
+
+ unsorted_list_spot = pi;
+ pi = next;
+ }
+
+ if (!old_select) {
+ old_select = bgp_dest_get_bgp_path_info(dest);
+ if (old_select &&
+ !CHECK_FLAG(old_select->flags, BGP_PATH_SELECTED))
+ old_select = NULL;
+ }
+
+ if (!unsorted_list)
+ unsorted_items = true;
+ else
+ unsorted_items = false;
+
+ any_comparisons = false;
+ worse = NULL;
+ while (unsorted_list) {
+ first = unsorted_list;
+ unsorted_list = unsorted_list->next;
+
+ if (unsorted_list)
+ unsorted_list->prev = NULL;
+ first->next = NULL;
+ first->prev = NULL;
+
+ /*
+ * It's not likely that the just received unsorted entry
+ * is in holddown and scheduled for removal but we should
+ * check
+ */
+ if (BGP_PATH_HOLDDOWN(first)) {
+ /*
+ * reap REMOVED routes, if needs be
* selected route must stay for a while longer though
*/
if (debug)
- zlog_debug(
- "%s: %pBD(%s) pi from %s in holddown",
- __func__, dest, bgp->name_pretty,
- pi->peer->host);
+ zlog_debug("%s: %pBD(%s) pi %p from %s in holddown",
+ __func__, dest, bgp->name_pretty,
+ first, first->peer->host);
- if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) &&
- (pi != old_select)) {
- dest = bgp_path_info_reap(dest, pi);
+ if (old_select != first &&
+ CHECK_FLAG(first->flags, BGP_PATH_REMOVED)) {
+ dest = bgp_path_info_reap_unsorted(dest, first);
assert(dest);
- }
+ } else {
+ /*
+ * We are in hold down, so we cannot sort this
+ * item yet. Let's wait, so hold the unsorted
+ * to the side
+ */
+ if (unsorted_holddown) {
+ first->next = unsorted_holddown;
+ unsorted_holddown->prev = first;
+ unsorted_holddown = first;
+ } else
+ unsorted_holddown = first;
+ UNSET_FLAG(first->flags, BGP_PATH_UNSORTED);
+ }
continue;
}
- if (pi->peer && pi->peer != bgp->peer_self
- && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
- if (!peer_established(pi->peer->connection)) {
+ bgp_path_info_unset_flag(dest, first, BGP_PATH_DMED_CHECK);
+
+ worse = NULL;
+
+ struct bgp_path_info *look_thru_next;
+
+ for (look_thru = bgp_dest_get_bgp_path_info(dest); look_thru;
+ look_thru = look_thru_next) {
+ /* look thru can be reaped save the next pointer */
+ look_thru_next = look_thru->next;
+
+ /*
+ * Now we have the first unsorted and the best selected
+ * Let's do best path comparison
+ */
+ if (BGP_PATH_HOLDDOWN(look_thru)) {
+ /* reap REMOVED routes, if needs be
+ * selected route must stay for a while longer though
+ */
if (debug)
- zlog_debug(
- "%s: %pBD(%s) non self peer %s not estab state",
- __func__, dest,
- bgp->name_pretty,
- pi->peer->host);
+ zlog_debug("%s: %pBD(%s) pi from %s %p in holddown",
+ __func__, dest,
+ bgp->name_pretty,
+ look_thru->peer->host,
+ look_thru);
+
+ if (CHECK_FLAG(look_thru->flags,
+ BGP_PATH_REMOVED) &&
+ (look_thru != old_select)) {
+ dest = bgp_path_info_reap(dest,
+ look_thru);
+ assert(dest);
+ }
continue;
}
- bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
+ if (look_thru->peer &&
+ look_thru->peer != bgp->peer_self &&
+ !CHECK_FLAG(look_thru->peer->sflags,
+ PEER_STATUS_NSF_WAIT))
+ if (!peer_established(
+ look_thru->peer->connection)) {
+ if (debug)
+ zlog_debug("%s: %pBD(%s) non self peer %s not estab state",
+ __func__, dest,
+ bgp->name_pretty,
+ look_thru->peer->host);
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED) &&
- (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
- if (debug)
- zlog_debug("%s: %pBD(%s) pi %s dmed", __func__,
- dest, bgp->name_pretty,
- pi->peer->host);
- continue;
+ continue;
+ }
+
+ bgp_path_info_unset_flag(dest, look_thru,
+ BGP_PATH_DMED_CHECK);
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED) &&
+ (!CHECK_FLAG(look_thru->flags,
+ BGP_PATH_DMED_SELECTED))) {
+ bgp_path_info_unset_flag(dest, look_thru,
+ BGP_PATH_DMED_CHECK);
+ if (debug)
+ zlog_debug("%s: %pBD(%s) pi %s dmed",
+ __func__, dest,
+ bgp->name_pretty,
+ look_thru->peer->host);
+
+ worse = look_thru;
+ continue;
+ }
+
+ reason = dest->reason;
+ any_comparisons = true;
+ if (bgp_path_info_cmp(bgp, first, look_thru, &paths_eq,
+ mpath_cfg, debug, pfx_buf, afi,
+ safi, &reason)) {
+ first->reason = reason;
+ worse = look_thru;
+ /*
+ * We can stop looking
+ */
+ break;
+ }
+
+ look_thru->reason = reason;
}
- reason = dest->reason;
- if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
- debug, pfx_buf, afi, safi,
- &dest->reason)) {
- if (new_select == NULL &&
- reason != bgp_path_selection_none)
- dest->reason = reason;
- new_select = pi;
+ if (!any_comparisons)
+ first->reason = bgp_path_selection_first;
+
+ /*
+ * At this point worse if NON-NULL is where the first
+ * pointer should be before. if worse is NULL then
+ * first is bestpath too. Let's remove first from the
+ * list and place it in the right spot
+ */
+
+ if (!worse) {
+ struct bgp_path_info *end =
+ bgp_dest_get_bgp_path_info(dest);
+
+ for (; end && end->next != NULL; end = end->next)
+ ;
+
+ if (end)
+ end->next = first;
+ else
+ bgp_dest_set_bgp_path_info(dest, first);
+ first->prev = end;
+ first->next = NULL;
+
+ dest->reason = first->reason;
+ } else {
+ if (worse->prev)
+ worse->prev->next = first;
+ first->next = worse;
+ if (worse) {
+ first->prev = worse->prev;
+ worse->prev = first;
+ } else
+ first->prev = NULL;
+
+ if (dest->info == worse) {
+ bgp_dest_set_bgp_path_info(dest, first);
+ dest->reason = first->reason;
+ }
}
+ UNSET_FLAG(first->flags, BGP_PATH_UNSORTED);
+ }
+
+ if (!unsorted_items) {
+ new_select = bgp_dest_get_bgp_path_info(dest);
+ while (new_select && BGP_PATH_HOLDDOWN(new_select))
+ new_select = new_select->next;
+
+ if (new_select) {
+ if (new_select->reason == bgp_path_selection_none)
+ new_select->reason = bgp_path_selection_first;
+ else if (new_select == bgp_dest_get_bgp_path_info(dest) &&
+ new_select->next == NULL)
+ new_select->reason = bgp_path_selection_first;
+ dest->reason = new_select->reason;
+ } else
+ dest->reason = bgp_path_selection_none;
+ } else
+ new_select = old_select;
+
+
+ /*
+ * Reinsert all the unsorted_holddown items for future processing
+ * at the end of the list.
+ */
+ if (unsorted_holddown) {
+ struct bgp_path_info *top = bgp_dest_get_bgp_path_info(dest);
+ struct bgp_path_info *prev = NULL;
+
+ while (top != NULL) {
+ prev = top;
+ top = top->next;
+ }
+
+ if (prev) {
+ prev->next = unsorted_holddown;
+ unsorted_holddown->prev = prev;
+ } else
+ bgp_dest_set_bgp_path_info(dest, unsorted_holddown);
}
/* Now that we know which path is the bestpath see if any of the other
@@ -3339,7 +3619,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
return;
}
+#ifdef ENABLE_BGP_VNC
const struct prefix *p = bgp_dest_get_prefix(dest);
+#endif
debug = bgp_debug_bestpath(dest);
if (debug)
@@ -3464,7 +3746,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
if (new_select) {
if (debug)
- zlog_debug("%s: setting SELECTED flag", __func__);
+ zlog_debug("%s: %pBD setting SELECTED flag", __func__,
+ dest);
bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
bgp_path_info_unset_flag(dest, new_select,
BGP_PATH_ATTR_CHANGED);
@@ -3689,13 +3972,38 @@ static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
return pqnode;
}
-void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
+void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *pi, afi_t afi, safi_t safi)
{
#define ARBITRARY_PROCESS_QLEN 10000
struct work_queue *wq = bgp->process_queue;
struct bgp_process_queue *pqnode;
int pqnode_reuse = 0;
+ /*
+ * Indicate that *this* pi is in an unsorted
+ * situation, even if the node is already
+ * scheduled.
+ */
+ if (pi) {
+ struct bgp_path_info *first = bgp_dest_get_bgp_path_info(dest);
+
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
+
+ if (pi != first) {
+ if (pi->next)
+ pi->next->prev = pi->prev;
+ if (pi->prev)
+ pi->prev->next = pi->next;
+
+ if (first)
+ first->prev = pi;
+ pi->next = first;
+ pi->prev = NULL;
+ bgp_dest_set_bgp_path_info(dest, pi);
+ }
+ }
+
/* already scheduled for processing? */
if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
return;
@@ -3944,7 +4252,7 @@ void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
}
hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
- bgp_process(peer->bgp, dest, afi, safi);
+ bgp_process(peer->bgp, dest, pi, afi, safi);
}
static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
@@ -4550,7 +4858,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
!= BGP_DAMP_SUPPRESSED) {
bgp_aggregate_increment(bgp, p, pi, afi,
safi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
} else /* Duplicate - odd */
{
@@ -4578,7 +4886,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_path_info_unset_flag(
dest, pi, BGP_PATH_STALE);
bgp_dest_set_defer_flag(dest, false);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
@@ -4868,7 +5176,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Process change. */
bgp_aggregate_increment(bgp, p, pi, afi, safi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
bgp_dest_unlock_node(dest);
if (SAFI_UNICAST == safi
@@ -5013,7 +5321,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
/* Process change. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, new, afi, safi);
if (SAFI_UNICAST == safi
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
@@ -5584,7 +5892,7 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
struct bgp_clear_node_queue *cnq = data;
struct bgp_dest *dest = cnq->dest;
struct peer *peer = wq->spec.data;
- struct bgp_path_info *pi;
+ struct bgp_path_info *pi, *next;
struct bgp *bgp;
afi_t afi = bgp_dest_table(dest)->afi;
safi_t safi = bgp_dest_table(dest)->safi;
@@ -5595,7 +5903,8 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
/* It is possible that we have multiple paths for a prefix from a peer
* if that peer is using AddPath.
*/
- for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next) {
if (pi->peer != peer)
continue;
@@ -5857,7 +6166,7 @@ void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
{
struct bgp_dest *dest;
- struct bgp_path_info *pi;
+ struct bgp_path_info *pi, *next;
struct bgp_table *table;
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
@@ -5872,8 +6181,9 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
for (rm = bgp_table_top(table); rm;
rm = bgp_route_next(rm))
- for (pi = bgp_dest_get_bgp_path_info(rm); pi;
- pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(rm);
+ (pi != NULL) && (next = pi->next, 1);
+ pi = next) {
if (pi->peer != peer)
continue;
if (CHECK_FLAG(
@@ -5906,8 +6216,8 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
} else {
for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
dest = bgp_route_next(dest))
- for (pi = bgp_dest_get_bgp_path_info(dest); pi;
- pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next) {
if (pi->peer != peer)
continue;
if (CHECK_FLAG(peer->af_sflags[afi][safi],
@@ -6520,7 +6830,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
/* Process change. */
bgp_aggregate_increment(bgp, p, pi, afi, safi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
if (SAFI_MPLS_VPN == safi &&
bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
@@ -6578,7 +6888,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
bgp_dest_unlock_node(dest);
/* Process change. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, new, afi, safi);
if (SAFI_UNICAST == safi &&
(bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
@@ -6617,6 +6927,7 @@ void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
/* Withdraw static BGP route from routing table. */
if (pi) {
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
rfapiProcessWithdraw(pi->peer, NULL, p, prd, pi->attr,
@@ -6635,7 +6946,7 @@ void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
bgp_aggregate_decrement(bgp, p, pi, afi, safi);
bgp_unlink_nexthop(pi);
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
/* Unlock bgp_node_lookup. */
@@ -7036,7 +7347,7 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
safi);
bgp_unlink_nexthop(pi);
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
}
@@ -7399,8 +7710,10 @@ static void bgp_aggregate_install(
/*
* Mark the old as unusable
*/
- if (pi)
+ if (pi) {
bgp_path_info_delete(dest, pi);
+ bgp_process(bgp, dest, pi, afi, safi);
+ }
attr = bgp_attr_aggregate_intern(
bgp, origin, aspath, community, ecommunity, lcommunity,
@@ -7425,7 +7738,7 @@ static void bgp_aggregate_install(
SET_FLAG(new->flags, BGP_PATH_VALID);
bgp_path_info_add(dest, new);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, new, afi, safi);
} else {
uninstall_aggregate_route:
for (pi = orig; pi; pi = pi->next)
@@ -7437,7 +7750,7 @@ static void bgp_aggregate_install(
/* Withdraw static BGP route from routing table. */
if (pi) {
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
@@ -7523,7 +7836,6 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
const struct prefix *dest_p;
struct bgp_dest *dest, *top;
struct bgp_path_info *pi;
- bool toggle_suppression;
/* We've found a different MED we must revert any suppressed routes. */
top = bgp_node_get(table, p);
@@ -7533,7 +7845,6 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
if (dest_p->prefixlen <= p->prefixlen)
continue;
- toggle_suppression = false;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (BGP_PATH_HOLDDOWN(pi))
continue;
@@ -7544,17 +7855,14 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
if (suppress) {
/* Suppress route if not suppressed already. */
if (aggr_suppress_path(aggregate, pi))
- toggle_suppression = true;
+ bgp_process(bgp, dest, pi, afi, safi);
continue;
}
/* Install route if there is no more suppression. */
if (aggr_unsuppress_path(aggregate, pi))
- toggle_suppression = true;
+ bgp_process(bgp, dest, pi, afi, safi);
}
-
- if (toggle_suppression)
- bgp_process(bgp, dest, afi, safi);
}
bgp_dest_unlock_node(top);
}
@@ -7613,7 +7921,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
struct ecommunity *ecommunity = NULL;
struct lcommunity *lcommunity = NULL;
struct bgp_path_info *pi;
- unsigned long match = 0;
uint8_t atomic_aggregate = 0;
/* If the bgp instance is being deleted or self peer is deleted
@@ -7663,8 +7970,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (!bgp_check_advertise(bgp, dest, safi))
continue;
- match = 0;
-
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (BGP_PATH_HOLDDOWN(pi))
continue;
@@ -7688,7 +7993,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (aggregate->summary_only
&& AGGREGATE_MED_VALID(aggregate)) {
if (aggr_suppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, dest, pi, afi, safi);
}
/*
@@ -7704,7 +8009,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
&& AGGREGATE_MED_VALID(aggregate)
&& aggr_suppress_map_test(bgp, aggregate, pi)) {
if (aggr_suppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, dest, pi, afi, safi);
}
aggregate->count++;
@@ -7765,8 +8070,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
aggregate,
bgp_attr_get_lcommunity(pi->attr));
}
- if (match)
- bgp_process(bgp, dest, afi, safi);
}
if (aggregate->as_set) {
bgp_compute_aggregate_aspath_val(aggregate);
@@ -7826,7 +8129,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
struct bgp_dest *top;
struct bgp_dest *dest;
struct bgp_path_info *pi;
- unsigned long match;
table = bgp->rib[afi][safi];
@@ -7838,7 +8140,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (dest_p->prefixlen <= p->prefixlen)
continue;
- match = 0;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (BGP_PATH_HOLDDOWN(pi))
@@ -7856,10 +8157,11 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (pi->extra && pi->extra->aggr_suppressors &&
listcount(pi->extra->aggr_suppressors)) {
if (aggr_unsuppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, dest, pi, afi, safi);
}
- aggregate->count--;
+ if (aggregate->count > 0)
+ aggregate->count--;
if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
aggregate->incomplete_origin_count--;
@@ -7898,10 +8200,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
pi->attr));
}
}
-
- /* If this node was suppressed, process the change. */
- if (match)
- bgp_process(bgp, dest, afi, safi);
}
if (aggregate->as_set) {
aspath_free(aggregate->aspath);
@@ -8050,7 +8348,6 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
struct community *community = NULL;
struct ecommunity *ecommunity = NULL;
struct lcommunity *lcommunity = NULL;
- unsigned long match = 0;
/* If the bgp instance is being deleted or self peer is deleted
* then do not create aggregate route
@@ -8067,12 +8364,12 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
if (aggr_unsuppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, pi->net, pi, afi, safi);
if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
&& aggr_suppress_map_test(bgp, aggregate, pi))
if (aggr_unsuppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, pi->net, pi, afi, safi);
/*
* This must be called after `summary`, `suppress-map` check to avoid
@@ -8114,10 +8411,6 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
aggregate, bgp_attr_get_lcommunity(pi->attr));
}
- /* If this node was suppressed, process the change. */
- if (match)
- bgp_process(bgp, pi->net, afi, safi);
-
origin = BGP_ORIGIN_IGP;
if (aggregate->incomplete_origin_count > 0)
origin = BGP_ORIGIN_INCOMPLETE;
@@ -8727,7 +9020,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
/* Process change. */
bgp_aggregate_increment(bgp, p, bpi, afi,
SAFI_UNICAST);
- bgp_process(bgp, bn, afi, SAFI_UNICAST);
+ bgp_process(bgp, bn, bpi, afi, SAFI_UNICAST);
bgp_dest_unlock_node(bn);
aspath_unintern(&attr.aspath);
@@ -8750,7 +9043,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
bgp_path_info_add(bn, new);
bgp_dest_unlock_node(bn);
SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
- bgp_process(bgp, bn, afi, SAFI_UNICAST);
+ bgp_process(bgp, bn, new, afi, SAFI_UNICAST);
if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
|| (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
@@ -8791,7 +9084,7 @@ void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
}
bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, SAFI_UNICAST);
+ bgp_process(bgp, dest, pi, afi, SAFI_UNICAST);
}
bgp_dest_unlock_node(dest);
}
@@ -8825,7 +9118,7 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
bgp_path_info_delete(dest, pi);
if (!CHECK_FLAG(bgp->flags,
BGP_FLAG_DELETE_IN_PROGRESS))
- bgp_process(bgp, dest, afi, SAFI_UNICAST);
+ bgp_process(bgp, dest, pi, afi, SAFI_UNICAST);
else {
dest = bgp_path_info_reap(dest, pi);
assert(dest);
@@ -8971,6 +9264,9 @@ static void route_vty_short_status_out(struct vty *vty,
if (path->extra && bgp_path_suppressed(path))
json_object_boolean_true_add(json_path, "suppressed");
+ if (CHECK_FLAG(path->flags, BGP_PATH_UNSORTED))
+ json_object_boolean_true_add(json_path, "unsorted");
+
if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
json_object_boolean_true_add(json_path, "valid");
@@ -9033,6 +9329,8 @@ static void route_vty_short_status_out(struct vty *vty,
/* Selected */
if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
vty_out(vty, "h");
+ else if (CHECK_FLAG(path->flags, BGP_PATH_UNSORTED))
+ vty_out(vty, "u");
else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
vty_out(vty, "d");
else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
@@ -9405,14 +9703,16 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
}
/* MED/Metric */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
+ if (use_bgp_med_value(attr, path->peer->bgp)) {
+ uint32_t value = bgp_med_value(attr, path->peer->bgp);
+
if (json_paths)
- json_object_int_add(json_path, "metric", attr->med);
+ json_object_int_add(json_path, "metric", value);
else if (wide)
- vty_out(vty, "%7u", attr->med);
+ vty_out(vty, "%7u", value);
else
- vty_out(vty, "%10u", attr->med);
- else if (!json_paths) {
+ vty_out(vty, "%10u", value);
+ } else if (!json_paths) {
if (wide)
vty_out(vty, "%*s", 7, " ");
else
@@ -9533,7 +9833,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
}
/* called from terminal list command */
-void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
+void route_vty_out_tmp(struct vty *vty, struct bgp *bgp, struct bgp_dest *dest,
const struct prefix *p, struct attr *attr, safi_t safi,
bool use_json, json_object *json_ar, bool wide)
{
@@ -9592,10 +9892,11 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
&attr->mp_nexthop_global_in);
}
- if (attr->flag
- & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
- json_object_int_add(json_net, "metric",
- attr->med);
+ if (use_bgp_med_value(attr, bgp)) {
+ uint32_t value = bgp_med_value(attr, bgp);
+
+ json_object_int_add(json_net, "metric", value);
+ }
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
json_object_int_add(json_net, "locPrf",
@@ -9635,13 +9936,15 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
else
vty_out(vty, "%*s", len, " ");
}
- if (attr->flag
- & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
+
+ if (use_bgp_med_value(attr, bgp)) {
+ uint32_t value = bgp_med_value(attr, bgp);
+
if (wide)
- vty_out(vty, "%7u", attr->med);
+ vty_out(vty, "%7u", value);
else
- vty_out(vty, "%10u", attr->med);
- else if (wide)
+ vty_out(vty, "%10u", value);
+ } else if (wide)
vty_out(vty, " ");
else
vty_out(vty, " ");
@@ -10638,11 +10941,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, " Origin %s",
bgp_origin_long_str[attr->origin]);
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
+ if (use_bgp_med_value(attr, bgp)) {
+ uint32_t value = bgp_med_value(attr, bgp);
+
if (json_paths)
- json_object_int_add(json_path, "metric", attr->med);
+ json_object_int_add(json_path, "metric", value);
else
- vty_out(vty, ", metric %u", attr->med);
+ vty_out(vty, ", metric %u", value);
}
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
@@ -13673,21 +13978,23 @@ enum bgp_pcounts {
PCOUNT_COUNTED,
PCOUNT_BPATH_SELECTED,
PCOUNT_PFCNT, /* the figure we display to users */
+ PCOUNT_UNSORTED,
PCOUNT_MAX,
};
static const char *const pcount_strs[] = {
- [PCOUNT_ADJ_IN] = "Adj-in",
- [PCOUNT_DAMPED] = "Damped",
- [PCOUNT_REMOVED] = "Removed",
- [PCOUNT_HISTORY] = "History",
- [PCOUNT_STALE] = "Stale",
- [PCOUNT_VALID] = "Valid",
- [PCOUNT_ALL] = "All RIB",
- [PCOUNT_COUNTED] = "PfxCt counted",
- [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
- [PCOUNT_PFCNT] = "Useable",
- [PCOUNT_MAX] = NULL,
+ [PCOUNT_ADJ_IN] = "Adj-in",
+ [PCOUNT_DAMPED] = "Damped",
+ [PCOUNT_REMOVED] = "Removed",
+ [PCOUNT_HISTORY] = "History",
+ [PCOUNT_STALE] = "Stale",
+ [PCOUNT_VALID] = "Valid",
+ [PCOUNT_ALL] = "All RIB",
+ [PCOUNT_COUNTED] = "PfxCt counted",
+ [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
+ [PCOUNT_PFCNT] = "Useable",
+ [PCOUNT_UNSORTED] = "Unsorted",
+ [PCOUNT_MAX] = NULL,
};
struct peer_pcounts {
@@ -13728,6 +14035,8 @@ static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
pc->count[PCOUNT_PFCNT]++;
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
pc->count[PCOUNT_BPATH_SELECTED]++;
+ if (CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED))
+ pc->count[PCOUNT_UNSORTED]++;
if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
pc->count[PCOUNT_COUNTED]++;
@@ -14286,7 +14595,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
json_ar, json_net,
"%pFX", rn_p);
} else
- route_vty_out_tmp(vty, dest, rn_p,
+ route_vty_out_tmp(vty, bgp, dest, rn_p,
&attr, safi, use_json,
json_ar, wide);
bgp_attr_flush(&attr);
@@ -14349,11 +14658,15 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
"%pFX",
rn_p);
} else
- route_vty_out_tmp(
- vty, dest, rn_p,
- &attr, safi,
- use_json,
- json_ar, wide);
+ route_vty_out_tmp(vty,
+ bgp,
+ dest,
+ rn_p,
+ &attr,
+ safi,
+ use_json,
+ json_ar,
+ wide);
(*output_count)++;
} else {
(*filtered_count)++;
@@ -14391,9 +14704,10 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
json_ar, json_net,
"%pFX", rn_p);
} else
- route_vty_out_tmp(
- vty, dest, rn_p, pi->attr, safi,
- use_json, json_ar, wide);
+ route_vty_out_tmp(vty, bgp, dest, rn_p,
+ pi->attr, safi,
+ use_json, json_ar,
+ wide);
(*output_count)++;
}
}
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 9be3f063f3..25fc327a17 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -59,7 +59,7 @@ enum bgp_show_adj_route_type {
#define BGP_SHOW_SCODE_HEADER \
"Status codes: s suppressed, d damped, " \
- "h history, * valid, > best, = multipath,\n" \
+ "h history, u unsorted, * valid, > best, = multipath,\n" \
" i internal, r RIB-failure, S Stale, R Removed\n"
#define BGP_SHOW_OCODE_HEADER \
"Origin codes: i - IGP, e - EGP, ? - incomplete\n"
@@ -327,6 +327,7 @@ struct bgp_path_info {
#define BGP_PATH_ACCEPT_OWN (1 << 16)
#define BGP_PATH_MPLSVPN_LABEL_NH (1 << 17)
#define BGP_PATH_MPLSVPN_NH_LABEL_BIND (1 << 18)
+#define BGP_PATH_UNSORTED (1 << 19)
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
uint8_t type;
@@ -345,6 +346,8 @@ struct bgp_path_info {
unsigned short instance;
+ enum bgp_path_selection_reason reason;
+
/* Addpath identifiers */
uint32_t addpath_rx_id;
struct bgp_addpath_info_data tx_addpath;
@@ -801,7 +804,8 @@ extern void bgp_withdraw(struct peer *peer, const struct prefix *p,
struct bgp_route_evpn *evpn);
/* for bgp_nexthop and bgp_damp */
-extern void bgp_process(struct bgp *, struct bgp_dest *, afi_t, safi_t);
+extern void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *pi, afi_t afi, safi_t safi);
/*
* Add an end-of-initial-update marker to the process queue. This is just a
@@ -845,10 +849,10 @@ extern void route_vty_out(struct vty *vty, const struct prefix *p,
extern void route_vty_out_tag(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
safi_t safi, json_object *json);
-extern void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
- const struct prefix *p, struct attr *attr,
- safi_t safi, bool use_json, json_object *json_ar,
- bool wide);
+extern void route_vty_out_tmp(struct vty *vty, struct bgp *bgp,
+ struct bgp_dest *dest, const struct prefix *p,
+ struct attr *attr, safi_t safi, bool use_json,
+ json_object *json_ar, bool wide);
extern void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
json_object *json);
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 5d7a8b2ba1..0a852c75de 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -328,15 +328,16 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp,
}
if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv &&
adj->adv->baa) {
- route_vty_out_tmp(
- vty, dest, dest_p, adj->adv->baa->attr,
- SUBGRP_SAFI(subgrp), 0, NULL, false);
+ route_vty_out_tmp(vty, bgp, dest, dest_p,
+ adj->adv->baa->attr,
+ SUBGRP_SAFI(subgrp), 0, NULL,
+ false);
output_count++;
}
if ((flags & UPDWALK_FLAGS_ADVERTISED) && adj->attr) {
- route_vty_out_tmp(vty, dest, dest_p, adj->attr,
- SUBGRP_SAFI(subgrp), 0, NULL,
- false);
+ route_vty_out_tmp(vty, bgp, dest, dest_p,
+ adj->attr, SUBGRP_SAFI(subgrp),
+ 0, NULL, false);
output_count++;
}
}
diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c
index 8fe24ebe20..2470fb8844 100644
--- a/bgpd/bgp_vpn.c
+++ b/bgpd/bgp_vpn.c
@@ -191,7 +191,7 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
}
rd_header = 0;
}
- route_vty_out_tmp(vty, rm, bgp_dest_get_prefix(rm),
+ route_vty_out_tmp(vty, bgp, rm, bgp_dest_get_prefix(rm),
attr, safi, use_json, json_routes,
false);
output_count++;
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index bcd029dcad..9faba65a58 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -3035,14 +3035,17 @@ DEFUN (bgp_graceful_restart,
VTY_DECLVAR_CONTEXT(bgp, bgp);
ret = bgp_gr_update_all(bgp, GLOBAL_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
- ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("[BGP_GR] bgp_graceful_restart_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
+
return bgp_vty_return(vty, ret);
}
@@ -3062,14 +3065,16 @@ DEFUN (no_bgp_graceful_restart,
int ret = BGP_GR_FAILURE;
ret = bgp_gr_update_all(bgp, NO_GLOBAL_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
- ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("[BGP_GR] no_bgp_graceful_restart_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3277,24 +3282,25 @@ DEFUN (bgp_graceful_restart_disable,
VTY_DECLVAR_CONTEXT(bgp, bgp);
ret = bgp_gr_update_all(bgp, GLOBAL_DISABLE_CMD);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
- bgp->peer, ret);
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_UNSET);
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_LLGR,
+ CAPABILITY_ACTION_UNSET);
+ }
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] bgp_graceful_restart_disable_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
-
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
- CAPABILITY_CODE_RESTART,
- CAPABILITY_ACTION_UNSET);
- bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
- CAPABILITY_CODE_LLGR,
- CAPABILITY_ACTION_UNSET);
- }
+ zlog_debug("[BGP_GR] bgp_graceful_restart_disable_cmd : END ");
return bgp_vty_return(vty, ret);
}
@@ -3316,15 +3322,17 @@ DEFUN (no_bgp_graceful_restart_disable,
int ret = BGP_GR_FAILURE;
ret = bgp_gr_update_all(bgp, NO_GLOBAL_DISABLE_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
- ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_graceful_restart_disable_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3352,15 +3360,16 @@ DEFUN (bgp_neighbor_graceful_restart_set,
return CMD_WARNING_CONFIG_FAILED;
ret = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] bgp_neighbor_graceful_restart_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3389,15 +3398,16 @@ DEFUN (no_bgp_neighbor_graceful_restart,
"[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : START ");
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3427,15 +3437,16 @@ DEFUN (bgp_neighbor_graceful_restart_helper_set,
ret = bgp_neighbor_graceful_restart(peer, PEER_HELPER_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] bgp_neighbor_graceful_restart_helper_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3464,15 +3475,16 @@ DEFUN (no_bgp_neighbor_graceful_restart_helper,
"[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : START ");
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_HELPER_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3500,18 +3512,19 @@ DEFUN (bgp_neighbor_graceful_restart_disable_set,
return CMD_WARNING_CONFIG_FAILED;
ret = bgp_neighbor_graceful_restart(peer, PEER_DISABLE_CMD);
+ if (ret == BGP_GR_SUCCESS) {
+ if (peer->bgp->t_startup)
+ bgp_peer_gr_flags_update(peer);
- if (peer->bgp->t_startup)
- bgp_peer_gr_flags_update(peer);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR]bgp_neighbor_graceful_restart_disable_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3540,15 +3553,16 @@ DEFUN (no_bgp_neighbor_graceful_restart_disable,
"[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : START ");
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_DISABLE_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -4340,6 +4354,9 @@ DEFUN (bgp_network_import_check,
return CMD_SUCCESS;
}
+#if CONFDATE > 20241013
+CPP_NOTICE("Drop `bgp network import-check exact` command")
+#endif
ALIAS_HIDDEN(bgp_network_import_check, bgp_network_import_check_exact_cmd,
"bgp network import-check exact",
BGP_STR
@@ -10738,7 +10755,10 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
if (rm_p->prefixlen == match.prefixlen) {
SET_FLAG(rm->flags,
BGP_NODE_USER_CLEAR);
- bgp_process(bgp, rm, afi, safi);
+ bgp_process(bgp, rm,
+ bgp_dest_get_bgp_path_info(
+ rm),
+ afi, safi);
}
bgp_dest_unlock_node(rm);
}
@@ -10750,7 +10770,9 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
if (dest_p->prefixlen == match.prefixlen) {
SET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest,
+ bgp_dest_get_bgp_path_info(dest),
+ afi, safi);
}
bgp_dest_unlock_node(dest);
}
@@ -21187,6 +21209,15 @@ void bgp_vty_init(void)
install_element(BGP_VPNV6_NODE,
&neighbor_maximum_prefix_threshold_restart_cmd);
install_element(BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_EVPN_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_EVPN_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_maximum_prefix_cmd);
/* "neighbor allowas-in" */
install_element(BGP_NODE, &neighbor_allowas_in_hidden_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index dbba1dc71a..9a81965773 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1782,7 +1782,7 @@ static void bgp_handle_route_announcements_to_zebra(struct event *e)
table = bgp_dest_table(dest);
install = CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
- if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
+ if (table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
is_evpn = true;
if (BGP_DEBUG(zebra, ZEBRA))
@@ -2154,7 +2154,7 @@ bool bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red,
bgp_path_info_set_flag(dest, pi,
BGP_PATH_ATTR_CHANGED);
- bgp_process(bgp, dest, afi, SAFI_UNICAST);
+ bgp_process(bgp, dest, pi, afi, SAFI_UNICAST);
}
}
}
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index d98df754ef..5fd4ebe8cc 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -1377,7 +1377,7 @@ int bgp_global_gr_init(struct bgp *bgp)
/*GLOBAL_GR_cmd */ /*no_Global_GR_cmd*/
GLOBAL_GR, GLOBAL_INVALID,
/*GLOBAL_DISABLE_cmd*//*no_Global_Disable_cmd*/
- GLOBAL_INVALID, GLOBAL_HELPER
+ GLOBAL_DISABLE, GLOBAL_HELPER
},
/* GLOBAL_INVALID Mode */
{
@@ -1411,13 +1411,13 @@ int bgp_peer_gr_init(struct peer *peer)
/* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
{PEER_DISABLE, bgp_peer_gr_action }, {PEER_INVALID, NULL },
/* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
- { PEER_INVALID, NULL }, {PEER_GLOBAL_INHERIT,
+ { PEER_HELPER, NULL }, {PEER_GLOBAL_INHERIT,
bgp_peer_gr_action }
},
{
/* PEER_GR Mode */
/* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
- { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT,
+ { PEER_GR, NULL }, { PEER_GLOBAL_INHERIT,
bgp_peer_gr_action },
/* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
{PEER_DISABLE, bgp_peer_gr_action }, { PEER_INVALID, NULL },
@@ -1429,7 +1429,7 @@ int bgp_peer_gr_init(struct peer *peer)
/* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
{ PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL },
/* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
- { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT,
+ { PEER_DISABLE, NULL }, { PEER_GLOBAL_INHERIT,
bgp_peer_gr_action },
/* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
{ PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL }
@@ -1853,21 +1853,31 @@ void bgp_peer_conf_if_to_su_update(struct peer_connection *connection)
void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi, safi_t safi)
{
struct bgp_dest *dest, *ndest;
+ struct bgp_path_info *pi, *next;
struct bgp_table *table;
for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
- if (table != NULL) {
- /* Special handling for 2-level routing
- * tables. */
- if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
- || safi == SAFI_EVPN) {
- for (ndest = bgp_table_top(table); ndest;
- ndest = bgp_route_next(ndest))
- bgp_process(bgp, ndest, afi, safi);
- } else
- bgp_process(bgp, dest, afi, safi);
+
+ if (!table)
+ continue;
+
+ /* Special handling for 2-level routing
+ * tables. */
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
+ || safi == SAFI_EVPN) {
+ for (ndest = bgp_table_top(table); ndest;
+ ndest = bgp_route_next(ndest)) {
+ for (pi = bgp_dest_get_bgp_path_info(ndest);
+ (pi != NULL) && (next = pi->next, 1);
+ pi = next)
+ bgp_process(bgp, ndest, pi, afi, safi);
+ }
+ } else {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next)
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
}
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index 382af05c24..ae899daf82 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -463,7 +463,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, bpi, afi, safi);
} else {
vnc_zlog_debug_verbose(
"%s: Couldn't find route (safi=%d) at prefix %pFX",
@@ -1001,7 +1001,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
/* Process change. */
bgp_aggregate_increment(bgp, p, bpi, afi, safi);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, bpi, afi, safi);
bgp_dest_unlock_node(bn);
vnc_zlog_debug_any(
@@ -1046,7 +1046,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
}
bgp_dest_unlock_node(bn);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, new, afi, safi);
vnc_zlog_debug_any(
"%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRDP)",
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 4619fec6a7..68ae796bc9 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -425,6 +425,11 @@ Route Selection
Disabled by default.
+.. clicmd:: bgp bestpath med missing-as-worst
+
+ If the paths MED value is missing and this command is configured
+ then treat it as the worse possible value that it can be.
+
.. clicmd:: maximum-paths (1-128)
Sets the maximum-paths value used for ecmp calculations for this
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 36986a19c5..294c03def1 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -2908,7 +2908,7 @@ static void show_isis_route_common(struct vty *vty, int levels,
struct isis_spftree *spftree;
struct listnode *node;
struct isis_area *area;
- char key[8];
+ char key[18];
if (!isis->area_list || isis->area_list->count == 0)
return;
diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c
index be1042f260..229e0a4db8 100644
--- a/ospf6d/ospf6_gr_helper.c
+++ b/ospf6d/ospf6_gr_helper.c
@@ -938,15 +938,6 @@ static void show_ospf6_gr_helper_details(struct vty *vty, struct ospf6 *ospf6,
? "Enabled"
: "Disabled");
-#if CONFDATE > 20240401
- CPP_NOTICE("Remove deprecated json key: restartSupoort")
-#endif
- json_object_string_add(
- json, "restartSupoort",
- (ospf6->ospf6_helper_cfg.only_planned_restart)
- ? "Planned Restart only"
- : "Planned and Unplanned Restarts");
-
json_object_string_add(
json, "restartSupport",
(ospf6->ospf6_helper_cfg.only_planned_restart)
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index e26fe6f53a..198309c1ef 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -2740,9 +2740,9 @@ static void show_sr_node(struct vty *vty, struct json_object *json,
if (srn->algo[i] == SR_ALGORITHM_UNSET)
continue;
json_obj = json_object_new_object();
- char tmp[2];
+ char tmp[12];
- snprintf(tmp, sizeof(tmp), "%u", i);
+ snprintf(tmp, sizeof(tmp), "%d", i);
json_object_string_add(json_obj, tmp,
srn->algo[i] == SR_ALGORITHM_SPF
? "SPF"
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index bf131ff225..b366b3ca30 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -10446,15 +10446,6 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf,
json_object_string_add(json_vrf, "strictLsaCheck",
(ospf->strict_lsa_check) ? "Enabled"
: "Disabled");
-#if CONFDATE > 20240401
- CPP_NOTICE("Remove deprecated json key: restartSupoort")
-#endif
- json_object_string_add(
- json_vrf, "restartSupoort",
- (ospf->only_planned_restart)
- ? "Planned Restart only"
- : "Planned and Unplanned Restarts");
-
json_object_string_add(
json_vrf, "restartSupport",
(ospf->only_planned_restart)
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref
index 80c727c7e7..eb4e51a074 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref
@@ -1,5 +1,5 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref
index 6a837f5ae7..8fe3ea41a6 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref
@@ -1,5 +1,5 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref
index cc3c098518..67b907131c 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref
@@ -1,6 +1,6 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
Default local pref 100, local AS 100
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref
index 9b6f2f1c94..4f21a5711b 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref
@@ -1,5 +1,5 @@
BGP table version is 1, local router ID is 192.168.0.1
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref
index 5fe04bfa23..69e44e77ed 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref
@@ -1,5 +1,5 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref
index c4469d2230..77aab38b0d 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref
@@ -1,5 +1,5 @@
BGP table version is 1, local router ID is 192.168.0.1
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref
index 6ca07ec01d..a99400a6b0 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref
@@ -1,6 +1,6 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
Default local pref 100, local AS 100
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/__init__.py b/tests/topotests/bgp_evpn_maximum_prefix/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/__init__.py
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf
new file mode 100644
index 0000000000..7476a3723d
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf
@@ -0,0 +1,4 @@
+!
+int c1-eth0
+ ip address 192.168.0.1/24
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf
new file mode 100644
index 0000000000..a203daae05
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf
@@ -0,0 +1,4 @@
+!
+int c2-eth0
+ ip address 192.168.0.2/24
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf
new file mode 100644
index 0000000000..0534518cfb
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf
@@ -0,0 +1,30 @@
+!
+!debug bgp neighbor
+!debug route-map detail
+!
+vni 10
+!
+int lo
+ ip address 10.10.10.1/32
+!
+int r1-eth1
+ ip address 192.168.1.1/24
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ network 10.10.10.10/32
+ exit-address-family
+ !
+ address-family l2vpn evpn
+ neighbor 192.168.1.2 activate
+ advertise-all-vni
+ advertise ipv4 unicast
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf
new file mode 100644
index 0000000000..353302b9e7
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf
@@ -0,0 +1,25 @@
+!
+!debug bgp neighbor
+!
+int lo
+ ip address 10.10.10.2/32
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ !
+ address-family l2vpn evpn
+ neighbor 192.168.1.1 activate
+ neighbor 192.168.1.1 maximum-prefix 2
+ advertise-all-vni
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py b/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py
new file mode 100644
index 0000000000..5469eff144
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import re
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("c1", "r1"), "s2": ("r1", "r2"), "s3": ("r2", "c2")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ tgen.net["r1"].cmd(
+ """
+ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.10.10.1 nolearning
+ip link add name br10 type bridge
+ip link set dev vxlan10 master br10
+ip link set dev r1-eth0 master br10
+ip link set up dev br10
+ip link set up dev vxlan10"""
+ )
+
+ tgen.net["r2"].cmd(
+ """
+ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.10.10.2 nolearning
+ip link add name br10 type bridge
+ip link set dev vxlan10 master br10
+ip link set dev r2-eth1 master br10
+ip link set up dev br10
+ip link set up dev vxlan10"""
+ )
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_evpn_maximum_prefix():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show bgp l2vpn evpn summary failed json"))
+ expected = {
+ "peers": {
+ "192.168.1.1": {
+ "lastNotificationReason": "Cease/Maximum Number of Prefixes Reached",
+ "lastResetDueTo": "BGP Notification send",
+ }
+ },
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assert result is None, "Can't limit maximum-prefixes for EVPN routes"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf b/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf
index 33b6d08aba..d246517898 100644
--- a/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65101
+ timers bgp 3 10
bgp router-id 192.168.100.13
no bgp ebgp-requires-policy
neighbor 192.168.50.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf b/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf
index 428998b0fe..6855a436d4 100644
--- a/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65101
+ timers bgp 3 10
bgp router-id 192.168.100.14
no bgp ebgp-requires-policy
neighbor 192.168.61.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/spine1/evpn.conf b/tests/topotests/bgp_evpn_mh/spine1/evpn.conf
index b9fce46ea4..7d6fef699d 100644
--- a/tests/topotests/bgp_evpn_mh/spine1/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/spine1/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65001
+ timers bgp 3 10
bgp router-id 192.168.100.13
no bgp ebgp-requires-policy
neighbor 192.168.50.2 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/spine2/evpn.conf b/tests/topotests/bgp_evpn_mh/spine2/evpn.conf
index 1430e10b68..c651ada686 100644
--- a/tests/topotests/bgp_evpn_mh/spine2/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/spine2/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65001
+ timers bgp 3 10
bgp router-id 192.168.100.14
no bgp ebgp-requires-policy
neighbor 192.168.60.2 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/torm11/evpn.conf b/tests/topotests/bgp_evpn_mh/torm11/evpn.conf
index 2c1c695a18..62b7ec5855 100644
--- a/tests/topotests/bgp_evpn_mh/torm11/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm11/evpn.conf
@@ -7,6 +7,7 @@ frr defaults datacenter
!
!
router bgp 65002
+ timers bgp 3 10
bgp router-id 192.168.100.15
no bgp ebgp-requires-policy
neighbor 192.168.1.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/torm12/evpn.conf b/tests/topotests/bgp_evpn_mh/torm12/evpn.conf
index 8b0ce1d98f..3ceb974c47 100644
--- a/tests/topotests/bgp_evpn_mh/torm12/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm12/evpn.conf
@@ -7,6 +7,7 @@ frr defaults datacenter
!
!
router bgp 65003
+ timers bgp 3 10
bgp router-id 192.168.100.16
no bgp ebgp-requires-policy
neighbor 192.168.2.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/torm21/evpn.conf b/tests/topotests/bgp_evpn_mh/torm21/evpn.conf
index 5247dc1ebd..ecaf85ddb7 100644
--- a/tests/topotests/bgp_evpn_mh/torm21/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm21/evpn.conf
@@ -7,6 +7,7 @@ frr defaults datacenter
!
!
router bgp 65004
+ timers bgp 3 10
bgp router-id 192.168.100.17
no bgp ebgp-requires-policy
neighbor 192.168.3.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/torm22/evpn.conf b/tests/topotests/bgp_evpn_mh/torm22/evpn.conf
index ec56360176..c7e152498c 100644
--- a/tests/topotests/bgp_evpn_mh/torm22/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm22/evpn.conf
@@ -6,6 +6,7 @@ frr defaults datacenter
! debug bgp zebra
!
router bgp 65005
+ timers bgp 3 10
bgp router-id 192.168.100.18
no bgp ebgp-requires-policy
neighbor 192.168.4.1 remote-as external
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
index f0950a2db3..45c1325917 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
@@ -49,7 +49,7 @@ from lib.ospf import (
verify_ospf_interface,
)
-pytestmark = [pytest.mark.ospfd, pytest.mark.staticd]
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd, pytest.mark.staticd]
# Global variables
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index f092fc5c85..dde4704936 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1550,7 +1550,7 @@ static ssize_t fill_seg6ipt_encap(char *buffer, size_t buflen,
srh->first_segment = segs->num_segs - 1;
for (i = 0; i < segs->num_segs; i++) {
- memcpy(&srh->segments[i], &segs->seg[i],
+ memcpy(&srh->segments[segs->num_segs - i - 1], &segs->seg[i],
sizeof(struct in6_addr));
}
diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c
index 04eac63d3e..ae6232a1bb 100644
--- a/zebra/zebra_nb_config.c
+++ b/zebra/zebra_nb_config.c
@@ -3187,6 +3187,7 @@ int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create(
strlcpy(dnssl.name, yang_dnode_get_string(args->dnode, "domain"),
sizeof(dnssl.name));
ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
+ dnssl.encoded_len = ret;
if (args->event == NB_EV_VALIDATE) {
if (ret < 0) {
diff --git a/zebra/zebra_neigh.c b/zebra/zebra_neigh.c
index 941088afd6..a222e7f6e8 100644
--- a/zebra/zebra_neigh.c
+++ b/zebra/zebra_neigh.c
@@ -83,7 +83,7 @@ zebra_neigh_new(ifindex_t ifindex, struct ipaddr *ip, struct ethaddr *mac)
n->ifindex = ifindex;
if (mac) {
memcpy(&n->mac, mac, sizeof(*mac));
- n->flags |= ZEBRA_NEIGH_ENT_ACTIVE;
+ SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE);
}
/* Add to rb_tree */
@@ -118,10 +118,8 @@ static void zebra_neigh_free(struct zebra_neigh_ent *n)
/* if rules are still using the neigh mark it as inactive and
* update the dataplane
*/
- if (n->flags & ZEBRA_NEIGH_ENT_ACTIVE) {
- n->flags &= ~ZEBRA_NEIGH_ENT_ACTIVE;
- memset(&n->mac, 0, sizeof(n->mac));
- }
+ UNSET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE);
+ memset(&n->mac, 0, sizeof(n->mac));
zebra_neigh_pbr_rules_update(n);
return;
}
@@ -181,7 +179,7 @@ void zebra_neigh_add(struct interface *ifp, struct ipaddr *ip,
return;
memcpy(&n->mac, mac, sizeof(*mac));
- n->flags |= ZEBRA_NEIGH_ENT_ACTIVE;
+ SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE);
/* update rules linked to the neigh */
zebra_neigh_pbr_rules_update(n);
@@ -201,7 +199,7 @@ void zebra_neigh_deref(struct zebra_pbr_rule *rule)
rule->action.neigh = NULL;
/* remove rule from the list and free if it is inactive */
list_delete_node(n->pbr_rule_list, &rule->action.neigh_listnode);
- if (!(n->flags & ZEBRA_NEIGH_ENT_ACTIVE))
+ if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE))
zebra_neigh_free(n);
}
diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c
index 1af3a3e857..4cee3b89f1 100644
--- a/zebra/zebra_netns_id.c
+++ b/zebra/zebra_netns_id.c
@@ -42,7 +42,7 @@
#define NETLINK_SOCKET_BUFFER_SIZE 512
#define NETLINK_ALIGNTO 4
#define NETLINK_ALIGN(len) \
- (((len) + NETLINK_ALIGNTO - 1) & ~(NETLINK_ALIGNTO - 1))
+ CHECK_FLAG(((len) + NETLINK_ALIGNTO - 1), ~(NETLINK_ALIGNTO - 1))
#define NETLINK_NLATTR_LEN(_a, _b) (unsigned int)((char *)_a - (char *)_b)
#endif /* defined(HAVE_NETLINK) */
@@ -66,7 +66,7 @@ static struct nlmsghdr *initiate_nlh(char *buf, unsigned int *seq, int type)
nlh->nlmsg_type = type;
nlh->nlmsg_flags = NLM_F_REQUEST;
if (type == RTM_NEWNSID)
- nlh->nlmsg_flags |= NLM_F_ACK;
+ SET_FLAG(nlh->nlmsg_flags, NLM_F_ACK);
nlh->nlmsg_seq = *seq = frr_sequence32_next();
return nlh;
}
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index 1bb1292e34..617a2225f8 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -304,7 +304,7 @@ static void zebra_ns_notify_read(struct event *t)
char *netnspath;
struct zebra_netns_info *netnsinfo;
- if (!(event->mask & (IN_CREATE | IN_DELETE)))
+ if (!CHECK_FLAG(event->mask, (IN_CREATE | IN_DELETE)))
continue;
if (offsetof(struct inotify_event, name) + event->len
@@ -350,7 +350,7 @@ static void zebra_ns_notify_read(struct event *t)
memcpy(event_name, event->name, event->len);
event_name[event->len - 1] = 0;
- if (event->mask & IN_DELETE) {
+ if (CHECK_FLAG(event->mask, IN_DELETE)) {
zebra_ns_delete(event_name);
continue;
}
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 934b8ba0db..ff97a11c17 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -1795,8 +1795,8 @@ static struct nexthop *nexthop_set_resolved(afi_t afi,
break;
}
- if (newhop->flags & NEXTHOP_FLAG_ONLINK)
- resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
+ if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_ONLINK))
+ SET_FLAG(resolved_hop->flags, NEXTHOP_FLAG_ONLINK);
/* Copy labels of the resolved route and the parent resolving to it */
if (policy) {