diff options
author | Renato Westphal <renato@cvs.openbsd.org> | 2016-06-13 20:19:41 +0000 |
---|---|---|
committer | Renato Westphal <renato@cvs.openbsd.org> | 2016-06-13 20:19:41 +0000 |
commit | 6c049eef8f288bea7deaa6dc9bc2672f93802b3f (patch) | |
tree | ebeb6a69eddc28f40b1e926626a104e3ae04771b /usr.sbin/ldpd | |
parent | 8d0c21ec0c22a79077078afaab1297007e6c19bf (diff) |
Implement a timeout for the session initialization FSM.
This prevents neighbors stuck in the initialization FSM to linger forever
as long as the associated transport connection is up.
This timeout can be seen in the 'Session Initialization State Transition
Diagram' of RFC 5036. The RFC, however, doesn't specify how much we
should wait. Let's use 180 seconds for that, the default LDP hold time.
Fixes IxANVL LDP test 6.15.
Diffstat (limited to 'usr.sbin/ldpd')
-rw-r--r-- | usr.sbin/ldpd/ldpe.h | 4 | ||||
-rw-r--r-- | usr.sbin/ldpd/neighbor.c | 42 | ||||
-rw-r--r-- | usr.sbin/ldpd/packet.c | 3 |
3 files changed, 46 insertions, 3 deletions
diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h index 52a10a60d22..62341870b52 100644 --- a/usr.sbin/ldpd/ldpe.h +++ b/usr.sbin/ldpd/ldpe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ldpe.h,v 1.59 2016/06/11 01:46:36 renato Exp $ */ +/* $OpenBSD: ldpe.h,v 1.60 2016/06/13 20:19:40 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -68,6 +68,7 @@ struct nbr { struct event ev_connect; struct event keepalive_timer; struct event keepalive_timeout; + struct event init_timeout; struct event initdelay_timer; struct mapping_head mapping_list; @@ -228,6 +229,7 @@ int nbr_adj_count(struct nbr *, int); int nbr_session_active_role(struct nbr *); void nbr_stop_ktimer(struct nbr *); void nbr_stop_ktimeout(struct nbr *); +void nbr_stop_itimeout(struct nbr *); void nbr_start_idtimer(struct nbr *); void nbr_stop_idtimer(struct nbr *); int nbr_pending_idtimer(struct nbr *); diff --git a/usr.sbin/ldpd/neighbor.c b/usr.sbin/ldpd/neighbor.c index 5755bd1fa11..4b607c0ce3f 100644 --- a/usr.sbin/ldpd/neighbor.c +++ b/usr.sbin/ldpd/neighbor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: neighbor.c,v 1.72 2016/05/23 19:20:55 renato Exp $ */ +/* $OpenBSD: neighbor.c,v 1.73 2016/06/13 20:19:40 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -41,6 +41,8 @@ static void nbr_ktimer(int, short, void *); static void nbr_start_ktimer(struct nbr *); static void nbr_ktimeout(int, short, void *); static void nbr_start_ktimeout(struct nbr *); +static void nbr_itimeout(int, short, void *); +static void nbr_start_itimeout(struct nbr *); static void nbr_idtimer(int, short, void *); static int nbr_act_session_operational(struct nbr *); static void nbr_send_labelmappings(struct nbr *); @@ -164,6 +166,11 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event) } } + if (nbr->state == NBR_STA_OPER || nbr->state == NBR_STA_PRESENT) + nbr_stop_itimeout(nbr); + else + nbr_start_itimeout(nbr); + switch (nbr_fsm_tbl[i].action) { case NBR_ACT_RST_KTIMEOUT: nbr_start_ktimeout(nbr); @@ -259,6 +266,7 @@ nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr, /* set event structures */ evtimer_set(&nbr->keepalive_timeout, nbr_ktimeout, nbr); evtimer_set(&nbr->keepalive_timer, nbr_ktimer, nbr); + evtimer_set(&nbr->init_timeout, nbr_itimeout, nbr); evtimer_set(&nbr->initdelay_timer, nbr_idtimer, nbr); nbrp = nbr_params_find(leconf, nbr->id); @@ -286,6 +294,7 @@ nbr_del(struct nbr *nbr) event_del(&nbr->ev_connect); nbr_stop_ktimer(nbr); nbr_stop_ktimeout(nbr); + nbr_stop_itimeout(nbr); nbr_stop_idtimer(nbr); mapping_list_clr(&nbr->mapping_list); @@ -431,6 +440,37 @@ nbr_stop_ktimeout(struct nbr *nbr) fatal(__func__); } +/* Session initialization timeout: if nbr got stuck in the initialization FSM */ + +static void +nbr_itimeout(int fd, short event, void *arg) +{ + struct nbr *nbr = arg; + + log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); + + nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); +} + +static void +nbr_start_itimeout(struct nbr *nbr) +{ + struct timeval tv; + + timerclear(&tv); + tv.tv_sec = DEFAULT_KEEPALIVE; + if (evtimer_add(&nbr->init_timeout, &tv) == -1) + fatal(__func__); +} + +void +nbr_stop_itimeout(struct nbr *nbr) +{ + if (evtimer_pending(&nbr->init_timeout, NULL) && + evtimer_del(&nbr->init_timeout) == -1) + fatal(__func__); +} + /* Init delay timer: timer to retry to iniziatize session */ static void diff --git a/usr.sbin/ldpd/packet.c b/usr.sbin/ldpd/packet.c index f8a7f45549b..a804a7f7c24 100644 --- a/usr.sbin/ldpd/packet.c +++ b/usr.sbin/ldpd/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.62 2016/06/13 20:13:34 renato Exp $ */ +/* $OpenBSD: packet.c,v 1.63 2016/06/13 20:19:40 renato Exp $ */ /* * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> @@ -648,6 +648,7 @@ session_close(struct nbr *nbr) tcp_close(nbr->tcp); nbr_stop_ktimer(nbr); nbr_stop_ktimeout(nbr); + nbr_stop_itimeout(nbr); } static ssize_t |