diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2013-06-04 01:32:17 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2013-06-04 01:32:17 +0000 |
commit | 9b63abab052ebdcdfdc6898968467164ad5f9b68 (patch) | |
tree | 01c569989facc8e8a980dc12f91d8a1435966893 /usr.sbin/ldpd | |
parent | 573766d7d96d4af6ea437216079d8c23e40f2c01 (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
Diffstat (limited to 'usr.sbin/ldpd')
-rw-r--r-- | usr.sbin/ldpd/init.c | 5 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldp.h | 3 | ||||
-rw-r--r-- | usr.sbin/ldpd/ldpe.h | 3 | ||||
-rw-r--r-- | usr.sbin/ldpd/neighbor.c | 30 | ||||
-rw-r--r-- | usr.sbin/ldpd/notification.c | 8 |
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); } |