summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2013-06-04 01:32:17 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2013-06-04 01:32:17 +0000
commit9b63abab052ebdcdfdc6898968467164ad5f9b68 (patch)
tree01c569989facc8e8a980dc12f91d8a1435966893
parent573766d7d96d4af6ea437216079d8c23e40f2c01 (diff)
Properly implement the exponential backoff timer on session initialization
According with the section 2.5.3 of RFC 5036, an LSR must throttle its session setup retry attempts with an exponential backoff in situations where Initialization messages are being NAK'd (because of disagreements on session parameters). It doesn't mention using this procedure for TCP connection failures. With that said, start the inactive delay timer only after receiving an appropriate notification message. When playing the active role of the initialization process, throttle the session setup retry attempts by not connecting to the remote peer. When playing the passive role, throttle the session setup retry attempts by delaying the processing of the received Initialization message. Diff by Renato Westphal, adjusted by myself
-rw-r--r--usr.sbin/ldpd/init.c5
-rw-r--r--usr.sbin/ldpd/ldp.h3
-rw-r--r--usr.sbin/ldpd/ldpe.h3
-rw-r--r--usr.sbin/ldpd/neighbor.c30
-rw-r--r--usr.sbin/ldpd/notification.c8
5 files changed, 37 insertions, 12 deletions
diff --git a/usr.sbin/ldpd/init.c b/usr.sbin/ldpd/init.c
index 0a940e562dd..90937841f53 100644
--- a/usr.sbin/ldpd/init.c
+++ b/usr.sbin/ldpd/init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init.c,v 1.10 2013/06/01 19:28:55 claudio Exp $ */
+/* $OpenBSD: init.c,v 1.11 2013/06/04 01:32:16 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -107,7 +107,8 @@ recv_init(struct nbr *nbr, char *buf, u_int16_t len)
else
nbr->keepalive = ntohs(sess.keepalive_time);
- nbr_fsm(nbr, NBR_EVT_INIT_RCVD);
+ if (!nbr_pending_idtimer(nbr))
+ nbr_fsm(nbr, NBR_EVT_INIT_RCVD);
return (ntohs(init.length));
}
diff --git a/usr.sbin/ldpd/ldp.h b/usr.sbin/ldpd/ldp.h
index b810d19a3dd..115d23deae8 100644
--- a/usr.sbin/ldpd/ldp.h
+++ b/usr.sbin/ldpd/ldp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldp.h,v 1.11 2013/06/01 01:34:57 claudio Exp $ */
+/* $OpenBSD: ldp.h,v 1.12 2013/06/04 01:32:16 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -49,6 +49,7 @@
#define MAX_HELLO_INTERVAL 0xffff /* XXX */
#define INIT_DELAY_TMR 15
+#define MAX_DELAY_TMR 120
#define DEFAULT_NBR_TMOUT 86400 /* 24 hours */
/* LDP message types */
diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h
index 8b0976aa990..ee70736ca29 100644
--- a/usr.sbin/ldpd/ldpe.h
+++ b/usr.sbin/ldpd/ldpe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.h,v 1.23 2013/06/04 00:56:49 claudio Exp $ */
+/* $OpenBSD: ldpe.h,v 1.24 2013/06/04 01:32:16 claudio Exp $ */
/*
* Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
@@ -60,6 +60,7 @@ struct nbr {
int fd;
int state;
+ int idtimer_cnt;
u_int16_t holdtime;
u_int16_t keepalive;
diff --git a/usr.sbin/ldpd/neighbor.c b/usr.sbin/ldpd/neighbor.c
index 907f7015ae2..13b2df1d0c4 100644
--- a/usr.sbin/ldpd/neighbor.c
+++ b/usr.sbin/ldpd/neighbor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: neighbor.c,v 1.34 2013/06/04 00:56:49 claudio Exp $ */
+/* $OpenBSD: neighbor.c,v 1.35 2013/06/04 01:32:16 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -219,7 +219,6 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event)
ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0,
NULL, 0);
session_close(nbr);
- nbr_start_idtimer(nbr);
break;
case NBR_ACT_NOTHING:
/* do nothing */
@@ -446,13 +445,13 @@ nbr_idtimer(int fd, short event, void *arg)
{
struct nbr *nbr = arg;
- if (!nbr_session_active_role(nbr))
- return;
-
log_debug("nbr_idtimer: neighbor ID %s peerid %lu", inet_ntoa(nbr->id),
nbr->peerid);
- nbr_establish_connection(nbr);
+ if (nbr_session_active_role(nbr))
+ nbr_establish_connection(nbr);
+ else if (nbr->state == NBR_STA_INITIAL)
+ nbr_fsm(nbr, NBR_EVT_INIT_RCVD);
}
void
@@ -461,7 +460,23 @@ nbr_start_idtimer(struct nbr *nbr)
struct timeval tv;
timerclear(&tv);
+
tv.tv_sec = INIT_DELAY_TMR;
+ switch(nbr->idtimer_cnt) {
+ default:
+ /* do not further increase the counter */
+ tv.tv_sec = MAX_DELAY_TMR;
+ break;
+ case 2:
+ tv.tv_sec *= 2;
+ /* FALLTHROUGH */
+ case 1:
+ tv.tv_sec *= 2;
+ /* FALLTHROUGH */
+ case 0:
+ nbr->idtimer_cnt++;
+ break;
+ }
if (evtimer_add(&nbr->initdelay_timer, &tv) == -1)
fatal("nbr_start_idtimer");
@@ -561,7 +576,6 @@ nbr_establish_connection(struct nbr *nbr)
}
log_debug("nbr_establish_connection: error while "
"connecting to %s", inet_ntoa(nbr->addr));
- nbr_start_idtimer(nbr);
close(nbr->fd);
return (-1);
}
@@ -585,6 +599,8 @@ nbr_act_session_operational(struct nbr *nbr)
{
struct lde_nbr rn;
+ nbr->idtimer_cnt = 0;
+
bzero(&rn, sizeof(rn));
rn.id.s_addr = nbr->id.s_addr;
diff --git a/usr.sbin/ldpd/notification.c b/usr.sbin/ldpd/notification.c
index 580167e5568..be57dd1acc4 100644
--- a/usr.sbin/ldpd/notification.c
+++ b/usr.sbin/ldpd/notification.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: notification.c,v 1.12 2013/06/01 19:42:07 claudio Exp $ */
+/* $OpenBSD: notification.c,v 1.13 2013/06/04 01:32:16 claudio Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -111,6 +111,12 @@ recv_notification(struct nbr *nbr, char *buf, u_int16_t len)
notification_name(ntohl(st.status_code)));
if (st.status_code & htonl(STATUS_FATAL)) {
+ if (st.status_code == htonl(S_NO_HELLO) ||
+ st.status_code == htonl(S_PARM_ADV_MODE) ||
+ st.status_code == htonl(S_MAX_PDU_LEN) ||
+ st.status_code == htonl(S_PARM_L_RANGE))
+ nbr_start_idtimer(nbr);
+
nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
return (-1);
}