]> git.puffer.fish Git - mirror/frr.git/commitdiff
Support for multi-client and client reg msg
authorradhika <radhika@cumulusnetworks.com>
Wed, 9 Mar 2016 07:31:32 +0000 (23:31 -0800)
committerradhika <radhika@cumulusnetworks.com>
Wed, 9 Mar 2016 07:31:32 +0000 (23:31 -0800)
Ticket: CM-7615, CM-7773
Reviewed By: CCR-3610, CCR-3708
Testing Done: Unit, BGP Smoke and OSPF Smoke

Changes (70790261926b17200c8c9377c4576cd3b486fcef) ported from 2.5

Issue (related to CM-7615): 1. CM-7615: There is mismatch in the client name between ptm display of client BFD sessions and the zebra logs. For example, if bgpd added BFD session, zebra logs will show the client as “bgp” but the ptm display will show it as “quagga”
2. Bigger problem is when 2 clients (for example OSPF and BGP) from Quagga register for same BFD session and only one client de-registers the BFD session. This results in BFD session deletion from PTM even though other client still has the BFD registration.

Root Cause: Even though BGP, OSPF and OSPF6 are 3 different clients from Quagga that are trying to register/deregister BFD sessions with PTM, all 3 are represented as one client “quagga” from zebra. This makes it hard for PTM/BFD to distinguish between all three when BFD peer registration/deregistration happens from the clients.

Fix: Send the actual client name bgp, ospf or ospf6 from zebra with BFD reg/dereg messages instead of one unified client name “quagga”

CM-7773: BFD sessions are not getting cleaned from PTM even though no BGP peering exists in Quagga.

Root Cause: PTM cleans up stale BFD sessions from a client when it finds a change in seq id advertised by the client. But, if PTM never detects a change in the seq id then the stale BFD sessions never get cleaned up. The test restarts the quagga without saving the configuration, which results in no BGP peering. No BGP peers are registered with PTM after restart and PTM does not detect a client seq id change resulting in stale BFD sessions.

Fix: New client registration message was added in PTM. Every client that is interested in BFD monitoring will register with PTM with the client seq id. Client will register with a different seq id (typically pid) every time it restarts. This will help in detecting the change in seq id and cleanup of stale BFD sessions for a client.

Code Changes: To support the new client registration message following changes have been made
  - Added support for client registration messaging in zebra for sending messages to PTM.
  - Added support for client registration messaging between zebra and clients (BGP, OSPF and OSPF6) in BFD library.
  - Expanded the reg/de reg peer messaging between zebra and clients to support client specific seq id to distinguish between multiple clients registering for BFD peer rather than one “quagga” client.
  - Changes in bgpd, ospfd and ospf6d to send client registrations at the time of daemon initialization and on receiving BFD peer replay message.

bgpd/bgp_bfd.c
lib/bfd.c
lib/bfd.h
lib/log.c
lib/zebra.h
ospf6d/ospf6_bfd.c
ospfd/ospf_bfd.c
zebra/zebra_ptm.c
zebra/zebra_ptm.h
zebra/zserv.c
zebra/zserv.h

index 6679206de96c827b64024690d18a57b26e4d20db..3f5c4d025782f344524b789ef38d372fec012c32 100644 (file)
@@ -185,6 +185,9 @@ bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length,
   if (BGP_DEBUG (zebra, ZEBRA))
     zlog_debug("Zebra: BFD Dest replay request");
 
+  /* Send the client registration */
+  bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+
   /* Replay the peer, if BFD is enabled in BGP */
 
   for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
@@ -524,4 +527,7 @@ bgp_bfd_init(void)
   install_element (BGP_NODE, &neighbor_bfd_param_cmd);
   install_element (BGP_NODE, &no_neighbor_bfd_cmd);
   install_element (BGP_NODE, &no_neighbor_bfd_val_cmd);
+
+  /* Send the client registration */
+  bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
 }
