]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: add vty command to enable bfd control-plane-check-failure
authorPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 16 Apr 2019 09:50:47 +0000 (11:50 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 14 May 2019 14:49:49 +0000 (16:49 +0200)
new vty command is added:
neighbor XXX bfd check-control-plane-failure

this command will enforce the check of bgp controlplane, when bfd
detects changes in the dataplane.
- at configuration, the cbit will be set if that command is executed
- at flapping time, if the command is configured and remote cbit is set
  accordingly, then the bfd event will be ignored.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/bgp_bfd.c
lib/bfd.h

index cf172509314b36380ffb62d21be2b60f699efa3b..57fef8e9139f5cc467dd35e26713b8379a1bc31f 100644 (file)
@@ -112,11 +112,13 @@ static void bgp_bfd_peer_sendmsg(struct peer *peer, int command)
                if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop)
                        SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
        }
-       /* while graceful restart with fwd path preserved is not kept
+       /* while graceful restart with fwd path preserved
+        * and bfd controlplane check not configured is not kept
         * keep bfd independent controlplane bit set to 1
         */
        if (!bgp_flag_check(peer->bgp, BGP_FLAG_GRACEFUL_RESTART)
-           && !bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD))
+           && !bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD)
+           && !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE))
                SET_FLAG(bfd_info->flags,  BFD_FLAG_BFD_CBIT_ON);
 
        cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
@@ -290,6 +292,7 @@ static void bgp_bfd_peer_status_update(struct peer *peer, int status,
        }
        if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) {
                if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE) &&
+                   CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE) &&
                    !remote_cbit) {
                        zlog_info("%s BFD DOWN message ignored in the process"
                                  " of graceful restart when C bit is cleared",
@@ -556,6 +559,9 @@ void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
        if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)
            && (bfd_info->type == BFD_TYPE_NOT_CONFIGURED))
                vty_out(vty, " neighbor %s bfd\n", addr);
+
+       if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE))
+               vty_out(vty, " neighbor %s bfd check-control-plane-failure\n", addr);
 }
 
 /*
@@ -666,6 +672,73 @@ DEFUN_HIDDEN (neighbor_bfd_type,
        return CMD_SUCCESS;
 }
 
+static int bgp_bfd_set_check_controlplane_failure_peer(struct vty *vty, struct peer *peer,
+                                                      const char *no)
+{
+       struct bfd_info *bfd_info;
+
+       if (!peer->bfd_info) {
+               if (no)
+                       return CMD_SUCCESS;
+               vty_out(vty, "%% Specify bfd command first\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+       bfd_info = (struct bfd_info *)peer->bfd_info;
+       if (!no) {
+               if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) {
+                       SET_FLAG(bfd_info->flags,  BFD_FLAG_BFD_CHECK_CONTROLPLANE);
+                       bgp_bfd_update_peer(peer);
+               }
+       } else {
+               if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) {
+                       UNSET_FLAG(bfd_info->flags,  BFD_FLAG_BFD_CHECK_CONTROLPLANE);
+                       bgp_bfd_update_peer(peer);
+               }
+       }
+       return CMD_SUCCESS;
+}
+
+
+DEFUN (neighbor_bfd_check_controlplane_failure,
+       neighbor_bfd_check_controlplane_failure_cmd,
+       "[no] neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BFD support\n"
+       "Link dataplane status with BGP controlplane\n")
+{
+       const char *no = strmatch(argv[0]->text, "no") ? "no" : NULL;
+       int idx_peer = 0;
+       struct peer *peer;
+       struct peer_group *group;
+       struct listnode *node, *nnode;
+       int ret = CMD_SUCCESS;
+
+       if (no)
+               idx_peer = 2;
+       else
+               idx_peer = 1;
+       peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+       if (!peer) {
+               vty_out(vty, "%% Specify remote-as or peer-group commands first\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+       if (!peer->bfd_info) {
+               if (no)
+                       return CMD_SUCCESS;
+               vty_out(vty, "%% Specify bfd command first\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+       if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+               group = peer->group;
+               for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer))
+                       ret = bgp_bfd_set_check_controlplane_failure_peer(vty, peer, no);
+       } else
+               ret = bgp_bfd_set_check_controlplane_failure_peer(vty, peer, no);
+       return ret;
+ }
+
 DEFUN (no_neighbor_bfd,
        no_neighbor_bfd_cmd,
 #if HAVE_BFDD > 0
@@ -740,6 +813,7 @@ void bgp_bfd_init(void)
        install_element(BGP_NODE, &neighbor_bfd_cmd);
        install_element(BGP_NODE, &neighbor_bfd_param_cmd);
        install_element(BGP_NODE, &neighbor_bfd_type_cmd);
+       install_element(BGP_NODE, &neighbor_bfd_check_controlplane_failure_cmd);
        install_element(BGP_NODE, &no_neighbor_bfd_cmd);
        install_element(BGP_NODE, &no_neighbor_bfd_type_cmd);
 }
index 7f376a24708d1f038f8419123fea990e46079623..e4781f4eaf9e45cbe664dd029620f14c444fbe47 100644 (file)
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -49,6 +49,7 @@ struct bfd_gbl {
 #define BFD_FLAG_BFD_REG   (1 << 1) /* Peer registered with BFD */
 #define BFD_FLAG_BFD_TYPE_MULTIHOP (1 << 2) /* Peer registered with BFD as multihop */
 #define BFD_FLAG_BFD_CBIT_ON (1 << 3) /* Peer registered with CBIT set to on */
+#define BFD_FLAG_BFD_CHECK_CONTROLPLANE (1 << 4) /* BFD and controlplane daemon are linked */
 
 #define BFD_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */
 #define BFD_STATUS_DOWN    (1 << 1) /* BFD session status is down */