diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2005-09-19 16:15:55 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2005-09-19 16:15:55 +0000 |
commit | a61a902ae520e49b92f74ac38df50816399205e6 (patch) | |
tree | f58fb217393497ae99c443c6451811902575b3ad | |
parent | efa6310b5093a2046682e38f1d0b42eae1fbceb0 (diff) |
implement fast reconnects
when a peer drops to IDLE, we have to force him in IDLE for some time to
prevent fast flapping. however, the forced idle time is annoying when the
connection could be re-established immediately, i. e. bgpctl nei $peer clear
or similar.
implement an error counter per peer, increased every time we receive a
notification. when we are in state IDLE and get a connection from the peer
in question, check if the error counter is 1 or smaller. if so, change state
to active and accept the connection, otherwise keep the current behaviour
and reject the connection.
the error counter gets scaled back by the IdleHoldResetTimer that scales the
IdleHoldTime back as well
-rw-r--r-- | usr.sbin/bgpd/session.c | 18 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.h | 4 |
2 files changed, 16 insertions, 6 deletions
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index c6fdc57e90c..4901d585f5c 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.233 2005/09/08 10:46:40 henning Exp $ */ +/* $OpenBSD: session.c,v 1.234 2005/09/19 16:15:54 henning Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> @@ -379,6 +379,7 @@ session_main(struct bgpd_config *config, struct peer *cpeers, p->IdleHoldTime = INTERVAL_IDLE_HOLD_INITIAL; p->IdleHoldResetTimer = 0; + p->errcnt = 0; } else p->IdleHoldResetTimer = time(NULL) + p->IdleHoldTime; @@ -579,7 +580,8 @@ bgp_fsm(struct peer *peer, enum session_events event) if (!peer->depend_ok) peer->ConnectRetryTimer = 0; - else if (peer->conf.passive || peer->conf.template) { + else if (peer->passive || peer->conf.passive || + peer->conf.template) { change_state(peer, STATE_ACTIVE, event); peer->ConnectRetryTimer = 0; } else { @@ -588,6 +590,7 @@ bgp_fsm(struct peer *peer, enum session_events event) time(NULL) + INTERVAL_CONNECTRETRY; session_connect(peer); } + peer->passive = 0; break; default: /* ignore */ @@ -870,9 +873,7 @@ change_state(struct peer *peer, enum session_state state, case STATE_OPENCONFIRM: break; case STATE_ESTABLISHED: - if (peer->IdleHoldTime > INTERVAL_IDLE_HOLD_INITIAL) - peer->IdleHoldResetTimer = - time(NULL) + peer->IdleHoldTime; + peer->IdleHoldResetTimer = time(NULL) + peer->IdleHoldTime; session_up(peer); break; default: /* something seriously fucked */ @@ -913,6 +914,12 @@ session_accept(int listenfd) p = getpeerbyip((struct sockaddr *)&cliaddr); + if (p != NULL && p->state == STATE_IDLE && p->errcnt < 2) { + /* fast reconnect after clear */ + p->passive = 1; + bgp_fsm(p, EVNT_START); + } + if (p != NULL && (p->state == STATE_CONNECT || p->state == STATE_ACTIVE)) { if (p->fd != -1) { @@ -1916,6 +1923,7 @@ parse_notification(struct peer *peer) datalen -= sizeof(subcode); log_notification(peer, errcode, subcode, p, datalen); + peer->errcnt++; if (errcode == ERR_OPEN && subcode == ERR_OPEN_CAPA) { if (datalen == 0) { /* zebra likes to send those.. humbug */ diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h index 950aeb425ea..7f613364c72 100644 --- a/usr.sbin/bgpd/session.h +++ b/usr.sbin/bgpd/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.77 2005/06/04 22:50:20 henning Exp $ */ +/* $OpenBSD: session.h,v 1.78 2005/09/19 16:15:54 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -168,6 +168,7 @@ struct peer { time_t IdleHoldResetTimer; int fd; int lasterr; + u_int errcnt; u_int IdleHoldTime; u_int32_t remote_bgpid; enum session_state state; @@ -175,6 +176,7 @@ struct peer { u_int16_t holdtime; u_int8_t auth_established; u_int8_t depend_ok; + u_int8_t passive; }; struct peer *peers; |