summaryrefslogtreecommitdiff
path: root/proto/bgp/bgp.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2013-07-13 01:39:41 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2013-07-13 01:39:41 +0200
commit48b15ef10fede35113af71bd0dbb0b27a5fcb8f5 (patch)
tree334e4f6dc25cbbbab792f47ba812e81ce0060c73 /proto/bgp/bgp.c
parent354496ace87341428e6005fbc073fbe57b4e6c0e (diff)
Fixes stuck connection during BGP session shutdown.
If TX buffers were full during BGP session shutdown then a protocol waited indefinitely to be able to send notification packet to close the session.
Diffstat (limited to 'proto/bgp/bgp.c')
-rw-r--r--proto/bgp/bgp.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index b1594b92..32153452 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -384,10 +384,12 @@ bgp_conn_enter_close_state(struct bgp_conn *conn)
int os = conn->state;
bgp_conn_set_state(conn, BS_CLOSE);
- tm_stop(conn->hold_timer);
tm_stop(conn->keepalive_timer);
conn->sk->rx_hook = NULL;
+ /* Timeout for CLOSE state, if we cannot send notification soon then we just hangup */
+ bgp_start_timer(conn->hold_timer, 10);
+
if (os == BS_ESTABLISHED)
bgp_conn_leave_established_state(p);
}
@@ -478,9 +480,18 @@ static void
bgp_hold_timeout(timer *t)
{
struct bgp_conn *conn = t->data;
+ struct bgp_proto *p = conn->bgp;
DBG("BGP: Hold timeout\n");
+ /* We are already closing the connection - just do hangup */
+ if (conn->state == BS_CLOSE)
+ {
+ BGP_TRACE(D_EVENTS, "Connection stalled");
+ bgp_conn_enter_idle_state(conn);
+ return;
+ }
+
/* If there is something in input queue, we are probably congested
and perhaps just not processed BGP packets in time. */