index 530086b1bd8e51962a16e6e36d679c7b3fc1d5af..e057bb05bf4d4a50dd84d5ecc2fef491cd23a613 100644 (file)
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -138,6 +138,8 @@ bfd_peer_sendmsg (struct zclient *zclient, struct bfd_info *bfd_info,
   stream_reset (s);
   zclient_create_header (s, command, vrf_id);
 
+  stream_putl(s, getpid());
+
   stream_putw(s, family);
   switch (family)
     {
@@ -436,3 +438,41 @@ bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop,
   else
     vty_out (vty, "%s", VTY_NEWLINE);
 }
+
+/*
+ * bfd_client_sendmsg - Format and send a client register
+ *                    command to Zebra to be forwarded to BFD
+ */
+void
+bfd_client_sendmsg (struct zclient *zclient, int command)
+{
+  struct stream *s;
+  int ret;
+
+  /* Check socket. */
+  if (!zclient || zclient->sock < 0)
+    {
+      zlog_debug("%s: Can't send BFD client register, Zebra client not "
+                  "established", __FUNCTION__);
+      return;
+    }
+
+  s = zclient->obuf;
+  stream_reset (s);
+  zclient_create_header (s, command, VRF_DEFAULT);
+
+  stream_putl(s, getpid());
+
+  stream_putw_at (s, 0, stream_get_endp (s));
+
+  ret = zclient_send_message(zclient);
+
+  if (ret < 0)
+    {
+      zlog_warn("bfd_client_sendmsg %d: zclient_send_message() failed",
+                  getpid());
+      return;
+    }
+
+  return;
+}
index 3cae1a521925672e05e82c41c09afafc0874f7af..31eb4ad9a3529855479ca9f4d541ef48afe55412 100644 (file)
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -95,4 +95,7 @@ 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);
 
+extern void
+bfd_client_sendmsg (struct zclient *zclient, int command);
+
 #endif /* _ZEBRA_BFD_H */
index fefc0db5260f33872b7675537f2a6b65b7b204c5..b031206a21a669539201dd246078851c46c07d3d 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -875,7 +875,8 @@ static const struct zebra_desc_table command_types[] = {
   DESC_ENTRY    (ZEBRA_REDISTRIBUTE_IPV4_DEL),
   DESC_ENTRY    (ZEBRA_REDISTRIBUTE_IPV6_ADD),
   DESC_ENTRY    (ZEBRA_REDISTRIBUTE_IPV6_DEL),
-  DESC_ENTRY    (ZEBRA_INTERFACE_VRF_UPDATE)
+  DESC_ENTRY    (ZEBRA_INTERFACE_VRF_UPDATE),
+  DESC_ENTRY    (ZEBRA_BFD_CLIENT_REGISTER)
 };
 #undef DESC_ENTRY
 
index 2945f15194853bfd6974c621f45ec9b4f7f8e6a8..f49db41d267cdf1480b2b54b87ca02e458ce5902 100644 (file)
@@ -446,7 +446,8 @@ struct in_pktinfo
 #define ZEBRA_VRF_ADD                     43
 #define ZEBRA_VRF_DELETE                  44
 #define ZEBRA_INTERFACE_VRF_UPDATE        45
-#define ZEBRA_MESSAGE_MAX                 46
+#define ZEBRA_BFD_CLIENT_REGISTER         46
+#define ZEBRA_MESSAGE_MAX                 47
 
 /* Marker value used in new Zserv, in the byte location corresponding
  * the command value in the old zserv header. To allow old and new
index 25bacd0d22384366f8d147e9c798298b1c46616c..f44dd5c0e6468dbbeea0c7916bf894a3ab4a6589 100644 (file)
@@ -145,7 +145,7 @@ ospf6_bfd_reg_dereg_all_nbr (struct ospf6_interface *oi, int command)
  *                        to zebra
  */
 static int
-ospf6_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length,
+ospf6_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length,
                       vrf_id_t vrf_id)
 {
   struct listnode *inode, *nnode;
@@ -157,6 +157,9 @@ ospf6_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length,
   if (IS_OSPF6_DEBUG_ZEBRA(RECV))
     zlog_debug("Zebra: BFD Dest replay request");
 
+  /* Send the client registration */
+  bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+
   /* Replay the neighbor, if BFD is enabled on the interface*/
   for (ALL_LIST_ELEMENTS_RO (iflist, inode, ifp))
     {
@@ -415,4 +418,7 @@ ospf6_bfd_init(void)
   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);
+
+  /* Send the client registration */
+  bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
 }
index 8e70b2479c4eb395629f86200d31604868637ed7..1a461e48b601436e83fea5aa5adf62856591ebc6 100644 (file)
@@ -147,7 +147,7 @@ ospf_bfd_reg_dereg_all_nbr (struct interface *ifp, int command)
  *                       to zebra
  */
 static int
-ospf_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length,
+ospf_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length,
                      vrf_id_t vrf_id)
 {
   struct listnode *inode, *node, *onode;
@@ -163,6 +163,9 @@ ospf_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length,
       zlog_debug("Zebra: BFD Dest replay request");
     }
 
+  /* Send the client registration */
+  bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+
   /* Replay the neighbor, if BFD is enabled in BGP */
   for (ALL_LIST_ELEMENTS (om->ospf, node, onode, ospf))
     {
@@ -447,4 +450,7 @@ ospf_bfd_init(void)
   install_element (INTERFACE_NODE, &ip_ospf_bfd_param_cmd);
   install_element (INTERFACE_NODE, &no_ip_ospf_bfd_cmd);
   install_element (INTERFACE_NODE, &no_ip_ospf_bfd_param_cmd);
+
+  /* Send the client registration */
+  bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
 }
