summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2005-09-19 16:15:55 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2005-09-19 16:15:55 +0000
commita61a902ae520e49b92f74ac38df50816399205e6 (patch)
treef58fb217393497ae99c443c6451811902575b3ad
parentefa6310b5093a2046682e38f1d0b42eae1fbceb0 (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.c18
-rw-r--r--usr.sbin/bgpd/session.h4
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;