[bgpd] Implement 'debug bgp zebra' to log all messages to and from zebra.

2006-11-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>

	* bgp_debug.h: Declare new bgp_debug_zebra conf and term flags,
	  and define BGP_DEBUG_ZEBRA.
	* bgp_debug.c: Declare conf_bgp_debug_zebra and term_bgp_debug_zebra.
	  (debug_bgp_zebra, no_debug_bgp_zebra, undebug_bgp_zebra) New
	  functions to enable/disable bgp zebra debugging.
	  (no_debug_bgp_all) Turn off zebra debugging.
	  (show_debugging_bgp) Show whether zebra debugging is on.
	  (bgp_config_write_debug) Add 'debug bgp zebra' if configured.
	  (bgp_debug_init) Add new zebra debugging commands.
	* bgp_zebra.c: (bgp_router_id_update, bgp_interface_add,
	  bgp_interface_delete, bgp_interface_up, bgp_interface_down,
	  bgp_interface_address_add, bgp_interface_address_delete,
	  zebra_read_ipv4, zebra_read_ipv6, bgp_zebra_announce,
	  bgp_zebra_withdraw, bgp_redistribute_set, bgp_redistribute_unset)
	  If zebra debugging is enabled, log an appropriate debug message.
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index c862949..7ad200a 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,21 @@
+2006-11-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+	* bgp_debug.h: Declare new bgp_debug_zebra conf and term flags,
+	  and define BGP_DEBUG_ZEBRA.
+	* bgp_debug.c: Declare conf_bgp_debug_zebra and term_bgp_debug_zebra.
+	  (debug_bgp_zebra, no_debug_bgp_zebra, undebug_bgp_zebra) New
+	  functions to enable/disable bgp zebra debugging.
+	  (no_debug_bgp_all) Turn off zebra debugging.
+	  (show_debugging_bgp) Show whether zebra debugging is on.
+	  (bgp_config_write_debug) Add 'debug bgp zebra' if configured.
+	  (bgp_debug_init) Add new zebra debugging commands.
+	* bgp_zebra.c: (bgp_router_id_update, bgp_interface_add,
+	  bgp_interface_delete, bgp_interface_up, bgp_interface_down,
+	  bgp_interface_address_add, bgp_interface_address_delete,
+	  zebra_read_ipv4, zebra_read_ipv6, bgp_zebra_announce,
+	  bgp_zebra_withdraw, bgp_redistribute_set, bgp_redistribute_unset)
+	  If zebra debugging is enabled, log an appropriate debug message.
+
 2006-11-28 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
 
 	* bgp_route.c: (bgp_info_restore) New function that undoes
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 1e0fcd1..1986b35 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -43,6 +43,7 @@
 unsigned long conf_bgp_debug_keepalive;
 unsigned long conf_bgp_debug_update;
 unsigned long conf_bgp_debug_normal;
+unsigned long conf_bgp_debug_zebra;
 
 unsigned long term_bgp_debug_fsm;
 unsigned long term_bgp_debug_events;
@@ -51,6 +52,7 @@
 unsigned long term_bgp_debug_keepalive;
 unsigned long term_bgp_debug_update;
 unsigned long term_bgp_debug_normal;
+unsigned long term_bgp_debug_zebra;
 
 /* messages for BGP-4 status */
 struct message bgp_status_msg[] = 
@@ -590,6 +592,49 @@
        UNDEBUG_STR
        BGP_STR)
 
+DEFUN (debug_bgp_zebra,
+       debug_bgp_zebra_cmd,
+       "debug bgp zebra",
+       DEBUG_STR
+       BGP_STR
+       "BGP Zebra messages\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_ON (zebra, ZEBRA);
+  else
+    {
+      TERM_DEBUG_ON (zebra, ZEBRA);
+      vty_out (vty, "BGP zebra debugging is on%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_zebra,
+       no_debug_bgp_zebra_cmd,
+       "no debug bgp zebra",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP Zebra messages\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_OFF (zebra, ZEBRA);
+  else
+    {
+      TERM_DEBUG_OFF (zebra, ZEBRA);
+      vty_out (vty, "BGP zebra debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_zebra,
+       undebug_bgp_zebra_cmd,
+       "undebug bgp zebra",
+       UNDEBUG_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP Zebra messages\n")
+
 DEFUN (no_debug_bgp_all,
        no_debug_bgp_all_cmd,
        "no debug all bgp",
@@ -605,6 +650,7 @@
   TERM_DEBUG_OFF (update, UPDATE_OUT);
   TERM_DEBUG_OFF (fsm, FSM);
   TERM_DEBUG_OFF (filter, FILTER);
+  TERM_DEBUG_OFF (zebra, ZEBRA);
   vty_out (vty, "All possible debugging has been turned off%s", VTY_NEWLINE);
       
   return CMD_SUCCESS;
@@ -642,6 +688,8 @@
     vty_out (vty, "  BGP fsm debugging is on%s", VTY_NEWLINE);
   if (BGP_DEBUG (filter, FILTER))
     vty_out (vty, "  BGP filter debugging is on%s", VTY_NEWLINE);
+  if (BGP_DEBUG (zebra, ZEBRA))
+    vty_out (vty, "  BGP zebra debugging is on%s", VTY_NEWLINE);
   vty_out (vty, "%s", VTY_NEWLINE);
   return CMD_SUCCESS;
 }
@@ -697,6 +745,12 @@
       write++;
     }
 
+  if (CONF_BGP_DEBUG (zebra, ZEBRA))
+    {
+      vty_out (vty, "debug bgp zebra%s", VTY_NEWLINE);
+      write++;
+    }
+
   return write;
 }
 
@@ -728,6 +782,8 @@
   install_element (CONFIG_NODE, &debug_bgp_update_direct_cmd);
   install_element (ENABLE_NODE, &debug_bgp_normal_cmd);
   install_element (CONFIG_NODE, &debug_bgp_normal_cmd);
+  install_element (ENABLE_NODE, &debug_bgp_zebra_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_zebra_cmd);
 
   install_element (ENABLE_NODE, &no_debug_bgp_fsm_cmd);
   install_element (ENABLE_NODE, &undebug_bgp_fsm_cmd);
@@ -747,6 +803,9 @@
   install_element (ENABLE_NODE, &no_debug_bgp_normal_cmd);
   install_element (ENABLE_NODE, &undebug_bgp_normal_cmd);
   install_element (CONFIG_NODE, &no_debug_bgp_normal_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_zebra_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_zebra_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_zebra_cmd);
   install_element (ENABLE_NODE, &no_debug_bgp_all_cmd);
   install_element (ENABLE_NODE, &undebug_bgp_all_cmd);
 }
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
index bc8acf9..eab95d0 100644
--- a/bgpd/bgp_debug.h
+++ b/bgpd/bgp_debug.h
@@ -63,6 +63,7 @@
 extern unsigned long conf_bgp_debug_keepalive;
 extern unsigned long conf_bgp_debug_update;
 extern unsigned long conf_bgp_debug_normal;
+extern unsigned long conf_bgp_debug_zebra;
 
 extern unsigned long term_bgp_debug_fsm;
 extern unsigned long term_bgp_debug_events;
@@ -71,6 +72,7 @@
 extern unsigned long term_bgp_debug_keepalive;
 extern unsigned long term_bgp_debug_update;
 extern unsigned long term_bgp_debug_normal;
+extern unsigned long term_bgp_debug_zebra;
 
 #define BGP_DEBUG_FSM                 0x01
 #define BGP_DEBUG_EVENTS              0x01
@@ -80,6 +82,7 @@
 #define BGP_DEBUG_UPDATE_IN           0x01
 #define BGP_DEBUG_UPDATE_OUT          0x02
 #define BGP_DEBUG_NORMAL              0x01
+#define BGP_DEBUG_ZEBRA               0x01
 
 #define BGP_DEBUG_PACKET_SEND         0x01
 #define BGP_DEBUG_PACKET_SEND_DETAIL  0x02
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 0cb9e0e..301c15b 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -36,6 +36,7 @@
 #include "bgpd/bgp_nexthop.h"
 #include "bgpd/bgp_zebra.h"
 #include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_debug.h"
 
 /* All information about zebra. */
 static struct zclient *zclient = NULL;
@@ -50,6 +51,14 @@
   struct bgp *bgp;
 
   zebra_router_id_update_read(zclient->ibuf,&router_id);
+
+  if (BGP_DEBUG(zebra, ZEBRA))
+    {
+      char buf[128];
+      prefix2str(&router_id, buf, sizeof(buf));
+      zlog_debug("Zebra rcvd: router id update %s", buf);
+    }
+
   router_id_zebra = router_id.u.prefix4;
 
   for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
@@ -69,6 +78,9 @@
 
   ifp = zebra_interface_add_read (zclient->ibuf);
 
+  if (BGP_DEBUG(zebra, ZEBRA) && ifp)
+    zlog_debug("Zebra rcvd: interface add %s", ifp->name);
+
   return 0;
 }
 
@@ -83,6 +95,9 @@
   ifp = zebra_interface_state_read (s);
   ifp->ifindex = IFINDEX_INTERNAL;
 
+  if (BGP_DEBUG(zebra, ZEBRA))
+    zlog_debug("Zebra rcvd: interface delete %s", ifp->name);
+
   return 0;
 }
 
