]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra - BFD client de-registration support
authorradhika <radhika@cumulusnetworks.com>
Mon, 9 May 2016 03:11:18 +0000 (20:11 -0700)
committerradhika <radhika@cumulusnetworks.com>
Mon, 9 May 2016 03:11:18 +0000 (20:11 -0700)
CM-10680
Issue: When BGP daemon is stopped, all the BGP BFD sessions are not getting deleted from PTM.
Root cause: BGP daemon stop causes BFD de-register message to be sent for every peer on which BFD is enabled. But, all the de-register messages from bgpd to zebra are not processed before the socket close. This results in some stale BGP BFD sessions.
Fix: Support for client de-register message has been added in PTM/BFD.  Changes in Quagga to support BFD client de-registrations:
−   The BFD clients de-registration is sent directly from zebra daemon when zebra client (bgpd, ospfd and ospf6d) socket close is detected.
−   Introduced a BFD flag for the zebra clients to prevent BFD de-registration messages from being sent to zebra daemon when the client is shutting down. This reduces the BFD messaging.

CM-10540
Issue: Invalid ptm status “fail” instead of “n/a” being displayed for VRF interfaces.
Root cause: ptm status is not being initialized to “unknown” status when VRF interface is added or changed. The uninitialized value is ‘0’ which is the value for “fail”
Fix: Initialized the ptm status to the correct value.

Signed-off-by: Radhika Mahankali <radhika@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Kanna Rajagopal <kanna@cumulusnetworks.com>
Ticket: CM-10680, CM-10540
Reviewed By: CCR-4653
Testing Done: PTM smoke, BGP smoke and ptmd_test.py:TestMultipleAddrsIntfOspfBgp

12 files changed:
bgpd/bgp_bfd.c
bgpd/bgp_main.c
lib/bfd.c
lib/bfd.h
ospf6d/ospf6_bfd.c
ospf6d/ospf6_main.c
ospfd/ospf_bfd.c
ospfd/ospfd.c
zebra/rt_netlink.c
zebra/zebra_ptm.c
zebra/zebra_ptm.h
zebra/zserv.c

index da50fd2bae85e4970201fef290d61aaef248d8a5..b64fbee04d978a9401e91259319c61c1487cff06 100644 (file)
@@ -698,6 +698,8 @@ DEFUN_HIDDEN (no_neighbor_bfd_type,
 void
 bgp_bfd_init(void)
 {
+  bfd_gbl_init();
+
   /* Initialize BFD client functions */
   zclient->interface_bfd_dest_update = bgp_bfd_dest_update;
   zclient->bfd_dest_replay = bgp_bfd_dest_replay;
index 656f49d183523ca4faff69362b44b0da955b8456..271e1d97bb14fa13c147e6e37264c4abd327ea2f 100644 (file)
@@ -38,6 +38,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "stream.h"
 #include "queue.h"
 #include "vrf.h"
+#include "bfd.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_attr.h"
@@ -229,6 +230,8 @@ bgp_exit (int status)
   /* it only makes sense for this to be called on a clean exit */
   assert (status == 0);
 
+  bfd_gbl_exit();
+
   bgp_close();
 
   if (retain_mode)
index d48dc651c6f82e21e57a27c08bfeaaf51211d864..2116fa5c1f420e08829a4dc8078832888ee18c3b 100644 (file)
--- a/lib/bfd.c
+++ b/lib/bfd.c
 #include "bfd.h"
 
 int bfd_debug = 0;
+struct bfd_gbl bfd_gbl;
+
+/*
+ * bfd_gbl_init - Initialize the BFD global structure
+ */
+void
+bfd_gbl_init(void)
+{
+  memset(&bfd_gbl, 0, sizeof (struct bfd_gbl));
+}
+
+/*
+ * bfd_gbl_exit - Called when daemon exits
+ */
+void
+bfd_gbl_exit(void)
+{
+  SET_FLAG (bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN);
+}
 
 /*
  * bfd_info_create - Allocate the BFD information
@@ -129,6 +148,14 @@ bfd_peer_sendmsg (struct zclient *zclient, struct bfd_info *bfd_info,
   int ret;
   int len;
 
+  /* Individual reg/dereg messages are supressed during shutdown. */
+  if (CHECK_FLAG (bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN))
+    {
+      if (bfd_debug)
+       zlog_debug("%s: Suppressing BFD peer reg/dereg messages", __FUNCTION__);
+      return;
+    }
+
   /* Check socket. */
   if (!zclient || zclient->sock < 0)
     {
index 31e542d8b79363b8f7d9790e93a01f2a0b2650d5..bbe96b07b42df552aa2b02e874a8e107c307c6d5 100644 (file)
--- a/lib/bfd.h
+++ b/lib/bfd.h
 #define BFD_MIN_DETECT_MULT 2
 #define BFD_MAX_DETECT_MULT 255
 
+#define BFD_GBL_FLAG_IN_SHUTDOWN (1 << 0) /* The daemon in shutdown */
+struct bfd_gbl
+{
+  u_int16_t           flags;
+};
+
 #define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */
 #define BFD_FLAG_BFD_REG   (1 << 1) /* Peer registered with BFD */
 #define BFD_FLAG_BFD_TYPE_MULTIHOP (1 << 2) /* Peer registered with BFD as multihop */
@@ -107,4 +113,10 @@ bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop,
 extern void
 bfd_client_sendmsg (struct zclient *zclient, int command);
 
+extern void
+bfd_gbl_init(void);
+
+extern void
+bfd_gbl_exit(void);
+
 #endif /* _ZEBRA_BFD_H */
index adcfcbf19c0f62abbd30cc47bfd86efc4c436a13..503c7e0cd71a69cc7640fe7c906e3f8f5e765788 100644 (file)
@@ -410,6 +410,8 @@ DEFUN (no_ipv6_ospf6_bfd,
 void
 ospf6_bfd_init(void)
 {
+  bfd_gbl_init();
+
   /* Initialize BFD client functions */
   zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update;
   zclient->bfd_dest_replay = ospf6_bfd_nbr_replay;
index 9a73ccc4b8ef3571541a76c80cae2c9ea6873ae9..52dc6677f0f9c638774108f45ff35389a48f42f2 100644 (file)
@@ -37,6 +37,7 @@
 #include "sigevent.h"
 #include "zclient.h"
 #include "vrf.h"
+#include "bfd.h"
 
 #include "ospf6d.h"
 #include "ospf6_top.h"
@@ -144,6 +145,8 @@ ospf6_exit (int status)
   if (ospf6)
     ospf6_delete (ospf6);
 
+  bfd_gbl_exit();
+
   for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
     if (ifp->info != NULL)
       ospf6_interface_delete(ifp->info);
index e9c6bfd8e7e5519aadb0126b918f3feaed301119..ec486c46882747383a0dc91db2aaa8cf054577c3 100644 (file)
@@ -441,6 +441,8 @@ ALIAS (no_ip_ospf_bfd,
 void
 ospf_bfd_init(void)
 {
+  bfd_gbl_init();
+
   /* Initialize BFD client functions */
   zclient->interface_bfd_dest_update = ospf_bfd_interface_dest_update;
   zclient->bfd_dest_replay = ospf_bfd_nbr_replay;
index 3bb7148242b6c5aaa0b7bb82a2f4c2baefa5b269..91702c34b50519d2e138f76dc95b32a6aeefcd58 100644 (file)
@@ -34,6 +34,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "zclient.h"
 #include "plist.h"
 #include "sockopt.h"
+#include "bfd.h"
 
 #include "ospfd/ospfd.h"
 #include "ospfd/ospf_network.h"
@@ -468,6 +469,7 @@ ospf_terminate (void)
   if (listcount(om->ospf) == 0)
     exit(0);
 
+  bfd_gbl_exit();
   for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
     ospf_finish (ospf);
 
index 0c7d72130aa06eb28fc1e845098012dd2425498d..50a269dbc6aefdd237cad33786d88cc10e333bb8 100644 (file)
@@ -47,6 +47,7 @@
 #include "zebra/interface.h"
 #include "zebra/debug.h"
 #include "zebra/rtadv.h"
+#include "zebra/zebra_ptm.h"
 
 #include "rt_netlink.h"
 
@@ -684,6 +685,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
     SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
   ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]);
   ifp->metric = 0;
+  ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
 
   /* Hardware type and address. */
   ifp->hw_type = ifi->ifi_type;
@@ -1359,6 +1361,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
             SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
           ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
           ifp->metric = 0;
+          ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
 
           netlink_interface_update_hw_addr (tb, ifp);
 
index 731bd3562b57c4c22029a11c692319e9724d5b1a..bf6afb021603b9162cf647fb3899e1208f75786d 100644 (file)
@@ -48,6 +48,7 @@ const char ZEBRA_PTM_GET_STATUS_CMD[] = "get-status";
 const char ZEBRA_PTM_BFD_START_CMD[] = "start-bfd-sess";
 const char ZEBRA_PTM_BFD_STOP_CMD[] = "stop-bfd-sess";
 const char ZEBRA_PTM_BFD_CLIENT_REG_CMD[] = "reg-bfd-client";
+const char ZEBRA_PTM_BFD_CLIENT_DEREG_CMD[] = "dereg-bfd-client";
 
 const char ZEBRA_PTM_CMD_STR[] = "cmd";
 const char ZEBRA_PTM_CMD_STATUS_STR[] = "cmd_status";
@@ -1001,6 +1002,46 @@ zebra_ptm_bfd_client_register (struct zserv *client, int sock, u_short length)
   return 0;
 }
 
+/* BFD client deregister */
+void
+zebra_ptm_bfd_client_deregister (struct zserv *client)
+{
+  void *out_ctxt;
+  char tmp_buf[64];
+  int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
+
+  if (client->proto != ZEBRA_ROUTE_OSPF && client->proto != ZEBRA_ROUTE_BGP
+      && client->proto != ZEBRA_ROUTE_OSPF6)
+    return;
+
+  if (IS_ZEBRA_DEBUG_EVENT)
+    zlog_debug("bfd_client_deregister msg for client %s",
+                zebra_route_string(client->proto));
+
+  if (ptm_cb.ptm_sock == -1)
+    {
+      ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect,
+                                             NULL, ptm_cb.reconnect_time);
+      return;
+    }
+
+  ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
+
+  sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_DEREG_CMD);
+  ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf);
+
+  sprintf(tmp_buf, "%s", zebra_route_string(client->proto));
+  ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
+                      tmp_buf);
+
+  ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len);
+
+  if (IS_ZEBRA_DEBUG_SEND)
+    zlog_debug ("%s: Sent message (%d) %s", __func__, data_len,
+                  ptm_cb.out_data);
+  zebra_ptm_send_message(ptm_cb.out_data, data_len);
+}
+
 int
 zebra_ptm_get_enable_state(void)
 {
index 190ae996ec7726ed07c20a24bea0782bb483f459..27c0e42f99ef87e688398dc28124b43c74291280 100644 (file)
@@ -72,4 +72,5 @@ int zebra_ptm_bfd_client_register (struct zserv *client, int sock,
 void zebra_ptm_if_init(struct zebra_if *zebra_ifp);
 void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp);
 void zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp);
+void zebra_ptm_bfd_client_deregister (struct zserv *client);
 #endif
index c31a0b6a9e1743da20bf02bd9aa174e7d5a136bf..d6de0792e184302ac9f2def978d54c85221f1472 100644 (file)
@@ -1751,6 +1751,9 @@ zebra_client_close_cleanup_rnh (struct zserv *client)
 static void
 zebra_client_close (struct zserv *client)
 {
+  /* Send client de-registration to BFD */
+  zebra_ptm_bfd_client_deregister(client);
+
   /* Cleanup any registered nexthops - across all VRFs. */
   zebra_client_close_cleanup_rnh (client);