]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bfdd: refactor state change handler
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Tue, 15 Jan 2019 22:23:06 +0000 (20:23 -0200)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Thu, 14 Feb 2019 16:17:29 +0000 (14:17 -0200)
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 <rzalamena@opensourcerouting.org>
bfdd/bfd.c
bfdd/bfd.h
bfdd/bfd_packet.c

index df263a91c97a3d787c995918df358d1417a576f0..235f9c06a8f242c49a6d49e84406644a49c87271 100644 (file)
@@ -694,6 +694,129 @@ void bfd_set_polling(struct bfd_session *bs)
        bs->polling = 1;
 }
 
+/*
+ * bs_<state>_handler() functions implement the BFD state machine
+ * transition mechanism. `<state>` 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.
index a3e5ad14477ac07861281e6bec89c6fa4dd4b1f4..dccc3dfcc68409a5b2df4cba4a3dba82c4f120dc 100644 (file)
@@ -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);
index 9cfd7e866f8441338865d20ddac489b5fa4f0277..ef97e3462301e3eb4b661f17757739840800e29d 100644 (file)
@@ -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: