summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_connection.c91
-rw-r--r--bgpd/bgp_connection.h5
-rw-r--r--bgpd/bgp_fsm.c30
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)