@@ -100,6 +115,9 @@
   if (! ifp)
     return 0;
 
+  if (BGP_DEBUG(zebra, ZEBRA))
+    zlog_debug("Zebra rcvd: interface %s up", ifp->name);
+
   for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
     bgp_connected_add (c);
 
@@ -119,6 +137,9 @@
   if (! ifp)
     return 0;
 
+  if (BGP_DEBUG(zebra, ZEBRA))
+    zlog_debug("Zebra rcvd: interface %s down", ifp->name);
+
   for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
     bgp_connected_delete (c);
 
@@ -164,6 +185,14 @@
   if (ifc == NULL)
     return 0;
 
+  if (BGP_DEBUG(zebra, ZEBRA))
+    {
+      char buf[128];
+      prefix2str(ifc->address, buf, sizeof(buf));
+      zlog_debug("Zebra rcvd: interface %s address add %s",
+		 ifc->ifp->name, buf);
+    }
+
   if (if_is_operative (ifc->ifp))
     bgp_connected_add (ifc);
 
@@ -181,6 +210,14 @@
   if (ifc == NULL)
     return 0;
 
+  if (BGP_DEBUG(zebra, ZEBRA))
+    {
+      char buf[128];
+      prefix2str(ifc->address, buf, sizeof(buf));
+      zlog_debug("Zebra rcvd: interface %s address delete %s",
+		 ifc->ifp->name, buf);
+    }
+
   if (if_is_operative (ifc->ifp))
     bgp_connected_delete (ifc);
 
@@ -233,9 +270,34 @@
     api.metric = 0;
 
   if (command == ZEBRA_IPV4_ROUTE_ADD)
-    bgp_redistribute_add ((struct prefix *)&p, &nexthop, api.metric, api.type);
+    {
+      if (BGP_DEBUG(zebra, ZEBRA))
+	{
+	  char buf[2][INET_ADDRSTRLEN];
+	  zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
+		     zebra_route_string(api.type),
+		     inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
+		     p.prefixlen,
+		     inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
+		     api.metric);
+	}
+      bgp_redistribute_add((struct prefix *)&p, &nexthop, api.metric, api.type);
+    }
   else
-    bgp_redistribute_delete ((struct prefix *)&p, api.type);
+    {
+      if (BGP_DEBUG(zebra, ZEBRA))
+	{
+	  char buf[2][INET_ADDRSTRLEN];
+	  zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d "
+		     "nexthop %s metric %u",
+		     zebra_route_string(api.type),
+		     inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
+		     p.prefixlen,
+		     inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
+		     api.metric);
+	}
+      bgp_redistribute_delete((struct prefix *)&p, api.type);
+    }
 
   return 0;
 }
