]> git.proxmox.com Git - mirror_frr.git/commitdiff
This patch changes ospfd from only listening mode for BFD status updates to interacti...
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 22 Jul 2015 19:35:37 +0000 (12:35 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 22 Jul 2015 19:35:37 +0000 (12:35 -0700)
OSPF BFD command enhancement to configure BFD parameters (detect multiplier, min rx and min tx).
interface <if-name>
  ip ospf bfd <detect mult> <min rx> <min tx>

This patch also adds BFD support for IPv6 OSPF. ospf6d  will dynamically register/deregister IPv6 neighbors with BFD for monitoring the connectivity of the neighbor. Neighbor is registered with BFD when 2-way adjacency is established and deregistered when adjacency goes down if the BFD is enabled on the interface through which the neighbor was discovered.

OSPF6 BFD command added to configure BFD and parameters (detect multiplier, min rx and min tx).
interface <if-name>
  ipv6 ospf6 bfd <detect mult> <min rx> <min tx>

Signed-off-by: Radhika Mahankali <radhika@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Kanna Rajagopal <kanna@cumulusnetworks.com>
28 files changed:
bgpd/bgp_bfd.c
bgpd/bgp_bfd.h
bgpd/bgpd.c
bgpd/bgpd.h
lib/Makefile.am
lib/bfd.c [new file with mode: 0644]
lib/bfd.h [new file with mode: 0644]
lib/memtypes.c
lib/zclient.c
lib/zclient.h
ospf6d/Makefile.am
ospf6d/ospf6_bfd.c [new file with mode: 0644]
ospf6d/ospf6_bfd.h [new file with mode: 0644]
ospf6d/ospf6_interface.c
ospf6d/ospf6_interface.h
ospf6d/ospf6_neighbor.c
ospf6d/ospf6d.c
ospfd/Makefile.am
ospfd/ospf_bfd.c [new file with mode: 0644]
ospfd/ospf_bfd.h [new file with mode: 0644]
ospfd/ospf_interface.c
ospfd/ospf_interface.h
ospfd/ospf_main.c
ospfd/ospf_nsm.c
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
zebra/zebra_ptm.c
zebra/zebra_ptm_redistribute.c

index 02047f7f07e11bb38bd8b45b69a64cdb4dff2e04..87feebe8a6ebc46f8a0c4d49f5b9bab358121ec4 100644 (file)
 #include "stream.h"
 #include "zclient.h"
 #include "vty.h"
-#include "bgp_fsm.h"
+#include "bfd.h"
 #include "bgpd/bgpd.h"
+#include "bgp_fsm.h"
 #include "bgpd/bgp_bfd.h"
 #include "bgpd/bgp_debug.h"
 #include "bgpd/bgp_vty.h"
 
 extern struct zclient *zclient;
 
-/*
- * bgp_bfd_peer_init - Allocate and initialize the peer BFD information
- *                     with default values.
- */
-void
-bgp_bfd_peer_init(struct peer *peer)
-{
-  struct bgp_bfd_peer_info *bfd_info;
-
-  peer->bfd_info = XCALLOC (MTYPE_BGP_PEER_BFD_INFO,
-                                  sizeof (struct bgp_bfd_peer_info));
-
-  bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
-
-  /* Set default BFD parameter values */
-  bfd_info->required_min_rx = BGP_BFD_DEF_MIN_RX;
-  bfd_info->desired_min_tx = BGP_BFD_DEF_MIN_TX;
-  bfd_info->detect_mult = BGP_BFD_DEF_DETECT_MULT;
-}
-
-/*
- * bgp_bfd_peer_free - Free the peer BFD information.
- */
-void
-bgp_bfd_peer_free(struct peer *peer)
-{
-  XFREE (MTYPE_BGP_PEER_BFD_INFO, peer->bfd_info);
-}
-
 /*
  * bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group template
  *                                to peer.
@@ -76,11 +48,17 @@ bgp_bfd_peer_free(struct peer *peer)
 void
 bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
 {
-  struct bgp_bfd_peer_info *bfd_info;
-  struct bgp_bfd_peer_info *conf_bfd_info;
+  struct bfd_info *bfd_info;
+  struct bfd_info *conf_bfd_info;
+
+  if (!conf->bfd_info)
+    return;
+
+  conf_bfd_info = (struct bfd_info *)conf->bfd_info;
+  if (!peer->bfd_info)
+    peer->bfd_info = bfd_info_create();
 
-  bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
-  conf_bfd_info = (struct bgp_bfd_peer_info *)conf->bfd_info;
+  bfd_info = (struct bfd_info *)peer->bfd_info;
 
   /* Copy BFD parameter values */
   bfd_info->required_min_rx = conf_bfd_info->required_min_rx;
@@ -101,111 +79,28 @@ bgp_bfd_is_peer_multihop(struct peer *peer)
 }
 
 /*
- * sendmsg_bfd_peer - Format and send a Peer register/Unregister
- *                    command to Zebra to be forwarded to BFD
+ * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister
+ *                        command to Zebra to be forwarded to BFD
  */
 static void
-sendmsg_bfd_peer (struct peer *peer, int command)
+bgp_bfd_peer_sendmsg (struct peer *peer, int command)
 {
-  struct stream *s;
-  int ret;
-  int len;
-  struct bgp_bfd_peer_info *bfd_info;
-
-  bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
-
-  /* Check socket. */
-  if (!zclient || zclient->sock < 0)
-    {
-      zlog_debug("%s: Can't send BFD peer register, Zebra client not established",
-                __FUNCTION__);
-      return;
-    }
-
-  s = zclient->obuf;
-  stream_reset (s);
-  zclient_create_header (s, command);
-
-  stream_putw(s, peer->su.sa.sa_family);
-  switch (peer->su.sa.sa_family)
-    {
-    case AF_INET:
-      stream_put_in_addr (s, &peer->su.sin.sin_addr);
-      break;
-#ifdef HAVE_IPV6
-    case AF_INET6:
-      stream_put(s, &(peer->su.sin6.sin6_addr), 16);
-      break;
-#endif
-    default:
-      break;
-    }
-
-  if (command != ZEBRA_BFD_DEST_DEREGISTER)
-    {
-      stream_putl(s, bfd_info->required_min_rx);
-      stream_putl(s, bfd_info->desired_min_tx);
-      stream_putc(s, bfd_info->detect_mult);
-    }
-
-  if (bgp_bfd_is_peer_multihop(peer))
-    {
-      stream_putc(s, 1);
-      /* Multi-hop destination send the source IP address to BFD */
-      if (peer->su_local)
-        {
-          stream_putw(s, peer->su_local->sa.sa_family);
-          switch (peer->su_local->sa.sa_family)
-            {
-            case AF_INET:
-              stream_put_in_addr (s, &peer->su_local->sin.sin_addr);
-              break;
-        #ifdef HAVE_IPV6
-            case AF_INET6:
-              stream_put(s, &(peer->su_local->sin6.sin6_addr), 16);
-              break;
-        #endif
-            default:
-              break;
-            }
-        }
-      stream_putc(s, peer->ttl);
-    }
-  else
-    {
-      stream_putc(s, 0);
-#ifdef HAVE_IPV6
-      if ((peer->su.sa.sa_family == AF_INET6) && (peer->su_local))
-        {
-          stream_putw(s, peer->su_local->sa.sa_family);
-          stream_put(s, &(peer->su_local->sin6.sin6_addr), 16);
-        }
-#endif
-
-      if (peer->nexthop.ifp)
-        {
-          len = strlen(peer->nexthop.ifp->name);
-          stream_putc(s, len);
-          stream_put(s, peer->nexthop.ifp->name, len);
-        }
-      else
-        {
-          stream_putc(s, 0);
-        }
-    }
-
-  stream_putw_at (s, 0, stream_get_endp (s));
-
-  ret = zclient_send_message(zclient);
-
-  if (ret < 0)
-    zlog_warn("sendmsg_bfd_peer: zclient_send_message() failed");
-
-  if (command == ZEBRA_BFD_DEST_REGISTER)
-    SET_FLAG(bfd_info->flags, BGP_BFD_FLAG_BFD_REG);
-  else if (command == ZEBRA_BFD_DEST_DEREGISTER)
-    UNSET_FLAG(bfd_info->flags, BGP_BFD_FLAG_BFD_REG);
-  return;
+  struct bfd_info *bfd_info;
+
+  bfd_info = (struct bfd_info *)peer->bfd_info;
+
+  if (peer->su.sa.sa_family == AF_INET)
+    bfd_peer_sendmsg (zclient, bfd_info, AF_INET,
+                      &peer->su.sin.sin_addr,
+                      (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL,
+                      (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
+                      peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1);
+  else if (peer->su.sa.sa_family == AF_INET6)
+    bfd_peer_sendmsg (zclient, bfd_info, AF_INET6,
+                      &peer->su.sin6.sin6_addr,
+                      (peer->su_local) ? &peer->su_local->sin6.sin6_addr : NULL,
+                      (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
+                      peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1);
 }
 
 /*
@@ -215,16 +110,17 @@ sendmsg_bfd_peer (struct peer *peer, int command)
 void
 bgp_bfd_register_peer (struct peer *peer)
 {
-  struct bgp_bfd_peer_info *bfd_info;
+  struct bfd_info *bfd_info;
 
-  bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
+  if (!peer->bfd_info)
+    return;
+  bfd_info = (struct bfd_info *)peer->bfd_info;
 
   /* Check if BFD is enabled and peer has already been registered with BFD */
-  if (!CHECK_FLAG(peer->flags, PEER_FLAG_BFD) ||
-        CHECK_FLAG(bfd_info->flags, BGP_BFD_FLAG_BFD_REG))
+  if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
     return;
 
-  sendmsg_bfd_peer(peer, ZEBRA_BFD_DEST_REGISTER);
+  bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
 }
 
 /**
@@ -235,41 +131,44 @@ bgp_bfd_register_peer (struct peer *peer)
 void
 bgp_bfd_deregister_peer (struct peer *peer)
 {
-  struct bgp_bfd_peer_info *bfd_info;
+  struct bfd_info *bfd_info;
 
-  bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
+  if (!peer->bfd_info)
+    return;
+  bfd_info = (struct bfd_info *)peer->bfd_info;
 
   /* Check if BFD is eanbled and peer has not been registered */
-  if (!CHECK_FLAG(peer->flags, PEER_FLAG_BFD) ||
-        !CHECK_FLAG(bfd_info->flags, BGP_BFD_FLAG_BFD_REG))
+  if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
     return;
 
-  sendmsg_bfd_peer(peer, ZEBRA_BFD_DEST_DEREGISTER);
+  bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
 }
 
 /*
  * bgp_bfd_update_peer - update peer with BFD with new BFD paramters
  *                       through zebra.
  */
-void
+static void
 bgp_bfd_update_peer (struct peer *peer)
 {
-  struct bgp_bfd_peer_info *bfd_info;
+  struct bfd_info *bfd_info;
 
-  bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
+  if (!peer->bfd_info)
+    return;
+  bfd_info = (struct bfd_info *)peer->bfd_info;
 
   /* Check if the peer has been registered with BFD*/
-  if (!CHECK_FLAG(bfd_info->flags, BGP_BFD_FLAG_BFD_REG))
+  if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
     return;
 
-  sendmsg_bfd_peer(peer, ZEBRA_BFD_DEST_UPDATE);
+  bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE);
 }
 
 /*
  * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled
  *                       to zebra
  */
-int
+static int
 bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length)
 {
   struct listnode *mnode, *node, *nnode;
@@ -284,9 +183,6 @@ bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length)
   for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
     for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
       {
-        if (!CHECK_FLAG (peer->flags, PEER_FLAG_BFD))
-          continue;
-
         bgp_bfd_update_peer(peer);
       }
 
@@ -298,7 +194,7 @@ bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length)
  *                               has changed and bring down the peer
  *                               connectivity.
  */
-int
+static int
 bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
                              zebra_size_t length)
 {
@@ -306,7 +202,7 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
   struct prefix dp;
   struct prefix sp;
 
-  ifp = zebra_interface_bfd_read (zclient->ibuf, &dp, &sp);
+  ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp);
 
   if (BGP_DEBUG (zebra, ZEBRA))
     {
@@ -334,7 +230,7 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
     for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
         {
-          if (!CHECK_FLAG (peer->flags, PEER_FLAG_BFD))
+          if (!peer->bfd_info)
             continue;
 
           if ((dp.family == AF_INET) && (peer->su.sa.sa_family == AF_INET))
@@ -394,53 +290,39 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
 /*
  * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer.
  */
-int
+static int
 bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
-                         u_int8_t detect_mult, int reg_peer, int defaults)
+                         u_int8_t detect_mult, int defaults)
 {
   struct peer_group *group;
   struct listnode *node, *nnode;
-  int change = 0;
-  struct bgp_bfd_peer_info *bfd_info;
-
-  bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
-
-  if ((bfd_info->required_min_rx != min_rx) ||
-      (bfd_info->desired_min_tx != min_tx) ||
-      (bfd_info->detect_mult != detect_mult))
-    change = 1;
+  int command = 0;
 
-  bfd_info->required_min_rx = min_rx;
-  bfd_info->desired_min_tx = min_tx;
-  bfd_info->detect_mult = detect_mult;
-
-  if (!defaults)
-    SET_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG);
-  else
-    UNSET_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG);
+  bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult,
+                defaults, &command);
 
   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
       group = peer->group;
       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
         {
-          bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
-          bfd_info->required_min_rx = min_rx;
-          bfd_info->desired_min_tx = min_tx;
-          bfd_info->detect_mult = detect_mult;
-          SET_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG);
+          command = 0;
+          bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult,
+                        defaults, &command);
 
-          if (reg_peer && (peer->status == Established))
+          if ((peer->status == Established) &&
+              (command == ZEBRA_BFD_DEST_REGISTER))
             bgp_bfd_register_peer(peer);
-          else if (change)
+          else if (command == ZEBRA_BFD_DEST_UPDATE)
             bgp_bfd_update_peer(peer);
         }
     }
-   else
+  else
     {
-      if (reg_peer && (peer->status == Established))
+      if ((peer->status == Established) &&
+          (command == ZEBRA_BFD_DEST_REGISTER))
         bgp_bfd_register_peer(peer);
-      else if (change)
+      else if (command == ZEBRA_BFD_DEST_UPDATE)
         bgp_bfd_update_peer(peer);
     }
   return 0;
@@ -449,35 +331,30 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
 /*
  * bgp_bfd_peer_param_unset - Unset the configured BFD paramter values for peer.
  */
-int
+static int
 bgp_bfd_peer_param_unset (struct peer *peer)
 {
   struct peer_group *group;
   struct listnode *node, *nnode;
-  struct bgp_bfd_peer_info *bfd_info;
-
-  bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
 
-  bfd_info->required_min_rx = BGP_BFD_DEF_MIN_RX;
-  bfd_info->desired_min_tx = BGP_BFD_DEF_MIN_TX;
-  bfd_info->detect_mult = BGP_BFD_DEF_DETECT_MULT;
-  UNSET_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG);
+  if (!peer->bfd_info)
+    return 0;
 
   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
+      bfd_info_free(&(peer->bfd_info));
       group = peer->group;
       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
         {
-          bfd_info->required_min_rx = BGP_BFD_DEF_MIN_RX;
-          bfd_info->desired_min_tx = BGP_BFD_DEF_MIN_TX;
-          bfd_info->detect_mult = BGP_BFD_DEF_DETECT_MULT;
-          UNSET_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG);
-
           bgp_bfd_deregister_peer(peer);
+          bfd_info_free(&(peer->bfd_info));
         }
     }
   else
-    bgp_bfd_deregister_peer(peer);
+    {
+      bgp_bfd_deregister_peer(peer);
+      bfd_info_free(&(peer->bfd_info));
+    }
   return 0;
 }
 
@@ -487,11 +364,14 @@ bgp_bfd_peer_param_unset (struct peer *peer)
 void
 bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
 {
-  struct bgp_bfd_peer_info *bfd_info;
+  struct bfd_info *bfd_info;
 
-  bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
+  if (!peer->bfd_info)
+    return;
+
+  bfd_info = (struct bfd_info *)peer->bfd_info;
 
-  if (CHECK_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG))
+  if (CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG))
     vty_out (vty, " neighbor %s bfd %d %d %d%s", addr,
       bfd_info->detect_mult, bfd_info->required_min_rx,
       bfd_info->desired_min_tx, VTY_NEWLINE);
