diff options
author | David Schweizer <dschweizer@opensourcerouting.org> | 2020-10-20 16:49:58 +0200 |
---|---|---|
committer | David Schweizer <dschweizer@opensourcerouting.org> | 2020-10-20 16:49:58 +0200 |
commit | 6c537a18cffeee854a3f80cef1fb459d85f37a15 (patch) | |
tree | 414f15c8399655cd10bc113876c957e329831e30 /bgpd/bgp_fsm.c | |
parent | Merge pull request #7645 from sworleys/NHG-IFP-Error2Log (diff) | |
download | frr-6c537a18cffeee854a3f80cef1fb459d85f37a15.tar.xz frr-6c537a18cffeee854a3f80cef1fb459d85f37a15.zip |
bgpd: RFC 4271 DelayOpenTimer
Changes implement the DelayOpenTimer functionality proposed in RFC 4271.
Signed-off-by: David Schweizer <dschweizer@opensourcerouting.org>
Diffstat (limited to 'bgpd/bgp_fsm.c')
-rw-r--r-- | bgpd/bgp_fsm.c | 177 |
1 files changed, 161 insertions, 16 deletions
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index dd31a9b7c..ce665feb4 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -67,12 +67,14 @@ static const char *const bgp_event_str[] = { "BGP_Start", "BGP_Stop", "TCP_connection_open", + "TCP_connection_open_w_delay", "TCP_connection_closed", "TCP_connection_open_failed", "TCP_fatal_error", "ConnectRetry_timer_expired", "Hold_Timer_expired", "KeepAlive_timer_expired", + "DelayOpen_timer_expired", "Receive_OPEN_message", "Receive_KEEPALIVE_message", "Receive_UPDATE_message", @@ -92,6 +94,7 @@ int bgp_event(struct thread *); static int bgp_start_timer(struct thread *); static int bgp_connect_timer(struct thread *); static int bgp_holdtime_timer(struct thread *); +static int bgp_delayopen_timer(struct thread *); /* BGP FSM functions. */ static int bgp_start(struct peer *); @@ -174,10 +177,12 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) BGP_TIMER_OFF(peer->t_routeadv); BGP_TIMER_OFF(peer->t_connect); + BGP_TIMER_OFF(peer->t_delayopen); BGP_TIMER_OFF(peer->t_connect_check_r); BGP_TIMER_OFF(peer->t_connect_check_w); BGP_TIMER_OFF(from_peer->t_routeadv); BGP_TIMER_OFF(from_peer->t_connect); + BGP_TIMER_OFF(from_peer->t_delayopen); BGP_TIMER_OFF(from_peer->t_connect_check_r); BGP_TIMER_OFF(from_peer->t_connect_check_w); BGP_TIMER_OFF(from_peer->t_process_packet); @@ -233,6 +238,7 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) peer->v_holdtime = from_peer->v_holdtime; peer->v_keepalive = from_peer->v_keepalive; peer->v_routeadv = from_peer->v_routeadv; + peer->v_delayopen = from_peer->v_delayopen; peer->v_gr_restart = from_peer->v_gr_restart; peer->cap = from_peer->cap; status = peer->status; @@ -364,6 +370,7 @@ void bgp_timer_set(struct peer *peer) BGP_TIMER_OFF(peer->t_holdtime); bgp_keepalives_off(peer); BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_OFF(peer->t_delayopen); break; case Connect: @@ -371,8 +378,13 @@ void bgp_timer_set(struct peer *peer) status. Make sure start timer is off and connect timer is on. */ BGP_TIMER_OFF(peer->t_start); - BGP_TIMER_ON(peer->t_connect, bgp_connect_timer, - peer->v_connect); + if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN)) + BGP_TIMER_ON(peer->t_connect, bgp_connect_timer, + (peer->v_delayopen + peer->v_connect)); + else + BGP_TIMER_ON(peer->t_connect, bgp_connect_timer, + peer->v_connect); + BGP_TIMER_OFF(peer->t_holdtime); bgp_keepalives_off(peer); BGP_TIMER_OFF(peer->t_routeadv); @@ -387,8 +399,13 @@ void bgp_timer_set(struct peer *peer) || CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) { BGP_TIMER_OFF(peer->t_connect); } else { - BGP_TIMER_ON(peer->t_connect, bgp_connect_timer, - peer->v_connect); + if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN)) + BGP_TIMER_ON( + peer->t_connect, bgp_connect_timer, + (peer->v_delayopen + peer->v_connect)); + else + BGP_TIMER_ON(peer->t_connect, bgp_connect_timer, + peer->v_connect); } BGP_TIMER_OFF(peer->t_holdtime); bgp_keepalives_off(peer); @@ -407,6 +424,7 @@ void bgp_timer_set(struct peer *peer) } bgp_keepalives_off(peer); BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_OFF(peer->t_delayopen); break; case OpenConfirm: @@ -425,6 +443,7 @@ void bgp_timer_set(struct peer *peer) bgp_keepalives_on(peer); } BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_OFF(peer->t_delayopen); break; case Established: @@ -432,6 +451,7 @@ void bgp_timer_set(struct peer *peer) off. */ BGP_TIMER_OFF(peer->t_start); BGP_TIMER_OFF(peer->t_connect); + BGP_TIMER_OFF(peer->t_delayopen); /* Same as OpenConfirm, if holdtime is zero then both holdtime and keepalive must be turned off. */ @@ -455,6 +475,7 @@ void bgp_timer_set(struct peer *peer) BGP_TIMER_OFF(peer->t_holdtime); bgp_keepalives_off(peer); BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_OFF(peer->t_delayopen); break; case BGP_STATUS_MAX: flog_err(EC_LIB_DEVELOPMENT, @@ -488,6 +509,10 @@ static int bgp_connect_timer(struct thread *thread) peer = THREAD_ARG(thread); + /* stop the DelayOpenTimer if it is running */ + if (peer->t_delayopen) + BGP_TIMER_OFF(peer->t_delayopen); + assert(!peer->t_write); assert(!peer->t_read); @@ -564,6 +589,23 @@ int bgp_routeadv_timer(struct thread *thread) return 0; } +/* RFC 4271 DelayOpenTimer */ +int bgp_delayopen_timer(struct thread *thread) +{ + struct peer *peer; + + peer = THREAD_ARG(thread); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Timer (DelayOpentimer expire)", + peer->host); + + THREAD_VAL(thread) = DelayOpen_timer_expired; + bgp_event(thread); /* bgp_event unlocks peer */ + + return 0; +} + /* BGP Peer Down Cause */ const char *const peer_down_str[] = {"", "Router ID changed", @@ -1299,6 +1341,7 @@ int bgp_stop(struct peer *peer) BGP_TIMER_OFF(peer->t_connect); BGP_TIMER_OFF(peer->t_holdtime); BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_OFF(peer->t_delayopen); /* Clear input and output buffer. */ frr_with_mutex(&peer->io_mtx) { @@ -1357,6 +1400,12 @@ int bgp_stop(struct peer *peer) peer->v_holdtime = peer->bgp->default_holdtime; } + /* Reset DelayOpenTime */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN)) + peer->v_delayopen = peer->delayopen; + else + peer->v_delayopen = peer->bgp->default_delayopen; + peer->update_time = 0; /* Until we are sure that there is no problem about prefix count @@ -1469,7 +1518,10 @@ static int bgp_connect_check(struct thread *thread) /* When status is 0 then TCP connection is established. */ if (status == 0) { - BGP_EVENT_ADD(peer, TCP_connection_open); + if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN)) + BGP_EVENT_ADD(peer, TCP_connection_open_w_delay); + else + BGP_EVENT_ADD(peer, TCP_connection_open); return 1; } else { if (bgp_debug_neighbor_events(peer)) @@ -1516,11 +1568,63 @@ static int bgp_connect_success(struct peer *peer) zlog_debug("%s passive open", peer->host); } + /* Send an open message */ bgp_open_send(peer); return 0; } +/* TCP connection open with RFC 4271 optional session attribute DelayOpen flag + * set. + */ +static int bgp_connect_success_w_delayopen(struct peer *peer) +{ + if (peer->fd < 0) { + flog_err(EC_BGP_CONNECT, "%s: peer's fd is negative value %d", + __func__, peer->fd); + bgp_stop(peer); + return -1; + } + + if (bgp_getsockname(peer) < 0) { + flog_err_sys(EC_LIB_SOCKET, + "%s: bgp_getsockname(): failed for peer %s, fd %d", + __func__, peer->host, peer->fd); + bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, + bgp_fsm_error_subcode(peer->status)); + bgp_writes_on(peer); + return -1; + } + + bgp_reads_on(peer); + + if (bgp_debug_neighbor_events(peer)) { + char buf1[SU_ADDRSTRLEN]; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) + zlog_debug("%s open active, local address %s", + peer->host, + sockunion2str(peer->su_local, buf1, + SU_ADDRSTRLEN)); + else + zlog_debug("%s passive open", peer->host); + } + + /* set the DelayOpenTime to the inital value */ + peer->v_delayopen = peer->delayopen; + + /* Start the DelayOpenTimer if it is not already running */ + if (!peer->t_delayopen) + BGP_TIMER_ON(peer->t_delayopen, bgp_delayopen_timer, + peer->v_delayopen); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] BGP OPEN message delayed for %d seconds", + peer->host, peer->delayopen); + + return 0; +} + /* TCP connect fail */ static int bgp_connect_fail(struct peer *peer) { @@ -1535,7 +1639,8 @@ static int bgp_connect_fail(struct peer *peer) } /* This function is the first starting point of all BGP connection. It - try to connect to remote peer with non-blocking IO. */ + * try to connect to remote peer with non-blocking IO. + */ int bgp_start(struct peer *peer) { int status; @@ -1633,6 +1738,7 @@ int bgp_start(struct peer *peer) zlog_debug( "%s [FSM] Connect immediately success, fd %d", peer->host, peer->fd); + BGP_EVENT_ADD(peer, TCP_connection_open); break; case connect_in_progress: @@ -1682,6 +1788,10 @@ static int bgp_reconnect(struct peer *peer) static int bgp_fsm_open(struct peer *peer) { + /* If DelayOpen is active, we may still need to send an open message */ + if ((peer->status == Connect) || (peer->status == Active)) + bgp_open_send(peer); + /* Send keepalive and make keepalive timer */ bgp_keepalive_send(peer); @@ -1709,6 +1819,21 @@ static int bgp_fsm_holdtime_expire(struct peer *peer) return bgp_stop_with_notify(peer, BGP_NOTIFY_HOLD_ERR, 0); } +/* RFC 4271 DelayOpenTimer_Expires event */ +static int bgp_fsm_delayopen_timer_expire(struct peer *peer) +{ + /* Stop the DelayOpenTimer */ + BGP_TIMER_OFF(peer->t_delayopen); + + /* Send open message to peer */ + bgp_open_send(peer); + + /* Set the HoldTimer to a large value (4 minutes) */ + peer->v_holdtime = 245; + + return 0; +} + /* 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) @@ -2089,12 +2214,14 @@ static const struct { {bgp_start, Connect}, /* BGP_Start */ {bgp_stop, Idle}, /* BGP_Stop */ {bgp_stop, Idle}, /* TCP_connection_open */ + {bgp_stop, Idle}, /* TCP_connection_open_w_delay */ {bgp_stop, Idle}, /* TCP_connection_closed */ {bgp_ignore, Idle}, /* TCP_connection_open_failed */ {bgp_stop, Idle}, /* TCP_fatal_error */ {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */ {bgp_ignore, Idle}, /* Hold_Timer_expired */ {bgp_ignore, Idle}, /* KeepAlive_timer_expired */ + {bgp_ignore, Idle}, /* DelayOpen_timer_expired */ {bgp_ignore, Idle}, /* Receive_OPEN_message */ {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */ {bgp_ignore, Idle}, /* Receive_UPDATE_message */ @@ -2106,46 +2233,56 @@ static const struct { {bgp_ignore, Connect}, /* BGP_Start */ {bgp_stop, Idle}, /* BGP_Stop */ {bgp_connect_success, OpenSent}, /* TCP_connection_open */ + {bgp_connect_success_w_delayopen, + Connect}, /* TCP_connection_open_w_delay */ {bgp_stop, Idle}, /* TCP_connection_closed */ {bgp_connect_fail, Active}, /* TCP_connection_open_failed */ {bgp_connect_fail, Idle}, /* TCP_fatal_error */ {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */ {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */ {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */ - {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */ - {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */ - {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ - {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */ - {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ + {bgp_fsm_delayopen_timer_expire, + OpenSent}, /* DelayOpen_timer_expired */ + {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */ + {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */ + {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ + {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */ + {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ }, { /* Active, */ {bgp_ignore, Active}, /* BGP_Start */ {bgp_stop, Idle}, /* BGP_Stop */ {bgp_connect_success, OpenSent}, /* TCP_connection_open */ + {bgp_connect_success_w_delayopen, + Active}, /* TCP_connection_open_w_delay */ {bgp_stop, Idle}, /* TCP_connection_closed */ {bgp_ignore, Active}, /* TCP_connection_open_failed */ {bgp_fsm_exeption, Idle}, /* TCP_fatal_error */ {bgp_start, Connect}, /* ConnectRetry_timer_expired */ {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */ {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */ - {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */ - {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */ - {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ - {bgp_fsm_exeption, Idle}, /* Receive_NOTIFICATION_message */ - {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ + {bgp_fsm_delayopen_timer_expire, + OpenSent}, /* DelayOpen_timer_expired */ + {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */ + {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */ + {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ + {bgp_fsm_exeption, Idle}, /* Receive_NOTIFICATION_message */ + {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ }, { /* OpenSent, */ {bgp_ignore, OpenSent}, /* BGP_Start */ {bgp_stop, Idle}, /* BGP_Stop */ {bgp_stop, Active}, /* TCP_connection_open */ + {bgp_fsm_exeption, Idle}, /* TCP_connection_open_w_delay */ {bgp_stop, Active}, /* TCP_connection_closed */ {bgp_stop, Active}, /* TCP_connection_open_failed */ {bgp_stop, Active}, /* TCP_fatal_error */ {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */ {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */ {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */ + {bgp_fsm_exeption, Idle}, /* DelayOpen_timer_expired */ {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */ {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */ {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */ @@ -2157,12 +2294,14 @@ static const struct { {bgp_ignore, OpenConfirm}, /* BGP_Start */ {bgp_stop, Idle}, /* BGP_Stop */ {bgp_stop, Idle}, /* TCP_connection_open */ + {bgp_fsm_exeption, Idle}, /* TCP_connection_open_w_delay */ {bgp_stop, Idle}, /* TCP_connection_closed */ {bgp_stop, Idle}, /* TCP_connection_open_failed */ {bgp_stop, Idle}, /* TCP_fatal_error */ {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */ {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */ {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */ + {bgp_fsm_exeption, Idle}, /* DelayOpen_timer_expired */ {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */ {bgp_establish, Established}, /* Receive_KEEPALIVE_message */ {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ @@ -2174,12 +2313,14 @@ static const struct { {bgp_ignore, Established}, /* BGP_Start */ {bgp_stop, Clearing}, /* BGP_Stop */ {bgp_stop, Clearing}, /* TCP_connection_open */ + {bgp_fsm_exeption, Idle}, /* TCP_connection_open_w_delay */ {bgp_stop, Clearing}, /* TCP_connection_closed */ {bgp_stop, Clearing}, /* TCP_connection_open_failed */ {bgp_stop, Clearing}, /* TCP_fatal_error */ {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */ {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */ {bgp_ignore, Established}, /* KeepAlive_timer_expired */ + {bgp_fsm_exeption, Idle}, /* DelayOpen_timer_expired */ {bgp_stop, Clearing}, /* Receive_OPEN_message */ {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */ @@ -2193,12 +2334,14 @@ static const struct { {bgp_ignore, Clearing}, /* BGP_Start */ {bgp_stop, Clearing}, /* BGP_Stop */ {bgp_stop, Clearing}, /* TCP_connection_open */ + {bgp_stop, Clearing}, /* TCP_connection_open_w_delay */ {bgp_stop, Clearing}, /* TCP_connection_closed */ {bgp_stop, Clearing}, /* TCP_connection_open_failed */ {bgp_stop, Clearing}, /* TCP_fatal_error */ {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */ {bgp_stop, Clearing}, /* Hold_Timer_expired */ {bgp_stop, Clearing}, /* KeepAlive_timer_expired */ + {bgp_stop, Clearing}, /* DelayOpen_timer_expired */ {bgp_stop, Clearing}, /* Receive_OPEN_message */ {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */ {bgp_stop, Clearing}, /* Receive_UPDATE_message */ @@ -2210,12 +2353,14 @@ static const struct { {bgp_ignore, Deleted}, /* BGP_Start */ {bgp_ignore, Deleted}, /* BGP_Stop */ {bgp_ignore, Deleted}, /* TCP_connection_open */ + {bgp_ignore, Deleted}, /* TCP_connection_open_w_delay */ {bgp_ignore, Deleted}, /* TCP_connection_closed */ {bgp_ignore, Deleted}, /* TCP_connection_open_failed */ {bgp_ignore, Deleted}, /* TCP_fatal_error */ {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */ {bgp_ignore, Deleted}, /* Hold_Timer_expired */ {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */ + {bgp_ignore, Deleted}, /* DelayOpen_timer_expired */ {bgp_ignore, Deleted}, /* Receive_OPEN_message */ {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */ {bgp_ignore, Deleted}, /* Receive_UPDATE_message */ |