diff options
-rw-r--r-- | bgpd/bgp_connection.c | 91 | ||||
-rw-r--r-- | bgpd/bgp_connection.h | 5 | ||||
-rw-r--r-- | bgpd/bgp_fsm.c | 30 |
3 files changed, 58 insertions, 68 deletions
diff --git a/bgpd/bgp_connection.c b/bgpd/bgp_connection.c index 43a4fbc0..d9a22729 100644 --- a/bgpd/bgp_connection.c +++ b/bgpd/bgp_connection.c @@ -129,7 +129,6 @@ bgp_connection_init_new(bgp_connection connection, bgp_session session, * * read_pending nothing pending * * read_header not reading header * * notification_pending nothing pending - * * wbuff_full not full * * wbuff all pointers NULL -- empty buffer */ @@ -220,18 +219,19 @@ bgp_connection_make_primary(bgp_connection connection) /* Deal with the connection ordinal. */ if (connection->ordinal != bgp_connection_primary) { + assert(session->connections[bgp_connection_primary] == NULL) ; + session->connections[connection->ordinal] = NULL ; connection->ordinal = bgp_connection_primary ; - session->connections[bgp_connection_primary] = connection ; + session->connections[connection->ordinal] = connection ; } ; - session->connections[bgp_connection_secondary] = NULL ; + assert(session->connections[bgp_connection_secondary] == NULL) ; /* Move the open_state to the session. * Change the connection host to drop the primary/secondary distinction. * Copy the negotiated hold_timer_interval and keepalive_timer_interval * Copy the su_local and su_remote */ - session->open_recv = connection->open_recv ; connection->open_recv = NULL ; /* no longer interested in this */ @@ -244,10 +244,8 @@ bgp_connection_make_primary(bgp_connection connection) session->as4 = connection->as4 ; session->route_refresh_pre = connection->route_refresh_pre ; - session->su_local = connection->su_local ; - connection->su_local = NULL ; - session->su_remote = connection->su_remote ; - connection->su_remote = NULL ; + sockunion_set_mov(&session->su_local, &connection->su_local) ; + sockunion_set_mov(&session->su_remote, &connection->su_remote) ; } ; /*------------------------------------------------------------------------------ @@ -258,7 +256,7 @@ bgp_connection_make_primary(bgp_connection connection) extern void bgp_connection_exit(bgp_connection connection) { - bgp_connection_close(connection) ; /* make sure */ + bgp_connection_close(connection, 1) ; /* make sure */ assert( (connection->state == bgp_fsm_Stopping) && (connection->session == NULL) ) ; @@ -287,10 +285,10 @@ bgp_connection_free(bgp_connection connection) assert( (connection->state == bgp_fsm_Stopping) && (connection->session == NULL) ) ; - /* Make sure is closed, so no active file, no active timers, pending queue - * is empty, not on the connection queue, etc. + /* Make sure is closed, so no active file, no timers, pending queue is empty, + * not on the connection queue, etc. */ - bgp_connection_close(connection) ; + bgp_connection_close(connection, 1) ; /* Free any components which still exist */ bgp_notify_unset(&connection->notification) ; @@ -449,6 +447,11 @@ bgp_connection_queue_process(void) * * Expects connection to either be newly created or recently closed. * + * Resets: + * + * * closes any file that may be lingering (should never be) + * * resets all buffering (should all be empty) + * * Sets: * * * if accept() clears the session accept flag @@ -460,14 +463,14 @@ bgp_connection_queue_process(void) * Expects: * * * links to/from session to be set up (including ordinal) - * * timers to be initialised and unset + * * timers to be initialised * * log and host to be set up - * * buffers to exist and all buffering to be set empty - * * pending queue to be empty + * * buffers to exist * * Does not touch: * * * state of the connection (including post event) + * * timers -- FSM looks after those * * NB: requires the session to be LOCKED. */ @@ -476,9 +479,9 @@ bgp_connection_open(bgp_connection connection, int fd) { bgp_session session = connection->session ; + /* Make sure that there is no file and that buffers are clear, etc. */ /* If this is the secondary connection, do not accept any more. */ - if (connection->ordinal == bgp_connection_secondary) - bgp_connection_disable_accept(connection) ; + bgp_connection_close(connection, 0) ; /* Set the file going */ qps_add_file(bgp_nexus->selection, &connection->qf, fd, connection) ; @@ -488,9 +491,7 @@ bgp_connection_open(bgp_connection connection, int fd) bgp_notify_unset(&connection->notification) ; connection->err = 0 ; /* so far, so good */ - /* These accept NULL arguments */ - connection->open_recv = bgp_open_state_free(connection->open_recv) ; - bgp_notify_unset(&connection->notification) ; + bgp_open_state_unset(connection->open_recv) ; /* Copy the original hold_timer_interval and keepalive_timer_interval * Assume these have sensible initial values. @@ -527,11 +528,13 @@ bgp_connection_disable_accept(bgp_connection connection) * * if there is an fd, close it * * if qfile is active, remove it * * forget any addresses - * * unset any timers * * reset all buffering to empty * * empties the pending queue -- destroying all messages + * * * for secondary connection: disable accept * + * * if required: unset all timers + * * The following remain: * * * state of the connection @@ -550,12 +553,29 @@ bgp_connection_disable_accept(bgp_connection connection) * * bgp_connection_free() -- to finally discard * * * bgp_connection_close() -- can do this again - * */ extern void -bgp_connection_close(bgp_connection connection) +bgp_connection_close(bgp_connection connection, int unset_timers) { - bgp_connection_close_file(connection) ; + int fd ; + + /* Close connection's file, if any. */ + qps_remove_file(&connection->qf) ; + + fd = qps_file_unset_fd(&connection->qf) ; + if (fd != fd_undef) +#if 0 + close(fd) ; +#else + shutdown(fd, SHUT_RDWR) ; +#endif + + /* If required, unset the timers. */ + if (unset_timers) + { + qtimer_unset(&connection->hold_timer) ; + qtimer_unset(&connection->keepalive_timer) ; + } ; /* If this is the secondary connection, do not accept any more. */ if (connection->ordinal == bgp_connection_secondary) @@ -565,10 +585,6 @@ bgp_connection_close(bgp_connection connection) sockunion_unset(&connection->su_local) ; sockunion_unset(&connection->su_remote) ; - /* Unset all the timers */ - qtimer_unset(&connection->hold_timer) ; - qtimer_unset(&connection->keepalive_timer) ; - /* Reset all buffering empty. */ stream_reset(connection->ibuf) ; stream_reset(connection->obuf) ; @@ -586,25 +602,6 @@ bgp_connection_close(bgp_connection connection) } ; /*------------------------------------------------------------------------------ - * Close connection's file, if any. - * - * * if there is an fd, close it - * * if qfile is active, remove it - */ -extern void -bgp_connection_close_file(bgp_connection connection) -{ - int fd ; - - qps_remove_file(&connection->qf) ; - - fd = qps_file_unset_fd(&connection->qf) ; - if (fd != fd_undef) - shutdown(fd, SHUT_RDWR) ; - -} ; - -/*------------------------------------------------------------------------------ * Close connection for reading and purge the write buffers. * * This is done when the connection is about to be fully closed, but need to diff --git a/bgpd/bgp_connection.h b/bgpd/bgp_connection.h index 7a349974..2bffc5be 100644 --- a/bgpd/bgp_connection.h +++ b/bgpd/bgp_connection.h @@ -192,10 +192,7 @@ extern void bgp_connection_make_primary(bgp_connection connection) ; extern void -bgp_connection_close(bgp_connection connection) ; - -extern void -bgp_connection_close_file(bgp_connection connection) ; +bgp_connection_close(bgp_connection connection, int unset_timers) ; extern void bgp_connection_part_close(bgp_connection connection) ; diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 2d06cb2a..35cbbfa1 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1826,17 +1826,10 @@ static bgp_fsm_action(bgp_fsm_fatal) * If the connection failed, the connection will have been closed. For the * secondary connection accept() will have been disabled. * - * For primary connection: - * - * * close the attempt to connect() (if still active) - * * start the connect() attempt again - * - * For secondary connection: - * - * * re-enable accept (if has been cleared) and wait for same - * - * If no accept() has been attempted, then accept will still be enabled, - * and re-enabling it will make no difference. + * In any case, close the connection (but leave timers running) and then + * start a new attempt to connect (for secondary connection this momentarily + * disables and then enables accept(), but won't do a pselect until after + * that bounce. * * NB: the connection remains in the current state, and the retry timer will * still be running, because it automatically recharges. @@ -1845,8 +1838,7 @@ static bgp_fsm_action(bgp_fsm_fatal) */ static bgp_fsm_action(bgp_fsm_retry) { - if (connection->ordinal == bgp_connection_primary) - bgp_connection_close_file(connection) ; + bgp_connection_close(connection, 0) ; /* FSM does timers */ bgp_fsm_post_exception(connection, bgp_session_eRetry, NULL, 0) ; @@ -1881,7 +1873,7 @@ static bgp_fsm_action(bgp_fsm_expire) /* The process of sending a NOTIFICATION comes to an end here. */ if (connection->notification_pending) { - bgp_connection_close(connection) ; + bgp_connection_close(connection, 0) ; /* FSM deals with timers */ return next_state ; } ; @@ -2113,7 +2105,7 @@ static bgp_fsm_action(bgp_fsm_exit) * * Sending NOTIFICATION closes the connection for reading. * - * 1b) otherwise: close the connection. + * 1b) otherwise: close the connection file. * * 2) if next state is Stopping, and not eDiscard * @@ -2136,7 +2128,10 @@ static bgp_fsm_state_t bgp_fsm_catch(bgp_connection connection, bgp_fsm_state_t next_state) { /* If there is a NOTIFICATION to send, now is the time to do that. - * Otherwise, close the connection. + * Otherwise, close the connection but leave the timers. + * + * The state transition stuff looks after timers. In particular an error + * in Connect/Active states leaves the ConnectRetryTimer running. */ if ( (connection->notification != NULL) && (connection->except != bgp_session_eNOM_recv) ) @@ -2144,7 +2139,8 @@ bgp_fsm_catch(bgp_connection connection, bgp_fsm_state_t next_state) next_state = bgp_fsm_send_notification(connection, next_state) ; } else - bgp_connection_close(connection) ; + bgp_connection_close(connection, 0) ; /* FSM deals with timers */ + /* If stopping and not eDiscard, do in any sibling */ if ( (next_state == bgp_fsm_Stopping) |