@@ -505,20 +385,20 @@ bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
 void
 bgp_bfd_show_info(struct vty *vty, struct peer *peer)
 {
-  struct bgp_bfd_peer_info *bfd_info;
+  struct bfd_info *bfd_info;
+
+  if (!peer->bfd_info)
+    return;
 
-  bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info;
+  bfd_info = (struct bfd_info *)peer->bfd_info;
 
-  if (CHECK_FLAG(peer->flags, PEER_FLAG_BFD))
-    {
-      vty_out (vty, "  BFD: Multi-hop: %s%s",
-           (bgp_bfd_is_peer_multihop(peer)) ? "yes" : "no", VTY_NEWLINE);
-      vty_out (vty, "    Detect Mul: %d, Min Rx interval: %d,"
-                    " Min Tx interval: %d%s",
-                        bfd_info->detect_mult, bfd_info->required_min_rx,
-                        bfd_info->desired_min_tx, VTY_NEWLINE);
-      vty_out (vty, "%s", VTY_NEWLINE);
-    }
+  vty_out (vty, "  BFD: Multi-hop: %s%s",
+       (bgp_bfd_is_peer_multihop(peer)) ? "yes" : "no", VTY_NEWLINE);
+  vty_out (vty, "    Detect Mul: %d, Min Rx interval: %d,"
+                " Min Tx interval: %d%s",
+                    bfd_info->detect_mult, bfd_info->required_min_rx,
+                    bfd_info->desired_min_tx, VTY_NEWLINE);
+  vty_out (vty, "%s", VTY_NEWLINE);
 }
 
 DEFUN (neighbor_bfd,
@@ -530,23 +410,13 @@ DEFUN (neighbor_bfd,
 {
   struct peer *peer;
   int ret;
-  int reg_peer = 0;
 
   peer = peer_and_group_lookup_vty (vty, argv[0]);
   if (! peer)
     return CMD_WARNING;
 
-  if ( !CHECK_FLAG (peer->flags, PEER_FLAG_BFD) )
-    {
-      ret = peer_flag_set (peer, PEER_FLAG_BFD);
-      if (ret != 0)
-        return bgp_vty_return (vty, ret);
-
-      reg_peer = 1;
-    }
-
-  ret = bgp_bfd_peer_param_set (peer, BGP_BFD_DEF_MIN_RX, BGP_BFD_DEF_MIN_TX,
-                                  BGP_BFD_DEF_DETECT_MULT, reg_peer, 1);
+  ret = bgp_bfd_peer_param_set (peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
+                                  BFD_DEF_DETECT_MULT, 1);
   if (ret != 0)
     return bgp_vty_return (vty, ret);
 
@@ -556,7 +426,7 @@ DEFUN (neighbor_bfd,
 
 DEFUN (neighbor_bfd_param,
        neighbor_bfd_param_cmd,
-       NEIGHBOR_CMD2 "bfd <2-255> <50-60000> <50-60000>",
+       NEIGHBOR_CMD2 "bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE,
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR2
        "Enables BFD support\n"
@@ -569,26 +439,16 @@ DEFUN (neighbor_bfd_param,
   u_int32_t tx_val;
   u_int8_t dm_val;
   int ret;
-  int reg_peer = 0;
 
   peer = peer_and_group_lookup_vty (vty, argv[0]);
   if (!peer)
     return CMD_WARNING;
 
-  if (!CHECK_FLAG (peer->flags, PEER_FLAG_BFD))
-    {
-      ret = peer_flag_set (peer, PEER_FLAG_BFD);
-      if (ret != 0)
-        return bgp_vty_return (vty, ret);
-
-      reg_peer = 1;
-    }
-
-  VTY_GET_INTEGER_RANGE ("detect-mul", dm_val, argv[1], 2, 255);
-  VTY_GET_INTEGER_RANGE ("min-rx", rx_val, argv[2], 50, 60000);
-  VTY_GET_INTEGER_RANGE ("min-tx", tx_val, argv[3], 50, 60000);
+  if ((ret = bfd_validate_param (vty, argv[1], argv[2], argv[3], &dm_val,
+                                 &rx_val, &tx_val)) != CMD_SUCCESS)
+    return ret;
 
-  ret = bgp_bfd_peer_param_set (peer, rx_val, tx_val, dm_val, reg_peer, 0);
+  ret = bgp_bfd_peer_param_set (peer, rx_val, tx_val, dm_val, 0);
   if (ret != 0)
     return bgp_vty_return (vty, ret);
 
@@ -611,18 +471,10 @@ DEFUN (no_neighbor_bfd,
   if (! peer)
     return CMD_WARNING;
 
-  /* Do nothing if there is no change in the flag */
-  if ( !CHECK_FLAG (peer->flags, PEER_FLAG_BFD) )
-    return CMD_SUCCESS;
-
   ret = bgp_bfd_peer_param_unset(peer);
   if (ret != 0)
     return bgp_vty_return (vty, ret);
 
-  ret = peer_flag_unset (peer, PEER_FLAG_BFD);
-  if (ret != 0)
-    return bgp_vty_return (vty, ret);
-
   return CMD_SUCCESS;
 }
 
index 8c72c231e6528f848af23c7877f37b8b6133b425..97ad093eeea8a154f0d5e4768c9255f3b5e9c6d3 100644 (file)
 #ifndef _QUAGGA_BGP_BFD_H
 #define _QUAGGA_BGP_BFD_H
 
-#define BGP_BFD_DEF_MIN_RX 300
-#define BGP_BFD_DEF_MIN_TX 300
-#define BGP_BFD_DEF_DETECT_MULT 3
-
-#define BGP_BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */
-#define BGP_BFD_FLAG_BFD_REG   (1 << 1) /* Peer registered with BFD */
-
-struct bgp_bfd_peer_info
-{
-  u_int16_t flags;
-  u_int8_t  detect_mult;
-  u_int32_t desired_min_tx;
-  u_int32_t required_min_rx;
-};
-
 extern void
 bgp_bfd_init(void);
 
-extern void
-bgp_bfd_peer_init(struct peer *peer);
-
-extern void
-bgp_bfd_peer_free(struct peer *peer);
-
 extern void
 bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer);
 
@@ -57,9 +36,6 @@ bgp_bfd_register_peer (struct peer *peer);
 extern void
 bgp_bfd_deregister_peer (struct peer *peer);
 
-extern void
-bgp_bfd_update_peer (struct peer *peer);
-
 extern void
 bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr);
 
index 5a633ed60f9c21b5037f0ce894e740b6ee3fda56..dec6b7d688fb2c4e9c64670feb7f0fc726887f26 100644 (file)
@@ -36,6 +36,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "linklist.h"
 #include "workqueue.h"
 #include "queue.h"
+#include "bfd.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_table.h"
@@ -826,6 +827,8 @@ peer_global_config_reset (struct peer *peer)
   peer->v_holdtime = peer->bgp->default_holdtime;
   peer->v_keepalive = peer->bgp->default_keepalive;
 
+  bfd_info_free(&(peer->bfd_info));
+
   /* Set back the CONFIG_NODE flag. */
   SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE);
 }
@@ -951,8 +954,7 @@ peer_free (struct peer *peer)
   if (peer->conf_if)
     XFREE (MTYPE_PEER_CONF_IF, peer->conf_if);
 
-  if (peer->bfd_info)
-    bgp_bfd_peer_free(peer);
+  bfd_info_free(&(peer->bfd_info));
 
   memset (peer, 0, sizeof (struct peer));
   
@@ -1298,8 +1300,6 @@ peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp,
        }
     }
 
-  bgp_bfd_peer_init(peer);
-
   /* Set up peer's events and timers. */
   if (! active && peer_active (peer))
     bgp_timer_set (peer);
@@ -1905,7 +1905,6 @@ peer_group_get (struct bgp *bgp, const char *name)
   group->conf->connect = 0;
   SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
   listnode_add_sort (bgp->group, group);
-  bgp_bfd_peer_init(group->conf);
 
   return 0;
 }
@@ -2251,8 +2250,7 @@ peer_group_delete (struct peer_group *group)
   /* Delete from all peer_group list. */
   listnode_delete (bgp->group, group);
 
-  if (group->conf->bfd_info)
-    bgp_bfd_peer_free(group->conf);
+  bfd_info_free(&(group->conf->bfd_info));
 
   peer_group_free (group);
 
@@ -2569,6 +2567,7 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer,
            }
          return 0;
        }
+      bgp_bfd_deregister_peer(peer);
       peer_global_config_reset (peer);
     }
 
@@ -3234,7 +3233,6 @@ static const struct peer_flag_action peer_flag_action_list[] =
     { PEER_FLAG_DYNAMIC_CAPABILITY,       0, peer_change_reset },
     { PEER_FLAG_DISABLE_CONNECTED_CHECK,  0, peer_change_reset },
     { PEER_FLAG_CAPABILITY_ENHE,          0, peer_change_reset },
-    { PEER_FLAG_BFD,                      0, peer_change_none },
     { 0, 0, 0 }
   };
 
@@ -6073,9 +6071,8 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
          vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
 
       /* bfd. */
-      if (CHECK_FLAG (peer->flags, PEER_FLAG_BFD))
-        if (! peer_group_active (peer) ||
-            ! CHECK_FLAG (g_peer->flags, PEER_FLAG_BFD))
+      if (peer->bfd_info)
+        if (! peer_group_active (peer) || ! g_peer->bfd_info)
           {
             bgp_bfd_peer_config_write(vty, peer, addr);
           }
index 1778aadbef815afe320dbee2eb050138021c1f36..b20b0801234bcc1ee33b3941c5236802157a562d 100644 (file)
@@ -610,11 +610,10 @@ struct peer
 #define PEER_FLAG_LOCAL_AS_REPLACE_AS       (1 << 8) /* local-as no-prepend replace-as */
 #define PEER_FLAG_DELETE                   (1 << 9) /* mark the peer for deleting */
 #define PEER_FLAG_CONFIG_NODE              (1 << 10) /* the node to update configs on */
-#define PEER_FLAG_BFD                      (1 << 11) /* bfd */
-#define PEER_FLAG_LONESOUL                  (1 << 12)
-#define PEER_FLAG_DYNAMIC_NEIGHBOR          (1 << 13) /* dynamic neighbor */
-#define PEER_FLAG_CAPABILITY_ENHE           (1 << 14) /* Extended next-hop (rfc 5549)*/
-#define PEER_FLAG_IFPEER_V6ONLY             (1 << 15) /* if-based peer is v6 only *
+#define PEER_FLAG_LONESOUL                  (1 << 11)
+#define PEER_FLAG_DYNAMIC_NEIGHBOR          (1 << 12) /* dynamic neighbor */
+#define PEER_FLAG_CAPABILITY_ENHE           (1 << 13) /* Extended next-hop (rfc 5549)*/
+#define PEER_FLAG_IFPEER_V6ONLY             (1 << 14) /* if-based peer is v6 only *
 
   /* NSF mode (graceful restart) */
   u_char nsf[AFI_MAX][SAFI_MAX];
index 1ed1d0a702f77bb16b4f6cd059bc7e28ad55b5ef..76aedf2c0b9a672409c4402d60a84a3524a90fc2 100644 (file)
@@ -13,7 +13,7 @@ libzebra_la_SOURCES = \
        filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
        zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \
        sigevent.c pqueue.c jhash.c memtypes.c workqueue.c nexthop.c json.c \
-    ptm_lib.c csv.c
+       ptm_lib.c csv.c bfd.c
 
 BUILT_SOURCES = memtypes.h route_types.h gitversion.h
 
@@ -29,7 +29,7 @@ pkginclude_HEADERS = \
        plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \
        privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \
        workqueue.h route_types.h libospf.h nexthop.h json.h \
-    ptm_lib.h csv.h
+       ptm_lib.h csv.h bfd.h
 
 EXTRA_DIST = \
        regex.c regex-gnu.h \
