summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-12-24 08:33:45 +0100
committerDaniel Baumann <daniel@debian.org>2024-12-24 08:33:45 +0100
commit97216bc8112f1169e29e8450a0d406b1868a283e (patch)
tree697ed0dabc4e825248a98b855cc15bf021a08a71 /bgpd
parentReleasing debian version 10.2-2. (diff)
downloadfrr-97216bc8112f1169e29e8450a0d406b1868a283e.tar.xz
frr-97216bc8112f1169e29e8450a0d406b1868a283e.zip
Merging upstream version 10.2.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_bmp.c5
-rw-r--r--bgpd/bgp_evpn.c44
-rw-r--r--bgpd/bgp_evpn.h1
-rw-r--r--bgpd/bgp_flowspec_vty.c2
-rw-r--r--bgpd/bgp_fsm.c106
-rw-r--r--bgpd/bgp_mplsvpn.c6
-rw-r--r--bgpd/bgp_route.c102
-rw-r--r--bgpd/bgp_rpki.c170
-rw-r--r--bgpd/bgp_vty.c61
-rw-r--r--bgpd/bgp_zebra.c7
-rw-r--r--bgpd/bgpd.c22
-rw-r--r--bgpd/bgpd.h1
12 files changed, 270 insertions, 257 deletions
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 7b67d4b8..9605c3a8 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -2434,8 +2434,11 @@ DEFPY(bmp_connect,
}
ba = bmp_active_get(bt, hostname, port);
- if (srcif)
+ if (srcif) {
+ if (ba->ifsrc)
+ XFREE(MTYPE_TMP, ba->ifsrc);
ba->ifsrc = XSTRDUP(MTYPE_TMP, srcif);
+ }
if (min_retry_str)
ba->minretry = min_retry;
if (max_retry_str)
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 0a8ce615..13483190 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -5112,6 +5112,33 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
}
/*
+ * In cases such as 'no advertise-all-vni' and L2 VNI DELETE, we need to
+ * pop all the VPN routes present in the bgp_zebra_announce FIFO yet to
+ * be processed regardless of VNI is configured or not.
+ *
+ * NOTE: NO need to pop the VPN routes in two cases
+ * 1) In free_vni_entry
+ * - Called by bgp_free()->bgp_evpn_cleanup().
+ * - Since bgp_delete is called before bgp_free and we pop all the dest
+ * pertaining to bgp under delete.
+ * 2) evpn_delete_vni() when user configures "no vni" since the withdraw
+ * of all routes happen in normal cycle.
+ */
+void bgp_zebra_evpn_pop_items_from_announce_fifo(struct bgpevpn *vpn)
+{
+ struct bgp_dest *dest = NULL;
+ struct bgp_dest *dest_next = NULL;
+
+ for (dest = zebra_announce_first(&bm->zebra_announce_head); dest; dest = dest_next) {
+ dest_next = zebra_announce_next(&bm->zebra_announce_head, dest);
+ if (dest->za_vpn == vpn) {
+ zebra_announce_del(&bm->zebra_announce_head, dest);
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_dest_unlock_node(dest);
+ }
+ }
+}
+/*
* Cleanup specific VNI upon EVPN (advertise-all-vni) being disabled.
*/
static void cleanup_vni_on_disable(struct hash_bucket *bucket, struct bgp *bgp)
@@ -5123,6 +5150,8 @@ static void cleanup_vni_on_disable(struct hash_bucket *bucket, struct bgp *bgp)
/* Clear "live" flag and see if hash needs to be freed. */
UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE);
+ /* Pop items from bgp_zebra_announce FIFO for any VPN routes pending*/
+ bgp_zebra_evpn_pop_items_from_announce_fifo(vpn);
if (!is_vni_configured(vpn))
bgp_evpn_free(bgp, vpn);
}
@@ -6354,19 +6383,6 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
*/
void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn)
{
- struct bgp_dest *dest = NULL;
- struct bgp_dest *dest_next = NULL;
-
- for (dest = zebra_announce_first(&bm->zebra_announce_head); dest;
- dest = dest_next) {
- dest_next = zebra_announce_next(&bm->zebra_announce_head, dest);
- if (dest->za_vpn == vpn) {
- zebra_announce_del(&bm->zebra_announce_head, dest);
- bgp_path_info_unlock(dest->za_bgp_pi);
- bgp_dest_unlock_node(dest);
- }
- }
-
bgp_evpn_remote_ip_hash_destroy(vpn);
bgp_evpn_vni_es_cleanup(vpn);
bgpevpn_unlink_from_l3vni(vpn);
@@ -7047,6 +7063,8 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
/* Clear "live" flag and see if hash needs to be freed. */
UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE);
+ /* Pop items from bgp_zebra_announce FIFO for any VPN routes pending*/
+ bgp_zebra_evpn_pop_items_from_announce_fifo(vpn);
if (!is_vni_configured(vpn))
bgp_evpn_free(bgp, vpn);
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index 10eff1dc..1a333a5a 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -199,4 +199,5 @@ bool bgp_evpn_skip_vrf_import_of_local_es(struct bgp *bgp_vrf, const struct pref
struct bgp_path_info *pi, int install);
int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, const struct prefix_evpn *evp,
struct bgp_path_info *parent_pi);
+extern void bgp_zebra_evpn_pop_items_from_announce_fifo(struct bgpevpn *vpn);
#endif /* _QUAGGA_BGP_EVPN_H */
diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c
index d4ccca84..3d2dda4e 100644
--- a/bgpd/bgp_flowspec_vty.c
+++ b/bgpd/bgp_flowspec_vty.c
@@ -441,7 +441,7 @@ int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi,
}
if (total_count && !use_json)
vty_out(vty,
- "\nDisplayed %ld flowspec entries\n",
+ "\nDisplayed %ld flowspec entries\n",
total_count);
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 94fca23e..ac33e8a6 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -661,7 +661,7 @@ static void bgp_llgr_stale_timer_expire(struct event *thread)
static void bgp_set_llgr_stale(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;
struct attr attr;
@@ -676,8 +676,8 @@ static void bgp_set_llgr_stale(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;
@@ -708,8 +708,8 @@ static void bgp_set_llgr_stale(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;
@@ -2724,33 +2724,55 @@ static void bgp_gr_update_mode_of_all_peers(struct bgp *bgp,
struct listnode *node = {0};
struct listnode *nnode = {0};
enum peer_mode peer_old_state = PEER_INVALID;
-
- /* TODO: Need to handle peer-groups. */
+ struct peer_group *group;
+ struct peer *member;
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- peer_old_state = bgp_peer_gr_mode_get(peer);
- if (peer_old_state != PEER_GLOBAL_INHERIT)
- continue;
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ peer_old_state = bgp_peer_gr_mode_get(peer);
+ if (peer_old_state != PEER_GLOBAL_INHERIT)
+ continue;
- bgp_peer_inherit_global_gr_mode(peer, global_new_state);
- bgp_peer_gr_flags_update(peer);
+ bgp_peer_inherit_global_gr_mode(peer, global_new_state);
+ bgp_peer_gr_flags_update(peer);
- if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug("%pBP: Inherited Global GR mode, GR flags 0x%x peer flags 0x%" PRIx64
- "...resetting session",
- peer, peer->peer_gr_new_status_flag,
- peer->flags);
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug("%pBP: Inherited Global GR mode, GR flags 0x%x peer flags 0x%" PRIx64
+ "...resetting session",
+ peer, peer->peer_gr_new_status_flag, peer->flags);
- peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+ peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
- /* Reset session to match with behavior for other peer
- * configs that require the session to be re-setup.
- */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
- bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- else
- bgp_session_reset_safe(peer, &nnode);
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
+ bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ else
+ bgp_session_reset_safe(peer, &nnode);
+ } else {
+ group = peer->group;
+ for (ALL_LIST_ELEMENTS(group->peer, node, nnode, member)) {
+ peer_old_state = bgp_peer_gr_mode_get(member);
+ if (peer_old_state != PEER_GLOBAL_INHERIT)
+ continue;
+
+ bgp_peer_inherit_global_gr_mode(member, global_new_state);
+ bgp_peer_gr_flags_update(member);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug("%pBP: Inherited Global GR mode, GR flags 0x%x peer flags 0x%" PRIx64
+ "...resetting session",
+ member, member->peer_gr_new_status_flag,
+ member->flags);
+
+ member->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status))
+ bgp_notify_send(member->connection, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ else
+ bgp_session_reset(member);
+ }
+ }
}
}
@@ -2936,6 +2958,9 @@ unsigned int bgp_peer_gr_action(struct peer *peer, enum peer_mode old_state,
{
enum global_mode global_gr_mode;
bool session_reset = true;
+ struct peer_group *group;
+ struct peer *member;
+ struct listnode *node, *nnode;
if (old_state == new_state)
return BGP_GR_NO_OPERATION;
@@ -2970,16 +2995,27 @@ unsigned int bgp_peer_gr_action(struct peer *peer, enum peer_mode old_state,
bgp_peer_move_to_gr_mode(peer, new_state);
if (session_reset) {
- peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
- /* Reset session to match with behavior for other peer
- * configs that require the session to be re-setup.
- */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
- bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- else
- bgp_session_reset(peer);
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status))
+ bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ else
+ bgp_session_reset(peer);
+ } else {
+ group = peer->group;
+ for (ALL_LIST_ELEMENTS(group->peer, node, nnode, member)) {
+ member->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+ bgp_peer_move_to_gr_mode(member, new_state);
+
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status))
+ bgp_notify_send(member->connection, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ else
+ bgp_session_reset(member);
+ }
+ }
}
return BGP_GR_SUCCESS;
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index df45cf23..5eca5e3e 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -2158,6 +2158,8 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
struct interface *ifp = NULL;
char rd_buf[RD_ADDRSTRLEN];
struct aspath *new_aspath;
+ int32_t aspath_loop_count = 0;
+ struct peer *peer = path_vpn->peer;
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
@@ -2218,7 +2220,9 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, NULL);
/* Check if leaked route has our asn. If so, don't import it. */
- if (aspath_loop_check(path_vpn->attr->aspath, to_bgp->as)) {
+ if (CHECK_FLAG(peer->af_flags[afi][SAFI_MPLS_VPN], PEER_FLAG_ALLOWAS_IN))
+ aspath_loop_count = peer->allowas_in[afi][SAFI_MPLS_VPN];
+ if (aspath_loop_check(path_vpn->attr->aspath, to_bgp->as) > aspath_loop_count) {
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
bpi = bpi->next) {
if (bpi->extra && bpi->extra->vrfleak &&
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 619252b0..0124b12c 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2960,7 +2960,10 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
old_select = NULL;
pi = bgp_dest_get_bgp_path_info(dest);
- while (pi && CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED)) {
+ while (pi && (CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED) ||
+ (pi->peer != bgp->peer_self &&
+ !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT) &&
+ !peer_established(pi->peer->connection)))) {
struct bgp_path_info *next = pi->next;
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
@@ -3054,6 +3057,30 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
continue;
}
+ if (first->peer && first->peer != bgp->peer_self &&
+ !CHECK_FLAG(first->peer->sflags, PEER_STATUS_NSF_WAIT) &&
+ !peer_established(first->peer->connection)) {
+ if (debug)
+ zlog_debug("%s: %pBD(%s) pi %p from %s is not in established state",
+ __func__, dest, bgp->name_pretty, first,
+ first->peer->host);
+
+ /*
+ * Peer is not in established state we cannot sort this
+ * item yet. Let's wait, so hold this one 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;
+ }
+
bgp_path_info_unset_flag(dest, first, BGP_PATH_DMED_CHECK);
worse = NULL;
@@ -4406,7 +4433,7 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
uint8_t type, uint8_t stype, struct attr *attr,
struct bgp_dest *dest)
{
- bool ret = false;
+ bool nh_invalid = false;
bool is_bgp_static_route =
(type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
: false;
@@ -4428,13 +4455,15 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
(safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
return false;
- /* If NEXT_HOP is present, validate it. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
- if (attr->nexthop.s_addr == INADDR_ANY ||
- !ipv4_unicast_valid(&attr->nexthop) ||
- bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
- return true;
- }
+ /* If NEXT_HOP is present, validate it:
+ * The route can have both nexthop + mp_nexthop encoded as multiple NLRIs,
+ * and we MUST check if at least one of them is valid.
+ * E.g.: IPv6 prefix can be with nexthop: 0.0.0.0, and mp_nexthop: fc00::1.
+ */
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)))
+ nh_invalid = (attr->nexthop.s_addr == INADDR_ANY ||
+ !ipv4_unicast_valid(&attr->nexthop) ||
+ bgp_nexthop_self(bgp, afi, type, stype, attr, dest));
/* If MP_NEXTHOP is present, validate it. */
/* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
@@ -4449,39 +4478,31 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
switch (attr->mp_nexthop_len) {
case BGP_ATTR_NHLEN_IPV4:
case BGP_ATTR_NHLEN_VPNV4:
- ret = (attr->mp_nexthop_global_in.s_addr ==
- INADDR_ANY ||
- !ipv4_unicast_valid(
- &attr->mp_nexthop_global_in) ||
- bgp_nexthop_self(bgp, afi, type, stype, attr,
- dest));
+ nh_invalid = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY ||
+ !ipv4_unicast_valid(&attr->mp_nexthop_global_in) ||
+ bgp_nexthop_self(bgp, afi, type, stype, attr, dest));
break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
- ret = (IN6_IS_ADDR_UNSPECIFIED(
- &attr->mp_nexthop_global)
- || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
- || IN6_IS_ADDR_MULTICAST(
- &attr->mp_nexthop_global)
- || bgp_nexthop_self(bgp, afi, type, stype, attr,
- dest));
+ nh_invalid = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global) ||
+ IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global) ||
+ IN6_IS_ADDR_MULTICAST(&attr->mp_nexthop_global) ||
+ bgp_nexthop_self(bgp, afi, type, stype, attr, dest));
break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
- ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
- || IN6_IS_ADDR_MULTICAST(
- &attr->mp_nexthop_global)
- || bgp_nexthop_self(bgp, afi, type, stype, attr,
- dest));
+ nh_invalid = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global) ||
+ IN6_IS_ADDR_MULTICAST(&attr->mp_nexthop_global) ||
+ bgp_nexthop_self(bgp, afi, type, stype, attr, dest));
break;
default:
- ret = true;
+ nh_invalid = true;
break;
}
}
- return ret;
+ return nh_invalid;
}
static void bgp_attr_add_no_export_community(struct attr *attr)
@@ -7411,7 +7432,7 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
{
struct bgp_table *table;
struct bgp_dest *dest;
- struct bgp_path_info *pi;
+ struct bgp_path_info *pi, *next;
/* Do not install the aggregate route if BGP is in the
* process of termination.
@@ -7422,7 +7443,8 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
table = bgp->rib[afi][safi];
for (dest = bgp_table_top(table); 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 == bgp->peer_self
&& ((pi->type == ZEBRA_ROUTE_BGP
&& pi->sub_type == BGP_ROUTE_STATIC)
@@ -7922,7 +7944,7 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
struct bgp_table *table = bgp->rib[afi][safi];
const struct prefix *dest_p;
struct bgp_dest *dest, *top;
- struct bgp_path_info *pi;
+ struct bgp_path_info *pi, *next;
/* We've found a different MED we must revert any suppressed routes. */
top = bgp_node_get(table, p);
@@ -7932,7 +7954,8 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
if (dest_p->prefixlen <= p->prefixlen)
continue;
- 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 (BGP_PATH_HOLDDOWN(pi))
continue;
if (pi->sub_type == BGP_ROUTE_AGGREGATE)
@@ -8007,7 +8030,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
struct community *community = NULL;
struct ecommunity *ecommunity = NULL;
struct lcommunity *lcommunity = NULL;
- struct bgp_path_info *pi;
+ struct bgp_path_info *pi, *next;
uint8_t atomic_aggregate = 0;
/* If the bgp instance is being deleted or self peer is deleted
@@ -8057,7 +8080,8 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (!bgp_check_advertise(bgp, dest, safi))
continue;
- 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 (BGP_PATH_HOLDDOWN(pi))
continue;
@@ -8215,7 +8239,7 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
struct bgp_table *table;
struct bgp_dest *top;
struct bgp_dest *dest;
- struct bgp_path_info *pi;
+ struct bgp_path_info *pi, *next;
table = bgp->rib[afi][safi];
@@ -8228,7 +8252,8 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (dest_p->prefixlen <= p->prefixlen)
continue;
- 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 (BGP_PATH_HOLDDOWN(pi))
continue;
@@ -12321,8 +12346,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
} else {
if (incremental_print) {
vty_out(vty, "\"prefix\": \"%pFX\",\n", p);
- vty_out(vty, "\"version\": \"%" PRIu64 "\",",
- dest->version);
+ vty_out(vty, "\"version\": %" PRIu64 ",", dest->version);
} else {
json_object_string_addf(json, "prefix", "%pFX",
p);
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 347c5d02..04a709b3 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -155,7 +155,6 @@ static enum route_map_cmd_result_t route_match(void *rule,
void *object);
static void *route_match_compile(const char *arg);
static void revalidate_bgp_node(struct bgp_dest *dest, afi_t afi, safi_t safi);
-static void revalidate_all_routes(struct rpki_vrf *rpki_vrf);
static bool rpki_debug_conf, rpki_debug_term;
@@ -586,48 +585,10 @@ static void rpki_revalidate_prefix(struct event *thread)
XFREE(MTYPE_BGP_RPKI_REVALIDATE, rrp);
}
-static void bgpd_sync_callback(struct event *thread)
+static void revalidate_single_prefix(struct vrf *vrf, struct prefix prefix, afi_t afi)
{
struct bgp *bgp;
struct listnode *node;
- struct prefix prefix;
- struct pfx_record rec;
- struct rpki_vrf *rpki_vrf = EVENT_ARG(thread);
- struct vrf *vrf = NULL;
-
- event_add_read(bm->master, bgpd_sync_callback, rpki_vrf,
- rpki_vrf->rpki_sync_socket_bgpd, NULL);
-
- if (atomic_load_explicit(&rpki_vrf->rtr_update_overflow,
- memory_order_seq_cst)) {
- while (read(rpki_vrf->rpki_sync_socket_bgpd, &rec,
- sizeof(struct pfx_record)) != -1)
- ;
-
- atomic_store_explicit(&rpki_vrf->rtr_update_overflow, 0,
- memory_order_seq_cst);
- revalidate_all_routes(rpki_vrf);
- return;
- }
-
- int retval = read(rpki_vrf->rpki_sync_socket_bgpd, &rec,
- sizeof(struct pfx_record));
- if (retval != sizeof(struct pfx_record)) {
- RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
- return;
- }
- pfx_record_to_prefix(&rec, &prefix);
-
- afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
-
- if (rpki_vrf->vrfname) {
- vrf = vrf_lookup_by_name(rpki_vrf->vrfname);
- if (!vrf) {
- zlog_err("%s(): vrf for rpki %s not found", __func__,
- rpki_vrf->vrfname);
- return;
- }
- }
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
safi_t safi;
@@ -655,101 +616,76 @@ static void bgpd_sync_callback(struct event *thread)
}
}
-static void revalidate_bgp_node(struct bgp_dest *bgp_dest, afi_t afi,
- safi_t safi)
+static void bgpd_sync_callback(struct event *thread)
{
- struct bgp_adj_in *ain;
- mpls_label_t *label;
- uint8_t num_labels;
-
- for (ain = bgp_dest->adj_in; ain; ain = ain->next) {
- struct bgp_path_info *path =
- bgp_dest_get_bgp_path_info(bgp_dest);
-
- num_labels = BGP_PATH_INFO_NUM_LABELS(path);
- label = num_labels ? path->extra->labels->label : NULL;
-
- (void)bgp_update(ain->peer, bgp_dest_get_prefix(bgp_dest),
- ain->addpath_rx_id, ain->attr, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label,
- num_labels, 1, NULL);
- }
-}
-
-/*
- * The act of a soft reconfig in revalidation is really expensive
- * coupled with the fact that the download of a full rpki state
- * from a rpki server can be expensive, let's break up the revalidation
- * to a point in time in the future to allow other bgp events
- * to take place too.
- */
-struct rpki_revalidate_peer {
+ struct prefix prefix;
+ struct pfx_record rec;
+ struct rpki_vrf *rpki_vrf = EVENT_ARG(thread);
+ struct vrf *vrf = NULL;
afi_t afi;
- safi_t safi;
- struct peer *peer;
-};
+ int retval;
-static void bgp_rpki_revalidate_peer(struct event *thread)
-{
- struct rpki_revalidate_peer *rvp = EVENT_ARG(thread);
-
- /*
- * Here's the expensive bit of gnomish deviousness
- */
- bgp_soft_reconfig_in(rvp->peer, rvp->afi, rvp->safi);
-
- XFREE(MTYPE_BGP_RPKI_REVALIDATE, rvp);
-}
-
-static void revalidate_all_routes(struct rpki_vrf *rpki_vrf)
-{
- struct bgp *bgp;
- struct listnode *node;
- struct vrf *vrf = NULL;
+ event_add_read(bm->master, bgpd_sync_callback, rpki_vrf, rpki_vrf->rpki_sync_socket_bgpd,
+ NULL);
if (rpki_vrf->vrfname) {
vrf = vrf_lookup_by_name(rpki_vrf->vrfname);
if (!vrf) {
- zlog_err("%s(): vrf for rpki %s not found", __func__,
- rpki_vrf->vrfname);
+ zlog_err("%s(): vrf for rpki %s not found", __func__, rpki_vrf->vrfname);
return;
}
}
- for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
- struct peer *peer;
- struct listnode *peer_listnode;
+ if (atomic_load_explicit(&rpki_vrf->rtr_update_overflow, memory_order_seq_cst)) {
+ ssize_t size = 0;
- if (!vrf && bgp->vrf_id != VRF_DEFAULT)
- continue;
- if (vrf && bgp->vrf_id != vrf->vrf_id)
- continue;
+ retval = read(rpki_vrf->rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
+ while (retval != -1) {
+ if (retval != sizeof(struct pfx_record))
+ break;
- for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
- afi_t afi;
- safi_t safi;
+ size += retval;
+ pfx_record_to_prefix(&rec, &prefix);
+ afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
+ revalidate_single_prefix(vrf, prefix, afi);
- FOREACH_AFI_SAFI (afi, safi) {
- struct rpki_revalidate_peer *rvp;
+ retval = read(rpki_vrf->rpki_sync_socket_bgpd, &rec,
+ sizeof(struct pfx_record));
+ }
- if (!bgp->rib[afi][safi])
- continue;
+ RPKI_DEBUG("Socket overflow detected (%zu), revalidating affected prefixes", size);
- if (!peer_established(peer->connection))
- continue;
+ atomic_store_explicit(&rpki_vrf->rtr_update_overflow, 0, memory_order_seq_cst);
+ return;
+ }
- rvp = XCALLOC(MTYPE_BGP_RPKI_REVALIDATE,
- sizeof(*rvp));
- rvp->peer = peer;
- rvp->afi = afi;
- rvp->safi = safi;
+ retval = read(rpki_vrf->rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
+ if (retval != sizeof(struct pfx_record)) {
+ RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
+ return;
+ }
+ pfx_record_to_prefix(&rec, &prefix);
- event_add_event(
- bm->master, bgp_rpki_revalidate_peer,
- rvp, 0,
- &peer->t_revalidate_all[afi][safi]);
- }
- }
+ afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
+
+ revalidate_single_prefix(vrf, prefix, afi);
+}
+
+static void revalidate_bgp_node(struct bgp_dest *bgp_dest, afi_t afi, safi_t safi)
+{
+ struct bgp_adj_in *ain;
+ mpls_label_t *label;
+ uint8_t num_labels;
+
+ for (ain = bgp_dest->adj_in; ain; ain = ain->next) {
+ struct bgp_path_info *path = bgp_dest_get_bgp_path_info(bgp_dest);
+
+ num_labels = BGP_PATH_INFO_NUM_LABELS(path);
+ label = num_labels ? path->extra->labels->label : NULL;
+
+ (void)bgp_update(ain->peer, bgp_dest_get_prefix(bgp_dest), ain->addpath_rx_id,
+ ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
+ label, num_labels, 1, NULL);
}
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 68ced14d..0f963175 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -3517,11 +3517,6 @@ DEFUN (bgp_neighbor_graceful_restart_set,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- vty_out(vty,
- "Per peer-group graceful-restart configuration is not yet supported\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
result = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD);
if (result == BGP_GR_SUCCESS) {
@@ -3552,11 +3547,6 @@ DEFUN (no_bgp_neighbor_graceful_restart,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- vty_out(vty,
- "Per peer-group graceful-restart configuration is not yet supported\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
result = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD);
if (ret == BGP_GR_SUCCESS) {
@@ -3586,11 +3576,6 @@ DEFUN (bgp_neighbor_graceful_restart_helper_set,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- vty_out(vty,
- "Per peer-group graceful-restart configuration is not yet supported\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
ret = bgp_neighbor_graceful_restart(peer, PEER_HELPER_CMD);
if (ret == BGP_GR_SUCCESS) {
@@ -3621,11 +3606,6 @@ DEFUN (no_bgp_neighbor_graceful_restart_helper,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- vty_out(vty,
- "Per peer-group graceful-restart configuration is not yet supported\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_HELPER_CMD);
if (ret == BGP_GR_SUCCESS) {
@@ -3655,11 +3635,6 @@ DEFUN (bgp_neighbor_graceful_restart_disable_set,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- vty_out(vty,
- "Per peer-group graceful-restart configuration is not yet supported\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
ret = bgp_neighbor_graceful_restart(peer, PEER_DISABLE_CMD);
if (ret == BGP_GR_SUCCESS) {
@@ -3691,11 +3666,6 @@ DEFUN (no_bgp_neighbor_graceful_restart_disable,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- vty_out(vty,
- "Per peer-group graceful-restart configuration is not yet supported\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_DISABLE_CMD);
if (ret == BGP_GR_SUCCESS) {
@@ -5273,7 +5243,7 @@ DEFUN (neighbor_peer_group,
DEFUN (no_neighbor,
no_neighbor_cmd,
- "no neighbor <WORD|<A.B.C.D|X:X::X:X> [remote-as <(1-4294967295)|internal|external|auto>]>",
+ "no neighbor <WORD|<A.B.C.D|X:X::X:X> [remote-as <ASNUM|internal|external|auto>]>",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
@@ -5352,7 +5322,7 @@ DEFUN (no_neighbor,
DEFUN (no_neighbor_interface_config,
no_neighbor_interface_config_cmd,
- "no neighbor WORD interface [v6only] [peer-group PGNAME] [remote-as <(1-4294967295)|internal|external|auto>]",
+ "no neighbor WORD interface [v6only] [peer-group PGNAME] [remote-as <ASNUM|internal|external|auto>]",
NO_STR
NEIGHBOR_STR
"Interface name\n"
@@ -9846,6 +9816,8 @@ DEFPY (af_rd_vpn_export,
bgp_get_default(), bgp);
if (yes) {
+ if (bgp->vpn_policy[afi].tovpn_rd_pretty)
+ XFREE(MTYPE_BGP_NAME, bgp->vpn_policy[afi].tovpn_rd_pretty);
bgp->vpn_policy[afi].tovpn_rd_pretty = XSTRDUP(MTYPE_BGP_NAME,
rd_str);
bgp->vpn_policy[afi].tovpn_rd = prd;
@@ -14935,22 +14907,31 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) ||
CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV)) {
if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV) &&
- CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV))
+ CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)) {
json_object_string_add(
json_cap, "gracefulRestart",
"advertisedAndReceived");
- else if (CHECK_FLAG(p->cap,
- PEER_CAP_RESTART_ADV))
+ } else if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV)) {
+ json_object_string_add(json_cap, "gracefulRestart",
+ "advertised");
+#if CONFDATE > 20250525
+CPP_NOTICE("Remove `gracefulRestartCapability` JSON field")
+#endif
json_object_string_add(
json_cap,
"gracefulRestartCapability",
"advertised");
- else if (CHECK_FLAG(p->cap,
- PEER_CAP_RESTART_RCV))
+ } else if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)) {
+ json_object_string_add(json_cap, "gracefulRestart",
+ "received");
+#if CONFDATE > 20250525
+CPP_NOTICE("Remove `gracefulRestartCapability` JSON field")
+#endif
json_object_string_add(
json_cap,
"gracefulRestartCapability",
"received");
+ }
if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)) {
int restart_af_count = 0;
@@ -18831,7 +18812,11 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
/* enforce-first-as */
if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS)) {
- if (!peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
+ /* The `no` form is printed because by default this enforcing
+ * is enabled, thus we need to print it inverted.
+ * See peer_new().
+ */
+ if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
vty_out(vty, " no neighbor %s enforce-first-as\n", addr);
} else {
if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 9053df31..64994715 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1187,9 +1187,10 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
ifindex =
pi->peer->nexthop.ifp->ifindex;
if (!ifindex) {
- if (pi->peer->conf_if)
- ifindex = pi->peer->ifp->ifindex;
- else if (pi->peer->ifname)
+ if (pi->peer->conf_if) {
+ if (pi->peer->ifp)
+ ifindex = pi->peer->ifp->ifindex;
+ } else if (pi->peer->ifname)
ifindex = ifname2ifindex(
pi->peer->ifname,
pi->peer->bgp->vrf_id);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 58183818..80e70219 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -462,6 +462,10 @@ void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set)
if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
return;
+ /* Do nothing if already in a desired state */
+ if (set == !!CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING))
+ return;
+
if (set) {
SET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING);
/* Send msg to zebra for the first instance of bgp enabled
@@ -1251,8 +1255,6 @@ static void peer_free(struct peer *peer)
bgp_reads_off(peer->connection);
bgp_writes_off(peer->connection);
event_cancel_event_ready(bm->master, peer->connection);
- FOREACH_AFI_SAFI (afi, safi)
- EVENT_OFF(peer->t_revalidate_all[afi][safi]);
assert(!peer->connection->t_write);
assert(!peer->connection->t_read);
@@ -1592,8 +1594,13 @@ struct peer *peer_new(struct bgp *bgp)
SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS))
- peer_flag_set(peer, PEER_FLAG_ENFORCE_FIRST_AS);
+ /* By default this is enabled, thus we need to mark it as
+ * inverted in order to display correctly in the configuration.
+ */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS)) {
+ SET_FLAG(peer->flags_invert, PEER_FLAG_ENFORCE_FIRST_AS);
+ SET_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS);
+ }
if (CHECK_FLAG(bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY))
peer_flag_set(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION);
@@ -2191,8 +2198,7 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,
/* When this peer is a member of peer-group. */
if (peer->group) {
/* peer-group already has AS number/internal/external */
- if (peer->group->conf->as
- || peer->group->conf->as_type) {
+ if (peer->group->conf->as || peer->group->conf->as_type != AS_UNSPECIFIED) {
/* Return peer group's AS number. */
*as = peer->group->conf->as;
return BGP_ERR_PEER_GROUP_MEMBER;
@@ -2720,8 +2726,6 @@ int peer_delete(struct peer *peer)
bgp_reads_off(peer->connection);
bgp_writes_off(peer->connection);
event_cancel_event_ready(bm->master, peer->connection);
- FOREACH_AFI_SAFI (afi, safi)
- EVENT_OFF(peer->t_revalidate_all[afi][safi]);
assert(!CHECK_FLAG(peer->connection->thread_flags,
PEER_THREAD_WRITES_ON));
assert(!CHECK_FLAG(peer->connection->thread_flags,
@@ -2902,6 +2906,7 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name);
group->conf->group = group;
group->conf->as = 0;
+ group->conf->as_type = AS_UNSPECIFIED;
group->conf->ttl = BGP_DEFAULT_TTL;
group->conf->gtsm_hops = BGP_GTSM_HOPS_DISABLED;
group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
@@ -3023,6 +3028,7 @@ static void peer_group2peer_config_copy(struct peer_group *group,
PEER_ATTR_INHERIT(peer, group, local_role);
/* Update GR flags for the peer. */
+ PEER_ATTR_INHERIT(peer, group, peer_gr_new_status_flag);
bgp_peer_gr_flags_update(peer);
/* Apply BFD settings from group to peer if it exists. */
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 8aeb0eb4..f9c4e7e9 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1646,7 +1646,6 @@ struct peer {
/* Threads. */
struct event *t_llgr_stale[AFI_MAX][SAFI_MAX];
- struct event *t_revalidate_all[AFI_MAX][SAFI_MAX];
struct event *t_refresh_stalepath;
/* Thread flags. */