index 8e20226cb0485699b119e939ea61b0cfe3f2b79c..f32fedd9f602e680ff6d92271a852168b2ee37cd 100644 (file)
@@ -45,6 +45,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_CMD_STR[] = "cmd";
 const char ZEBRA_PTM_CMD_STATUS_STR[] = "cmd_status";
@@ -572,6 +573,7 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
   char tmp_buf[64];
   int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
   struct zebra_vrf *zvrf;
+  unsigned int pid;
 
   if (command == ZEBRA_BFD_DEST_UPDATE)
     client->bfd_peer_upd8_cnt++;
@@ -592,15 +594,16 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
   ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
   sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_START_CMD);
   ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf);
-  sprintf(tmp_buf, "quagga");
+  sprintf(tmp_buf, "%s", zebra_route_string(client->proto));
   ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
                       tmp_buf);
-  sprintf(tmp_buf, "%d", ptm_cb.pid);
-  ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD,
-                      tmp_buf);
 
   s = client->ibuf;
 
+  pid = stream_getl(s);
+  sprintf(tmp_buf, "%d", pid);
+  ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf);
+
   dst_p.family = stream_getw(s);
 
   if (dst_p.family == AF_INET)
@@ -741,6 +744,7 @@ zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length,
   int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
   void *out_ctxt;
   struct zebra_vrf *zvrf;
+  unsigned int pid;
 
   client->bfd_peer_del_cnt++;
 
@@ -760,16 +764,16 @@ zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length,
   sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_STOP_CMD);
   ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf);
 
-  sprintf(tmp_buf, "%s", "quagga");
+  sprintf(tmp_buf, "%s", zebra_route_string(client->proto));
   ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
                       tmp_buf);
 
-  sprintf(tmp_buf, "%d", ptm_cb.pid);
-  ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD,
-                      tmp_buf);
-
   s = client->ibuf;
 
+  pid = stream_getl(s);
+  sprintf(tmp_buf, "%d", pid);
+  ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf);
+
   dst_p.family = stream_getw(s);
 
   if (dst_p.family == AF_INET)
@@ -873,6 +877,54 @@ zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length,
   return 0;
 }
 
+/* BFD client register */
+int
+zebra_ptm_bfd_client_register (struct zserv *client, int sock, u_short length)
+{
+  struct stream *s;
+  unsigned int pid;
+  void *out_ctxt;
+  char tmp_buf[64];
+  int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
+
+  client->bfd_client_reg_cnt++;
+
+  if (IS_ZEBRA_DEBUG_EVENT)
+    zlog_debug("bfd_client_register msg from client %s: length=%d",
+                zebra_route_string(client->proto), length);
+
+  if (ptm_cb.ptm_sock == -1)
+    {
+      ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect,
+                                             NULL, ptm_cb.reconnect_time);
+      return -1;
+    }
+
+  ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
+
+  sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_REG_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);
+
+  s = client->ibuf;
+
+  pid = stream_getl(s);
+  sprintf(tmp_buf, "%d", pid);
+  ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_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);
+  return 0;
+}
+
 int
 zebra_ptm_get_enable_state(void)
 {
index 15a4228298c94e7510d4ac3a9cba73cc32a49ed1..4914fc03514fb231d1c1e9f345376cffb2ad9700 100644 (file)
@@ -62,4 +62,6 @@ int zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock,
                                   u_short length, vrf_id_t vrf_id);
 void
 zebra_ptm_show_status(struct vty *vty, struct interface *ifp);
+int zebra_ptm_bfd_client_register (struct zserv *client, int sock,
+                                    u_short length);
 #endif
index 3d5cbec03cc3ac55a3e5e312a49ac70344092677..863622d4b1cefac88d42001946825f52da1e3447 100644 (file)
@@ -2076,6 +2076,9 @@ zebra_client_read (struct thread *thread)
     case ZEBRA_VRF_UNREGISTER:
       zread_vrf_unregister (client, length, vrf_id);
       break;
+    case ZEBRA_BFD_CLIENT_REGISTER:
+      zebra_ptm_bfd_client_register(client, sock, length);
+      break;
     default:
       zlog_info ("Zebra received unknown command %d", command);
       break;
index f3e7a3b88389d15f69d3aacc97e4712d83d5bc35..0a9b2cbbd4d1aa26cc0098fd5c9714d4f3e3cd04 100644 (file)
@@ -103,6 +103,7 @@ struct zserv
   u_int32_t vrfadd_cnt;
   u_int32_t vrfdel_cnt;
   u_int32_t if_vrfchg_cnt;
+  u_int32_t bfd_client_reg_cnt;
 
   time_t connect_time;
   time_t last_read_time;