From d1adb448435de26af9cea6b16256a8db39a293dd Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 8 Nov 2021 09:48:24 +0100 Subject: [PATCH] bgpd: support TCP keepalive for BGP connection TCP keepalive is enabled once BGP connection is established. New vty commands: bgp tcp-keepalive <1-65535> <1-65535> <1-30> no bgp tcp-keepalive Signed-off-by: Xiaofeng Liu Signed-off-by: Philippe Guibert --- bgpd/bgp_network.c | 26 +++++++++++++++++++++++++ bgpd/bgp_vty.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ bgpd/bgpd.c | 16 ++++++++++++++++ bgpd/bgpd.h | 8 ++++++++ doc/user/bgp.rst | 7 +++++++ 5 files changed, 105 insertions(+) diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 9ecc2ae4e4..9582ec01ed 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -207,6 +207,25 @@ int bgp_md5_set(struct peer *peer) return bgp_md5_set_password(peer, peer->password); } +static void bgp_update_setsockopt_tcp_keepalive(struct bgp *bgp, int fd) +{ + if (!bgp) + return; + if (bgp->tcp_keepalive_idle != 0) { + int ret; + + ret = setsockopt_tcp_keepalive(fd, bgp->tcp_keepalive_idle, + bgp->tcp_keepalive_intvl, + bgp->tcp_keepalive_probes); + if (ret < 0) + zlog_err( + "Can't set TCP keepalive on socket %d, idle %u intvl %u probes %u", + fd, bgp->tcp_keepalive_idle, + bgp->tcp_keepalive_intvl, + bgp->tcp_keepalive_probes); + } +} + int bgp_md5_unset(struct peer *peer) { /* Unset the password from listen socket. */ @@ -415,6 +434,9 @@ static void bgp_accept(struct thread *thread) bgp_socket_set_buffer_size(bgp_sock); + /* Set TCP keepalive when TCP keepalive is enabled */ + bgp_update_setsockopt_tcp_keepalive(bgp, bgp_sock); + /* Check remote IP address */ peer1 = peer_lookup(bgp, &su); @@ -718,12 +740,16 @@ int bgp_connect(struct peer *peer) bgp_socket_set_buffer_size(peer->fd); + /* Set TCP keepalive when TCP keepalive is enabled */ + bgp_update_setsockopt_tcp_keepalive(peer->bgp, peer->fd); + if (bgp_set_socket_ttl(peer, peer->fd) < 0) { peer->last_reset = PEER_DOWN_SOCKET_ERROR; if (bgp_debug_neighbor_events(peer)) zlog_debug("%s: Failure to set socket ttl for connection to %s, error received: %s(%d)", __func__, peer->host, safe_strerror(errno), errno); + return -1; } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 80c8753708..029a6a0f8c 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2335,6 +2335,15 @@ void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp) vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time); } +/* BGP TCP keepalive */ +static void bgp_config_tcp_keepalive(struct vty *vty, struct bgp *bgp) +{ + if (bgp->tcp_keepalive_idle) { + vty_out(vty, " bgp tcp-keepalive %u %u %u\n", + bgp->tcp_keepalive_idle, bgp->tcp_keepalive_intvl, + bgp->tcp_keepalive_probes); + } +} DEFUN (bgp_coalesce_time, bgp_coalesce_time_cmd, @@ -2558,6 +2567,38 @@ DEFUN(no_bgp_minimum_holdtime, no_bgp_minimum_holdtime_cmd, return CMD_SUCCESS; } +DEFPY(bgp_tcp_keepalive, bgp_tcp_keepalive_cmd, + "bgp tcp-keepalive (1-65535)$idle (1-65535)$intvl (1-30)$probes", + BGP_STR + "TCP keepalive parameters\n" + "TCP keepalive idle time (seconds)\n" + "TCP keepalive interval (seconds)\n" + "TCP keepalive maximum probes\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + bgp_tcp_keepalive_set(bgp, (uint16_t)idle, (uint16_t)intvl, + (uint16_t)probes); + + return CMD_SUCCESS; +} + +DEFPY(no_bgp_tcp_keepalive, no_bgp_tcp_keepalive_cmd, + "no bgp tcp-keepalive [(1-65535) (1-65535) (1-30)]", + NO_STR + BGP_STR + "TCP keepalive parameters\n" + "TCP keepalive idle time (seconds)\n" + "TCP keepalive interval (seconds)\n" + "TCP keepalive maximum probes\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + bgp_tcp_keepalive_unset(bgp); + + return CMD_SUCCESS; +} + DEFUN (bgp_client_to_client_reflection, bgp_client_to_client_reflection_cmd, "bgp client-to-client reflection", @@ -17633,6 +17674,9 @@ int bgp_config_write(struct vty *vty) vty_out(vty, " bgp graceful-restart preserve-fw-state\n"); + /* BGP TCP keepalive */ + bgp_config_tcp_keepalive(vty, bgp); + /* Stale timer for RIB */ if (bgp->rib_stale_time != BGP_DEFAULT_RIB_STALE_TIME) vty_out(vty, @@ -19414,6 +19458,10 @@ void bgp_vty_init(void) install_element(BGP_NODE, &neighbor_ttl_security_cmd); install_element(BGP_NODE, &no_neighbor_ttl_security_cmd); + /* "bgp tcp-keepalive" commands */ + install_element(BGP_NODE, &bgp_tcp_keepalive_cmd); + install_element(BGP_NODE, &no_bgp_tcp_keepalive_cmd); + /* "show [ip] bgp memory" commands. */ install_element(VIEW_NODE, &show_bgp_memory_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index bd3e61377a..15b4d7c5a9 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -564,6 +564,21 @@ void bgp_timers_unset(struct bgp *bgp) bgp->default_delayopen = BGP_DEFAULT_DELAYOPEN; } +void bgp_tcp_keepalive_set(struct bgp *bgp, uint16_t keepalive_idle, + uint16_t keepalive_intvl, uint16_t keepalive_probes) +{ + bgp->tcp_keepalive_idle = keepalive_idle; + bgp->tcp_keepalive_intvl = keepalive_intvl; + bgp->tcp_keepalive_probes = keepalive_probes; +} + +void bgp_tcp_keepalive_unset(struct bgp *bgp) +{ + bgp->tcp_keepalive_idle = 0; + bgp->tcp_keepalive_intvl = 0; + bgp->tcp_keepalive_probes = 0; +} + /* BGP confederation configuration. */ void bgp_confederation_id_set(struct bgp *bgp, as_t as) { @@ -3202,6 +3217,7 @@ static struct bgp *bgp_create(as_t *as, const char *name, bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; bgp->default_subgroup_pkt_queue_max = BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX; + bgp_tcp_keepalive_unset(bgp); bgp_timers_unset(bgp); bgp->default_min_holdtime = 0; bgp->restart_time = BGP_DEFAULT_RESTART_TIME; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index bcb214873f..2d6b78d509 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -132,6 +132,7 @@ struct bgp_master { /* Various BGP global configuration. */ uint8_t options; + #define BGP_OPT_NO_FIB (1 << 0) #define BGP_OPT_NO_LISTEN (1 << 1) #define BGP_OPT_NO_ZEBRA (1 << 2) @@ -768,6 +769,10 @@ struct bgp { char srv6_locator_name[SRV6_LOCNAME_SIZE]; struct list *srv6_locator_chunks; struct list *srv6_functions; + /* TCP keepalive parameters for BGP connection */ + uint16_t tcp_keepalive_idle; + uint16_t tcp_keepalive_intvl; + uint16_t tcp_keepalive_probes; struct timeval ebgprequirespolicywarning; #define FIFTEENMINUTE2USEC (int64_t)15 * 60 * 1000000 @@ -2201,6 +2206,9 @@ extern int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, const char *rmap, struct route_map *route_map); extern int peer_default_originate_unset(struct peer *, afi_t, safi_t); +extern void bgp_tcp_keepalive_set(struct bgp *bgp, uint16_t idle, + uint16_t interval, uint16_t probes); +extern void bgp_tcp_keepalive_unset(struct bgp *bgp); extern void peer_port_set(struct peer *, uint16_t); extern void peer_port_unset(struct peer *); diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index daaf80ae07..7993dd96c2 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1781,6 +1781,13 @@ Configuring Peers with lower holdtime less than configured minimum holdtime. When this command is not set, minimum holdtime does not work. +.. clicmd:: bgp tcp-keepalive (1-65535) (1-65535) (1-30) + + This command allows user to configure TCP keepalive with new BGP peers. + Each parameter respectively stands for TCP keepalive idle timer (seconds), + interval (seconds), and maximum probes. By default, TCP keepalive is + disabled. + Displaying Information about Peers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- 2.39.5