diff --git a/lib/bfd.c b/lib/bfd.c
new file mode 100644 (file)
index 0000000..78e0158
--- /dev/null
+++ b/lib/bfd.c
@@ -0,0 +1,287 @@
+/**
+ * bfd.c: BFD handling routines
+ *
+ * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "memory.h"
+#include "prefix.h"
+#include "thread.h"
+#include "stream.h"
+#include "zclient.h"
+#include "table.h"
+#include "vty.h"
+#include "bfd.h"
+
+/*
+ * bfd_info_create - Allocate the BFD information
+ */
+struct bfd_info *
+bfd_info_create(void)
+{
+  struct bfd_info *bfd_info;
+
+  bfd_info = XCALLOC (MTYPE_BFD_INFO, sizeof (struct bfd_info));
+  assert(bfd_info);
+
+  return bfd_info;
+}
+
+/*
+ * bfd_info_free - Free the BFD information.
+ */
+void
+bfd_info_free(void **bfd_info)
+{
+  if (*bfd_info)
+    {
+      XFREE (MTYPE_BFD_INFO, *bfd_info);
+      *bfd_info = NULL;
+    }
+}
+
+/*
+ * bfd_validate_param - Validate the BFD paramter information.
+ */
+int
+bfd_validate_param(struct vty *vty, const char *dm_str, const char *rx_str,
+                    const char *tx_str, u_int8_t *dm_val, u_int32_t *rx_val,
+                    u_int32_t *tx_val)
+{
+  VTY_GET_INTEGER_RANGE ("detect-mul", *dm_val, dm_str,
+                         BFD_MIN_DETECT_MULT, BFD_MAX_DETECT_MULT);
+  VTY_GET_INTEGER_RANGE ("min-rx", *rx_val, rx_str,
+                         BFD_MIN_MIN_RX, BFD_MAX_MIN_RX);
+  VTY_GET_INTEGER_RANGE ("min-tx", *tx_val, tx_str,
+                         BFD_MIN_MIN_TX, BFD_MAX_MIN_TX);
+  return CMD_SUCCESS;
+}
+
+/*
+ * bfd_set_param - Set the configured BFD paramter values
+ */
+void
+bfd_set_param (struct bfd_info **bfd_info, u_int32_t min_rx, u_int32_t min_tx,
+               u_int8_t detect_mult, int defaults, int *command)
+{
+  if (!*bfd_info)
+    {
+      *bfd_info = bfd_info_create();
+      *command = ZEBRA_BFD_DEST_REGISTER;
+    }
+  else
+    {
+      if (((*bfd_info)->required_min_rx != min_rx) ||
+          ((*bfd_info)->desired_min_tx != min_tx) ||
+          ((*bfd_info)->detect_mult != detect_mult))
+        *command = ZEBRA_BFD_DEST_UPDATE;
+    }
+
+  if (*command)
+    {
+      (*bfd_info)->required_min_rx = min_rx;
+      (*bfd_info)->desired_min_tx = min_tx;
+      (*bfd_info)->detect_mult = detect_mult;
+    }
+
+  if (!defaults)
+    SET_FLAG ((*bfd_info)->flags, BFD_FLAG_PARAM_CFG);
+  else
+    UNSET_FLAG ((*bfd_info)->flags, BFD_FLAG_PARAM_CFG);
+}
+
+/*
+ * bfd_peer_sendmsg - Format and send a peer register/Unregister
+ *                    command to Zebra to be forwarded to BFD
+ */
+void
+bfd_peer_sendmsg (struct zclient *zclient, struct bfd_info *bfd_info,
+                  int family, void *dst_ip, void *src_ip, char *if_name,
+                  int ttl, int multihop, int command, int set_flag)
+{
+  struct stream *s;
+  int ret;
+  int len;
+
+  /* Check socket. */
+  if (!zclient || zclient->sock < 0)
+    {
+      zlog_debug("%s: Can't send BFD peer register, Zebra client not "
+                  "established", __FUNCTION__);
+      return;
+    }
+
+  s = zclient->obuf;
+  stream_reset (s);
+  zclient_create_header (s, command);
+
+  stream_putw(s, family);
+  switch (family)
+    {
+    case AF_INET:
+      stream_put_in_addr (s, (struct in_addr *)dst_ip);
+      break;
+#ifdef HAVE_IPV6
+    case AF_INET6:
+      stream_put(s, dst_ip, 16);
+      break;
+#endif
+    default:
+      break;
+    }
+
+  if (command != ZEBRA_BFD_DEST_DEREGISTER)
+    {
+      stream_putl(s, bfd_info->required_min_rx);
+      stream_putl(s, bfd_info->desired_min_tx);
+      stream_putc(s, bfd_info->detect_mult);
+    }
+
+  if (multihop)
+    {
+      stream_putc(s, 1);
+      /* Multi-hop destination send the source IP address to BFD */
+      if (src_ip)
+        {
+          stream_putw(s, family);
+          switch (family)
+            {
+            case AF_INET:
+              stream_put_in_addr (s, (struct in_addr *) src_ip);
+              break;
+        #ifdef HAVE_IPV6
+            case AF_INET6:
+              stream_put(s, src_ip, 16);
+              break;
+        #endif
+            default:
+              break;
+            }
+        }
+      stream_putc(s, ttl);
+    }
+  else
+    {
+      stream_putc(s, 0);
+#ifdef HAVE_IPV6
+      if ((family == AF_INET6) && (src_ip))
+        {
+          stream_putw(s, family);
+          stream_put(s, src_ip, 16);
+        }
+#endif
+      if (if_name)
+        {
+          len = strlen(if_name);
+          stream_putc(s, len);
+          stream_put(s, if_name, len);
+        }
+      else
+        {
+          stream_putc(s, 0);
+        }
+    }
+
+  stream_putw_at (s, 0, stream_get_endp (s));
+
+  ret = zclient_send_message(zclient);
+
+  if (ret < 0)
+    {
+      zlog_warn("bfd_peer_sendmsg: zclient_send_message() failed");
+      return;
+    }
+
+  if (set_flag)
+    {
+      if (command == ZEBRA_BFD_DEST_REGISTER)
+        SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG);
+      else if (command == ZEBRA_BFD_DEST_DEREGISTER)
+        UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG);
+    }
+
+  return;
+}
+
+/*
+ * bfd_get_command_dbg_str - Convert command to a debug string.
+ */
+const char *
+bfd_get_command_dbg_str(int command)
+{
+  switch (command)
+  {
+    case ZEBRA_BFD_DEST_REGISTER:
+      return "Register";
+    case ZEBRA_BFD_DEST_DEREGISTER:
+      return "Deregister";
+    case ZEBRA_BFD_DEST_UPDATE:
+      return "Update";
+    default:
+      return "Unknown";
+  }
+}
+
+/*
+ * bfd_get_peer_info - Extract the Peer information for which the BFD session
+ *                     went down from the message sent from Zebra to clients.
+ */
+struct interface *
+bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp)
+{
+  unsigned int ifindex;
+  struct interface *ifp = NULL;
+  int plen;
+
+  /* Get interface index. */
+  ifindex = stream_getl (s);
+
+  /* Lookup index. */
+  if (ifindex != 0)
+    {
+      ifp = if_lookup_by_index (ifindex);
+      if (ifp == NULL)
+        {
+          zlog_warn ("zebra_interface_bfd_read: "
+                     "Can't find interface by ifindex: %d ", ifindex);
+          return NULL;
+        }
+    }
+
+  /* Fetch destination address. */
+  dp->family = stream_getc (s);
+
+  plen = prefix_blen (dp);
+  stream_get (&dp->u.prefix, s, plen);
+  dp->prefixlen = stream_getc (s);
+
+  if (sp)
+    {
+      sp->family = stream_getc (s);
+
+      plen = prefix_blen (sp);
+      stream_get (&sp->u.prefix, s, plen);
+      sp->prefixlen = stream_getc (s);
+    }
+  return ifp;
+}
diff --git a/lib/bfd.h b/lib/bfd.h
new file mode 100644 (file)
index 0000000..6ad1868
--- /dev/null
+++ b/lib/bfd.h
@@ -0,0 +1,77 @@
+/**
+ * bfd.h: BFD definitions and structures
+ *
+ * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_BFD_H
+#define _ZEBRA_BFD_H
+
+#define BFD_CMD_DETECT_MULT_RANGE "<2-255> "
+#define BFD_CMD_MIN_RX_RANGE "<50-60000> "
+#define BFD_CMD_MIN_TX_RANGE "<50-60000>"
+
+#define BFD_DEF_MIN_RX 300
+#define BFD_MIN_MIN_RX 50
+#define BFD_MAX_MIN_RX 60000
+#define BFD_DEF_MIN_TX 300
+#define BFD_MIN_MIN_TX 50
+#define BFD_MAX_MIN_TX 60000
+#define BFD_DEF_DETECT_MULT 3
+#define BFD_MIN_DETECT_MULT 2
+#define BFD_MAX_DETECT_MULT 255
+
+#define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */
+#define BFD_FLAG_BFD_REG   (1 << 1) /* Peer registered with BFD */
+
+struct bfd_info
+{
+  u_int16_t flags;
+  u_int8_t  detect_mult;
+  u_int32_t desired_min_tx;
+  u_int32_t required_min_rx;
+};
+
+extern struct bfd_info *
+bfd_info_create(void);
+
+extern void
+bfd_info_free(void **bfd_info);
+
+extern int
+bfd_validate_param(struct vty *vty, const char *dm_str, const char *rx_str,
+                   const char *tx_str, u_int8_t *dm_val, u_int32_t *rx_val,
+                   u_int32_t *tx_val);
+
+extern void
+bfd_set_param (struct bfd_info **bfd_info, u_int32_t min_rx, u_int32_t min_tx,
+               u_int8_t detect_mult, int defaults, int *command);
+extern void
+bfd_peer_sendmsg (struct zclient *zclient, struct bfd_info *bfd_info,
+                  int family, void *dst_ip, void *src_ip, char *if_name,
+                  int ttl, int multihop, int command, int set_flag);
+
+extern const char *
+bfd_get_command_dbg_str(int command);
+
+extern struct interface *
+bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp);
+
+#endif /* _ZEBRA_BFD_H */
index 57eb31ff34754761ebe38dc748c26ae1ae78f8bc..f0f11c2ca7c4504cfc41626853bfc32d799c1a92 100644 (file)
@@ -71,6 +71,7 @@ struct memory_list memory_list_lib[] =
   { MTYPE_PQUEUE,              "Priority queue"                },
   { MTYPE_PQUEUE_DATA,         "Priority queue data"           },
   { MTYPE_HOST,                        "Host config"                   },
