diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index b62a42a4f6..0f2926d060 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -2196,7 +2196,8 @@ void bgp_fsm_nht_update(struct peer *peer, bool has_valid_nexthops) case OpenConfirm: case Established: if (!has_valid_nexthops - && (peer->gtsm_hops == BGP_GTSM_HOPS_CONNECTED)) + && (peer->gtsm_hops == BGP_GTSM_HOPS_CONNECTED + || peer->bgp->fast_convergence)) BGP_EVENT_ADD(peer, TCP_fatal_error); case Clearing: case Deleted: diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 63b2fbd4e6..ebd6e92d9b 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -4158,6 +4158,28 @@ DEFUN (neighbor_remote_as, return peer_remote_as_vty(vty, argv[idx_peer]->arg, argv[idx_remote_as]->arg); } +/* Enable fast convergence of bgp sessions. If this is enabled, bgp + * sessions do not wait for hold timer expiry to bring down the sessions + * when nexthop becomes unreachable + */ +DEFUN(bgp_fast_convergence, bgp_fast_convergence_cmd, "bgp fast-convergence", + BGP_STR "Fast convergence for bgp sessions\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp->fast_convergence = true; + + return CMD_SUCCESS; +} + +DEFUN(no_bgp_fast_convergence, no_bgp_fast_convergence_cmd, + "no bgp fast-convergence", + NO_STR BGP_STR "Fast convergence for bgp sessions\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp->fast_convergence = false; + + return CMD_SUCCESS; +} static int peer_conf_interface_get(struct vty *vty, const char *conf_if, int v6only, @@ -17147,6 +17169,9 @@ int bgp_config_write(struct vty *vty) if (CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN)) vty_out(vty, " bgp shutdown\n"); + if (bgp->fast_convergence) + vty_out(vty, " bgp fast-convergence\n"); + if (bgp->srv6_enabled) { vty_frame(vty, " !\n segment-routing srv6\n"); if (strlen(bgp->srv6_locator_name)) @@ -17410,6 +17435,10 @@ void bgp_vty_init(void) install_element(CONFIG_NODE, &bgp_set_route_map_delay_timer_cmd); install_element(CONFIG_NODE, &no_bgp_set_route_map_delay_timer_cmd); + /* bgp fast-convergence command */ + install_element(BGP_NODE, &bgp_fast_convergence_cmd); + install_element(BGP_NODE, &no_bgp_fast_convergence_cmd); + /* global bgp update-delay command */ install_element(CONFIG_NODE, &bgp_global_update_delay_cmd); install_element(CONFIG_NODE, &no_bgp_global_update_delay_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 591fc1214c..1c558cc550 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3165,7 +3165,7 @@ static struct bgp *bgp_create(as_t *as, const char *name, bgp->reject_as_sets = false; bgp->condition_check_period = DEFAULT_CONDITIONAL_ROUTES_POLL_TIME; bgp_addpath_init_bgp_data(&bgp->tx_addpath); - + bgp->fast_convergence = false; bgp->as = *as; #ifdef ENABLE_BGP_VNC diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 867062a88b..ed7642f315 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -746,6 +746,8 @@ struct bgp { /* Process Queue for handling routes */ struct work_queue *process_queue; + bool fast_convergence; + /* BGP Conditional advertisement */ uint32_t condition_check_period; uint32_t condition_filter_count;