diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 01c61615a3..f110005e49 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -634,7 +634,8 @@ const char *const peer_down_str[] = {"", "AS Set config change", "Waiting for peer OPEN", "Reached received prefix count", - "Socket Error"}; + "Socket Error", + "Admin. shutdown (RTT)"}; static void bgp_graceful_restart_timer_off(struct peer *peer) { @@ -1832,7 +1833,9 @@ int bgp_start(struct peer *peer) flog_err(EC_BGP_FSM, "%s [FSM] Trying to start suppressed peer - this is never supposed to happen!", peer->host); - if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) + if (CHECK_FLAG(peer->sflags, PEER_STATUS_RTT_SHUTDOWN)) + peer->last_reset = PEER_DOWN_RTT_SHUTDOWN; + else if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) peer->last_reset = PEER_DOWN_USER_SHUTDOWN; else if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHUTDOWN)) peer->last_reset = PEER_DOWN_USER_SHUTDOWN; diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 72d6a92317..f3ca3bba0a 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1011,9 +1011,12 @@ static void bgp_notify_send_internal(struct peer *peer, uint8_t code, if (code == BGP_NOTIFY_CEASE) { if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET) peer->last_reset = PEER_DOWN_USER_RESET; - else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN) - peer->last_reset = PEER_DOWN_USER_SHUTDOWN; - else + else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_RTT_SHUTDOWN)) + peer->last_reset = PEER_DOWN_RTT_SHUTDOWN; + else + peer->last_reset = PEER_DOWN_USER_SHUTDOWN; + } else peer->last_reset = PEER_DOWN_NOTIFY_SEND; } else peer->last_reset = PEER_DOWN_NOTIFY_SEND; @@ -1749,15 +1752,24 @@ static int bgp_keepalive_receive(struct peer *peer, bgp_size_t size) /* If the peer's RTT is higher than expected, shutdown * the peer automatically. */ - if (CHECK_FLAG(peer->flags, PEER_FLAG_RTT_SHUTDOWN) - && peer->rtt > peer->rtt_expected) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_RTT_SHUTDOWN)) + return Receive_KEEPALIVE_message; + if (peer->rtt > peer->rtt_expected) { peer->rtt_keepalive_rcv++; if (peer->rtt_keepalive_rcv > peer->rtt_keepalive_conf) { - zlog_warn( - "%s shutdown due to high round-trip-time (%dms > %dms)", - peer->host, peer->rtt, peer->rtt_expected); + char rtt_shutdown_reason[BUFSIZ] = {}; + + snprintfrr( + rtt_shutdown_reason, + sizeof(rtt_shutdown_reason), + "shutdown due to high round-trip-time (%dms > %dms, hit %u times)", + peer->rtt, peer->rtt_expected, + peer->rtt_keepalive_rcv); + zlog_warn("%s %s", peer->host, rtt_shutdown_reason); + SET_FLAG(peer->sflags, PEER_STATUS_RTT_SHUTDOWN); + peer_tx_shutdown_message_set(peer, rtt_shutdown_reason); peer_flag_set(peer, PEER_FLAG_SHUTDOWN); } } else { diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 1f66080e93..6f0bd5eded 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -5272,8 +5272,10 @@ static int peer_flag_modify_vty(struct vty *vty, const char *ip_str, return CMD_WARNING_CONFIG_FAILED; } - if (!set && flag == PEER_FLAG_SHUTDOWN) + if (!set && flag == PEER_FLAG_SHUTDOWN) { peer_tx_shutdown_message_unset(peer); + UNSET_FLAG(peer->sflags, PEER_STATUS_RTT_SHUTDOWN); + } if (set) ret = peer_flag_set(peer, flag); @@ -14565,9 +14567,18 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, if (use_json) { json_object_int_add(json_neigh, "connectRetryTimer", p->v_connect); - if (peer_established(p) && p->rtt) + if (peer_established(p)) { json_object_int_add(json_neigh, "estimatedRttInMsecs", p->rtt); + if (CHECK_FLAG(p->flags, PEER_FLAG_RTT_SHUTDOWN)) { + json_object_int_add(json_neigh, + "shutdownRttInMsecs", + p->rtt_expected); + json_object_int_add(json_neigh, + "shutdownRttAfterCount", + p->rtt_keepalive_rcv); + } + } if (p->t_start) json_object_int_add( json_neigh, "nextStartTimerDueInMsecs", @@ -14602,9 +14613,14 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, } else { vty_out(vty, "BGP Connect Retry Timer in Seconds: %d\n", p->v_connect); - if (peer_established(p) && p->rtt) + if (peer_established(p)) { vty_out(vty, "Estimated round trip time: %d ms\n", p->rtt); + if (CHECK_FLAG(p->flags, PEER_FLAG_RTT_SHUTDOWN)) + vty_out(vty, + "Shutdown when RTT > %dms, count > %u\n", + p->rtt_expected, p->rtt_keepalive_rcv); + } if (p->t_start) vty_out(vty, "Next start timer due in %ld seconds\n", thread_timer_remain_second(p->t_start)); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index b3fce07344..8a0ec5ad2d 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1524,6 +1524,7 @@ struct peer { /* LLGR aware 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 */ /* Configured timer values. */ _Atomic uint32_t holdtime; @@ -1737,6 +1738,7 @@ struct peer { #define PEER_DOWN_WAITING_OPEN 32U /* Waiting for open to succeed */ #define PEER_DOWN_PFX_COUNT 33U /* Reached received prefix count */ #define PEER_DOWN_SOCKET_ERROR 34U /* Some socket error happened */ +#define PEER_DOWN_RTT_SHUTDOWN 35U /* Automatically shutdown due to RTT */ /* * Remember to update peer_down_str in bgp_fsm.c when you add * a new value to the last_reset reason