+  { MTYPE_BFD_INFO,             "BFD info"                     },
   { -1, NULL },
 };
 
@@ -162,7 +163,6 @@ struct memory_list memory_list_bgp[] =
   { MTYPE_BGP_REGEXP,          "BGP regexp"                    },
   { MTYPE_BGP_AGGREGATE,       "BGP aggregate"                 },
   { MTYPE_BGP_ADDR,            "BGP own address"               },
-  { MTYPE_BGP_PEER_BFD_INFO,    "BGP peer BFD info"            },
   { -1, NULL }
 };
 
index 1b03510ed555c3d1a36858f8d7bf15df18d0f70f..39b6f8ec5f79412ebec549155f358b3a0a9d1df3 100644 (file)
@@ -942,46 +942,6 @@ memconstant(const void *s, int c, size_t n)
   return 1;
 }
 
-struct interface*
-zebra_interface_bfd_read (struct stream *s, struct prefix *dp,
-                          struct prefix *sp)
-{
-  unsigned int ifindex;
-  struct interface *ifp = NULL;
-  int plen;
-
-  /* Get interface index. */
-  ifindex = stream_getl (s);
-
-  /* Lookup index. */
-  if (ifindex != 0)
-    {
-      ifp = if_lookup_by_index (ifindex);
-      if (ifp == NULL)
-        {
-          zlog_warn ("zebra_interface_bfd_read: "
-                     "Can't find interface by ifindex: %d ", ifindex);
-          return NULL;
-        }
-    }
-
-  /* Fetch destination address. */
-  dp->family = stream_getc (s);
-
-  plen = prefix_blen (dp);
-  stream_get (&dp->u.prefix, s, plen);
-  dp->prefixlen = stream_getc (s);
-
-  if (sp)
-    {
-      sp->family = stream_getc (s);
-
-      plen = prefix_blen (sp);
-      stream_get (&sp->u.prefix, s, plen);
-      sp->prefixlen = stream_getc (s);
-    }
-  return ifp;
-}
 
 struct connected *
 zebra_interface_address_read (int type, struct stream *s)
index ab8c03e2d10d8b3ea3da7127d1310f333941f791..26cae04344d466c49fca98d1886ecb92d07289f3 100644 (file)
@@ -177,9 +177,6 @@ extern void zclient_create_header (struct stream *, uint16_t);
 extern struct interface *zebra_interface_add_read (struct stream *);
 extern struct interface *zebra_interface_state_read (struct stream *s);
 extern struct connected *zebra_interface_address_read (int, struct stream *);
-extern struct interface *zebra_interface_bfd_read (struct stream *s,
-                                                    struct prefix *,
-                                                    struct prefix *);
 extern struct nbr_connected *zebra_interface_nbr_address_read (int, struct stream *);
 extern void zebra_interface_if_set_value (struct stream *, struct interface *);
 extern void zebra_router_id_update_read (struct stream *s, struct prefix *rid);
index 726ce543e17f564d60f21b83f9cdcf12ea552f67..ec729d899cbdcceca1caf39adb465456e946b07f 100644 (file)
@@ -15,14 +15,14 @@ libospf6_a_SOURCES = \
        ospf6_top.c ospf6_area.c ospf6_interface.c ospf6_neighbor.c \
        ospf6_flood.c ospf6_route.c ospf6_intra.c ospf6_zebra.c \
        ospf6_spf.c ospf6_proto.c ospf6_asbr.c ospf6_abr.c ospf6_snmp.c \
-       ospf6d.c
+       ospf6d.c ospf6_bfd.c
 
 noinst_HEADERS = \
        ospf6_network.h ospf6_message.h ospf6_lsa.h ospf6_lsdb.h \
        ospf6_top.h ospf6_area.h ospf6_interface.h ospf6_neighbor.h \
        ospf6_flood.h ospf6_route.h ospf6_intra.h ospf6_zebra.h \
        ospf6_spf.h ospf6_proto.h ospf6_asbr.h ospf6_abr.h ospf6_snmp.h \
-       ospf6d.h
+       ospf6d.h ospf6_bfd.h
 
 ospf6d_SOURCES = \
        ospf6_main.c $(libospf6_a_SOURCES)
diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c
new file mode 100644 (file)
index 0000000..e30f496
--- /dev/null
@@ -0,0 +1,341 @@
+/**
+ * ospf6_bfd.c: IPv6 OSPF BFD handling routines
+ *
+ * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "linklist.h"
+#include "memory.h"
+#include "prefix.h"
+#include "thread.h"
+#include "buffer.h"
+#include "stream.h"
+#include "zclient.h"
+#include "vty.h"
+#include "table.h"
+#include "bfd.h"
+#include "if.h"
+#include "ospf6d.h"
+#include "ospf6_message.h"
+#include "ospf6_neighbor.h"
+#include "ospf6_interface.h"
+#include "ospf6_route.h"
+#include "ospf6_zebra.h"
+#include "ospf6_bfd.h"
+
+extern struct zclient *zclient;
+
+/*
+ * ospf6_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
+ *                           zebra for starting/stopping the monitoring of
+ *                           the neighbor rechahability.
+ */
+static void
+ospf6_bfd_reg_dereg_nbr (struct ospf6_neighbor *on, int command)
+{
+  struct ospf6_interface *oi = on->ospf6_if;
+  struct interface *ifp = oi->interface;
+  struct bfd_info *bfd_info;
+  char src[64];
+
+  if (!oi->bfd_info)
+    return;
+  bfd_info = (struct bfd_info *)oi->bfd_info;
+
+  if (IS_OSPF6_DEBUG_ZEBRA(SEND))
+    {
+      inet_ntop (AF_INET6, &on->linklocal_addr, src, sizeof (src));
+      zlog_debug ("%s nbr (%s) with BFD",
+                    bfd_get_command_dbg_str(command), src);
+    }
+
+  bfd_peer_sendmsg (zclient, bfd_info, AF_INET6, &on->linklocal_addr,
+                    on->ospf6_if->linklocal_addr, ifp->name,
+                    0, 0, command, 0);
+}
+
+/*
+ * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
+ *                           neighbor state is changed to/from 2way.
+ */
+void
+ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state, int state)
+{
+  if ((old_state < OSPF6_NEIGHBOR_TWOWAY) && (state >= OSPF6_NEIGHBOR_TWOWAY))
+    ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_REGISTER);
+  else if ((old_state >= OSPF6_NEIGHBOR_TWOWAY) &&
+            (state < OSPF6_NEIGHBOR_TWOWAY))
+    ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER);
+}
+
+/*
+ * ospf6_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated
+ *                               with a interface with BFD through
+ *                               zebra for starting/stopping the monitoring of
+ *                               the neighbor rechahability.
+ */
+static void
+ospf6_bfd_reg_dereg_all_nbr (struct ospf6_interface *oi, int command)
+{
+  struct ospf6_neighbor *on;
+  struct listnode *node;
+
+  for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, node, on))
+    {
+      if (on->state < OSPF6_NEIGHBOR_TWOWAY)
+        continue;
+
+      ospf6_bfd_reg_dereg_nbr(on, command);
+    }
+}
+
+/*
+ * ospf6_bfd_nbr_replay - Replay all the neighbors that have BFD enabled
+ *                        to zebra
+ */
+static int
+ospf6_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length)
+{
+  struct listnode *inode, *nnode;
+  struct interface *ifp;
+  struct ospf6_interface *oi;
+  struct ospf6_neighbor *on;
+  char dst[64];
+
+  if (IS_OSPF6_DEBUG_ZEBRA(RECV))
+    zlog_debug("Zebra: BFD Dest replay request");
+
+  /* Replay the neighbor, if BFD is enabled on the interface*/
+  for (ALL_LIST_ELEMENTS_RO (iflist, inode, ifp))
+    {
+      oi = (struct ospf6_interface *) ifp->info;
+
+      if (!oi || !oi->bfd_info)
+        continue;
+
+      for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, nnode, on))
+        {
+          if (on->state < OSPF6_NEIGHBOR_TWOWAY)
+            continue;
+
+          if (IS_OSPF6_DEBUG_ZEBRA(SEND))
+            {
+              inet_ntop (AF_INET6, &on->linklocal_addr, dst, sizeof (dst));
+              zlog_debug ("Replaying nbr (%s) to BFD", dst);
+            }
+
+          ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_UPDATE);
+        }
+    }
+  return 0;
+}
+
+/*
+ * ospf6_bfd_interface_dest_down - Find the neighbor for which the BFD status
+ *                                 has changed and bring down the neighbor
+ *                                 connectivity.
+ */
+static int
+ospf6_bfd_interface_dest_down (int command, struct zclient *zclient,
+                              zebra_size_t length)
+{
+  struct interface *ifp;
+  struct ospf6_interface *oi;
+  struct ospf6_neighbor *on;
+  struct prefix dp;
+  struct prefix sp;
+  struct listnode *node, *nnode;
+  char dst[64];
+
+  ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp);
+
+  if ((ifp == NULL) || (dp.family != AF_INET6))
+    return 0;
+
+  if (IS_OSPF6_DEBUG_ZEBRA (RECV))
+    {
+      char buf[128];
+      prefix2str(&dp, buf, sizeof(buf));
+      zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf);
+    }
+
+
+  oi = (struct ospf6_interface *) ifp->info;
+  if (!oi || !oi->bfd_info)
+    return 0;
+
+  for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
+    {
+      if (memcmp(&(on->linklocal_addr), &dp.u.prefix6, sizeof(struct in6_addr)))
+        continue;
+
+      if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+        {
+          inet_ntop (AF_INET6, &on->linklocal_addr, dst, sizeof (dst));
+          zlog_debug ("[%s:%s]: BFD Down", ifp->name, dst);
+        }
+
+      THREAD_OFF (on->inactivity_timer);
+      thread_add_event (master, inactivity_timer, on, 0);
+    }
+
+  return 0;
+}
+
+/*
+ * ospf6_bfd_write_config - Write the interface BFD configuration.
+ */
+void
+ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi)
+{
+  struct bfd_info *bfd_info;
+
+  if (!oi->bfd_info)
+    return;
+
+  bfd_info = (struct bfd_info *)oi->bfd_info;
+
+  if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
+    vty_out (vty, " ipv6 ospf6 bfd %d %d %d%s",
+              bfd_info->detect_mult, bfd_info->required_min_rx,
+              bfd_info->desired_min_tx, VTY_NEWLINE);
+  else
+    vty_out (vty, " ipv6 ospf6 bfd%s", VTY_NEWLINE);
+}
+
+/*
+ * ospf6_bfd_if_param_set - Set the configured BFD paramter values for
+ *                            interface.
+ */
+static void
+ospf6_bfd_if_param_set (struct ospf6_interface *oi, u_int32_t min_rx,
+                        u_int32_t min_tx, u_int8_t detect_mult,
+                        int defaults)
+{
+  int command = 0;
+
+  bfd_set_param((struct bfd_info **)&(oi->bfd_info), min_rx, min_tx, detect_mult,
+                defaults, &command);
+  if (command)
+    ospf6_bfd_reg_dereg_all_nbr(oi, command);
+}
+
+DEFUN (ipv6_ospf6_bfd,
+       ipv6_ospf6_bfd_cmd,
+       "ipv6 ospf6 bfd",
+       IP6_STR
+       OSPF6_STR
+       "Enables BFD support\n"
+       )
+{
+  struct ospf6_interface *oi;
+  struct interface *ifp;
+
+  ifp = (struct interface *) vty->index;
+  assert (ifp);
+
+  oi = (struct ospf6_interface *) ifp->info;
+  if (oi == NULL)
+    oi = ospf6_interface_create (ifp);
+  assert (oi);
+
+  ospf6_bfd_if_param_set (oi, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
+                          BFD_DEF_DETECT_MULT, 1);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ipv6_ospf6_bfd_param,
+       ipv6_ospf6_bfd_param_cmd,
+       "ipv6 ospf6 bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE,
+       IP6_STR
+       OSPF6_STR
+       "Enables BFD support\n"
+       "Detect Multiplier\n"
+       "Required min receive interval\n"
+       "Desired min transmit interval\n")
+{
+  struct ospf6_interface *oi;
+  struct interface *ifp;
+  u_int32_t rx_val;
+  u_int32_t tx_val;
+  u_int8_t dm_val;
+  int ret;
+
+  ifp = (struct interface *) vty->index;
+  assert (ifp);
+
+  oi = (struct ospf6_interface *) ifp->info;
+  if (oi == NULL)
+    oi = ospf6_interface_create (ifp);
+  assert (oi);
+
+  if ((ret = bfd_validate_param (vty, argv[0], argv[1], argv[2], &dm_val,
+                                 &rx_val, &tx_val)) != CMD_SUCCESS)
+    return ret;
+
+  ospf6_bfd_if_param_set (oi, rx_val, tx_val, dm_val, 0);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_ospf6_bfd,
+       no_ipv6_ospf6_bfd_cmd,
+       "no ipv6 ospf6 bfd",
+       NO_STR
+       IP6_STR
+       OSPF6_STR
+       "Disables BFD support\n"
+       )
+{
+  struct ospf6_interface *oi;
+  struct interface *ifp;
+
+  ifp = (struct interface *) vty->index;
+  assert (ifp);
+
+  oi = (struct ospf6_interface *) ifp->info;
+  if (oi == NULL)
+    oi = ospf6_interface_create (ifp);
+  assert (oi);
+
+  if (oi->bfd_info)
+    {
+      ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER);
+      bfd_info_free(&(oi->bfd_info));
+    }
+
+  return CMD_SUCCESS;
+}
+
+void
+ospf6_bfd_init(void)
+{
+  /* Initialize BFD client functions */
+  zclient->interface_bfd_dest_down = ospf6_bfd_interface_dest_down;
+  zclient->bfd_dest_replay = ospf6_bfd_nbr_replay;
+
+  /* Install BFD command */
+  install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_cmd);
+  install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd);
+  install_element (INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd);
+}
diff --git a/ospf6d/ospf6_bfd.h b/ospf6d/ospf6_bfd.h
new file mode 100644 (file)
index 0000000..eaaf157
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * ospf6_bfd.h: OSPF6 BFD definitions and structures
+ *
+ * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef OSPF6_BFD_H
+#define OSPF6_BFD_H
+
+extern void
+ospf6_bfd_init(void);
+
+extern void
+ospf6_bfd_trigger_event(struct ospf6_neighbor *nbr, int old_state, int state);
+
+extern void
+ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi);
+
+#endif /* OSPF6_BFD_H */
index 5043be4358ef1ec1d2678a823ecbfd1430404eaf..a45bdd5d6e4aaebc84f891dda0a36643b220ed68 100644 (file)
@@ -28,6 +28,7 @@
 #include "thread.h"
 #include "prefix.h"
 #include "plist.h"
+#include "bfd.h"
 
 #include "ospf6_lsa.h"
 #include "ospf6_lsdb.h"
@@ -41,6 +42,7 @@
 #include "ospf6_intra.h"
 #include "ospf6_spf.h"
 #include "ospf6d.h"
+#include "ospf6_bfd.h"
 
 unsigned char conf_debug_ospf6_interface = 0;
 
@@ -260,6 +262,8 @@ ospf6_interface_delete (struct ospf6_interface *oi)
   if (oi->plist_name)
     XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);
 
+  bfd_info_free(&(oi->bfd_info));
+
   XFREE (MTYPE_OSPF6_IF, oi);
 }
 
@@ -1859,6 +1863,8 @@ config_write_ospf6_interface (struct vty *vty)
       else if (oi->type == OSPF_IFTYPE_BROADCAST)
        vty_out (vty, " ipv6 ospf6 network broadcast%s", VNL);
 
+      ospf6_bfd_write_config(vty, oi);
+
       vty_out (vty, "!%s", VNL);
     }
   return 0;
index dde589b8faaceaa219590717d94c5efe97e5783a..6ef9e37822b5657114883e2888c10ba09fc2146b 100644 (file)
@@ -113,6 +113,9 @@ struct ospf6_interface
 
   /* prefix-list name to filter connected prefix */
   char *plist_name;
+
+  /* BFD information */
+  void *bfd_info;
 };
 
 /* interface state */
index 7f6c6c5cd811091c371dceee61f71fb82bfe6312..c5edd226d535d1d3b33ad614c20934f24e5bbf4c 100644 (file)
@@ -39,6 +39,7 @@
 #include "ospf6_intra.h"
 #include "ospf6_flood.h"
 #include "ospf6d.h"
+#include "ospf6_bfd.h"
 
 unsigned char conf_debug_ospf6_neighbor = 0;
 
@@ -199,7 +200,7 @@ ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int e
       (next_state < prev_state))
     ospf6TrapNbrStateChange (on);
 #endif
-
+  ospf6_bfd_trigger_event(on, prev_state, next_state);
 }
 
 /* RFC2328 section 10.4 */
index 0f456b1a7c3d8ea110c24908dcc9587169d5f7f5..98d4e1787d66ae675a1ba944094b37eab1f13f6e 100644 (file)
@@ -43,6 +43,7 @@
 #include "ospf6_abr.h"
 #include "ospf6_flood.h"
 #include "ospf6d.h"
+#include "ospf6_bfd.h"
 
 #ifdef HAVE_SNMP
 #include "ospf6_snmp.h"
@@ -1780,6 +1781,7 @@ ospf6_init (void)
   ospf6_snmp_init (master);
 #endif /*HAVE_SNMP*/
 
+  ospf6_bfd_init();
   install_node (&debug_node, config_write_ospf6_debug);
 
   install_element_ospf6_debug_message ();
index 4e1a4fe9f0235ea4410f4af91340babe71c81ed8..8a325ed7d357ca4c46f39ffc47e31143ff63b632 100644 (file)
@@ -14,7 +14,8 @@ libospf_la_SOURCES = \
        ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \
        ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \
        ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \
-       ospf_opaque.c ospf_te.c ospf_vty.c ospf_api.c ospf_apiserver.c
+       ospf_opaque.c ospf_te.c ospf_vty.c ospf_api.c ospf_apiserver.c \
+        ospf_bfd.c
 
 ospfdheaderdir = $(pkgincludedir)/ospfd
 
@@ -25,7 +26,8 @@ ospfdheader_HEADERS = \
 noinst_HEADERS = \
        ospf_interface.h ospf_neighbor.h ospf_network.h ospf_packet.h \
        ospf_zebra.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \
-       ospf_flood.h ospf_snmp.h ospf_te.h ospf_vty.h ospf_apiserver.h
+       ospf_flood.h ospf_snmp.h ospf_te.h ospf_vty.h ospf_apiserver.h \
+        ospf_bfd.h
 
 ospfd_SOURCES = ospf_main.c
 
diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c
new file mode 100644 (file)
index 0000000..054a806
--- /dev/null
@@ -0,0 +1,352 @@
+/**
+ * ospf_bfd.c: OSPF BFD handling routines
+ *
+ * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "linklist.h"
+#include "memory.h"
+#include "prefix.h"
+#include "thread.h"
+#include "buffer.h"
+#include "stream.h"
+#include "zclient.h"
+#include "vty.h"
+#include "table.h"
+#include "bfd.h"
+#include "ospfd.h"
+#include "ospf_asbr.h"
+#include "ospf_lsa.h"
+#include "ospf_lsdb.h"
+#include "ospf_neighbor.h"
+#include "ospf_interface.h"
+#include "ospf_nsm.h"
+#include "ospf_bfd.h"
+#include "ospf_dump.h"
+#include "ospf_vty.h"
+
+extern struct zclient *zclient;
+
+/*
+ * ospf_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
+ *                          zebra for starting/stopping the monitoring of
+ *                          the neighbor rechahability.
+ */
+static void
+ospf_bfd_reg_dereg_nbr (struct ospf_neighbor *nbr, int command)
+{
+  struct ospf_interface *oi = nbr->oi;
+  struct interface *ifp = oi->ifp;
+  struct ospf_if_params *params;
+  struct bfd_info *bfd_info;
+
+  /* Check if BFD is enabled */
+  params = IF_DEF_PARAMS (ifp);
+
+  /* Check if BFD is enabled */
+  if (!params->bfd_info)
+    return;
+  bfd_info = (struct bfd_info *)params->bfd_info;
+
+  if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
+    zlog_debug ("%s nbr (%s) with BFD",
+                  bfd_get_command_dbg_str(command),
+                  inet_ntoa (nbr->src));
+
+  bfd_peer_sendmsg (zclient, bfd_info, AF_INET,
+                    &nbr->src, NULL, ifp->name, 0, 0, command, 0);
+}
+
+/*
+ * ospf_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
+ *                          neighbor state is changed to/from 2way.
+ */
+void
+ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state)
+{
+  if ((old_state < NSM_TwoWay) && (state >= NSM_TwoWay))
+    ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_REGISTER);
+  else if ((old_state >= NSM_TwoWay) && (state < NSM_TwoWay))
+    ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_DEREGISTER);
+}
+
+/*
+ * ospf_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated
+ *                              with a interface with BFD through
+ *                              zebra for starting/stopping the monitoring of
+ *                              the neighbor rechahability.
+ */
+static int
+ospf_bfd_reg_dereg_all_nbr (struct interface *ifp, int command)
+{
+  struct ospf_interface *oi;
+  struct route_table *nbrs;
+  struct ospf_neighbor *nbr;
+  struct route_node *irn;
+  struct route_node *nrn;
+
+  for (irn = route_top (IF_OIFS (ifp)); irn; irn = route_next (irn))
+    {
+      if ((oi = irn->info) == NULL)
+        continue;
+
+      if ((nbrs = oi->nbrs) == NULL)
+        continue;
+
+      for (nrn = route_top (nbrs); nrn; nrn = route_next (nrn))
+        {
+          if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self)
+            continue;
+
+          if (nbr->state < NSM_TwoWay)
+            continue;
+
+          ospf_bfd_reg_dereg_nbr(nbr, command);
+        }
+    }
+
+  return 0;
+}
+
+/*
+ * ospf_bfd_nbr_replay - Replay all the neighbors that have BFD enabled
+ *                       to zebra
+ */
+static int
+ospf_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length)
+{
+  struct listnode *inode, *node, *onode;
+  struct ospf *ospf;
+  struct ospf_interface *oi;
+  struct route_table *nbrs;
+  struct route_node *rn;
+  struct ospf_neighbor *nbr;
+  struct ospf_if_params *params;
+
+  if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
+    {
+      zlog_debug("Zebra: BFD Dest replay request");
+    }
+
+  /* Replay the neighbor, if BFD is enabled in BGP */
+  for (ALL_LIST_ELEMENTS (om->ospf, node, onode, ospf))
+    {
+      for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, inode, oi))
+        {
+          if ((nbrs = oi->nbrs) == NULL)
+            continue;
+
+          params = IF_DEF_PARAMS (oi->ifp);
+          if (!params->bfd_info)
+            continue;
+
+          for (rn = route_top (nbrs); rn; rn = route_next (rn))
+            {
+              if ((nbr = rn->info) == NULL || nbr == oi->nbr_self)
+                continue;
+
+              if (nbr->state < NSM_TwoWay)
+                continue;
+
+              if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
+                zlog_debug ("Replaying nbr (%s) to BFD", inet_ntoa (nbr->src));
+
+              ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_UPDATE);
+            }
+        }
+    }
+  return 0;
+}
+
+/*
+ * ospf_bfd_interface_dest_down - Find the neighbor for which the BFD status
+ *                                has changed and bring down the neighbor
+ *                                connectivity.
+ */
+static int
+ospf_bfd_interface_dest_down (int command, struct zclient *zclient,
+                              zebra_size_t length)
+{
+  struct interface *ifp;
+  struct ospf_interface *oi;
+  struct ospf_if_params *params;
+  struct ospf_neighbor *nbr;
+  struct route_node *node;
+  struct prefix p;
+
+  ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL);
+
+  if ((ifp == NULL) || (p.family != AF_INET))
+    return 0;
+
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+    {
+      char buf[128];
+      prefix2str(&p, buf, sizeof(buf));
+      zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf);
+    }
+
+  params = IF_DEF_PARAMS (ifp);
+  if (!params->bfd_info)
+    return 0;
+
+  for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node))
+    {
+      if ((oi = node->info) == NULL)
+        continue;
+
+      nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &p.u.prefix4);
+      if (!nbr)
+        continue;
+
+      if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
+        zlog_debug ("NSM[%s:%s]: BFD Down",
+                    IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4));
+
+      OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer);
+    }
+
+  return 0;
+}
+
+/*
+ * ospf_bfd_write_config - Write the interface BFD configuration.
+ */
+void
+ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params)
+
+{
+  struct bfd_info *bfd_info;
+
+  if (!params->bfd_info)
+    return;
+
+  bfd_info = (struct bfd_info *)params->bfd_info;
+
+  if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
+    vty_out (vty, " ip ospf bfd %d %d %d%s",
+              bfd_info->detect_mult, bfd_info->required_min_rx,
+              bfd_info->desired_min_tx, VTY_NEWLINE);
+  else
+    vty_out (vty, " ip ospf bfd%s", VTY_NEWLINE);
+}
+
+
+/*
+ * ospf_bfd_if_param_set - Set the configured BFD paramter values for
+ *                         interface.
+ */
+static void
+ospf_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx,
+                       u_int32_t min_tx, u_int8_t detect_mult, int defaults)
+{
+  struct ospf_if_params *params;
+  int command = 0;
+
+  params = IF_DEF_PARAMS (ifp);
+
+  bfd_set_param(&(params->bfd_info), min_rx, min_tx, detect_mult,
+                defaults, &command);
+  if (command)
+    ospf_bfd_reg_dereg_all_nbr(ifp, command);
+}
+
+
+DEFUN (ip_ospf_bfd,
+       ip_ospf_bfd_cmd,
+       "ip ospf bfd",
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Enables BFD support\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+
+  assert (ifp);
+  ospf_bfd_if_param_set (ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
+                         BFD_DEF_DETECT_MULT, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (ip_ospf_bfd_param,
+       ip_ospf_bfd_param_cmd,
+       "ip ospf bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE,
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Enables BFD support\n"
+       "Detect Multiplier\n"
+       "Required min receive interval\n"
+       "Desired min transmit interval\n")
+{
+  struct interface *ifp = (struct interface *) vty->index;
+  u_int32_t rx_val;
+  u_int32_t tx_val;
+  u_int8_t dm_val;
+  int ret;
+
+  assert (ifp);
+
+  if ((ret = bfd_validate_param (vty, argv[0], argv[1], argv[2], &dm_val,
+                                 &rx_val, &tx_val)) != CMD_SUCCESS)
+    return ret;
+
+  ospf_bfd_if_param_set (ifp, rx_val, tx_val, dm_val, 0);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_ospf_bfd,
+       no_ip_ospf_bfd_cmd,
+       "no ip ospf bfd",
+       NO_STR
+       "IP Information\n"
+       "OSPF interface commands\n"
+       "Disables BFD support\n")
+{
+  struct interface *ifp = (struct interface *)vty->index;
+  struct ospf_if_params *params;
+
+  assert (ifp);
+
+  params = IF_DEF_PARAMS (ifp);
+  if (params->bfd_info)
+    {
+      ospf_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER);
+      bfd_info_free(&(params->bfd_info));
+    }
+
+  return CMD_SUCCESS;
+}
+
+void
+ospf_bfd_init(void)
+{
+  /* Initialize BFD client functions */
+  zclient->interface_bfd_dest_down = ospf_bfd_interface_dest_down;
+  zclient->bfd_dest_replay = ospf_bfd_nbr_replay;
+
+  /* Install BFD command */
+  install_element (INTERFACE_NODE, &ip_ospf_bfd_cmd);
+  install_element (INTERFACE_NODE, &ip_ospf_bfd_param_cmd);
+  install_element (INTERFACE_NODE, &no_ip_ospf_bfd_cmd);
+}
diff --git a/ospfd/ospf_bfd.h b/ospfd/ospf_bfd.h
new file mode 100644 (file)
index 0000000..436597c
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * ospf_bfd.h: OSPF BFD definitions and structures
+ *
+ * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_OSPF_BFD_H
+#define _ZEBRA_OSPF_BFD_H
+
+extern void
+ospf_bfd_init(void);
+
+extern void
+ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params);
+
+extern void
+ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state);
+
+#endif /* _ZEBRA_OSPF_BFD_H */
index 14af7e3425eff3e59624134eba7807934a47bdb4..61fd629b8aa7f56921436a8288cf19fc7e1fdc63 100644 (file)
@@ -31,6 +31,7 @@
 #include "command.h"
 #include "stream.h"
 #include "log.h"
+#include "bfd.h"
 
 #include "ospfd/ospfd.h"
 #include "ospfd/ospf_spf.h"
@@ -560,6 +561,7 @@ void
 ospf_del_if_params (struct ospf_if_params *oip)
 {
   list_delete (oip->auth_crypt);
+  bfd_info_free(&(oip->bfd_info));
   XFREE (MTYPE_OSPF_IF_PARAMS, oip);
 }
 
index e2d929020fe8b212c972ec11884cb5f6910cecbf..addc8c7ba3824e3a42a3cc1e03e0b98e37d6dfeb 100644 (file)
@@ -45,7 +45,6 @@ struct ospf_if_params
   DECLARE_IF_PARAM (u_int32_t, transmit_delay); /* Interface Transmisson Delay */
   DECLARE_IF_PARAM (u_int32_t, output_cost_cmd);/* Command Interface Output Cost */
   DECLARE_IF_PARAM (u_int32_t, retransmit_interval); /* Retransmission Interval */
-  DECLARE_IF_PARAM (u_char, bfd);                    /* Respond to BFD events */
   DECLARE_IF_PARAM (u_char, passive_interface);      /* OSPF Interface is passive: no sending or receiving (no need to join multicast groups) */
   DECLARE_IF_PARAM (u_char, priority);               /* OSPF Interface priority */
   /* Enable OSPF on this interface with area if_area */
@@ -79,6 +78,9 @@ struct ospf_if_params
   
   /* Other, non-configuration state */
   u_int32_t network_lsa_seqnum;                /* Network LSA seqnum */
+
+  /* BFD configuration */
+  void *bfd_info;
 };
 
 enum
index d34e65dc4227377245ea49540c37ae853d972367..77490b310a7f23a2e09a9e51928d472dc1a3bfbd 100644 (file)
@@ -49,6 +49,7 @@
 #include "ospfd/ospf_dump.h"
 #include "ospfd/ospf_zebra.h"
 #include "ospfd/ospf_vty.h"
+#include "ospfd/ospf_bfd.h"
 
 /* ospfd privileges */
 zebra_capabilities_t _caps_p [] = 
@@ -312,6 +313,9 @@ main (int argc, char **argv)
   ospf_vty_show_init ();
   ospf_vty_clear_init ();
 
+  /* OSPF BFD init */
+  ospf_bfd_init();
+
   ospf_route_map_init ();
 #ifdef HAVE_SNMP
   ospf_snmp_init ();
index b7338784962f8811ebe5cce1e0f1bd24853a2b88..baf01b22e4fdf3349ad4a28d6dc77edd7f3434f0 100644 (file)
@@ -48,6 +48,7 @@
 #include "ospfd/ospf_flood.h"
 #include "ospfd/ospf_abr.h"
 #include "ospfd/ospf_snmp.h"
+#include "ospfd/ospf_bfd.h"
 
 static void nsm_clear_adj (struct ospf_neighbor *);
 
@@ -811,6 +812,8 @@ nsm_change_state (struct ospf_neighbor *nbr, int state)
   if (state == NSM_Down)
     nbr->crypt_seqnum = 0;
   
+  ospf_bfd_trigger_event(nbr, old_state, state);
+
   /* Preserve old status? */
 }
 
index 17b5eb27cfbc2db3fd663441eea92c98034112aa..06cf7fa27239ae9d0426dc070e4666c750eb5a4d 100644 (file)
@@ -50,6 +50,7 @@
 /*#include "ospfd/ospf_routemap.h" */
 #include "ospfd/ospf_vty.h"
 #include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_bfd.h"
 
 #define QUAGGA_REDIST_STR_OSPFD \
   "(kernel|connected|static|rip|isis|bgp|babel)"
@@ -7072,39 +7073,6 @@ ALIAS (no_ip_ospf_priority,
        "OSPF interface commands\n"
        "Router priority\n")
 
-DEFUN (ip_ospf_bfd,
-       ip_ospf_bfd_cmd,
-       "ip ospf bfd",
-       "IP Information\n"
-       "OSPF interface commands\n"
-       "Respond to BFD session event\n")
-{
-  struct interface *ifp = vty->index;
-  struct ospf_if_params *params;
-
-  params = IF_DEF_PARAMS (ifp);
-  SET_IF_PARAM (params, bfd);
-
-  return CMD_SUCCESS;
-}
-
-DEFUN (no_ip_ospf_bfd,
-       no_ip_ospf_bfd_cmd,
-       "no ip ospf bfd",
-       NO_STR
-       "IP Information\n"
-       "OSPF interface commands\n"
-       "Respond to BFD session event\n")
-{
-  struct interface *ifp = vty->index;
-  struct ospf_if_params *params;
-
-  params = IF_DEF_PARAMS (ifp);
-  UNSET_IF_PARAM (params, bfd);
-
-  return CMD_SUCCESS;
-}
-
 
 DEFUN (ip_ospf_retransmit_interval,
        ip_ospf_retransmit_interval_addr_cmd,
@@ -8795,8 +8763,7 @@ config_write_interface (struct vty *vty)
          }
 
        /* bfd  print. */
-       if (OSPF_IF_PARAM_CONFIGURED (params, bfd))
-         vty_out (vty, " ip ospf bfd%s", VTY_NEWLINE);
+        ospf_bfd_write_config(vty, params);
 
     /* MTU ignore print. */
     if (OSPF_IF_PARAM_CONFIGURED (params, mtu_ignore) &&
@@ -9544,8 +9511,6 @@ ospf_vty_if_init (void)
   install_element (INTERFACE_NODE, &no_ospf_retransmit_interval_cmd);
   install_element (INTERFACE_NODE, &ospf_transmit_delay_cmd);
   install_element (INTERFACE_NODE, &no_ospf_transmit_delay_cmd);
-  install_element (INTERFACE_NODE, &ip_ospf_bfd_cmd);
-  install_element (INTERFACE_NODE, &no_ip_ospf_bfd_cmd);
 }
 
 static void
index 38a4228ce6ded48b4f2a619fafbdca925386e741..58e55564f47af05ff1fd3e79c97619e952024d62 100644 (file)
@@ -327,52 +327,6 @@ ospf_interface_address_delete (int command, struct zclient *zclient,
   return 0;
 }
 
-static int
-ospf_interface_bfd_dest_down (int command, struct zclient *zclient,
-                              zebra_size_t length)
-{
-  struct interface *ifp;
-  struct ospf_interface *oi;
-  struct ospf_if_params *params;
-  struct ospf_neighbor *nbr;
-  struct route_node *node;
-  struct prefix p;
-
-  ifp = zebra_interface_bfd_read (zclient->ibuf, &p, NULL);
-
-  if (ifp == NULL)
-    return 0;
-
-  if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
-    {
-      char buf[128];
-      prefix2str(&p, buf, sizeof(buf));
-      zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf);
-    }
-
-  params = IF_DEF_PARAMS (ifp);
-  if (!OSPF_IF_PARAM_CONFIGURED (params, bfd))
-    return 0;
-
-  for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node))
-    {
-      if ((oi = node->info) == NULL)
-        continue;
-
-      nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &p.u.prefix4);
-      if (!nbr)
-        continue;
-
-      if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
-        zlog_debug ("NSM[%s:%s]: BFD Down",
-                    IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4));
-
-      OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer);
-    }
-
-  return 0;
-}
-
 void
 ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
 {
@@ -1590,7 +1544,6 @@ ospf_zebra_init (u_short instance)
   zclient->interface_down = ospf_interface_state_down;
   zclient->interface_address_add = ospf_interface_address_add;
   zclient->interface_address_delete = ospf_interface_address_delete;
-  zclient->interface_bfd_dest_down = ospf_interface_bfd_dest_down;
   zclient->ipv4_route_add = ospf_zebra_read_ipv4;
   zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
 
index 4681649475a907c87f8bb82c99217007a88f66bc..0a90afcaca7e119afdac2b5039db69c7b4282a7b 100644 (file)
@@ -303,8 +303,6 @@ zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt)
   ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSTATUS_STR, bfdst_str);
 
   if (bfdst_str[0] == '\0') {
-    zlog_debug("%s: Key %s not found in PTM msg", __func__,
-               ZEBRA_PTM_BFDSTATUS_STR);
     return -1;
   }
 
index 5d231de85dcac1b94b3c82fc37bc667b55ea9921..40394f059c78631ef0452c1b5e9f4150a948d025 100644 (file)
@@ -78,7 +78,8 @@ zebra_interface_bfd_update (struct interface *ifp, struct prefix *dp,
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
     {
       /* Supporting for OSPF and BGP */
-      if (client->proto != ZEBRA_ROUTE_OSPF && client->proto != ZEBRA_ROUTE_BGP)
+      if (client->proto != ZEBRA_ROUTE_OSPF && client->proto != ZEBRA_ROUTE_BGP
+          && client->proto != ZEBRA_ROUTE_OSPF6)
         continue;
 
       /* Notify to the protocol daemons. */
@@ -113,7 +114,9 @@ zebra_bfd_peer_replay_req (void)
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
     {
       /* Supporting for BGP */
-      if (client->proto != ZEBRA_ROUTE_BGP)
+      if ((client->proto != ZEBRA_ROUTE_BGP) &&
+          (client->proto != ZEBRA_ROUTE_OSPF) &&
+          (client->proto != ZEBRA_ROUTE_OSPF6))
         continue;
 
       /* Notify to the protocol daemons. */