@@ -291,9 +353,29 @@
     return 0;
 
   if (command == ZEBRA_IPV6_ROUTE_ADD)
-    bgp_redistribute_add ((struct prefix *)&p, NULL, api.metric, api.type);
+    {
+      if (BGP_DEBUG(zebra, ZEBRA))
+	{
+	  char buf[INET6_ADDRSTRLEN];
+	  zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d metric %u",
+		     zebra_route_string(api.type),
+		     inet_ntop(AF_INET6, &p.prefix, buf, sizeof(buf)),
+		     p.prefixlen, api.metric);
+	}
+      bgp_redistribute_add ((struct prefix *)&p, NULL, api.metric, api.type);
+    }
   else
-    bgp_redistribute_delete ((struct prefix *) &p, api.type);
+    {
+      if (BGP_DEBUG(zebra, ZEBRA))
+	{
+	  char buf[INET6_ADDRSTRLEN];
+	  zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d metric %u",
+		     zebra_route_string(api.type),
+		     inet_ntop(AF_INET6, &p.prefix, buf, sizeof(buf)),
+		     p.prefixlen, api.metric);
+	}
+      bgp_redistribute_delete ((struct prefix *) &p, api.type);
+    }
   
   return 0;
 }
@@ -640,6 +722,17 @@
 	  SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
 	  api.distance = distance;
 	}
+
+      if (BGP_DEBUG(zebra, ZEBRA))
+	{
+	  char buf[2][INET_ADDRSTRLEN];
+	  zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u",
+		     inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
+		     p->prefixlen,
+		     inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])),
+		     api.metric);
+	}
+
       zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, 
                        (struct prefix_ipv4 *) p, &api);
     }
@@ -696,6 +789,16 @@
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = info->attr->med;
 
+      if (BGP_DEBUG(zebra, ZEBRA))
+	{
+	  char buf[2][INET6_ADDRSTRLEN];
+	  zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u",
+		     inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
+		     p->prefixlen,
+		     inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
+		     api.metric);
+	}
+
       zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, 
                        (struct prefix_ipv6 *) p, &api);
     }
@@ -744,6 +847,16 @@
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = info->attr->med;
 
+      if (BGP_DEBUG(zebra, ZEBRA))
+	{
+	  char buf[2][INET_ADDRSTRLEN];
+	  zlog_debug("Zebra send: IPv4 route delete %s/%d nexthop %s metric %u",
+		     inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
+		     p->prefixlen,
+		     inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])),
+		     api.metric);
+	}
+
       zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, 
                        (struct prefix_ipv4 *) p, &api);
     }
@@ -789,6 +902,16 @@
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = info->attr->med;
 
+      if (BGP_DEBUG(zebra, ZEBRA))
+	{
+	  char buf[2][INET6_ADDRSTRLEN];
+	  zlog_debug("Zebra send: IPv6 route delete %s/%d nexthop %s metric %u",
+		     inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
+		     p->prefixlen,
+		     inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
+		     api.metric);
+	}
+
       zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, 
                        (struct prefix_ipv6 *) p, &api);
     }
@@ -811,6 +934,9 @@
   /* Return if zebra connection is not established. */
   if (zclient->sock < 0)
     return CMD_WARNING;
+
+  if (BGP_DEBUG(zebra, ZEBRA))
+    zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type));
     
   /* Send distribute add message to zebra. */
   zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
@@ -875,8 +1001,13 @@
   if (bgp->redist[AFI_IP][type] == 0 
       && bgp->redist[AFI_IP6][type] == 0 
       && zclient->sock >= 0)
-    /* Send distribute delete message to zebra. */
-    zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
+    {
+      /* Send distribute delete message to zebra. */
+      if (BGP_DEBUG(zebra, ZEBRA))
+	zlog_debug("Zebra send: redistribute delete %s",
+		   zebra_route_string(type));
+      zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
+    }
   
   /* Withdraw redistributed routes from current BGP's routing table. */
   bgp_redistribute_withdraw (bgp, afi, type);