]> git.proxmox.com Git - mirror_frr.git/commitdiff
Support of BFD status in Quagga
authorradhika <radhika@cumulusnetworks.com>
Mon, 31 Aug 2015 21:56:11 +0000 (14:56 -0700)
committerradhika <radhika@cumulusnetworks.com>
Mon, 31 Aug 2015 21:56:11 +0000 (14:56 -0700)
Ticket:CM-6802, CM-6952
Reviewed By: Donald, Kanna
Testing Done:

Double commit of b76943235e09472ec174edcf7204fc82d27fe966 from br2.5. But, manually resolved all the compilation errors. Also, modified the shows to support the json format which was not supported in br2.5.

CM-6802 – Currently, BFD session status can be monitored only through ptmctl. There is no way to check the BFD status of a peer/neighbor through Quagga. Debugging becomes easier if BFD status is shown in Quagga too. BFD status is relevant when it is shown against the BGP peer/OSPF neighbor. For, this following code changes have been done:
   - Only down messages from PTM were being propagated from Zebra daemon to clients (bgpd, ospfd and ospf6d). Now, both up and down messages are redistributed to the clients from zebra. BFD status field has been added to the messaging. Handling of BFD session up messages has been added to the client code. BGP/OSPF neighbor is brought down only if the old BFD session status is ‘Up’ to handle extra/initial down messages.
   - BFD status and last update timestamp fields have been added to the common BFD info structure. Also, common show functions for showing BFD information have been added to BFD lib.
   - Modified the BGP neighbor show functions to call common BFD lib functions.
   - For ospf and ospf6, BFD information was maintained only at interface level. To show BFD status per neighbor, BFD information has been added at neighbor level too. “show ip ospf interface”, “show ip ospf neighbor detail”, “show ipv6 ospf6 interface” and “show ipv6 ospf6 neighbor detail” output have been modified to show BFD information.

CM-6952 - IBGP peers were always assumed to be multi-hop since there was no easy way to determine whether an IBGP peer was single hop or multihop unlike EBGP. But, this is causing problem with IBGP link local peers since BFD doesn't allow multihop BFD session with link local IP addresses. Link local peers were discovered when the interface peering was enabled. Interface peering is always singlehop. So, added checks to treat all interface based peers as single hop irrespective of whether the peer is IBGP or EBGP.

22 files changed:
bgpd/bgp_bfd.c
lib/bfd.c
lib/bfd.h
lib/log.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
ospf6d/ospf6_bfd.c
ospf6d/ospf6_bfd.h
ospf6d/ospf6_interface.c
ospf6d/ospf6_interface.h
ospf6d/ospf6_neighbor.c
ospf6d/ospf6_neighbor.h
ospfd/ospf_bfd.c
ospfd/ospf_bfd.h
ospfd/ospf_neighbor.c
ospfd/ospf_neighbor.h
ospfd/ospf_vty.c
zebra/zebra_ptm.c
zebra/zebra_ptm_null.c
zebra/zebra_ptm_redistribute.c
zebra/zebra_ptm_redistribute.h

index 22b8adcdb65f0a436f7f338a4d5ce230877d7814..5505ced9268781d053706784d8adc3302cb4d3a9 100644 (file)
@@ -73,7 +73,8 @@ bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
 static int
 bgp_bfd_is_peer_multihop(struct peer *peer)
 {
-  if((peer->sort == BGP_PEER_IBGP) || is_ebgp_multihop_configured(peer))
+  if((peer->conf_if == NULL) && ((peer->sort == BGP_PEER_IBGP) ||
+                          is_ebgp_multihop_configured(peer)))
     return 1;
   else
     return 0;
@@ -191,19 +192,46 @@ bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length)
 }
 
 /*
- * bgp_interface_bfd_dest_down - Find the peer for which the BFD status
- *                               has changed and bring down the peer
- *                               connectivity.
+ * bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring
+ *                              down the peer if the BFD session went down from  *                              up.
+ */
+static void
+bgp_bfd_peer_status_update (struct peer *peer, int status)
+{
+  struct bfd_info *bfd_info;
+  int old_status;
+
+  bfd_info = (struct bfd_info *)peer->bfd_info;
+
+  if (bfd_info->status == status)
+    return;
+
+  old_status = bfd_info->status;
+  bfd_info->status = status;
+  bfd_info->last_update = bgp_clock();
+
+  if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP))
+    {
+      peer->last_reset = PEER_DOWN_BFD_DOWN;
+      BGP_EVENT_ADD (peer, BGP_Stop);
+    }
+}
+
+/*
+ * bgp_bfd_dest_update - Find the peer for which the BFD status
+ *                       has changed and bring down the peer
+ *                       connectivity if the BFD session went down.
  */
 static int
-bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
+bgp_bfd_dest_update (int command, struct zclient *zclient,
                              zebra_size_t length)
 {
   struct interface *ifp;
   struct prefix dp;
   struct prefix sp;
+  int status;
 
-  ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp);
+  ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp, &status);
 
   if (BGP_DEBUG (zebra, ZEBRA))
     {
@@ -211,14 +239,14 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
       prefix2str(&dp, buf[0], sizeof(buf[0]));
       if (ifp)
         {
-          zlog_debug("Zebra: interface %s bfd destination %s down",
-                      ifp->name, buf[0]);
+          zlog_debug("Zebra: interface %s bfd destination %s %s",
+                      ifp->name, buf[0], bfd_get_status_str(status));
         }
       else
         {
           prefix2str(&sp, buf[1], sizeof(buf[1]));
-          zlog_debug("Zebra: source %s bfd destination %s down",
-                      buf[1], buf[0]);
+          zlog_debug("Zebra: source %s bfd destination %s %s",
+                      buf[1], buf[0], bfd_get_status_str(status));
         }
     }
 
@@ -253,8 +281,7 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
 
           if (ifp && (ifp == peer->nexthop.ifp))
             {
-              peer->last_reset = PEER_DOWN_BFD_DOWN;
-              BGP_EVENT_ADD (peer, BGP_Stop);
+              bgp_bfd_peer_status_update(peer, status);
             }
           else
             {
@@ -279,8 +306,7 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
               else
                 continue;
 
-              peer->last_reset = PEER_DOWN_BFD_DOWN;
-              BGP_EVENT_ADD (peer, BGP_Stop);
+              bgp_bfd_peer_status_update(peer, status);
             }
         }
   }
@@ -299,8 +325,8 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
   struct listnode *node, *nnode;
   int command = 0;
 
-  bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult,
-                defaults, &command);
+  bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx,
+                detect_mult, defaults, &command);
 
   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
@@ -308,8 +334,8 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
         {
           command = 0;
-          bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult,
-                        defaults, &command);
+          bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx,
+                        detect_mult, defaults, &command);
 
           if ((peer->status == Established) &&
               (command == ZEBRA_BFD_DEST_REGISTER))
@@ -386,38 +412,8 @@ bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
 void
 bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh)
 {
-  struct bfd_info *bfd_info;
-  json_object *json_bfd = NULL;
-
-  if (!peer->bfd_info)
-    return;
-
-  if (use_json)
-    json_bfd = json_object_new_object();
-
-  bfd_info = (struct bfd_info *)peer->bfd_info;
-
-  if (use_json)
-    {
-      if (bgp_bfd_is_peer_multihop(peer))
-        json_object_string_add(json_bfd, "bfdMultiHop", "yes");
-      else
-        json_object_string_add(json_bfd, "bfdMultiHop", "no");
-      json_object_int_add(json_bfd, "detectMultiplier", bfd_info->detect_mult);
-      json_object_int_add(json_bfd, "rxMinInterval", bfd_info->required_min_rx);
-      json_object_int_add(json_bfd, "txMinInterval", bfd_info->desired_min_tx);
-      json_object_object_add(json_neigh, "peerBfdInfo", json_bfd);
-    }
-  else
-    {
-      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);
-    }
+  bfd_show_info(vty, (struct bfd_info *)peer->bfd_info,
+                bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh);
 }
 
 DEFUN (neighbor_bfd,
@@ -501,7 +497,7 @@ void
 bgp_bfd_init(void)
 {
   /* Initialize BFD client functions */
-  zclient->interface_bfd_dest_down = bgp_interface_bfd_dest_down;
+  zclient->interface_bfd_dest_update = bgp_bfd_dest_update;
   zclient->bfd_dest_replay = bgp_bfd_dest_replay;
 
   /* "neighbor bfd" commands. */
index 862a95dacdb5e5b0f83fb3b1f73a38b94d3fe88f..613c71487e4e37f7e7767bd393abfa2c8e977bd3 100644 (file)
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -44,6 +44,8 @@ bfd_info_create(void)
   bfd_info = XCALLOC (MTYPE_BFD_INFO, sizeof (struct bfd_info));
   assert(bfd_info);
 
+  bfd_info->status = BFD_STATUS_UNKNOWN;
+  bfd_info->last_update = 0;
   return bfd_info;
 }
 
@@ -247,7 +249,8 @@ bfd_get_command_dbg_str(int command)
  *                     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)
+bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp,
+                    int *status)
 {
   unsigned int ifindex;
   struct interface *ifp = NULL;
@@ -275,6 +278,9 @@ bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp)
   stream_get (&dp->u.prefix, s, plen);
   dp->prefixlen = stream_getc (s);
 
+  /* Get BFD status. */
+  *status = stream_getl (s);
+
   if (sp)
     {
       sp->family = stream_getc (s);
@@ -285,3 +291,147 @@ bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp)
     }
   return ifp;
 }
+
+/*
+ * bfd_get_status_str - Convert BFD status to a display string.
+ */
+const char *
+bfd_get_status_str(int status)
+{
+  switch (status)
+  {
+    case BFD_STATUS_DOWN:
+      return "Down";
+    case BFD_STATUS_UP:
+      return "Up";
+    case BFD_STATUS_UNKNOWN:
+    default:
+      return "Unknown";
+  }
+}
+
+/*
+ * bfd_last_update - Calculate the last BFD update time and convert it
+ *                   into a dd:hh:mm:ss display format.
+ */
+static void
+bfd_last_update (time_t last_update, char *buf, size_t len)
+{
+  time_t curr;
+  time_t diff;
+  struct tm *tm;
+  struct timeval tv;
+
+  /* If no BFD satatus update has ever been received, print `never'. */
+  if (last_update == 0)
+    {
+      snprintf (buf, len, "never");
+      return;
+    }
+
+  /* Get current time. */
+  quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
+  curr = tv.tv_sec;
+  diff = curr - last_update;
+  tm = gmtime (&diff);
+
+  snprintf (buf, len, "%d:%02d:%02d:%02d",
+            tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+/*
+ * bfd_show_param - Show the BFD parameter information.
+ */
+void
+bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag,
+                int extra_space, u_char use_json, json_object *json_obj)
+{
+  json_object *json_bfd = NULL;
+
+  if (!bfd_info)
+    return;
+
+  if (use_json)
+    {
+      if (bfd_tag)
+        json_bfd = json_object_new_object();
+      else
+        json_bfd = json_obj;
+
+      json_object_int_add(json_bfd, "detectMultiplier", bfd_info->detect_mult);
+      json_object_int_add(json_bfd, "rxMinInterval", bfd_info->required_min_rx);
+      json_object_int_add(json_bfd, "txMinInterval", bfd_info->desired_min_tx);
+      if (bfd_tag)
+        json_object_object_add(json_obj, "peerBfdInfo", json_bfd);
+    }
+  else
+    {
+      vty_out (vty, "  %s%sDetect Mul: %d, Min Rx interval: %d,"
+                " Min Tx interval: %d%s",
+                    (extra_space) ? "  ": "", (bfd_tag) ? "BFD: " : "  ",
+                    bfd_info->detect_mult, bfd_info->required_min_rx,
+                    bfd_info->desired_min_tx, VTY_NEWLINE);
+    }
+}
+
+/*
+ * bfd_show_status - Show the BFD status information.
+ */
+static void
+bfd_show_status(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag,
+                int extra_space, u_char use_json, json_object *json_bfd)
+{
+  char time_buf[32];
+
+  if (!bfd_info)
+    return;
+
+  bfd_last_update(bfd_info->last_update, time_buf, 32);
+  if (use_json)
+    {
+      json_object_string_add(json_bfd, "status",
+                              bfd_get_status_str(bfd_info->status));
+      json_object_string_add(json_bfd, "lastUpdate", time_buf);
+    }
+  else
+    {
+      vty_out (vty, "  %s%sStatus: %s, Last update: %s%s",
+                  (extra_space) ? "  ": "", (bfd_tag) ? "BFD: " : "  ",
+                  bfd_get_status_str(bfd_info->status), time_buf, VTY_NEWLINE);
+    }
+}
+
+/*
+ * bfd_show_info - Show the BFD information.
+ */
+void
+bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop,
+              int extra_space, u_char use_json, json_object *json_obj)
+{
+  json_object *json_bfd = NULL;
+
+  if (!bfd_info)
+    return;
+
+  if (use_json)
+    {
+      json_bfd = json_object_new_object();
+      if (multihop)
+        json_object_string_add(json_bfd, "type", "multi hop");
+      else
+        json_object_string_add(json_bfd, "type", "single hop");
+    }
+  else
+    {
+      vty_out (vty, "  %sBFD: Type: %s%s", (extra_space) ? "  " : "",
+              (multihop) ? "multi hop" : "single hop", VTY_NEWLINE);
+    }
+
+  bfd_show_param(vty, bfd_info, 0, extra_space, use_json, json_bfd);
+  bfd_show_status(vty, bfd_info, 0, extra_space, use_json, json_bfd);
+
+  if (use_json)
+    json_object_object_add(json_obj, "peerBfdInfo", json_bfd);
+  else
+    vty_out (vty, "%s", VTY_NEWLINE);
+}
index f0051d93a211680db9523c0c3e6385031242e0dc..0b5743b9108880cfb64a6dc17165f0c4481567c7 100644 (file)
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -24,6 +24,8 @@
 #ifndef _ZEBRA_BFD_H
 #define _ZEBRA_BFD_H
 
+#include "lib/json.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_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */
 #define BFD_FLAG_BFD_REG   (1 << 1) /* Peer registered with BFD */
 
+#define BFD_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */
+#define BFD_STATUS_DOWN    (1 << 1) /* BFD session status is down */
+#define BFD_STATUS_UP      (1 << 2) /* BFD session status is up */
+
 struct bfd_info
 {
   u_int16_t flags;
   u_int8_t  detect_mult;
   u_int32_t desired_min_tx;
   u_int32_t required_min_rx;
+  time_t    last_update;
+  u_int8_t  status;
 };
 
 extern struct bfd_info *
@@ -72,6 +80,18 @@ 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);
+bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp,
+                   int *status);
+
+const char *
+bfd_get_status_str(int status);
+
+extern void
+bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag,
+                int extra_space, u_char use_json, json_object *json_obj);
+
+extern void
+bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop,
+              int extra_space, u_char use_json, json_object *json_obj);
 
 #endif /* _ZEBRA_BFD_H */
index 64bd1645878dd75a902117f6eebaa281bf98caf1..1046f904dbf67282538960ae6b0a0ea62747dc80 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -836,7 +836,7 @@ static const struct zebra_desc_table command_types[] = {
   DESC_ENTRY   (ZEBRA_INTERFACE_NBR_ADDRESS_ADD),
   DESC_ENTRY   (ZEBRA_INTERFACE_NBR_ADDRESS_DELETE),
   DESC_ENTRY    (ZEBRA_IMPORT_CHECK_UPDATE),
-  DESC_ENTRY   (ZEBRA_INTERFACE_BFD_DEST_DOWN),
+  DESC_ENTRY   (ZEBRA_INTERFACE_BFD_DEST_UPDATE),
   DESC_ENTRY   (ZEBRA_BFD_DEST_REGISTER),
   DESC_ENTRY   (ZEBRA_BFD_DEST_DEREGISTER),
   DESC_ENTRY   (ZEBRA_BFD_DEST_UPDATE),
index 39b6f8ec5f79412ebec549155f358b3a0a9d1df3..35b18cb959df0a365d9cb8ee2274f0b4e6b253fc 100644 (file)
@@ -1208,9 +1208,9 @@ zclient_read (struct thread *thread)
       if (zclient->interface_address_delete)
        (*zclient->interface_address_delete) (command, zclient, length);
       break;
-    case ZEBRA_INTERFACE_BFD_DEST_DOWN:
-      if (zclient->interface_bfd_dest_down)
-       (*zclient->interface_bfd_dest_down) (command, zclient, length);
+    case ZEBRA_INTERFACE_BFD_DEST_UPDATE:
+      if (zclient->interface_bfd_dest_update)
+       (*zclient->interface_bfd_dest_update) (command, zclient, length);
       break;
     case ZEBRA_INTERFACE_NBR_ADDRESS_ADD:
       if (zclient->interface_nbr_address_add)
index 26cae04344d466c49fca98d1886ecb92d07289f3..6ed4fede46c10d0298ef378541a7e91c66e283a0 100644 (file)
@@ -85,7 +85,7 @@ struct zclient
   int (*interface_down) (int, struct zclient *, uint16_t);
   int (*interface_address_add) (int, struct zclient *, uint16_t);
   int (*interface_address_delete) (int, struct zclient *, uint16_t);
-  int (*interface_bfd_dest_down) (int, struct zclient *, uint16_t);
+  int (*interface_bfd_dest_update) (int, struct zclient *, uint16_t);
   int (*interface_nbr_address_add) (int, struct zclient *, uint16_t);
   int (*interface_nbr_address_delete) (int, struct zclient *, uint16_t);
   int (*ipv4_route_add) (int, struct zclient *, uint16_t);
index 387cd6541502eadf8348e81dd066ab4ce37d7c15..41de01ec25219a1720aa68356c76f838a717aa96 100644 (file)
@@ -429,7 +429,7 @@ struct in_pktinfo
 #define ZEBRA_NEXTHOP_UPDATE              26
 #define ZEBRA_INTERFACE_NBR_ADDRESS_ADD   27
 #define ZEBRA_INTERFACE_NBR_ADDRESS_DELETE 28
-#define ZEBRA_INTERFACE_BFD_DEST_DOWN    29
+#define ZEBRA_INTERFACE_BFD_DEST_UPDATE   29
 #define ZEBRA_IMPORT_ROUTE_REGISTER       30
 #define ZEBRA_IMPORT_ROUTE_UNREGISTER     31
 #define ZEBRA_IMPORT_CHECK_UPDATE         32
index e30f4962d16004100a196dd8c46b266c63c7484d..5ef4ab4ca85116d4cf1244ae85e3dedb6c6a58ef 100644 (file)
 
 extern struct zclient *zclient;
 
+/*
+ * ospf6_bfd_info_free - Free BFD info structure
+ */
+void
+ospf6_bfd_info_free(void **bfd_info)
+{
+  bfd_info_free((struct bfd_info **) bfd_info);
+}
+
+/*
+ * ospf6_bfd_show_info - Show BFD info structure
+ */
+void
+ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only)
+{
+  if (param_only)
+    bfd_show_param(vty, bfd_info, 1, 0, 0, NULL);
+  else
+    bfd_show_info(vty, bfd_info, 0, 1, 0, NULL);
+}
+
 /*
  * ospf6_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
  *                           zebra for starting/stopping the monitoring of
@@ -102,6 +123,11 @@ ospf6_bfd_reg_dereg_all_nbr (struct ospf6_interface *oi, int command)
 
   for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, node, on))
     {
+      if (command != ZEBRA_BFD_DEST_DEREGISTER)
+        ospf6_bfd_info_nbr_create(oi, on);
+      else
+        bfd_info_free((struct bfd_info **)&on->bfd_info);
+
       if (on->state < OSPF6_NEIGHBOR_TWOWAY)
         continue;
 
@@ -151,13 +177,13 @@ ospf6_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length)
 }
 
 /*
- * ospf6_bfd_interface_dest_down - Find the neighbor for which the BFD status
- *                                 has changed and bring down the neighbor
- *                                 connectivity.
+ * ospf6_bfd_interface_dest_update - Find the neighbor for which the BFD status
+ *                                   has changed and bring down the neighbor
+ *                                   connectivity if BFD down is received.
  */
 static int
-ospf6_bfd_interface_dest_down (int command, struct zclient *zclient,
-                              zebra_size_t length)
+ospf6_bfd_interface_dest_update (int command, struct zclient *zclient,
+                                  zebra_size_t length)
 {
   struct interface *ifp;
   struct ospf6_interface *oi;
@@ -166,8 +192,12 @@ ospf6_bfd_interface_dest_down (int command, struct zclient *zclient,
   struct prefix sp;
   struct listnode *node, *nnode;
   char dst[64];
+  int status;
+  int old_status;
+  struct bfd_info *bfd_info;
+  struct timeval tv;
 
-  ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp);
+  ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status);
 
   if ((ifp == NULL) || (dp.family != AF_INET6))
     return 0;
@@ -176,7 +206,8 @@ ospf6_bfd_interface_dest_down (int command, struct zclient *zclient,
     {
       char buf[128];
       prefix2str(&dp, buf, sizeof(buf));
-      zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf);
+      zlog_debug("Zebra: interface %s bfd destination %s %s", ifp->name, buf,
+                 bfd_get_status_str(status));
     }
 
 
@@ -192,16 +223,56 @@ ospf6_bfd_interface_dest_down (int command, struct zclient *zclient,
       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);
+          zlog_debug ("[%s:%s]: BFD %s", ifp->name, dst,
+                      bfd_get_status_str(status));
         }
 
-      THREAD_OFF (on->inactivity_timer);
-      thread_add_event (master, inactivity_timer, on, 0);
+      if (!on->bfd_info)
+        continue;
+
+      bfd_info = (struct bfd_info *)on->bfd_info;
+      if (bfd_info->status == status)
+        continue;
+
+      old_status = bfd_info->status;
+      bfd_info->status = status;
+      quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv);
+      bfd_info->last_update = tv.tv_sec;
+
+      if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP))
+        {
+          THREAD_OFF (on->inactivity_timer);
+          thread_add_event (master, inactivity_timer, on, 0);
+        }
     }
 
   return 0;
 }
 
