From: Rafael Zalamena Date: Tue, 15 Jan 2019 22:23:06 +0000 (-0200) Subject: bfdd: refactor state change handler X-Git-Tag: 7.1_pulled~230^2~18 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=aef131afc5fd722b34c4503e35753283530dfdc8;p=matthieu%2Ffrr.git bfdd: refactor state change handler Expand state change handling into smaller functions with more explanatory commentaries. This also handles some corner cases that were not being handled. Signed-off-by: Rafael Zalamena --- diff --git a/bfdd/bfd.c b/bfdd/bfd.c index df263a91c9..235f9c06a8 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -694,6 +694,129 @@ void bfd_set_polling(struct bfd_session *bs) bs->polling = 1; } +/* + * bs__handler() functions implement the BFD state machine + * transition mechanism. `` is the current session state and + * the parameter `nstate` is the peer new state. + */ +void bs_admin_down_handler(struct bfd_session *bs, int nstate); +void bs_down_handler(struct bfd_session *bs, int nstate); +void bs_init_handler(struct bfd_session *bs, int nstate); +void bs_up_handler(struct bfd_session *bs, int nstate); + +void bs_admin_down_handler(struct bfd_session *bs __attribute__((__unused__)), + int nstate __attribute__((__unused__))) +{ + /* + * We are administratively down, there is no state machine + * handling. + */ +} + +void bs_down_handler(struct bfd_session *bs, int nstate) +{ + switch (nstate) { + case PTM_BFD_ADM_DOWN: + /* + * Remote peer doesn't want to talk, so lets keep the + * connection down. + */ + case PTM_BFD_UP: + /* Peer can't be up yet, wait it go to 'init' or 'down'. */ + break; + + case PTM_BFD_DOWN: + /* + * Remote peer agreed that the path is down, lets try to + * bring it up. + */ + bs->ses_state = PTM_BFD_INIT; + break; + + case PTM_BFD_INIT: + /* + * Remote peer told us his path is up, lets turn + * activate the session. + */ + ptm_bfd_ses_up(bs); + break; + + default: + log_debug("state-change: unhandled neighbor state: %d", nstate); + break; + } +} + +void bs_init_handler(struct bfd_session *bs, int nstate) +{ + switch (nstate) { + case PTM_BFD_ADM_DOWN: + /* + * Remote peer doesn't want to talk, so lets make the + * connection down. + */ + bs->ses_state = PTM_BFD_DOWN; + break; + + case PTM_BFD_DOWN: + /* Remote peer hasn't moved to first stage yet. */ + break; + + case PTM_BFD_INIT: + case PTM_BFD_UP: + /* We agreed on the settings and the path is up. */ + ptm_bfd_ses_up(bs); + break; + + default: + log_debug("state-change: unhandled neighbor state: %d", nstate); + break; + } +} + +void bs_up_handler(struct bfd_session *bs, int nstate) +{ + switch (nstate) { + case PTM_BFD_ADM_DOWN: + case PTM_BFD_DOWN: + /* Peer lost or asked to shutdown connection. */ + ptm_bfd_ses_dn(bs, BD_NEIGHBOR_DOWN); + break; + + case PTM_BFD_INIT: + case PTM_BFD_UP: + /* Path is up and working. */ + break; + + default: + log_debug("state-change: unhandled neighbor state: %d", nstate); + break; + } +} + +void bs_state_handler(struct bfd_session *bs, int nstate) +{ + switch (bs->ses_state) { + case PTM_BFD_ADM_DOWN: + bs_admin_down_handler(bs, nstate); + break; + case PTM_BFD_DOWN: + bs_down_handler(bs, nstate); + break; + case PTM_BFD_INIT: + bs_init_handler(bs, nstate); + break; + case PTM_BFD_UP: + bs_up_handler(bs, nstate); + break; + + default: + log_debug("state-change: [%s] is in invalid state: %d", + bs_to_string(bs), nstate); + break; + } +} + /* * Helper functions. diff --git a/bfdd/bfd.h b/bfdd/bfd.h index a3e5ad1447..dccc3dfcc6 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -525,6 +525,7 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp, char *port_name, struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc); int bfd_session_update_label(struct bfd_session *bs, const char *nlabel); void bfd_set_polling(struct bfd_session *bs); +void bs_state_handler(struct bfd_session *, int); const char *satostr(struct sockaddr_any *sa); const char *diag2str(uint8_t diag); int strtosa(const char *addr, struct sockaddr_any *sa); diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c index 9cfd7e866f..ef97e34623 100644 --- a/bfdd/bfd_packet.c +++ b/bfdd/bfd_packet.c @@ -668,29 +668,8 @@ int bfd_recv_cb(struct thread *t) /* Save remote diagnostics before state switch. */ bfd->remote_diag = cp->diag & BFD_DIAGMASK; - /* State switch from section 6.8.6 */ - if (BFD_GETSTATE(cp->flags) == PTM_BFD_ADM_DOWN) { - if (bfd->ses_state != PTM_BFD_DOWN) - ptm_bfd_ses_dn(bfd, BD_NEIGHBOR_DOWN); - } else { - switch (bfd->ses_state) { - case (PTM_BFD_DOWN): - if (BFD_GETSTATE(cp->flags) == PTM_BFD_INIT) - ptm_bfd_ses_up(bfd); - else if (BFD_GETSTATE(cp->flags) == PTM_BFD_DOWN) - bfd->ses_state = PTM_BFD_INIT; - break; - case (PTM_BFD_INIT): - if (BFD_GETSTATE(cp->flags) == PTM_BFD_INIT - || BFD_GETSTATE(cp->flags) == PTM_BFD_UP) - ptm_bfd_ses_up(bfd); - break; - case (PTM_BFD_UP): - if (BFD_GETSTATE(cp->flags) == PTM_BFD_DOWN) - ptm_bfd_ses_dn(bfd, BD_NEIGHBOR_DOWN); - break; - } - } + /* State switch from section 6.2. */ + bs_state_handler(bfd, BFD_GETSTATE(cp->flags)); /* * Handle echo packet status: