summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-12-24 08:32:19 +0100
committerDaniel Baumann <daniel@debian.org>2024-12-24 08:32:19 +0100
commitd1f707efc3252786252b10e49a397d0461710e58 (patch)
treeaa2fc03aa522e5d8494fd6fae2a3fcb588815e3f
parentAdding upstream version 10.2. (diff)
downloadfrr-upstream.tar.xz
frr-upstream.zip
Adding upstream version 10.2.1.upstream/10.2.1upstream
Signed-off-by: Daniel Baumann <daniel@debian.org>
-rw-r--r--bfdd/dplane.c3
-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
-rw-r--r--configure.ac2
-rw-r--r--lib/bfd.c8
-rw-r--r--lib/plist.c4
-rw-r--r--lib/sockopt.c8
-rw-r--r--lib/sockopt.h4
-rw-r--r--lib/vty.c16
-rw-r--r--lib/vty.h3
-rw-r--r--ospfd/ospf_asbr.c70
-rw-r--r--ospfd/ospf_asbr.h4
-rw-r--r--ospfd/ospf_lsa.c7
-rw-r--r--ospfd/ospf_vty.c3
-rw-r--r--ospfd/ospf_zebra.c30
-rw-r--r--ospfd/ospf_zebra.h3
-rw-r--r--pimd/pim_autorp.c5
-rw-r--r--pimd/pim_iface.c3
-rw-r--r--pimd/pim_vty.c6
-rw-r--r--pimd/pimd.c2
-rw-r--r--redhat/frr.spec.in37
-rw-r--r--tests/topotests/bgp_peer_group/r1/bgpd.conf12
-rw-r--r--tests/topotests/bgp_peer_group/r1/frr.conf21
-rw-r--r--tests/topotests/bgp_peer_group/r1/zebra.conf9
-rw-r--r--tests/topotests/bgp_peer_group/r2/bgpd.conf11
-rw-r--r--tests/topotests/bgp_peer_group/r2/frr.conf19
-rw-r--r--tests/topotests/bgp_peer_group/r2/zebra.conf9
-rw-r--r--tests/topotests/bgp_peer_group/r3/frr.conf (renamed from tests/topotests/bgp_peer_group/r3/bgpd.conf)5
-rw-r--r--tests/topotests/bgp_peer_group/r3/zebra.conf6
-rw-r--r--tests/topotests/bgp_peer_group/test_bgp_peer-group.py41
-rw-r--r--vtysh/vtysh.c6
41 files changed, 524 insertions, 360 deletions
diff --git a/bfdd/dplane.c b/bfdd/dplane.c
index 7f55f340..b1a32fb1 100644
--- a/bfdd/dplane.c
+++ b/bfdd/dplane.c
@@ -948,6 +948,9 @@ static void bfd_dplane_client_connect(struct event *t)
_bfd_dplane_client_bootstrap(bdc);
}
+ /* Continue with the connection */
+ return;
+
reschedule_connect:
EVENT_OFF(bdc->inbufev);
EVENT_OFF(bdc->outbufev);
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. */
diff --git a/configure.ac b/configure.ac
index a177e5cd..8de5a9e6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
##
AC_PREREQ([2.69])
-AC_INIT([frr], [10.2], [https://github.com/frrouting/frr/issues])
+AC_INIT([frr], [10.2.1], [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
AC_SUBST([PACKAGE_URL])
PACKAGE_FULLNAME="FRRouting"
diff --git a/lib/bfd.c b/lib/bfd.c
index 4535fc12..bc4b1c5b 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -32,6 +32,8 @@ enum bfd_session_event {
BSE_UNINSTALL,
/** Install the BFD session configuration. */
BSE_INSTALL,
+ /** We should install but it couldn't because of a error talking to zebra */
+ BSE_VALID_FOR_INSTALL,
};
/**
@@ -527,6 +529,10 @@ static void _bfd_sess_send(struct event *t)
vrf_id_to_name(bsp->args.vrf_id), bsp->args.vrf_id,
bsp->lastev == BSE_INSTALL ? "installed"
: "uninstalled");
+
+ bsp->installed = false;
+ if (bsp->lastev == BSE_INSTALL)
+ bsp->lastev = BSE_VALID_FOR_INSTALL;
}
}
@@ -883,7 +889,7 @@ int zclient_bfd_session_replay(ZAPI_CALLBACK_ARGS)
/* Replay all activated peers. */
TAILQ_FOREACH (bsp, &bsglobal.bsplist, entry) {
/* Skip not installed sessions. */
- if (!bsp->installed)
+ if (!bsp->installed && bsp->lastev != BSE_VALID_FOR_INSTALL)
continue;
/* We are reconnecting, so we must send installation. */
diff --git a/lib/plist.c b/lib/plist.c
index 2cfaa7d8..6950ab57 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -1136,8 +1136,10 @@ static int vty_show_prefix_list_prefix(struct vty *vty, afi_t afi,
match = 0;
if (type == normal_display || type == first_match_display)
- if (prefix_same(&p, &pentry->prefix))
+ if (prefix_list_entry_match(pentry, &p, false)) {
+ pentry->hitcnt++;
match = 1;
+ }
if (type == longer_display) {
if ((p.family == pentry->prefix.family)
diff --git a/lib/sockopt.c b/lib/sockopt.c
index 74bc034c..003ddb72 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -19,7 +19,7 @@
#define HAVE_BSD_STRUCT_IP_MREQ_HACK
#endif
-void setsockopt_so_recvbuf(int sock, int size)
+int setsockopt_so_recvbuf(int sock, int size)
{
int orig_req = size;
@@ -34,9 +34,11 @@ void setsockopt_so_recvbuf(int sock, int size)
flog_err(EC_LIB_SOCKET,
"%s: fd %d: SO_RCVBUF set to %d (requested %d)",
__func__, sock, size, orig_req);
+
+ return size;
}
-void setsockopt_so_sendbuf(const int sock, int size)
+int setsockopt_so_sendbuf(const int sock, int size)
{
int orig_req = size;
@@ -51,6 +53,8 @@ void setsockopt_so_sendbuf(const int sock, int size)
flog_err(EC_LIB_SOCKET,
"%s: fd %d: SO_SNDBUF set to %d (requested %d)",
__func__, sock, size, orig_req);
+
+ return size;
}
int getsockopt_so_sendbuf(const int sock)
diff --git a/lib/sockopt.h b/lib/sockopt.h
index e6fb78d5..cbf988cb 100644
--- a/lib/sockopt.h
+++ b/lib/sockopt.h
@@ -12,8 +12,8 @@
extern "C" {
#endif
-extern void setsockopt_so_recvbuf(int sock, int size);
-extern void setsockopt_so_sendbuf(const int sock, int size);
+extern int setsockopt_so_recvbuf(int sock, int size);
+extern int setsockopt_so_sendbuf(const int sock, int size);
extern int getsockopt_so_sendbuf(const int sock);
extern int getsockopt_so_recvbuf(const int sock);
diff --git a/lib/vty.c b/lib/vty.c
index 256a3bb3..1d04e75b 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -43,6 +43,7 @@
#include "northbound_cli.h"
#include "printfrr.h"
#include "json.h"
+#include "sockopt.h"
#include <arpa/telnet.h>
#include <termios.h>
@@ -352,7 +353,7 @@ int vty_out(struct vty *vty, const char *format, ...)
* put the data of collective vty->obuf Linked List items on the
* socket and free the vty->obuf data.
*/
- if (vty->vty_buf_size_accumulated >= VTY_MAX_INTERMEDIATE_FLUSH) {
+ if (vty->vty_buf_size_accumulated >= vty->buf_size_intermediate) {
vty->vty_buf_size_accumulated = 0;
vtysh_flush(vty);
}
@@ -2157,15 +2158,15 @@ static void vtysh_accept(struct event *thread)
* Increasing the SEND socket buffer size so that the socket can hold
* before sending it to VTY shell.
*/
- ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbufsize,
- sizeof(sndbufsize));
- if (ret < 0) {
+ ret = setsockopt_so_sendbuf(sock, sndbufsize);
+ if (ret <= 0) {
flog_err(EC_LIB_SOCKET,
"Cannot set socket %d send buffer size, %s", sock,
safe_strerror(errno));
close(sock);
return;
}
+
set_cloexec(sock);
#ifdef VTYSH_DEBUG
@@ -2173,6 +2174,13 @@ static void vtysh_accept(struct event *thread)
#endif /* VTYSH_DEBUG */
vty = vty_new();
+
+ vty->buf_size_set = ret;
+ if (vty->buf_size_set < VTY_MAX_INTERMEDIATE_FLUSH)
+ vty->buf_size_intermediate = vty->buf_size_set / 2;
+ else
+ vty->buf_size_intermediate = VTY_MAX_INTERMEDIATE_FLUSH;
+
vty->fd = sock;
vty->wfd = sock;
vty->type = VTY_SHELL_SERV;
diff --git a/lib/vty.h b/lib/vty.h
index e511e8e7..be54159a 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -237,6 +237,9 @@ struct vty {
bool mgmt_locked_candidate_ds;
bool mgmt_locked_running_ds;
uint64_t vty_buf_size_accumulated;
+
+ int buf_size_set;
+ uint64_t buf_size_intermediate;
};
static inline void vty_push_context(struct vty *vty, int node, uint64_t id)
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
index b47c3900..738ac6d8 100644
--- a/ospfd/ospf_asbr.c
+++ b/ospfd/ospf_asbr.c
@@ -168,6 +168,38 @@ void ospf_external_info_delete(struct ospf *ospf, uint8_t type,
}
}
+/*
+ * ospf_external_info_delete_multi_instance
+ *
+ * Delete instances of the external route information for a given route type.
+ * The preserve_instance parameter may be used to prevent the current instance
+ * from being deleted.
+ */
+void ospf_external_info_delete_multi_instance(struct ospf *ospf, uint8_t type, struct prefix_ipv4 p,
+ unsigned long preserve_instance)
+{
+ struct route_node *rn;
+ struct ospf_external *ext;
+ struct list *ext_list;
+ struct listnode *node;
+
+ ext_list = ospf->external[type];
+ if (!ext_list)
+ return;
+
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+ if (ext->instance != preserve_instance) {
+ rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p);
+ if (rn) {
+ ospf_external_info_free(rn->info);
+ rn->info = NULL;
+ route_unlock_node(rn);
+ route_unlock_node(rn);
+ }
+ }
+ }
+}
+
struct external_info *ospf_external_info_lookup(struct ospf *ospf, uint8_t type,
unsigned short instance,
struct prefix_ipv4 *p)
@@ -189,6 +221,44 @@ struct external_info *ospf_external_info_lookup(struct ospf *ospf, uint8_t type,
return NULL;
}
+/*
+ * ospf_external_info_default_lookup
+ *
+ * For default information criteria, we really don't care about the
+ * source of the route and there only should be one.
+ */
+struct external_info *ospf_external_info_default_lookup(struct ospf *ospf)
+{
+ struct ospf_external *ext;
+ struct external_info *ei;
+ struct list *ext_list;
+ struct listnode *node;
+ struct route_node *rn;
+ struct prefix_ipv4 p = {
+ .family = AF_INET,
+ .prefixlen = 0,
+ .prefix.s_addr = INADDR_ANY,
+ };
+
+ ext_list = ospf->external[DEFAULT_ROUTE];
+ if (!ext_list)
+ return (NULL);
+
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+ rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p);
+ if (rn) {
+ route_unlock_node(rn);
+ if (rn->info) {
+ ei = rn->info;
+ if (ei->type != ZEBRA_ROUTE_OSPF || ei->instance != ospf->instance)
+ return ei;
+ }
+ }
+ }
+
+ return NULL;
+}
+
struct ospf_lsa *ospf_external_info_find_lsa(struct ospf *ospf,
struct prefix_ipv4 *p)
{
diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h
index 6158d65f..648a5a11 100644
--- a/ospfd/ospf_asbr.h
+++ b/ospfd/ospf_asbr.h
@@ -109,6 +109,10 @@ ospf_external_info_add(struct ospf *, uint8_t, unsigned short,
route_tag_t, uint32_t metric);
extern void ospf_external_info_delete(struct ospf *, uint8_t, unsigned short,
struct prefix_ipv4);
+extern void ospf_external_info_delete_multi_instance(struct ospf *ospf, uint8_t type,
+ struct prefix_ipv4 p,
+ unsigned long preserve_instance);
+#define OSPF_DELETE_ANY_INSTANCE 0xffffffff
extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t,
unsigned short,
struct prefix_ipv4 *);
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index f125fa93..e04dad85 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -2396,15 +2396,10 @@ struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area,
static struct external_info *ospf_default_external_info(struct ospf *ospf)
{
int type;
- struct prefix_ipv4 p;
struct external_info *default_ei;
int ret = 0;
- p.family = AF_INET;
- p.prefix.s_addr = 0;
- p.prefixlen = 0;
-
- default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, 0, &p);
+ default_ei = ospf_external_info_default_lookup(ospf);
if (!default_ei)
return NULL;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 4e1c0838..ccc46424 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -7368,6 +7368,9 @@ DEFPY (show_ip_ospf_database,
struct in_addr *adv_router_p = NULL;
json_object *json = NULL;
+ if (instance_id != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
if (uj)
json = json_object_new_object();
if (lsid_str)
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index c7cba1e2..b718d498 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -1292,15 +1292,14 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
* originate)ZEBRA_ROUTE_MAX is used to delete the ex-info.
* Resolved this inconsistency by maintaining same route type.
*/
- if ((is_default_prefix(&pgen)) && (api.type != ZEBRA_ROUTE_OSPF))
+ if ((is_default_prefix(&pgen)) &&
+ ((api.type != ZEBRA_ROUTE_OSPF) || (api.instance != ospf->instance)))
rt_type = DEFAULT_ROUTE;
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
- zlog_debug("%s: cmd %s from client %s: vrf %s(%u), p %pFX, metric %d",
- __func__, zserv_command_string(cmd),
- zebra_route_string(api.type),
- ospf_vrf_id_to_name(vrf_id), vrf_id, &api.prefix,
- api.metric);
+ zlog_debug("%s: cmd %s from client %s-%d: vrf %s(%u), p %pFX, metric %d", __func__,
+ zserv_command_string(cmd), zebra_route_string(api.type), api.instance,
+ ospf_vrf_id_to_name(vrf_id), vrf_id, &api.prefix, api.metric);
if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
/* XXX|HACK|TODO|FIXME:
@@ -1315,16 +1314,17 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
api.tag = ospf->dtag[rt_type];
/*
- * Given zebra sends update for a prefix via ADD message, it
- * should
- * be considered as an implicit DEL for that prefix with other
- * source
- * types.
+ * Given zebra sends an update for a prefix via an ADD message, it
+ * will be considered as an impilict DELETE for that prefix for other
+ * types and instances other than the type and instance associated with
+ * the prefix.
*/
- for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
- if (i != rt_type)
- ospf_external_info_delete(ospf, i, api.instance,
- p);
+ for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
+ unsigned long preserve_instance;
+
+ preserve_instance = (i == rt_type) ? api.instance : OSPF_DELETE_ANY_INSTANCE;
+ ospf_external_info_delete_multi_instance(ospf, i, p, preserve_instance);
+ }
ei = ospf_external_info_add(ospf, rt_type, api.instance, p,
ifindex, nexthop, api.tag,
diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h
index 86a5678f..b8352430 100644
--- a/ospfd/ospf_zebra.h
+++ b/ospfd/ospf_zebra.h
@@ -47,6 +47,9 @@ extern uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *,
struct ospf_route *);
extern struct ospf_external *ospf_external_lookup(struct ospf *, uint8_t,
unsigned short);
+
+extern struct external_info *ospf_external_info_default_lookup(struct ospf *ospf);
+
extern struct ospf_external *ospf_external_add(struct ospf *, uint8_t,
unsigned short);
diff --git a/pimd/pim_autorp.c b/pimd/pim_autorp.c
index df4f809b..a07bd4ab 100644
--- a/pimd/pim_autorp.c
+++ b/pimd/pim_autorp.c
@@ -1014,12 +1014,13 @@ void pim_autorp_init(struct pim_instance *pim)
autorp->announce_interval = DEFAULT_ANNOUNCE_INTERVAL;
autorp->announce_holdtime = DEFAULT_ANNOUNCE_HOLDTIME;
+ pim->autorp = autorp;
+
if (!pim_autorp_socket_enable(autorp)) {
- zlog_err("%s: AutoRP failed to initialize", __func__);
+ zlog_err("%s: AutoRP failed to initialize, feature will not work correctly", __func__);
return;
}
- pim->autorp = autorp;
if (PIM_DEBUG_AUTORP)
zlog_debug("%s: AutoRP Initialized", __func__);
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 20e3ba18..19460aa4 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -1464,8 +1464,7 @@ static void pim_if_gm_join_del_all(struct interface *ifp)
return;
for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node, nextnode, ij))
- pim_if_gm_join_del(ifp, ij->group_addr, ij->source_addr,
- GM_JOIN_STATIC);
+ pim_if_gm_join_del(ifp, ij->group_addr, ij->source_addr, ij->join_type);
}
ferr_r pim_if_static_group_add(struct interface *ifp, pim_addr group_addr,
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index b633e81d..bb620b7a 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -325,6 +325,9 @@ static int gm_config_write(struct vty *vty, int writes,
struct listnode *node;
struct gm_join *ij;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_join_list, node, ij)) {
+ if (ij->join_type == GM_JOIN_PROXY)
+ continue;
+
if (pim_addr_is_any(ij->source_addr))
vty_out(vty, " ip igmp join-group %pPAs\n",
&ij->group_addr);
@@ -395,6 +398,9 @@ static int gm_config_write(struct vty *vty, int writes,
struct gm_join *ij;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_join_list, node, ij)) {
+ if (ij->join_type == GM_JOIN_PROXY)
+ continue;
+
if (pim_addr_is_any(ij->source_addr))
vty_out(vty, " ipv6 mld join-group %pPAs\n",
&ij->group_addr);
diff --git a/pimd/pimd.c b/pimd/pimd.c
index db619748..1a9ef0ce 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -17,6 +17,7 @@
#include "vrf.h"
#include "lib_errors.h"
#include "bfd.h"
+#include "filter.h"
#include "pimd.h"
#if PIM_IPV == 4
@@ -143,6 +144,7 @@ void pim_terminate(void)
prefix_list_add_hook(NULL);
prefix_list_delete_hook(NULL);
prefix_list_reset();
+ access_list_reset();
pim_vxlan_terminate();
pim_vrf_terminate();
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 9286cb81..539cb9c4 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -834,7 +834,42 @@ sed -i 's/ -M rpki//' %{_sysconfdir}/frr/daemons
%changelog
-* Tue Nov 12 2024 Jafar Al-Gharaibeh <jafar@atcorp.com> - %{version}
+* Mon Dec 23 2024 Donatas Abraitis <donatas@opensourcerouting.org> - %{version}
+
+* Mon Dec 23 2024 Donatas Abraitis <donatas@opensourcerouting.org> - 10.2.1
+- bfdd
+- retain remote dplane client socket
+- bgpd
+- Fix to pop items off zebra_announce FIFO for few EVPN triggers
+- Check if as_type is not specified when peer is a peer-group member
+- Do not reset peers on suppress-fib toggling
+- Fix bgp core with a possible Intf delete
+- Fix `enforce-first-as` per peer-group removal
+- Fix evpn bestpath calculation when path is not established
+- Fix graceful-restart for peer-groups
+- Fix memory leak when creating BMP connection with a source interface
+- Fix memory leak when reconfiguring a route distinguisher
+- Fix unconfigure asdot neighbor
+- Fix use single whitespace when displaying flowspec entries
+- Fix version attribute is an int, not a string
+- Import allowed routes with self AS if desired
+- Initialize as_type for peer-group as AS_UNSPECIFIED
+- Use gracefulRestart JSON field
+- Validate both nexthop information (NEXTHOP and NLRI)
+- Validate only affected RPKI prefixes instead of a full RIB
+- When calling bgp_process, prevent infinite loop
+- lib
+- Allow setsockopt functions to return size set
+- Fix session re-establishment
+- Take ge/le into consideration when checking the prefix with the prefix-list
+- Use backoff setsockopt option for freebsd
+- ospfd
+- OSPF multi-instance default origination fixes
+- pimd
+- Fix access-list memory leak in pimd
+- Free igmp proxy joins on interface deletion
+- igmp proxy joins should not be written as part of config
+- Prevent crash of pim when auto-rp's socket is not initialized
* Tue Nov 12 2024 Jafar Al-Gharaibeh <jafar@atcorp.com> - 10.2
- PIM candidate BSR/RP [#16438]
diff --git a/tests/topotests/bgp_peer_group/r1/bgpd.conf b/tests/topotests/bgp_peer_group/r1/bgpd.conf
deleted file mode 100644
index 68d8e61a..00000000
--- a/tests/topotests/bgp_peer_group/r1/bgpd.conf
+++ /dev/null
@@ -1,12 +0,0 @@
-!
-router bgp 65001
- neighbor PG peer-group
- neighbor PG remote-as external
- neighbor PG timers 3 10
- neighbor 192.168.255.3 peer-group PG
- neighbor r1-eth0 interface peer-group PG
- neighbor PG1 peer-group
- neighbor PG1 remote-as external
- neighbor PG1 timers 3 20
- neighbor 192.168.251.2 peer-group PG1
-!
diff --git a/tests/topotests/bgp_peer_group/r1/frr.conf b/tests/topotests/bgp_peer_group/r1/frr.conf
new file mode 100644
index 00000000..035c8e4c
--- /dev/null
+++ b/tests/topotests/bgp_peer_group/r1/frr.conf
@@ -0,0 +1,21 @@
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
+interface r1-eth1
+ ip address 192.168.251.1/30
+!
+ip forwarding
+!
+router bgp 65001
+ neighbor PG peer-group
+ neighbor PG remote-as external
+ neighbor PG timers 3 10
+ neighbor 192.168.255.3 peer-group PG
+ neighbor r1-eth0 interface peer-group PG
+ neighbor PG1 peer-group
+ neighbor PG1 remote-as external
+ neighbor PG1 timers 3 20
+ neighbor PG1 graceful-restart-disable
+ neighbor 192.168.251.2 peer-group PG1
+!
diff --git a/tests/topotests/bgp_peer_group/r1/zebra.conf b/tests/topotests/bgp_peer_group/r1/zebra.conf
deleted file mode 100644
index 16fd8c53..00000000
--- a/tests/topotests/bgp_peer_group/r1/zebra.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-!
-interface r1-eth0
- ip address 192.168.255.1/24
-!
-interface r1-eth1
- ip address 192.168.251.1/30
-!
-ip forwarding
-!
diff --git a/tests/topotests/bgp_peer_group/r2/bgpd.conf b/tests/topotests/bgp_peer_group/r2/bgpd.conf
deleted file mode 100644
index d0e8f017..00000000
--- a/tests/topotests/bgp_peer_group/r2/bgpd.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-!
-router bgp 65002
- neighbor PG peer-group
- neighbor PG remote-as external
- neighbor PG timers 3 10
- neighbor r2-eth0 interface peer-group PG
- neighbor PG1 peer-group
- neighbor PG1 remote-as external
- neighbor PG1 timers 3 20
- neighbor 192.168.251.1 peer-group PG1
-!
diff --git a/tests/topotests/bgp_peer_group/r2/frr.conf b/tests/topotests/bgp_peer_group/r2/frr.conf
new file mode 100644
index 00000000..4713789f
--- /dev/null
+++ b/tests/topotests/bgp_peer_group/r2/frr.conf
@@ -0,0 +1,19 @@
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
+interface r2-eth1
+ ip address 192.168.251.2/30
+!
+ip forwarding
+!
+router bgp 65002
+ neighbor PG peer-group
+ neighbor PG remote-as external
+ neighbor PG timers 3 10
+ neighbor r2-eth0 interface peer-group PG
+ neighbor PG1 peer-group
+ neighbor PG1 remote-as external
+ neighbor PG1 timers 3 20
+ neighbor 192.168.251.1 peer-group PG1
+!
diff --git a/tests/topotests/bgp_peer_group/r2/zebra.conf b/tests/topotests/bgp_peer_group/r2/zebra.conf
deleted file mode 100644
index c2ad956c..00000000
--- a/tests/topotests/bgp_peer_group/r2/zebra.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-!
-interface r2-eth0
- ip address 192.168.255.2/24
-!
-interface r2-eth1
- ip address 192.168.251.2/30
-!
-ip forwarding
-!
diff --git a/tests/topotests/bgp_peer_group/r3/bgpd.conf b/tests/topotests/bgp_peer_group/r3/frr.conf
index 5a1340fb..e8bffaab 100644
--- a/tests/topotests/bgp_peer_group/r3/bgpd.conf
+++ b/tests/topotests/bgp_peer_group/r3/frr.conf
@@ -1,4 +1,9 @@
!
+interface r3-eth0
+ ip address 192.168.255.3/24
+!
+ip forwarding
+!
router bgp 65003
no bgp ebgp-requires-policy
neighbor PG peer-group
diff --git a/tests/topotests/bgp_peer_group/r3/zebra.conf b/tests/topotests/bgp_peer_group/r3/zebra.conf
deleted file mode 100644
index e9fdfb70..00000000
--- a/tests/topotests/bgp_peer_group/r3/zebra.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-!
-interface r3-eth0
- ip address 192.168.255.3/24
-!
-ip forwarding
-!
diff --git a/tests/topotests/bgp_peer_group/test_bgp_peer-group.py b/tests/topotests/bgp_peer_group/test_bgp_peer-group.py
index 7d476b05..45f713b8 100644
--- a/tests/topotests/bgp_peer_group/test_bgp_peer-group.py
+++ b/tests/topotests/bgp_peer_group/test_bgp_peer-group.py
@@ -2,12 +2,14 @@
# SPDX-License-Identifier: ISC
#
-# Copyright (c) 2021 by
+# Copyright (c) 2021-2024 by
# Donatas Abraitis <donatas.abraitis@gmail.com>
+# Donatas Abraitis <donatas@opensourcerouting.org>
#
"""
-Test if peer-group works for numbered and unnumbered configurations.
+Test if various random settings with peer-group works for
+numbered and unnumbered configurations.
"""
import os
@@ -21,7 +23,7 @@ sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
from lib import topotest
-from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topogen import Topogen, get_topogen
from lib.topolog import logger
pytestmark = [pytest.mark.bgpd]
@@ -48,12 +50,7 @@ def setup_module(mod):
router_list = tgen.routers()
for _, (rname, router) in enumerate(router_list.items(), 1):
- router.load_config(
- TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
- )
- router.load_config(
- TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
- )
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
tgen.start_router()
@@ -72,14 +69,26 @@ def test_bgp_peer_group():
def _bgp_peer_group_configured():
output = json.loads(tgen.gears["r1"].vtysh_cmd("show ip bgp neighbor json"))
expected = {
- "r1-eth0": {"peerGroup": "PG", "bgpState": "Established"},
- "192.168.255.3": {"peerGroup": "PG", "bgpState": "Established"},
- "192.168.251.2": {"peerGroup": "PG1", "bgpState": "Established"},
+ "r1-eth0": {
+ "peerGroup": "PG",
+ "bgpState": "Established",
+ "neighborCapabilities": {"gracefulRestart": "advertisedAndReceived"},
+ },
+ "192.168.255.3": {
+ "peerGroup": "PG",
+ "bgpState": "Established",
+ "neighborCapabilities": {"gracefulRestart": "advertisedAndReceived"},
+ },
+ "192.168.251.2": {
+ "peerGroup": "PG1",
+ "bgpState": "Established",
+ "neighborCapabilities": {"gracefulRestart": "received"},
+ },
}
return topotest.json_cmp(output, expected)
test_func = functools.partial(_bgp_peer_group_configured)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert result is None, "Failed bgp convergence in r1"
def _bgp_peer_group_check_advertised_routes():
@@ -97,7 +106,7 @@ def test_bgp_peer_group():
return topotest.json_cmp(output, expected)
test_func = functools.partial(_bgp_peer_group_check_advertised_routes)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert result is None, "Failed checking advertised routes from r3"
@@ -122,7 +131,7 @@ def test_bgp_peer_group_remote_as_del_readd():
return topotest.json_cmp(output, expected)
test_func = functools.partial(_bgp_peer_group_remoteas_del)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert result is None, "Failed bgp convergence in r1"
logger.info("Re-add bgp peer-group PG1 remote-as neighbor should be established")
@@ -139,7 +148,7 @@ def test_bgp_peer_group_remote_as_del_readd():
return topotest.json_cmp(output, expected)
test_func = functools.partial(_bgp_peer_group_remoteas_add)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert result is None, "Failed bgp convergence in r1"
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 2d80feef..92f37f19 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -39,6 +39,7 @@
#include "frrstr.h"
#include "json.h"
#include "ferr.h"
+#include "sockopt.h"
DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy");
@@ -4694,9 +4695,8 @@ static int vtysh_connect(struct vtysh_client *vclient)
* Increasing the RECEIVE socket buffer size so that the socket can hold
* after receving from other process.
*/
- ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&rcvbufsize,
- sizeof(rcvbufsize));
- if (ret < 0) {
+ ret = setsockopt_so_recvbuf(sock, rcvbufsize);
+ if (ret <= 0) {
#ifdef DEBUG
fprintf(stderr, "Cannot set socket %d rcv buffer size, %s\n",
sock, safe_strerror(errno));