+/*
+ * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor.
+ */
+void
+ospf6_bfd_info_nbr_create (struct ospf6_interface *oi,
+                            struct ospf6_neighbor *on)
+{
+  struct bfd_info *oi_bfd_info;
+  struct bfd_info *on_bfd_info;
+
+  if (!oi->bfd_info)
+    return;
+
+  oi_bfd_info = (struct bfd_info *)oi->bfd_info;
+
+  if (!on->bfd_info)
+    on->bfd_info = bfd_info_create();
+
+  on_bfd_info = (struct bfd_info *)on->bfd_info;
+  on_bfd_info->detect_mult = oi_bfd_info->detect_mult;
+  on_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx;
+  on_bfd_info->required_min_rx = oi_bfd_info->required_min_rx;
+}
+
 /*
  * ospf6_bfd_write_config - Write the interface BFD configuration.
  */
@@ -321,7 +392,7 @@ DEFUN (no_ipv6_ospf6_bfd,
   if (oi->bfd_info)
     {
       ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER);
-      bfd_info_free(&(oi->bfd_info));
+      bfd_info_free((struct bfd_info **)&(oi->bfd_info));
     }
 
   return CMD_SUCCESS;
@@ -331,7 +402,7 @@ void
 ospf6_bfd_init(void)
 {
   /* Initialize BFD client functions */
-  zclient->interface_bfd_dest_down = ospf6_bfd_interface_dest_down;
+  zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update;
   zclient->bfd_dest_replay = ospf6_bfd_nbr_replay;
 
   /* Install BFD command */
index eaaf157852d0d426865148cdb1de210089e5086d..11b13d66fb9db085fbb61c3ebf09566cd6b843d9 100644 (file)
@@ -33,4 +33,14 @@ 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);
 
+extern void
+ospf6_bfd_info_nbr_create (struct ospf6_interface *oi,
+                            struct ospf6_neighbor *on);
+
+extern void
+ospf6_bfd_info_free(void **bfd_info);
+
+extern void
+ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only);
+
 #endif /* OSPF6_BFD_H */
index 63783cc8f014925867644d860ffb2afcd0f4703c..21751656b418f9652ef457916af99456f062066a 100644 (file)
@@ -29,7 +29,6 @@
 #include "prefix.h"
 #include "plist.h"
 #include "zclient.h"
-#include "bfd.h"
 
 #include "ospf6_lsa.h"
 #include "ospf6_lsdb.h"
@@ -263,7 +262,7 @@ 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));
+  ospf6_bfd_info_free(&(oi->bfd_info));
 
   XFREE (MTYPE_OSPF6_IF, oi);
 }
@@ -977,7 +976,7 @@ ospf6_interface_show (struct vty *vty, struct interface *ifp)
   for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     vty_out (vty, "      %s%s", lsa->name, VNL);
-
+  ospf6_bfd_show_info(vty, oi->bfd_info, 1);
   return 0;
 }
 
index 3f5c5f041f19c3658a5d23895aebb05a78b6ebd9..6ef9e37822b5657114883e2888c10ba09fc2146b 100644 (file)
@@ -115,7 +115,7 @@ struct ospf6_interface
   char *plist_name;
 
   /* BFD information */
-  struct bfd_info *bfd_info;
+  void *bfd_info;
 };
 
 /* interface state */
index c5edd226d535d1d3b33ad614c20934f24e5bbf4c..1636c262890cb87c5e5c9a4b345b8033fa5ee0b1 100644 (file)
@@ -103,6 +103,8 @@ ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *oi)
   on->lsack_list = ospf6_lsdb_create (on);
 
   listnode_add_sort (oi->neighbor_list, on);
+
+  ospf6_bfd_info_nbr_create(oi, on);
   return on;
 }
 
@@ -139,6 +141,7 @@ ospf6_neighbor_delete (struct ospf6_neighbor *on)
   THREAD_OFF (on->thread_send_lsupdate);
   THREAD_OFF (on->thread_send_lsack);
 
+  ospf6_bfd_info_free(&on->bfd_info);
   XFREE (MTYPE_OSPF6_NEIGHBOR, on);
 }
 
@@ -815,6 +818,7 @@ ospf6_neighbor_show_detail (struct vty *vty, struct ospf6_neighbor *on)
        lsa = ospf6_lsdb_next (lsa))
     vty_out (vty, "      %s%s", lsa->name, VNL);
 
+  ospf6_bfd_show_info(vty, on->bfd_info, 0);
 }
 
 DEFUN (show_ipv6_ospf6_neighbor,
index cba2cb99daf0847362e606edab4d0d21a54910cc..fad7fd578a562defaab68c9feea5c3bf8b3df6dc 100644 (file)
@@ -96,6 +96,9 @@ struct ospf6_neighbor
   struct thread *thread_send_lsreq;
   struct thread *thread_send_lsupdate;
   struct thread *thread_send_lsack;
+
+  /* BFD information */
+  void *bfd_info;
 };
 
 /* Neighbor state */
index 054a806bbd8c7849ec2ea06d4285e039b2aaf39a..46c1844e28a2a1b2b5ae5fbb1ef175c7d8185a0f 100644 (file)
 
 extern struct zclient *zclient;
 
+/*
+ * ospf_bfd_info_free - Free BFD info structure
+ */
+void
+ospf_bfd_info_free(void **bfd_info)
+{
+  bfd_info_free((struct bfd_info **) bfd_info);
+}
+
 /*
  * ospf_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
  *                          zebra for starting/stopping the monitoring of
@@ -118,6 +127,11 @@ ospf_bfd_reg_dereg_all_nbr (struct interface *ifp, int command)
           if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self)
             continue;
 
+          if (command != ZEBRA_BFD_DEST_DEREGISTER)
+            ospf_bfd_info_nbr_create(oi, nbr);
+          else
+            bfd_info_free((struct bfd_info **)&nbr->bfd_info);
+
           if (nbr->state < NSM_TwoWay)
             continue;
 
@@ -179,13 +193,14 @@ ospf_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length)
 }
 
 /*
- * ospf_bfd_interface_dest_down - Find the neighbor for which the BFD status
- *                                has changed and bring down the neighbor
- *                                connectivity.
+ * ospf_bfd_interface_dest_update - Find the neighbor for which the BFD status
+ *                                  has changed and bring down the neighbor
+ *                                  connectivity if the BFD status changed to
+ *                                  down.
  */
 static int
-ospf_bfd_interface_dest_down (int command, struct zclient *zclient,
-                              zebra_size_t length)
+ospf_bfd_interface_dest_update (int command, struct zclient *zclient,
+                                 zebra_size_t length)
 {
   struct interface *ifp;
   struct ospf_interface *oi;
@@ -193,8 +208,12 @@ ospf_bfd_interface_dest_down (int command, struct zclient *zclient,
   struct ospf_neighbor *nbr;
   struct route_node *node;
   struct prefix p;
+  int status;
+  int old_status;
+  struct bfd_info *bfd_info;
+  struct timeval tv;
 
-  ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL);
+  ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL, &status);
 
   if ((ifp == NULL) || (p.family != AF_INET))
     return 0;
@@ -203,7 +222,8 @@ ospf_bfd_interface_dest_down (int command, struct zclient *zclient,
     {
       char buf[128];
       prefix2str(&p, buf, sizeof(buf));
-      zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf);
+      zlog_debug("Zebra: interface %s bfd destination %s %s", ifp->name, buf,
+                 bfd_get_status_str(status));
     }
 
   params = IF_DEF_PARAMS (ifp);
@@ -216,19 +236,59 @@ ospf_bfd_interface_dest_down (int command, struct zclient *zclient,
         continue;
 
       nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &p.u.prefix4);
-      if (!nbr)
+      if (!nbr || !nbr->bfd_info)
+        continue;
+
+      bfd_info = (struct bfd_info *)nbr->bfd_info;
+      if (bfd_info->status == status)
         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));
+      old_status = bfd_info->status;
+      bfd_info->status = status;
+      quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv);
+      bfd_info->last_update = tv.tv_sec;
+
+      if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP))
+        {
+          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);
+          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer);
+        }
     }
 
   return 0;
 }
 
+/*
+ * ospf_bfd_info_nbr_create - Create/update BFD information for a neighbor.
+ */
+void
+ospf_bfd_info_nbr_create (struct ospf_interface *oi, struct ospf_neighbor *nbr)
+{
+  struct bfd_info *oi_bfd_info;
+  struct bfd_info *nbr_bfd_info;
+  struct interface *ifp = oi->ifp;
+  struct ospf_if_params *params;
+
+  /* Check if BFD is enabled */
+  params = IF_DEF_PARAMS (ifp);
+
+  /* Check if BFD is enabled */
+  if (!params->bfd_info)
+    return;
+
+  oi_bfd_info = (struct bfd_info *)params->bfd_info;
+  if (!nbr->bfd_info)
+    nbr->bfd_info = bfd_info_create();
+
+  nbr_bfd_info = (struct bfd_info *)nbr->bfd_info;
+  nbr_bfd_info->detect_mult = oi_bfd_info->detect_mult;
+  nbr_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx;
+  nbr_bfd_info->required_min_rx = oi_bfd_info->required_min_rx;
+}
+
 /*
  * ospf_bfd_write_config - Write the interface BFD configuration.
  */
@@ -251,6 +311,32 @@ ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params)
     vty_out (vty, " ip ospf bfd%s", VTY_NEWLINE);
 }
 
+/*
+ * ospf_bfd_show_info - Show BFD info structure
+ */
+void
+ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj,
+                    u_char use_json, int param_only)
+{
+  if (param_only)
+    bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json, json_obj);
+  else
+    bfd_show_info(vty, (struct bfd_info *)bfd_info, 0, 1, use_json, json_obj);
+}
+
+/*
+ * ospf_bfd_interface_show - Show the interface BFD configuration.
+ */
+void
+ospf_bfd_interface_show(struct vty *vty, struct interface *ifp,
+                          json_object *json_interface_sub, u_char use_json)
+{
+  struct ospf_if_params *params;
+
+  params = IF_DEF_PARAMS (ifp);
+
+  ospf_bfd_show_info(vty, params->bfd_info, json_interface_sub, use_json, 1);
+}
 
 /*
  * ospf_bfd_if_param_set - Set the configured BFD paramter values for
@@ -265,13 +351,12 @@ ospf_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx,
 
   params = IF_DEF_PARAMS (ifp);
 
-  bfd_set_param(&(params->bfd_info), min_rx, min_tx, detect_mult,
-                defaults, &command);
+  bfd_set_param((struct bfd_info **)&(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",
@@ -342,7 +427,7 @@ void
 ospf_bfd_init(void)
 {
   /* Initialize BFD client functions */
-  zclient->interface_bfd_dest_down = ospf_bfd_interface_dest_down;
+  zclient->interface_bfd_dest_update = ospf_bfd_interface_dest_update;
   zclient->bfd_dest_replay = ospf_bfd_nbr_replay;
 
   /* Install BFD command */
index 436597c0ba9ef4eecba33c3291716765cbc008b6..793962dae36b290b6f97385d72914d45e24c72f7 100644 (file)
@@ -24,6 +24,8 @@
 #ifndef _ZEBRA_OSPF_BFD_H
 #define _ZEBRA_OSPF_BFD_H
 
+#include "json.h"
+
 extern void
 ospf_bfd_init(void);
 
@@ -33,4 +35,18 @@ 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);
 
+extern void
+ospf_bfd_interface_show(struct vty *vty, struct interface *ifp,
+                          json_object *json_interface_sub, u_char use_json);
+
+extern void
+ospf_bfd_info_nbr_create (struct ospf_interface *oi, struct ospf_neighbor *nbr);
+
+extern void
+ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj,
+                    u_char use_json, int param_only);
+
+extern void
+ospf_bfd_info_free(void **bfd_info);
+
 #endif /* _ZEBRA_OSPF_BFD_H */
index 967ca15db03c9b1027b4b005c8b7df73f3ba610f..afc74d2b00d4a85bc28174cb471dc44c7ec2a56f 100644 (file)
@@ -30,6 +30,7 @@
 #include "stream.h"
 #include "table.h"
 #include "log.h"
+#include "json.h"
 
 #include "ospfd/ospfd.h"
 #include "ospfd/ospf_interface.h"
@@ -42,6 +43,7 @@
 #include "ospfd/ospf_network.h"
 #include "ospfd/ospf_flood.h"
 #include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_bfd.h"
 
 /* Fill in the the 'key' as appropriate to retrieve the entry for nbr
  * from the ospf_interface's nbrs table. Indexed by interface address
@@ -98,6 +100,7 @@ ospf_nbr_new (struct ospf_interface *oi)
 
   nbr->crypt_seqnum = 0;
 
+  ospf_bfd_info_nbr_create(oi, nbr);
   return nbr;
 }
 
@@ -141,6 +144,7 @@ ospf_nbr_free (struct ospf_neighbor *nbr)
   /* Cancel all events. *//* Thread lookup cost would be negligible. */
   thread_cancel_event (master, nbr);
 
+  ospf_bfd_info_free(&nbr->bfd_info);
   XFREE (MTYPE_OSPF_NEIGHBOR, nbr);
 }
 
index 25f135242c73335db34e613fc80d7838b3578c55..7118dd0210affd94d8e3ade693cee598490ecee7 100644 (file)
@@ -88,6 +88,9 @@ struct ospf_neighbor
   struct timeval ts_last_regress;   /* last regressive NSM change     */
   const char *last_regress_str;     /* Event which last regressed NSM */
   u_int32_t state_change;           /* NSM state change counter       */
+
+  /* BFD information */
+  void *bfd_info;
 };
 
 /* Macros. */
index 6caeda76585cc78d2d64855eca1032edc634c570..f2b34bab1738ecc940af6c8d948fd44f57dcc486 100644 (file)
@@ -3857,6 +3857,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, struct interface
         vty_out (vty, "  Neighbor Count is %d, Adjacent neighbor count is %d%s",
                  ospf_nbr_count (oi, 0), ospf_nbr_count (oi, NSM_Full),
                  VTY_NEWLINE);
+      ospf_bfd_interface_show(vty, ifp, json_interface_sub, use_json);
     }
 }
 
@@ -4622,6 +4623,8 @@ show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi,
       else
         json_object_object_add(json, inet_ntoa (nbr->router_id), json_sub);
     }
+
+  ospf_bfd_show_info(vty, nbr->bfd_info, json, use_json, 0);
 }
 
 static int
index 6c85eaa89f4ac6d5b3ad8b5405dcccfdfe052671..0fecd17d5dc606d45d8d5ba54be8ebfc031e041e 100644 (file)
@@ -33,6 +33,7 @@
 #include "ptm_lib.h"
 #include "buffer.h"
 #include "zebra/zebra_ptm_redistribute.h"
+#include "bfd.h"
 
 #define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */
 #define ZEBRA_PTM_RECONNECT_TIME_MAX     300
@@ -68,6 +69,7 @@ const char ZEBRA_PTM_BFD_CLIENT_FIELD[] = "client";
 const char ZEBRA_PTM_BFD_SEQID_FIELD[] = "seqid";
 const char ZEBRA_PTM_BFD_IFNAME_FIELD[] = "ifName";
 const char ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD[] = "maxHopCnt";
+const char ZEBRA_PTM_BFD_SEND_EVENT[] = "sendEvent";
 
 extern struct zebra_t zebrad;
 
@@ -341,7 +343,8 @@ zebra_ptm_install_commands (void)
 
 /* BFD session goes down, send message to the protocols. */
 static void
-if_bfd_session_down (struct interface *ifp, struct prefix *dp, struct prefix *sp)
+if_bfd_session_update (struct interface *ifp, struct prefix *dp,
+                      struct prefix *sp, int status)
 {
   if (IS_ZEBRA_DEBUG_EVENT)
     {
@@ -349,22 +352,24 @@ if_bfd_session_down (struct interface *ifp, struct prefix *dp, struct prefix *sp
 
       if (ifp)
         {
-          zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d on %s",
-                  inet_ntop (dp->family, &dp->u.prefix, buf[0],
-                              INET6_ADDRSTRLEN), dp->prefixlen, ifp->name);
+          zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s"
+                      " %s event",
+                        inet_ntop (dp->family, &dp->u.prefix, buf[0],
+                              INET6_ADDRSTRLEN), dp->prefixlen, ifp->name,
+                        bfd_get_status_str(status));
         }
       else
         {
-          zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d "
-                      "with src %s/%d",
+          zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d "
+                      "with src %s/%d %s event",
                   inet_ntop (dp->family, &dp->u.prefix, buf[0], INET6_ADDRSTRLEN),
                   dp->prefixlen,
                   inet_ntop (sp->family, &sp->u.prefix, buf[1], INET6_ADDRSTRLEN),
-                  sp->prefixlen);
+                  sp->prefixlen, bfd_get_status_str(status));
         }
     }
 
-  zebra_interface_bfd_update (ifp, dp, sp);
+  zebra_interface_bfd_update (ifp, dp, sp, status);
 }
 
 static int
@@ -403,44 +408,25 @@ zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt, struct interface *ifp)
                   __func__, ifp ? ifp->name : "N/A", bfdst_str,
                   dest_str, src_str);
 
-  /* we only care if bfd session goes down */
-  if (!strcmp (bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) {
-    if (inet_pton(AF_INET, dest_str, &dest_prefix.u.prefix4) > 0) {
-      dest_prefix.family = AF_INET;
-      dest_prefix.prefixlen = IPV4_MAX_PREFIXLEN;
-    }
-#ifdef HAVE_IPV6
-    else if (inet_pton(AF_INET6, dest_str, &dest_prefix.u.prefix6) > 0) {
-      dest_prefix.family = AF_INET6;
-      dest_prefix.prefixlen = IPV6_MAX_PREFIXLEN;
-    }
-#endif /* HAVE_IPV6 */
-    else {
-        zlog_err("%s: Peer addr %s not found", __func__,
-           dest_str);
-        return -1;
-    }
+  if (str2prefix(dest_str, &dest_prefix) == 0) {
+      zlog_err("%s: Peer addr %s not found", __func__,
+         dest_str);
+      return -1;
+  }
 
-    memset(&src_prefix, 0, sizeof(struct prefix));
-    if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) {
-      if (inet_pton(AF_INET, src_str, &src_prefix.u.prefix4) > 0) {
-        src_prefix.family = AF_INET;
-        src_prefix.prefixlen = IPV4_MAX_PREFIXLEN;
-      }
-#ifdef HAVE_IPV6
-      else if (inet_pton(AF_INET6, src_str, &src_prefix.u.prefix6) > 0) {
-        src_prefix.family = AF_INET6;
-        src_prefix.prefixlen = IPV6_MAX_PREFIXLEN;
-      }
-#endif /* HAVE_IPV6 */
-      else {
-          zlog_err("%s: Local addr %s not found", __func__,
-             src_str);
-          return -1;
-      }
+  memset(&src_prefix, 0, sizeof(struct prefix));
+  if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) {
+    if (str2prefix(src_str, &src_prefix) == 0) {
+        zlog_err("%s: Local addr %s not found", __func__,
+           src_str);
+        return -1;
     }
+  }
 
-    if_bfd_session_down(ifp, &dest_prefix, &src_prefix);
+  if (!strcmp (bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) {
+    if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_DOWN);
+  } else {
+    if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_UP);
   }
 
   return 0;
@@ -718,6 +704,10 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
                           if_name);
     }
 
+  sprintf(tmp_buf, "%d", 1);
+  ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT,
+                      tmp_buf);
+
   ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len);
 
   if (IS_ZEBRA_DEBUG_SEND)
index ad48f238565cdcda01966d9ed99f00fd0e9ecb78..293db2e674ff861def2424c5841ca8e8d1b5faa6 100644 (file)
@@ -24,7 +24,7 @@
 #include "zebra_ptm_redistribute.h"
 
 void zebra_interface_bfd_update (struct interface *a, struct prefix *dp,
-                                 struct prefix *sp)
+                                 struct prefix *sp, int status)
 { return; }
 
 void zebra_bfd_peer_replay_req (void)
index 6166fc002612cd85d4b6121a5b8285396b162526..1a81c79857d1a054afa8098042b3be7a9c086df8 100644 (file)
@@ -32,7 +32,7 @@ extern struct zebra_t zebrad;
 static int
 zsend_interface_bfd_update (int cmd, struct zserv *client,
                             struct interface *ifp, struct prefix *dp,
-                            struct prefix *sp)
+                            struct prefix *sp, int status)
 {
   int blen;
   struct stream *s;
@@ -56,6 +56,9 @@ zsend_interface_bfd_update (int cmd, struct zserv *client,
   stream_put (s, &dp->u.prefix, blen);
   stream_putc (s, dp->prefixlen);
 
+  /* BFD status */
+  stream_putl(s, status);
+
   /* BFD source prefix information. */
   stream_putc (s, sp->family);
   blen = prefix_blen (sp);
@@ -71,7 +74,7 @@ zsend_interface_bfd_update (int cmd, struct zserv *client,
 
 void
 zebra_interface_bfd_update (struct interface *ifp, struct prefix *dp,
-                            struct prefix *sp)
+                            struct prefix *sp, int status)
 {
   struct listnode *node, *nnode;
   struct zserv *client;
@@ -84,8 +87,8 @@ zebra_interface_bfd_update (struct interface *ifp, struct prefix *dp,
         continue;
 
       /* Notify to the protocol daemons. */
-      zsend_interface_bfd_update (ZEBRA_INTERFACE_BFD_DEST_DOWN, client, ifp,
-                                    dp, sp);
+      zsend_interface_bfd_update (ZEBRA_INTERFACE_BFD_DEST_UPDATE, client, ifp,
+                                    dp, sp, status);
     }
 }
 
index b79d122af5dd5ffc05c9d7db6ce6c9aa9e8b6240..d78390e890166d3ac32c749c9200fb98c753ab53 100644 (file)
@@ -23,6 +23,6 @@
 #ifndef _ZEBRA_PTM_REDISTRIBUTE_H
 #define _ZEBRA_PTM_REDISTRIBUTE_H
 extern void zebra_interface_bfd_update (struct interface *, struct prefix *,
-                                         struct prefix *);
+                                         struct prefix *, int);
 extern void zebra_bfd_peer_replay_req (void);
 #endif /* _ZEBRA_PTM_REDISTRIBUTE_H */