This commit is contained in:
Pooja Jagadeesh Doijode 2025-04-29 16:22:43 +00:00 committed by GitHub
commit c6a6dc7aaf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 926 additions and 937 deletions

View file

@ -186,6 +186,8 @@ static const struct message bgp_notify_fsm_msg[] = {
const char *const bgp_origin_str[] = {"i", "e", "?"};
const char *const bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"};
const char *const bgp_global_gr_mode_str[] = { "Helper", "Restarter", "Disabled", "Invalid" };
static void bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc,
struct prefix *p);
/* Given a string return a pointer the corresponding peer structure */

View file

@ -161,6 +161,7 @@ struct bgp_debug_filter {
#define CONF_BGP_DEBUG(a, b) (unlikely(conf_bgp_debug_##a & BGP_DEBUG_##b))
extern const char *const bgp_type_str[];
extern const char *const bgp_global_gr_mode_str[];
extern bool bgp_dump_attr(struct attr *attr, char *buf, size_t size);
extern bool bgp_debug_peer_updout_enabled(char *host);

View file

@ -852,12 +852,11 @@ static void bgp_graceful_deferral_timer_expire(struct event *thread)
"afi %d, safi %d : graceful restart deferral timer expired",
afi, safi);
bgp->gr_info[afi][safi].eor_required = 0;
bgp->gr_info[afi][safi].eor_received = 0;
bgp->gr_info[afi][safi].select_defer_over = true;
XFREE(MTYPE_TMP, info);
/* Best path selection */
bgp_best_path_select_defer(bgp, afi, safi);
bgp_do_deferred_path_selection(bgp, afi, safi);
}
static bool bgp_update_delay_applicable(struct bgp *bgp)
@ -1227,6 +1226,226 @@ static void bgp_update_delay_process_status_change(struct peer *peer)
}
}
static bool bgp_gr_check_all_eors(struct bgp *bgp, afi_t afi, safi_t safi)
{
struct listnode *node, *nnode;
struct peer *peer = NULL;
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("%s: Checking all peers for EOR receipt for %s", bgp->name_pretty,
get_afi_safi_str(afi, safi, false));
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("....examining peer %s status %s flags 0x%" PRIx64
" af_sflags 0x%x",
peer->host,
lookup_msg(bgp_status_msg, peer->connection->status, NULL),
peer->flags, peer->af_sflags[afi][safi]);
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) ||
CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN) ||
!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART))
continue;
if (!CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_GR_WAIT_EOR))
continue;
if (!CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED)) {
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(".... EOR still awaited from this peer for this %s",
get_afi_safi_str(afi, safi, false));
return false;
}
}
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(".... EOR received from all expected peers for this %s",
get_afi_safi_str(afi, safi, false));
return true;
}
void bgp_gr_check_path_select(struct bgp *bgp, afi_t afi, safi_t safi)
{
struct graceful_restart_info *gr_info;
if (bgp_gr_check_all_eors(bgp, afi, safi)) {
gr_info = &(bgp->gr_info[afi][safi]);
EVENT_OFF(gr_info->t_select_deferral);
gr_info->select_defer_over = true;
bgp_do_deferred_path_selection(bgp, afi, safi);
}
}
static void bgp_gr_mark_for_deferred_selection(struct bgp *bgp)
{
struct listnode *node, *nnode;
struct peer *peer;
afi_t afi;
safi_t safi;
/*
* Mark all peers in the instance for EOR wait for the
* AFI/SAFI supported for GR.
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
FOREACH_AFI_SAFI_NSF (afi, safi) {
if (bgp_gr_supported_for_afi_safi(afi, safi))
SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_GR_WAIT_EOR);
else
UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_GR_WAIT_EOR);
}
}
}
/*
* Start the selection deferral timer thread for the specified AFI, SAFI,
* mark peers from whom we need an EOR and inform zebra
*/
static void bgp_start_deferral_timer(struct bgp *bgp, afi_t afi, safi_t safi,
struct graceful_restart_info *gr_info)
{
struct afi_safi_info *thread_info;
/* Start the timer */
thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
thread_info->afi = afi;
thread_info->safi = safi;
thread_info->bgp = bgp;
event_add_timer(bm->master, bgp_graceful_deferral_timer_expire, thread_info,
bgp->select_defer_time, &gr_info->t_select_deferral);
gr_info->af_enabled = true;
bgp->gr_route_sync_pending = true;
/* Inform zebra */
bgp_zebra_update(bgp, afi, safi, ZEBRA_CLIENT_ROUTE_UPDATE_PENDING);
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("%s: Started path-select deferral timer for %s, duration %ds",
bgp->name_pretty, get_afi_safi_str(afi, safi, false),
bgp->select_defer_time);
}
static void bgp_gr_process_peer_up_ignore(struct bgp *bgp, struct peer *peer)
{
afi_t afi;
safi_t safi;
/*
* If peer has restarted, GR is disabled for peer or not negotiated
* with the peer, we have to ignore this peer for EOR-wait. This
* might also be the last peer we were waiting for, so check if
* we can move forward with path-selection.
*/
FOREACH_AFI_SAFI_NSF (afi, safi) {
UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_GR_WAIT_EOR);
if (bgp_gr_supported_for_afi_safi(afi, safi))
bgp_gr_check_path_select(bgp, afi, safi);
}
}
static void bgp_gr_process_peer_up_include(struct bgp *bgp, struct peer *peer)
{
afi_t afi;
safi_t safi;
struct graceful_restart_info *gr_info;
/*
* If peer has not restarted and is potentially a valid Helper,
* we need to wait for EOR from the peer for each AFI/SAFI that
* has been negotiated. This should also start the path selection
* deferral, if not yet done. OTOH, for non-negotiated AFI/SAFI,
* we need to check if path-selection can proceed.
*/
FOREACH_AFI_SAFI_NSF (afi, safi) {
if (!peer->afc_nego[afi][safi]) {
UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_GR_WAIT_EOR);
if (bgp_gr_supported_for_afi_safi(afi, safi))
bgp_gr_check_path_select(bgp, afi, safi);
} else if (!bgp_gr_supported_for_afi_safi(afi, safi)) {
UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_GR_WAIT_EOR);
} else {
SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_GR_WAIT_EOR);
gr_info = &(bgp->gr_info[afi][safi]);
if (!gr_info->t_select_deferral)
bgp_start_deferral_timer(bgp, afi, safi, gr_info);
}
}
}
static void bgp_gr_process_peer_status_change(struct peer *peer)
{
struct bgp *bgp;
afi_t afi;
safi_t safi;
bgp = peer->bgp;
if (peer_established(peer->connection)) {
/*
* If we haven't yet evaluated for path selection deferral,
* do it now.
*/
if (!bgp->gr_select_defer_evaluated) {
bgp_gr_mark_for_deferred_selection(bgp);
bgp->gr_select_defer_evaluated = true;
}
/*
* Peer has come up. We need to figure out if we need to
* wait for EOR from this peer for negotiated AFI/SAFI
* and potentially start deferred path selection. For any
* non-negotiated AFI/SAFI or if the peer has restarted etc.,
* evaluate if path-selection deferral should end
*/
if (CHECK_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV) ||
!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART) ||
!BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("%s: Peer %s cap 0x%" PRIx64 " flags 0x%" PRIx64
" restarted or GR not negotiated, check for path-selection",
bgp->name_pretty, peer->host, peer->cap, peer->flags);
bgp_gr_process_peer_up_ignore(bgp, peer);
} else {
bgp_gr_process_peer_up_include(bgp, peer);
}
} else if (peer->connection->ostatus == Established) {
/*
* If a peer (Helper) went down after establishing the
* session, we will not wait for a EOR from it.
* Note: This is not spelt out well in the RFC.
*/
FOREACH_AFI_SAFI_NSF (afi, safi)
UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_GR_WAIT_EOR);
}
}
static bool gr_path_select_deferral_applicable(struct bgp *bgp)
{
afi_t afi;
safi_t safi;
struct graceful_restart_info *gr_info;
/* True if BGP has (re)started gracefully (based on start
* settings and GR is not complete and path selection
* deferral not yet done for this instance
*/
if (!bgp_in_graceful_restart())
return false;
FOREACH_AFI_SAFI_NSF (afi, safi) {
if (!bgp_gr_supported_for_afi_safi(afi, safi))
continue;
gr_info = &(bgp->gr_info[afi][safi]);
if (!gr_info->select_defer_over)
return true;
}
return false;
}
/* Called after event occurred, this function change status and reset
read/write and timer thread. */
void bgp_fsm_change_status(struct peer_connection *connection,
@ -1326,9 +1545,10 @@ void bgp_fsm_change_status(struct peer_connection *connection,
peer->bgp->maxmed_onstartup_over = 1;
}
/* If update-delay processing is applicable, do the necessary. */
if (bgp_update_delay_configured(peer->bgp)
&& bgp_update_delay_applicable(peer->bgp))
/* Check for GR restarter or update-delay processing. */
if (gr_path_select_deferral_applicable(peer->bgp))
bgp_gr_process_peer_status_change(peer);
else if (bgp_update_delay_configured(peer->bgp) && bgp_update_delay_applicable(peer->bgp))
bgp_update_delay_process_status_change(peer);
if (bgp_debug_neighbor_events(peer))
@ -1359,8 +1579,6 @@ enum bgp_fsm_state_progress bgp_stop(struct peer_connection *connection)
char orf_name[BUFSIZ];
enum bgp_fsm_state_progress ret = BGP_FSM_SUCCESS;
struct peer *peer = connection->peer;
struct bgp *bgp = peer->bgp;
struct graceful_restart_info *gr_info = NULL;
peer->nsf_af_count = 0;
@ -1443,42 +1661,6 @@ enum bgp_fsm_state_progress bgp_stop(struct peer_connection *connection)
peer, bgp_peer_get_connection_direction(connection));
}
/* If peer reset before receiving EOR, decrement EOR count and
* cancel the selection deferral timer if there are no
* pending EOR messages to be received
*/
if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
FOREACH_AFI_SAFI (afi, safi) {
if (!peer->afc_nego[afi][safi]
|| CHECK_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_EOR_RECEIVED))
continue;
gr_info = &bgp->gr_info[afi][safi];
if (!gr_info)
continue;
if (gr_info->eor_required)
gr_info->eor_required--;
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("peer %s, EOR_required %d for %s", peer->host,
gr_info->eor_required,
bgp_peer_get_connection_direction(connection));
/* There is no pending EOR message */
if (gr_info->eor_required == 0) {
if (gr_info->t_select_deferral) {
void *info = EVENT_ARG(
gr_info->t_select_deferral);
XFREE(MTYPE_TMP, info);
}
EVENT_OFF(gr_info->t_select_deferral);
gr_info->eor_received = 0;
}
}
}
/* set last reset time */
peer->resettime = peer->uptime = monotime(NULL);
@ -2048,77 +2230,67 @@ bgp_fsm_delayopen_timer_expire(struct peer_connection *connection)
return BGP_FSM_SUCCESS;
}
/* Start the selection deferral timer thread for the specified AFI, SAFI */
static int bgp_start_deferral_timer(struct bgp *bgp, afi_t afi, safi_t safi,
struct graceful_restart_info *gr_info)
/*
* Upon session becoming established, process the GR capabilities announced
* by the peer, and clear stale routes if the peer has not announced a
* previously announced (afi,safi) or doesn't preserve forwarding for them.
* The clearing of stale routes applies only to a Helper router.
*/
static void bgp_peer_process_gr_cap_clear_stale(struct peer *peer)
{
struct afi_safi_info *thread_info;
afi_t afi;
safi_t safi;
int nsf_af_count = 0;
/* If the deferral timer is active, then increment eor count */
if (gr_info->t_select_deferral) {
gr_info->eor_required++;
return 0;
if (peer->connection->t_gr_restart) {
EVENT_OFF(peer->connection->t_gr_restart);
if (bgp_debug_neighbor_events(peer))
zlog_debug("%pBP: graceful restart timer stopped", peer);
}
/* Start the deferral timer when the first peer enabled for the graceful
* restart is established
*/
if (gr_info->eor_required == 0) {
thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
FOREACH_AFI_SAFI_NSF (afi, safi) {
if (peer->afc_nego[afi][safi] && CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV) &&
CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV)) {
/*
* If an (afi,safi) is negotiated with the
* peer and it has announced the GR capab
* for it, it supports NSF for this (afi,
* safi). However, if the peer didn't adv
* the F-bit, any previous (stale) routes
* should be flushed.
*/
if (peer->nsf[afi][safi] &&
!CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
bgp_clear_stale_route(peer, afi, safi);
thread_info->afi = afi;
thread_info->safi = safi;
thread_info->bgp = bgp;
event_add_timer(bm->master, bgp_graceful_deferral_timer_expire,
thread_info, bgp->select_defer_time,
&gr_info->t_select_deferral);
}
gr_info->eor_required++;
/* Send message to RIB indicating route update pending */
if (gr_info->af_enabled == false) {
gr_info->af_enabled = true;
gr_info->route_sync = false;
bgp->gr_route_sync_pending = true;
bgp_zebra_update(bgp, afi, safi,
ZEBRA_CLIENT_ROUTE_UPDATE_PENDING);
}
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("Started the deferral timer for %s eor_required %d",
get_afi_safi_str(afi, safi, false),
gr_info->eor_required);
return 0;
}
/* Update the graceful restart information for the specified AFI, SAFI */
static int bgp_update_gr_info(struct peer *peer, afi_t afi, safi_t safi)
{
struct graceful_restart_info *gr_info;
struct bgp *bgp = peer->bgp;
int ret = 0;
if ((afi < AFI_IP) || (afi >= AFI_MAX)) {
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("%s : invalid afi %d", __func__, afi);
return -1;
}
if ((safi < SAFI_UNICAST) || (safi > SAFI_MPLS_VPN)) {
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("%s : invalid safi %d", __func__, safi);
return -1;
}
/* Restarting router */
if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
&& BGP_PEER_RESTARTING_MODE(peer)) {
/* Check if the forwarding state is preserved */
if (bgp_gr_is_forwarding_preserved(bgp)) {
gr_info = &(bgp->gr_info[afi][safi]);
ret = bgp_start_deferral_timer(bgp, afi, safi, gr_info);
peer->nsf[afi][safi] = 1;
nsf_af_count++;
} else {
/*
* Some other situation like (afi,safi) not
* negotiated, GR not negotiated etc. Clear
* any previous (stale) routes.
*/
if (peer->nsf[afi][safi])
bgp_clear_stale_route(peer, afi, safi);
peer->nsf[afi][safi] = 0;
}
}
peer->nsf_af_count = nsf_af_count;
if (nsf_af_count)
SET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
else {
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
if (peer->connection->t_gr_stale) {
EVENT_OFF(peer->connection->t_gr_stale);
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s: graceful restart stalepath timer stopped",
peer->host);
}
}
return ret;
}
/**
@ -2132,10 +2304,8 @@ bgp_establish(struct peer_connection *connection)
{
afi_t afi;
safi_t safi;
int nsf_af_count = 0;
enum bgp_fsm_state_progress ret = BGP_FSM_SUCCESS;
struct peer *other;
int status;
struct peer *peer = connection->peer;
struct peer *orig = peer;
@ -2192,101 +2362,12 @@ bgp_establish(struct peer_connection *connection)
: VRF_DEFAULT_NAME)
: "");
}
/* assign update-group/subgroup */
update_group_adjust_peer_afs(peer);
/* graceful restart */
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
if (bgp_debug_neighbor_events(peer)) {
if (BGP_PEER_RESTARTING_MODE(peer))
zlog_debug("%pBP BGP_RESTARTING_MODE %s", peer,
bgp_peer_get_connection_direction(connection));
else if (BGP_PEER_HELPER_MODE(peer))
zlog_debug("%pBP BGP_HELPER_MODE %s", peer,
bgp_peer_get_connection_direction(connection));
}
FOREACH_AFI_SAFI_NSF (afi, safi) {
if (peer->afc_nego[afi][safi] &&
CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV) &&
CHECK_FLAG(peer->af_cap[afi][safi],
PEER_CAP_RESTART_AF_RCV)) {
if (peer->nsf[afi][safi] &&
!CHECK_FLAG(peer->af_cap[afi][safi],
PEER_CAP_RESTART_AF_PRESERVE_RCV))
bgp_clear_stale_route(peer, afi, safi);
peer->nsf[afi][safi] = 1;
nsf_af_count++;
} else {
if (peer->nsf[afi][safi])
bgp_clear_stale_route(peer, afi, safi);
peer->nsf[afi][safi] = 0;
}
/* Update the graceful restart information */
if (peer->afc_nego[afi][safi]) {
if (!BGP_SELECT_DEFER_DISABLE(peer->bgp)) {
status = bgp_update_gr_info(peer, afi, safi);
if (status < 0)
zlog_err(
"Error in updating graceful restart for %s",
get_afi_safi_str(afi, safi,
false));
} else {
if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer) &&
BGP_PEER_RESTARTING_MODE(peer) &&
bgp_gr_is_forwarding_preserved(peer->bgp))
peer->bgp->gr_info[afi][safi]
.eor_required++;
}
}
}
if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
if ((bgp_peer_gr_mode_get(peer) == PEER_GR)
|| ((bgp_peer_gr_mode_get(peer) == PEER_GLOBAL_INHERIT)
&& (bgp_global_gr_mode_get(peer->bgp) == GLOBAL_GR))) {
FOREACH_AFI_SAFI (afi, safi)
/* Send route processing complete
message to RIB */
bgp_zebra_update(
peer->bgp, afi, safi,
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
}
} else {
/* Peer sends R-bit. In this case, we need to send
* ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE to Zebra. */
if (CHECK_FLAG(peer->cap,
PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV)) {
FOREACH_AFI_SAFI (afi, safi)
/* Send route processing complete
message to RIB */
bgp_zebra_update(
peer->bgp, afi, safi,
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
}
}
peer->nsf_af_count = nsf_af_count;
if (nsf_af_count)
SET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
else {
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
if (connection->t_gr_stale) {
EVENT_OFF(connection->t_gr_stale);
if (bgp_debug_neighbor_events(peer))
zlog_debug("%pBP graceful restart stalepath timer stopped for %s",
peer, bgp_peer_get_connection_direction(connection));
}
}
if (connection->t_gr_restart) {
EVENT_OFF(connection->t_gr_restart);
if (bgp_debug_neighbor_events(peer))
zlog_debug("%pBP graceful restart timer stopped for %s", peer,
bgp_peer_get_connection_direction(connection));
}
/* graceful restart handling */
bgp_peer_process_gr_cap_clear_stale(peer);
/* Reset uptime, turn on keepalives, send current table. */
if (!peer->v_holdtime)
@ -2817,8 +2898,9 @@ int bgp_gr_update_all(struct bgp *bgp, enum global_gr_command global_gr_cmd)
if (global_old_state == GLOBAL_INVALID)
return BGP_ERR_GR_OPERATION_FAILED;
/* Next state 'invalid is actually an 'ignore' */
if (global_new_state == GLOBAL_INVALID)
return BGP_ERR_GR_INVALID_CMD;
return BGP_GR_NO_OPERATION;
if (global_new_state == global_old_state)
return BGP_GR_NO_OPERATION;
@ -2930,8 +3012,9 @@ int bgp_neighbor_graceful_restart(struct peer *peer,
if (peer_old_state == PEER_INVALID)
return BGP_ERR_GR_OPERATION_FAILED;
/* Next state 'invalid' is actually an 'ignore' */
if (peer_new_state == PEER_INVALID)
return BGP_ERR_GR_INVALID_CMD;
return BGP_GR_NO_OPERATION;
if (peer_new_state == peer_old_state)
return BGP_GR_NO_OPERATION;
@ -2962,8 +3045,10 @@ unsigned int bgp_peer_gr_action(struct peer *peer, enum peer_mode old_state,
if (old_state == new_state)
return BGP_GR_NO_OPERATION;
if ((old_state == PEER_INVALID) || (new_state == PEER_INVALID))
if (old_state == PEER_INVALID)
return BGP_ERR_GR_INVALID_CMD;
if (new_state == PEER_INVALID)
return BGP_GR_NO_OPERATION;
global_gr_mode = bgp_global_gr_mode_get(peer->bgp);

View file

@ -167,4 +167,5 @@ const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd);
const char *print_global_gr_mode(enum global_mode gl_mode);
const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd);
int bgp_peer_reg_with_nht(struct peer *peer);
void bgp_gr_check_path_select(struct bgp *bgp, afi_t afi, safi_t safi);
#endif /* _QUAGGA_BGP_FSM_H */

View file

@ -1603,7 +1603,7 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
rcapp = stream_get_endp(s);
stream_putc(s, 0);
restart_time = bgp->restart_time;
if (peer->bgp->t_startup || bgp_in_graceful_restart()) {
if (bgp_in_graceful_restart()) {
SET_FLAG(restart_time, GRACEFUL_RESTART_R_BIT);
SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV);
}
@ -1636,6 +1636,8 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
if (!peer->afc[afi][safi])
continue;
if (!bgp_gr_supported_for_afi_safi(afi, safi))
continue;
/* Convert AFI, SAFI to values for
* packet.

View file

@ -482,6 +482,12 @@ void bgp_generate_updgrp_packets(struct event *thread)
return;
}
/* If a GR restarter, we have to wait till path-selection
* is complete.
*/
if (bgp_in_graceful_restart())
return;
do {
enum bgp_af_index index;
@ -1319,7 +1325,7 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
stream_putc(s, 0);
gr_restart_time = peer->bgp->restart_time;
if (peer->bgp->t_startup || bgp_in_graceful_restart()) {
if (bgp_in_graceful_restart()) {
SET_FLAG(gr_restart_time, GRACEFUL_RESTART_R_BIT);
SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV);
}
@ -2232,6 +2238,40 @@ static void bgp_refresh_stalepath_timer_expire(struct event *thread)
bgp_timer_set(peer->connection);
}
static void bgp_update_receive_eor(struct bgp *bgp, struct peer *peer, afi_t afi, safi_t safi)
{
struct vrf *vrf = vrf_lookup_by_id(bgp->vrf_id);
zlog_info("%s: rcvd End-of-RIB for %s from %s in vrf %s", __func__,
get_afi_safi_str(afi, safi, false), peer->host,
vrf ? vrf->name : VRF_DEFAULT_NAME);
/* End-of-RIB received */
if (!CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED)) {
SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED);
/* update-delay related processing */
bgp_update_explicit_eors(peer);
/* graceful-restart related processing */
UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_GR_WAIT_EOR);
if (bgp_in_graceful_restart() && bgp_gr_supported_for_afi_safi(afi, safi)) {
struct graceful_restart_info *gr_info;
gr_info = &(bgp->gr_info[afi][safi]);
if (!gr_info->select_defer_over) {
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("%s: check for path-selection", bgp->name_pretty);
bgp_gr_check_path_select(bgp, afi, safi);
}
}
}
/* NSF delete stale route */
if (peer->nsf[afi][safi])
bgp_clear_stale_route(peer, afi, safi);
}
/**
* Process BGP UPDATE message for peer.
*
@ -2251,7 +2291,7 @@ static int bgp_update_receive(struct peer_connection *connection,
bgp_size_t attribute_len;
bgp_size_t update_len;
bgp_size_t withdraw_len;
bool restart = false;
struct bgp *bgp = peer->bgp;
enum NLRI_TYPES {
NLRI_UPDATE,
@ -2480,13 +2520,6 @@ static int bgp_update_receive(struct peer_connection *connection,
if (!update_len && !withdraw_len && nlris[NLRI_MP_UPDATE].length == 0) {
afi_t afi = 0;
safi_t safi;
struct graceful_restart_info *gr_info;
/* Restarting router */
if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
&& BGP_PEER_RESTARTING_MODE(peer))
restart = true;
/* Non-MP IPv4/Unicast is a completely emtpy UPDATE - already
* checked
* update and withdraw NLRI lengths are 0.
@ -2500,55 +2533,8 @@ static int bgp_update_receive(struct peer_connection *connection,
safi = nlris[NLRI_MP_WITHDRAW].safi;
}
if (afi && peer->afc[afi][safi]) {
struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
/* End-of-RIB received */
if (!CHECK_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_EOR_RECEIVED)) {
SET_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_EOR_RECEIVED);
bgp_update_explicit_eors(peer);
/* Update graceful restart information */
gr_info = &(peer->bgp->gr_info[afi][safi]);
if (restart)
gr_info->eor_received++;
/* If EOR received from all peers and selection
* deferral timer is running, cancel the timer
* and invoke the best path calculation
*/
if (gr_info->eor_required
== gr_info->eor_received) {
if (bgp_debug_neighbor_events(peer))
zlog_debug(
"%s %d, %s %d",
"EOR REQ",
gr_info->eor_required,
"EOR RCV",
gr_info->eor_received);
if (gr_info->t_select_deferral) {
void *info = EVENT_ARG(
gr_info->t_select_deferral);
XFREE(MTYPE_TMP, info);
}
EVENT_OFF(gr_info->t_select_deferral);
gr_info->eor_required = 0;
gr_info->eor_received = 0;
/* Best path selection */
bgp_best_path_select_defer(peer->bgp,
afi, safi);
}
}
/* NSF delete stale route */
if (peer->nsf[afi][safi])
bgp_clear_stale_route(peer, afi, safi);
zlog_info(
"%s: rcvd End-of-RIB for %s from %s in vrf %s",
__func__, get_afi_safi_str(afi, safi, false),
peer->host, vrf ? vrf->name : VRF_DEFAULT_NAME);
}
if (afi && peer->afc[afi][safi])
bgp_update_receive_eor(bgp, peer, afi, safi);
}
/* Everything is done. We unintern temporary structures which

View file

@ -500,9 +500,9 @@ static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
bgp->gr_info[afi][safi].gr_deferred++;
SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("DEFER route %pBD(%s), dest %p",
dest, bgp->name_pretty, dest);
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("%s: Defer route %pBD, dest %p", bgp->name_pretty, dest,
dest);
return 0;
}
}
@ -2947,7 +2947,7 @@ static void bgp_route_select_timer_expire(struct event *thread)
XFREE(MTYPE_TMP, info);
/* Best path selection */
bgp_best_path_select_defer(bgp, afi, safi);
bgp_do_deferred_path_selection(bgp, afi, safi);
}
void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
@ -4007,12 +4007,11 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
}
/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
void bgp_do_deferred_path_selection(struct bgp *bgp, afi_t afi, safi_t safi)
{
struct bgp_dest *dest;
int cnt = 0;
struct afi_safi_info *thread_info;
bool route_sync_pending = false;
if (bgp->gr_info[afi][safi].t_route_select) {
struct event *t = bgp->gr_info[afi][safi].t_route_select;
@ -4051,21 +4050,25 @@ void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
/* Send EOR message when all routes are processed */
if (!bgp->gr_info[afi][safi].gr_deferred) {
bool route_sync_pending = false;
bgp_send_delayed_eor(bgp);
/* Send route processing complete message to RIB */
bgp_zebra_update(bgp, afi, safi,
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
bgp->gr_info[afi][safi].route_sync = true;
/* If this instance is all done, check for GR completion overall */
FOREACH_AFI_SAFI_NSF (afi, safi) {
/*
* If this instance is all done,
* check for GR completion overall
*/
FOREACH_AFI_SAFI (afi, safi) {
if (bgp->gr_info[afi][safi].af_enabled &&
!bgp->gr_info[afi][safi].route_sync) {
route_sync_pending = true;
break;
}
}
if (!route_sync_pending) {
bgp->gr_route_sync_pending = false;
bgp_update_gr_completion();
@ -4457,9 +4460,6 @@ static void bgp_process_internal(struct bgp *bgp, struct bgp_dest *dest,
* the workqueue
*/
if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
dest);
bgp->node_deferred_on_queue++;
return;
}

View file

@ -975,7 +975,7 @@ extern int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t
struct bgp_table *table, struct prefix_rd *prd,
enum bgp_show_type type, void *output_arg,
uint16_t show_flags);
extern void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi);
extern void bgp_do_deferred_path_selection(struct bgp *bgp, afi_t afi, safi_t safi);
extern 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);

File diff suppressed because it is too large Load diff

View file

@ -55,14 +55,13 @@ FRR_CFG_DEFAULT_ULONG(BGP_CONNECT_RETRY,
"V AS LocalAS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc\n"
#define BGP_SHOW_SUMMARY_HEADER_FAILED "EstdCnt DropCnt ResetTime Reason\n"
#define BGP_SHOW_PEER_GR_CAPABILITY(vty, p, json) \
do { \
bgp_show_neighbor_graceful_restart_local_mode(vty, p, json); \
bgp_show_neighbor_graceful_restart_remote_mode(vty, p, json); \
bgp_show_neighnor_graceful_restart_flags(vty, p, json); \
bgp_show_neighbor_graceful_restart_time(vty, p, json); \
bgp_show_neighbor_graceful_restart_capability_per_afi_safi( \
vty, p, json); \
#define BGP_SHOW_PEER_GR_CAPABILITY(vty, p, json) \
do { \
bgp_show_neighbor_graceful_restart_local_mode(vty, p, json); \
bgp_show_neighbor_graceful_restart_remote_mode(vty, p, json); \
bgp_show_neighnor_graceful_restart_flags(vty, p, json); \
bgp_show_neighbor_graceful_restart_time(vty, p, json); \
bgp_show_peer_gr_info_afi_safi(vty, p, use_json, json); \
} while (0)
#define VTY_BGP_GR_DEFINE_LOOP_VARIABLE \
@ -140,6 +139,11 @@ FRR_CFG_DEFAULT_ULONG(BGP_CONNECT_RETRY,
} while (0)
extern void bgp_clear_soft_in(struct bgp *bgp, afi_t afi, safi_t safi);
/* Peer show flags */
/* Value of 0 means show all information */
#define VTY_BGP_PEER_SHOW_GR_INFO (1 << 0)
extern void bgp_vty_init(void);
extern void community_alias_vty(void);
extern const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);

View file

@ -1364,9 +1364,6 @@ struct peer *peer_unlock_with_caller(const char *name, struct peer *peer)
int bgp_global_gr_init(struct bgp *bgp)
{
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("%s called ..", __func__);
int local_GLOBAL_GR_FSM[BGP_GLOBAL_GR_MODE][BGP_GLOBAL_GR_EVENT_CMD] = {
/* GLOBAL_HELPER Mode */
{
@ -1436,9 +1433,6 @@ int bgp_global_gr_init(struct bgp *bgp)
int bgp_peer_gr_init(struct peer *peer)
{
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("%s called ..", __func__);
struct bgp_peer_gr local_Peer_GR_FSM[BGP_PEER_GR_MODE]
[BGP_PEER_GR_EVENT_CMD] = {
{
@ -1618,9 +1612,6 @@ struct peer *peer_new(struct bgp *bgp)
SET_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_FQDN);
SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN);
/* Initialize per peer bgp GR FSM */
bgp_peer_gr_init(peer);
/* Get service port number. */
sp = getservbyname("bgp", "tcp");
peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs(sp->s_port);
@ -2069,7 +2060,9 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
bgp_timer_set(peer->connection);
}
bgp_peer_gr_flags_update(peer);
/* Initialize per peer bgp GR FSM */
bgp_peer_gr_init(peer);
BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer);
return peer;
@ -2086,6 +2079,9 @@ struct peer *peer_create_accept(struct bgp *bgp)
listnode_add_sort(bgp->peer, peer);
(void)hash_get(bgp->peerhash, peer, hash_alloc_intern);
/* Initialize per peer bgp GR FSM */
bgp_peer_gr_init(peer);
return peer;
}
@ -3425,14 +3421,6 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
return 0;
}
static void bgp_startup_timer_expire(struct event *thread)
{
struct bgp *bgp;
bgp = EVENT_ARG(thread);
bgp->t_startup = NULL;
}
/*
* On shutdown we call the cleanup function which
* does a free of the link list nodes, free up
@ -3544,11 +3532,10 @@ peer_init:
bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_IBGP,
multipath_num, 0);
/* Initialize graceful restart info */
bgp->gr_info[afi][safi].eor_required = 0;
bgp->gr_info[afi][safi].eor_received = 0;
bgp->gr_info[afi][safi].t_select_deferral = NULL;
bgp->gr_info[afi][safi].t_route_select = NULL;
bgp->gr_info[afi][safi].gr_deferred = 0;
bgp->gr_info[afi][safi].select_defer_over = false;
}
bgp->v_update_delay = bm->v_update_delay;
@ -3612,9 +3599,6 @@ peer_init:
if (name && !bgp->name)
bgp->name = XSTRDUP(MTYPE_BGP_NAME, name);
event_add_timer(bm->master, bgp_startup_timer_expire, bgp,
bgp->restart_time, &bgp->t_startup);
/* printable name we can use in debug messages */
if (inst_type == BGP_INSTANCE_TYPE_DEFAULT && !hidden) {
bgp->name_pretty = XSTRDUP(MTYPE_BGP_NAME, "VRF default");
@ -4151,7 +4135,6 @@ int bgp_delete(struct bgp *bgp)
EVENT_OFF(bgp->t_revalidate[afi][safi]);
EVENT_OFF(bgp->t_condition_check);
EVENT_OFF(bgp->t_startup);
EVENT_OFF(bgp->t_maxmed_onstartup);
EVENT_OFF(bgp->t_update_delay);
EVENT_OFF(bgp->t_establish_wait);

View file

@ -323,11 +323,9 @@ enum bgp_instance_type {
BGP_INSTANCE_TYPE_VIEW
};
#define BGP_SEND_EOR(bgp, afi, safi) \
(!CHECK_FLAG(bgp->flags, BGP_FLAG_GR_DISABLE_EOR) \
&& ((bgp->gr_info[afi][safi].t_select_deferral == NULL) \
|| (bgp->gr_info[afi][safi].eor_required \
== bgp->gr_info[afi][safi].eor_received)))
#define BGP_SEND_EOR(bgp, afi, safi) \
(!CHECK_FLAG(bgp->flags, BGP_FLAG_GR_DISABLE_EOR) && \
(!bgp_in_graceful_restart() || bgp->gr_info[afi][safi].select_defer_over))
/* BGP GR Global ds */
@ -336,10 +334,6 @@ enum bgp_instance_type {
/* Graceful restart selection deferral timer info */
struct graceful_restart_info {
/* Count of EOR message expected */
uint32_t eor_required;
/* Count of EOR received */
uint32_t eor_received;
/* Deferral Timer */
struct event *t_select_deferral;
/* Routes Deferred */
@ -350,6 +344,7 @@ struct graceful_restart_info {
bool af_enabled;
/* Route update completed */
bool route_sync;
bool select_defer_over;
};
enum global_mode {
@ -559,9 +554,6 @@ struct bgp {
struct as_confed *confed_peers;
int confed_peers_cnt;
/* start-up timer on only once at the beginning */
struct event *t_startup;
struct event *clearing_end;
uint32_t v_maxmed_onstartup; /* Duration of max-med on start-up */
@ -682,6 +674,11 @@ struct bgp {
*/
enum zebra_gr_mode present_zebra_gr_state;
/* Is deferred path selection evaluated? Currently, this is done
* upon first peer establishing in an instance.
*/
bool gr_select_defer_evaluated;
/* Is deferred path selection still not complete? */
bool gr_route_sync_pending;
@ -1810,7 +1807,7 @@ struct peer {
#define PEER_STATUS_LLGR_WAIT (1U << 11)
#define PEER_STATUS_REFRESH_PENDING (1U << 12) /* refresh request from peer */
#define PEER_STATUS_RTT_SHUTDOWN (1U << 13) /* In shutdown state due to RTT */
#define PEER_STATUS_GR_WAIT_EOR (1U << 14) /* wait for EOR */
/* Configured timer values. */
_Atomic uint32_t holdtime;
_Atomic uint32_t keepalive;
@ -3027,6 +3024,17 @@ static inline bool bgp_gr_is_forwarding_preserved(struct bgp *bgp)
CHECK_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD));
}
static inline bool bgp_gr_supported_for_afi_safi(afi_t afi, safi_t safi)
{
/*
* GR restarter behavior is supported only for IPv4-unicast
* and IPv6-unicast.
*/
if ((afi == AFI_IP && safi == SAFI_UNICAST) || (afi == AFI_IP6 && safi == SAFI_UNICAST))
return true;
return false;
}
/* For benefit of rfapi */
extern struct peer *peer_new(struct bgp *bgp);

View file

@ -112,6 +112,7 @@ from lib.common_config import (
start_topology,
kill_router_daemons,
start_router_daemons,
start_router_daemons_gr,
verify_rib,
check_address_types,
write_test_footer,
@ -1034,7 +1035,8 @@ def test_BGP_GR_TC_4_p0(request):
)
logger.info("[Phase 5] : R2 is about to come up now ")
start_router_daemons(tgen, "r2", ["bgpd"])
start_router_daemons_gr(tgen, "r2", ["bgpd"])
logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
@ -1200,15 +1202,16 @@ def test_BGP_GR_TC_5_1_2_p1(request):
tc_name, result
)
#Verify that the Rbit is be set to false
result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
assert result is True, "Testcase {} : Failed \n Error {}".format(
assert result is not True, "Testcase {} : Failed \n Error {}".format(
tc_name, result
)
logger.info("[Phase 2] : Restart BGPd on router R2. ")
kill_router_daemons(tgen, "r2", ["bgpd"])
start_router_daemons(tgen, "r2", ["bgpd"])
start_router_daemons_gr(tgen, "r2", ["bgpd"])
logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")

View file

@ -113,6 +113,7 @@ from lib.common_config import (
start_topology,
kill_router_daemons,
start_router_daemons,
start_router_daemons_gr,
verify_rib,
check_address_types,
write_test_footer,
@ -359,7 +360,7 @@ def test_BGP_GR_TC_8_p1(request):
kill_router_daemons(tgen, "r1", ["bgpd"])
logger.info("[Phase 3] : R1 is about to come up now ")
start_router_daemons(tgen, "r1", ["bgpd"])
start_router_daemons_gr(tgen, "r1", ["bgpd"])
logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")

View file

@ -1597,7 +1597,7 @@ def test_BGP_GR_TC_9_p1(request):
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
assert result is not True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
result = verify_f_bit(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False

View file

@ -109,6 +109,7 @@ from lib.common_config import (
start_topology,
kill_router_daemons,
start_router_daemons,
start_router_daemons_gr,
verify_rib,
check_address_types,
write_test_footer,
@ -546,12 +547,12 @@ def test_BGP_GR_chaos_28_p1(request):
logger.info("[Step 3] : Start BGPd daemon on R1..")
# Start BGPd daemon on R1
start_router_daemons(tgen, "r1", ["bgpd"])
start_router_daemons_gr(tgen, "r1", ["bgpd"])
logger.info("[Step 4] : Start BGPd daemon on R3..")
# Start BGPd daemon on R3
start_router_daemons(tgen, "r3", ["bgpd"])
start_router_daemons_gr(tgen, "r3", ["bgpd"])
# Verify r_bit
for addr_type in ADDR_TYPES:

View file

@ -108,11 +108,13 @@ from lib.common_config import (
start_topology,
kill_router_daemons,
start_router_daemons,
start_router_daemons_gr,
verify_rib,
check_address_types,
write_test_footer,
check_router_status,
get_frr_ipv6_linklocal,
run_frr_cmd,
required_linux_kernel_version,
)
@ -722,10 +724,9 @@ def test_BGP_GR_chaos_37_p1(request):
logger.info("[Step 4] : Start BGPd daemon on R1..")
# Start BGPd daemon on R1
start_router_daemons(tgen, "r1", ["bgpd"])
start_router_daemons_gr(tgen, "r1", ["bgpd"])
logger.info("[Step 5] : Kill BGPd daemon on R3..")
# Kill BGPd daemon on R3
kill_router_daemons(tgen, "r3", ["bgpd"])
@ -738,7 +739,10 @@ def test_BGP_GR_chaos_37_p1(request):
logger.info("[Step 6] : Start BGPd daemon on R3..")
# Start BGPd daemon on R3
start_router_daemons(tgen, "r3", ["bgpd"])
start_router_daemons_gr(tgen, "r3", ["bgpd"])
#Wait for session to come up
sleep(120)
for addr_type in ADDR_TYPES:
# Verify r_bit
@ -910,7 +914,10 @@ def test_BGP_GR_chaos_30_p1(request):
logger.info("[Step 4] : Start BGPd daemon on R1..")
# Start BGPd daemon on R1
start_router_daemons(tgen, "r1", ["bgpd"])
start_router_daemons_gr(tgen, "r1", ["bgpd"])
# Wait for select-deferral-timer to expire/EORs to be received
sleep(360)
for addr_type in ADDR_TYPES:
# Verifying BGP RIB routes before shutting down BGPd daemon

View file

@ -3403,42 +3403,65 @@ def verify_graceful_restart(
rmode = "Helper"
else:
rmode = "Helper"
if show_bgp_graceful_json_out["localGrMode"] == lmode:
if (
show_bgp_graceful_json_out["gracefulRestartInfo"]["localGrMode"]
== lmode
):
logger.info(
"[DUT: {}]: localGrMode : {} ".format(
dut, show_bgp_graceful_json_out["localGrMode"]
dut,
show_bgp_graceful_json_out["gracefulRestartInfo"][
"localGrMode"
],
)
)
else:
errormsg = (
"[DUT: {}]: localGrMode is not correct"
" Expected: {}, Found: {}".format(
dut, lmode, show_bgp_graceful_json_out["localGrMode"]
dut,
lmode,
show_bgp_graceful_json_out["gracefulRestartInfo"][
"localGrMode"
],
)
)
return errormsg
if show_bgp_graceful_json_out["remoteGrMode"] == rmode:
if (
show_bgp_graceful_json_out["gracefulRestartInfo"]["remoteGrMode"]
== rmode
):
logger.info(
"[DUT: {}]: remoteGrMode : {} ".format(
dut, show_bgp_graceful_json_out["remoteGrMode"]
dut,
show_bgp_graceful_json_out["gracefulRestartInfo"][
"remoteGrMode"
],
)
)
elif (
show_bgp_graceful_json_out["remoteGrMode"] == "NotApplicable"
show_bgp_graceful_json_out["gracefulRestartInfo"]["remoteGrMode"]
== "NotApplicable"
and rmode == "Disable"
):
logger.info(
"[DUT: {}]: remoteGrMode : {} ".format(
dut, show_bgp_graceful_json_out["remoteGrMode"]
dut,
show_bgp_graceful_json_out["gracefulRestartInfo"][
"remoteGrMode"
],
)
)
else:
errormsg = (
"[DUT: {}]: remoteGrMode is not correct"
" Expected: {}, Found: {}".format(
dut, rmode, show_bgp_graceful_json_out["remoteGrMode"]
dut,
rmode,
show_bgp_graceful_json_out["gracefulRestartInfo"][
"remoteGrMode"
],
)
)
return errormsg
@ -3556,8 +3579,8 @@ def verify_r_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
)
return errormsg
if "rBit" in show_bgp_graceful_json_out:
if show_bgp_graceful_json_out["rBit"]:
if "rBit" in show_bgp_graceful_json_out["gracefulRestartInfo"]:
if show_bgp_graceful_json_out["gracefulRestartInfo"]["rBit"]:
logger.info("[DUT: {}]: Rbit true {}".format(dut, neighbor_ip))
else:
errormsg = "[DUT: {}]: Rbit false {}".format(dut, neighbor_ip)
@ -3682,7 +3705,9 @@ def verify_eor(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
errormsg = "Address type %s is not supported" % (addr_type)
return errormsg
eor_json = show_bgp_graceful_json_out[afi]["endOfRibStatus"]
eor_json = show_bgp_graceful_json_out["gracefulRestartInfo"][afi][
"endOfRibStatus"
]
if "endOfRibSend" in eor_json:
if eor_json["endOfRibSend"]:
logger.info(
@ -3827,9 +3852,9 @@ def verify_f_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
isjson=True,
)
show_bgp_graceful_json_out = show_bgp_graceful_json[neighbor_ip]
show_bgp_graceful_nbr_json_out = show_bgp_graceful_json[neighbor_ip]
if show_bgp_graceful_json_out["neighborAddr"] == neighbor_ip:
if show_bgp_graceful_nbr_json_out["neighborAddr"] == neighbor_ip:
logger.info(
"[DUT: {}]: Neighbor ip matched {}".format(dut, neighbor_ip)
)
@ -3839,6 +3864,10 @@ def verify_f_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
)
return errormsg
show_bgp_graceful_json_out = show_bgp_graceful_nbr_json_out[
"gracefulRestartInfo"
]
if "ipv4Unicast" in show_bgp_graceful_json_out:
if show_bgp_graceful_json_out["ipv4Unicast"]["fBit"]:
logger.info(
@ -3975,9 +4004,9 @@ def verify_graceful_restart_timers(tgen, topo, addr_type, input_dict, dut, peer)
if rs_timer == "restart-time":
receivedTimer = value
if (
show_bgp_graceful_json_out["timers"][
"receivedRestartTimer"
]
show_bgp_graceful_json_out["gracefulRestartInfo"][
"timers"
]["receivedRestartTimer"]
== receivedTimer
):
logger.info(
@ -4071,7 +4100,7 @@ def verify_gr_address_family(
return errormsg
if addr_family == "ipv4Unicast":
if "ipv4Unicast" in show_bgp_graceful_json_out:
if "ipv4Unicast" in show_bgp_graceful_json_out["gracefulRestartInfo"]:
logger.info("ipv4Unicast present for {} ".format(neighbor_ip))
return True
else:
@ -4079,7 +4108,7 @@ def verify_gr_address_family(
return errormsg
elif addr_family == "ipv6Unicast":
if "ipv6Unicast" in show_bgp_graceful_json_out:
if "ipv6Unicast" in show_bgp_graceful_json_out["gracefulRestartInfo"]:
logger.info("ipv6Unicast present for {} ".format(neighbor_ip))
return True
else:

View file

@ -430,6 +430,24 @@ def start_router_daemons(tgen, router, daemons):
return res
def start_router_daemons_gr(tgen, router, daemons):
"""
Set -K option in daemons file before starting
the daemon so that it can start in GR restarter mode.
Currently supported for bgpd and zebra only.
Remove -K option from daemons file once started
"""
#Adds extra parameters to daemons file for graceful restart
for daemon in daemons:
tgen.net[router].daemons_options[daemon] = "-K"
# Start daemon
start_router_daemons(tgen, router, daemons)
# Remove graceful restart option
for daemon in daemons:
tgen.net[router].daemons_options[daemon] = ""
def check_router_status(tgen):
"""
Check if all daemons are running for all routers in topology