From: Dinesh Dutt <[email protected]>

The display of zebra client info is rather paltry: just the name and the FD.
For troubleshooting and general helpfulness, its useful to gather more info
about each client and display that. This patch does just that.

Signed-off-by: Dinesh Dutt <[email protected]>
---
 zebra/redistribute.c |  50 +++++++++----
 zebra/zebra_rib.c    |   5 +-
 zebra/zebra_rnh.c    |   3 +
 zebra/zserv.c        | 200 ++++++++++++++++++++++++++++++++++++++++++++++++---
 zebra/zserv.h        |  28 ++++++++
 5 files changed, 264 insertions(+), 22 deletions(-)

diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 5ec8219..625bc30 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -154,7 +154,10 @@ zebra_redistribute (struct zserv *client, int type, 
vrf_id_t vrf_id)
            && newrib->type == type 
            && newrib->distance != DISTANCE_INFINITY
            && zebra_check_addr (&rn->p))
-         zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib);
+         {
+           client->redist_v4_add_cnt++;
+           zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, 
newrib);
+         }
   
 #ifdef HAVE_IPV6
   table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
@@ -165,7 +168,10 @@ zebra_redistribute (struct zserv *client, int type, 
vrf_id_t vrf_id)
            && newrib->type == type 
            && newrib->distance != DISTANCE_INFINITY
            && zebra_check_addr (&rn->p))
-         zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib);
+         {
+           client->redist_v6_add_cnt++;
+           zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, 
newrib);
+         }
 #endif /* HAVE_IPV6 */
 }
 
@@ -182,11 +188,15 @@ redistribute_add (struct prefix *p, struct rib *rib)
           || vrf_bitmap_check (client->redist[rib->type], rib->vrf_id))
         {
           if (p->family == AF_INET)
-            zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
-#ifdef HAVE_IPV6
+           {
+             client->redist_v4_add_cnt++;
+             zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
+           }
           if (p->family == AF_INET6)
-            zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
-#endif /* HAVE_IPV6 */   
+           {
+             client->redist_v6_add_cnt++;
+             zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
+           }
         }
     }
 }
@@ -275,7 +285,9 @@ zebra_interface_up_update (struct interface *ifp)
     zlog_debug ("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name);
 
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
-    zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp);
+    {
+      zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp);
+    }
 }
 
 /* Interface down information. */
@@ -289,7 +301,9 @@ zebra_interface_down_update (struct interface *ifp)
     zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name);
 
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
-    zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp);
+    {
+      zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp);
+    }
 }
 
 /* Interface information update. */
@@ -304,7 +318,10 @@ zebra_interface_add_update (struct interface *ifp)
     
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
     if (client->ifinfo)
-      zsend_interface_add (client, ifp);
+      {
+       client->ifadd_cnt++;
+       zsend_interface_add (client, ifp);
+      }
 }
 
 void
@@ -318,7 +335,10 @@ zebra_interface_delete_update (struct interface *ifp)
 
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
     if (client->ifinfo)
-      zsend_interface_delete (client, ifp);
+      {
+       client->ifdel_cnt++;
+       zsend_interface_delete (client, ifp);
+      }
 }
 
 /* Interface address addition. */
@@ -347,7 +367,10 @@ zebra_interface_address_add_update (struct interface *ifp,
 
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
     if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
-      zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, ifp, ifc);
+      {
+       client->connected_rt_add_cnt++;
+       zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, ifp, ifc);
+      }
 }
 
 /* Interface address deletion. */
@@ -373,5 +396,8 @@ zebra_interface_address_delete_update (struct interface 
*ifp,
 
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
     if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
-      zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, 
ifc);
+      {
+       client->connected_rt_del_cnt++;
+       zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, 
ifc);
+      }
 }
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 819b7bc..c3df67b 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -2164,6 +2164,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib 
*rib, safi_t safi)
   struct route_node *rn;
   struct rib *same;
   struct nexthop *nexthop;
+  int ret = 0;
   
   /* Lookup table.  */
   table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id);
@@ -2206,6 +2207,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib 
*rib, safi_t safi)
 
   /* Link new rib to node.*/
   rib_addnode (rn, rib);
+  ret = 1;
   if (IS_ZEBRA_DEBUG_RIB)
   {
     zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
@@ -2223,10 +2225,11 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct 
rib *rib, safi_t safi)
       rib_dump (p, same);
     }
     rib_delnode (rn, same);
+    ret = -1;
   }
   
   route_unlock_node (rn);
-  return 0;
+  return ret;
 }
 
 /* XXX factor with rib_delete_ipv6 */
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index d2061ca..db1552d 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -681,6 +681,9 @@ send_client (struct rnh *rnh, struct zserv *client, 
vrf_id_t vrf_id)
       stream_putc (s, 0);
     }
   stream_putw_at (s, 0, stream_get_endp (s));
+
+  client->nh_last_upd_time = quagga_time(NULL);
+  client->last_write_cmd = ZEBRA_NEXTHOP_UPDATE;
   return zebra_server_send_message(client);
 }
 
diff --git a/zebra/zserv.c b/zebra/zserv.c
index f887af9..f5cfd3f 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -101,6 +101,8 @@ zserv_flush_data(struct thread *thread)
     case BUFFER_EMPTY:
       break;
     }
+
+  client->last_write_time = quagga_time(NULL);
   return 0;
 }
 
@@ -109,6 +111,9 @@ zebra_server_send_message(struct zserv *client)
 {
   if (client->t_suicide)
     return -1;
+
+  stream_set_getp(client->obuf, 0);
+  client->last_write_cmd = stream_getw_from(client->obuf, 4);
   switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf),
                       stream_get_endp(client->obuf)))
     {
@@ -130,6 +135,8 @@ zebra_server_send_message(struct zserv *client)
                      zserv_flush_data, client, client->sock);
       break;
     }
+
+  client->last_write_time = quagga_time(NULL);
   return 0;
 }
 
@@ -194,6 +201,7 @@ zsend_interface_add (struct zserv *client, struct interface 
*ifp)
   zserv_create_header (s, ZEBRA_INTERFACE_ADD, ifp->vrf_id);
   zserv_encode_interface (s, ifp);
 
+  client->ifadd_cnt++;
   return zebra_server_send_message(client);
 }
 
@@ -213,6 +221,7 @@ zsend_interface_delete (struct zserv *client, struct 
interface *ifp)
   zserv_create_header (s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id);
   zserv_encode_interface (s, ifp);
 
+  client->ifdel_cnt++;
   return zebra_server_send_message (client);
 }
 
@@ -298,6 +307,7 @@ zsend_interface_address (int cmd, struct zserv *client,
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
+  client->connected_rt_add_cnt++;
   return zebra_server_send_message(client);
 }
 
@@ -463,6 +473,11 @@ zsend_interface_update (int cmd, struct zserv *client, 
struct interface *ifp)
   zserv_create_header (s, cmd, ifp->vrf_id);
   zserv_encode_interface (s, ifp);
 
+  if (cmd == ZEBRA_INTERFACE_UP)
+    client->ifup_cnt++;
+  else
+    client->ifdown_cnt++;
+
   return zebra_server_send_message(client);
 }
 
@@ -681,7 +696,7 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struct 
in6_addr *addr,
     }
 
   stream_putw_at (s, 0, stream_get_endp (s));
-  
+
   return zebra_server_send_message(client);
 }
 #endif /* HAVE_IPV6 */
@@ -854,6 +869,7 @@ zserv_nexthop_register (struct zserv *client, int sock, 
u_short length, vrf_id_t
       if (connected)
        SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
 
+      client->nh_reg_time = quagga_time(NULL);
       zebra_add_rnh_client(rnh, client, vrf_id);
     }
   zebra_evaluate_rnh_table(0, AF_INET, 0);
@@ -886,7 +902,10 @@ zserv_nexthop_unregister (struct zserv *client, int sock, 
u_short length)
       l += PSIZE(p.prefixlen);
       rnh = zebra_lookup_rnh(&p, 0);
       if (rnh)
-       zebra_remove_rnh_client(rnh, client);
+       {
+         client->nh_dereg_time = quagga_time(NULL);
+         zebra_remove_rnh_client(rnh, client);
+       }
     }
   return 0;
 }
@@ -951,7 +970,7 @@ zsend_ipv4_import_lookup (struct zserv *client, struct 
prefix_ipv4 *p,
     }
 
   stream_putw_at (s, 0, stream_get_endp (s));
-  
+
   return zebra_server_send_message(client);
 }
 
@@ -1053,7 +1072,7 @@ zread_ipv4_add (struct zserv *client, u_short length, 
vrf_id_t vrf_id)
   unsigned int ifindex;
   u_char ifname_len;
   safi_t safi; 
-
+  int ret;
 
   /* Get input stream.  */
   s = client->ibuf;
@@ -1131,7 +1150,13 @@ zread_ipv4_add (struct zserv *client, u_short length, 
vrf_id_t vrf_id)
 
   /* Table */
   rib->table=zebrad.rtm_table_default;
-  rib_add_ipv4_multipath (&p, rib, safi);
+  ret = rib_add_ipv4_multipath (&p, rib, safi);
+
+  /* Stats */
+  if (ret > 0)
+    client->v4_route_add_cnt++;
+  else if (ret < 0)
+    client->v4_route_upd8_cnt++;
   return 0;
 }
 
@@ -1220,6 +1245,7 @@ zread_ipv4_delete (struct zserv *client, u_short length, 
vrf_id_t vrf_id)
 
   rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex,
                    vrf_id, api.safi);
+  client->v4_route_del_cnt++;
   return 0;
 }
 
@@ -1281,6 +1307,7 @@ zread_ipv6_add (struct zserv *client, u_short length, 
vrf_id_t vrf_id)
   safi_t safi;
   static struct in6_addr nexthops[MULTIPATH_NUM];
   static unsigned int ifindices[MULTIPATH_NUM];
+  int ret;
 
   /* Get input stream.  */
   s = client->ibuf;
@@ -1371,7 +1398,13 @@ zread_ipv6_add (struct zserv *client, u_short length, 
vrf_id_t vrf_id)
 
   /* Table */
   rib->table=zebrad.rtm_table_default;
-  rib_add_ipv6_multipath (&p, rib, safi);
+  ret = rib_add_ipv6_multipath (&p, rib, safi);
+  /* Stats */
+  if (ret > 0)
+    client->v6_route_add_cnt++;
+  else if (ret < 0)
+    client->v6_route_upd8_cnt++;
+
   return 0;
 }
 
@@ -1448,6 +1481,8 @@ zread_ipv6_delete (struct zserv *client, u_short length, 
vrf_id_t vrf_id)
   else
     rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, vrf_id,
                      api.safi);
+
+  client->v6_route_del_cnt++;
   return 0;
 }
 
@@ -1608,6 +1643,7 @@ zebra_client_create (int sock)
   client->redist_default = vrf_bitmap_init ();
   client->ifinfo = vrf_bitmap_init ();
   client->ridinfo = vrf_bitmap_init ();
+  client->connect_time = quagga_time(NULL);
 
   /* Add this client to linked list. */
   listnode_add (zebrad.client_list, client);
@@ -1723,6 +1759,9 @@ zebra_client_read (struct thread *thread)
     zlog_debug ("zebra message received [%s] %d in VRF %u",
               zserv_command_string (command), length, vrf_id);
 
+  client->last_read_time = quagga_time(NULL);
+  client->last_read_cmd = command;
+
   switch (command) 
     {
     case ZEBRA_ROUTER_ID_ADD:
@@ -1985,6 +2024,127 @@ zebra_event (enum event event, int sock, struct zserv 
*client)
     }
 }
 
+#define ZEBRA_TIME_BUF 32
+static char *
+zserv_time_buf(time_t *time1, char *buf, int buflen)
+{
+  struct tm *tm;
+  time_t now;
+
+  assert (buf != NULL);
+  assert (buflen >= ZEBRA_TIME_BUF);
+  assert (time1 != NULL);
+
+  if (!*time1)
+    {
+      snprintf(buf, buflen, "never   ");
+      return (buf);
+    }
+
+  now = quagga_time(NULL);
+  now -= *time1;
+  tm = gmtime(&now);
+
+  /* Making formatted timer strings. */
+#define ONE_DAY_SECOND 60*60*24
+#define ONE_WEEK_SECOND 60*60*24*7
+
+  if (now < ONE_DAY_SECOND)
+    snprintf (buf, buflen, "%02d:%02d:%02d",
+             tm->tm_hour, tm->tm_min, tm->tm_sec);
+  else if (now < ONE_WEEK_SECOND)
+    snprintf (buf, buflen, "%dd%02dh%02dm",
+             tm->tm_yday, tm->tm_hour, tm->tm_min);
+  else
+    snprintf (buf, buflen, "%02dw%dd%02dh",
+             tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
+  return buf;
+}
+
+static void
+zebra_show_client_detail (struct vty *vty, struct zserv *client)
+{
+  char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF];
+  char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF];
+
+  vty_out (vty, "Client: %s %s",
+          zebra_route_string(client->proto), VTY_NEWLINE);
+  vty_out (vty, "------------------------ %s", VTY_NEWLINE);
+  vty_out (vty, "FD: %d %s", client->sock, VTY_NEWLINE);
+  vty_out (vty, "Route Table ID: %d %s", client->rtm_table, VTY_NEWLINE);
+
+  vty_out (vty, "Connect Time: %s %s",
+          zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF),
+          VTY_NEWLINE);
+  if (client->nh_reg_time)
+    {
+      vty_out (vty, "Nexthop Registry Time: %s %s",
+              zserv_time_buf(&client->nh_reg_time, nhbuf, ZEBRA_TIME_BUF),
+              VTY_NEWLINE);
+      if (client->nh_last_upd_time)
+       vty_out (vty, "Nexthop Last Update Time: %s %s",
+                zserv_time_buf(&client->nh_last_upd_time, mbuf, 
ZEBRA_TIME_BUF),
+                VTY_NEWLINE);
+      else
+       vty_out (vty, "No Nexthop Update sent%s", VTY_NEWLINE);
+    }
+  else
+    vty_out (vty, "Not registered for Nexthop Updates%s", VTY_NEWLINE);
+
+  vty_out (vty, "Last Msg Rx Time: %s %s",
+          zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF),
+          VTY_NEWLINE);
+  vty_out (vty, "Last Msg Tx Time: %s %s",
+          zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF),
+          VTY_NEWLINE);
+  if (client->last_read_time)
+    vty_out (vty, "Last Rcvd Cmd: %s %s",
+            zserv_command_string(client->last_read_cmd), VTY_NEWLINE);
+  if (client->last_write_time)
+    vty_out (vty, "Last Sent Cmd: %s %s",
+            zserv_command_string(client->last_write_cmd), VTY_NEWLINE);
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  vty_out (vty, "Type        Add        Update     Del %s", VTY_NEWLINE);
+  vty_out (vty, "================================================== %s", 
VTY_NEWLINE);
+  vty_out (vty, "IPv4        %-12d%-12d%-12d%s", client->v4_route_add_cnt,
+          client->v4_route_upd8_cnt, client->v4_route_del_cnt, VTY_NEWLINE);
+  vty_out (vty, "IPv6        %-12d%-12d%-12d%s", client->v6_route_add_cnt,
+          client->v6_route_upd8_cnt, client->v6_route_del_cnt, VTY_NEWLINE);
+  vty_out (vty, "Redist:v4   %-12d%-12d%-12d%s", client->redist_v4_add_cnt, 0,
+          client->redist_v4_del_cnt, VTY_NEWLINE);
+  vty_out (vty, "Redist:v6   %-12d%-12d%-12d%s", client->redist_v6_add_cnt, 0,
+          client->redist_v6_del_cnt, VTY_NEWLINE);
+  vty_out (vty, "Connected   %-12d%-12d%-12d%s", client->ifadd_cnt, 0,
+          client->ifdel_cnt, VTY_NEWLINE);
+  vty_out (vty, "Interface Up Notifications: %d%s", client->ifup_cnt,
+          VTY_NEWLINE);
+  vty_out (vty, "Interface Down Notifications: %d%s", client->ifdown_cnt,
+          VTY_NEWLINE);
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+  return;
+}
+
+static void
+zebra_show_client_brief (struct vty *vty, struct zserv *client)
+{
+  char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF];
+  char wbuf[ZEBRA_TIME_BUF];
+
+  vty_out (vty, "%-8s%12s %12s%12s%8d/%-8d%8d/%-8d%s",
+          zebra_route_string(client->proto),
+          zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF),
+          zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF),
+          zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF),
+          client->v4_route_add_cnt+client->v4_route_upd8_cnt,
+          client->v4_route_del_cnt,
+          client->v6_route_add_cnt+client->v6_route_upd8_cnt,
+          client->v6_route_del_cnt, VTY_NEWLINE);
+
+}
+
+
 /* Display default rtm_table for all clients. */
 DEFUN (show_table,
        show_table_cmd,
@@ -2062,10 +2222,31 @@ DEFUN (show_zebra_client,
   struct zserv *client;
 
   for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
-    vty_out (vty, "Client %s fd %d%s",
-            zebra_route_string(client->proto), client->sock,
-            VTY_NEWLINE);
+    zebra_show_client_detail(vty, client);
+
+  return CMD_SUCCESS;
+}
+
+/* This command is for debugging purpose. */
+DEFUN (show_zebra_client_summary,
+       show_zebra_client_summary_cmd,
+       "show zebra client summary",
+       SHOW_STR
+       "Zebra information brief"
+       "Client information brief")
+{
+  struct listnode *node;
+  struct zserv *client;
+
+  vty_out (vty, "Name    Connect Time    Last Read  Last Write  IPv4 Routes    
   IPv6 Routes    %s",
+          VTY_NEWLINE);
+  vty_out 
(vty,"--------------------------------------------------------------------------------%s",
+          VTY_NEWLINE);
+
+  for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
+    zebra_show_client_brief(vty, client);
 
+  vty_out (vty, "Routes column shows (added+updated)/deleted%s", VTY_NEWLINE);
   return CMD_SUCCESS;
 }
 
@@ -2224,6 +2405,7 @@ zebra_init (void)
   install_element (CONFIG_NODE, &ip_forwarding_cmd);
   install_element (CONFIG_NODE, &no_ip_forwarding_cmd);
   install_element (ENABLE_NODE, &show_zebra_client_cmd);
+  install_element (ENABLE_NODE, &show_zebra_client_summary_cmd);
 
 #ifdef HAVE_NETLINK
   install_element (VIEW_NODE, &show_table_cmd);
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 3aee505..3f8af08 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -73,6 +73,34 @@ struct zserv
 
   /* client's protocol */
   u_char proto;
+
+  /* Statistics */
+  u_int32_t redist_v4_add_cnt;
+  u_int32_t redist_v4_del_cnt;
+  u_int32_t redist_v6_add_cnt;
+  u_int32_t redist_v6_del_cnt;
+  u_int32_t v4_route_add_cnt;
+  u_int32_t v4_route_upd8_cnt;
+  u_int32_t v4_route_del_cnt;
+  u_int32_t v6_route_add_cnt;
+  u_int32_t v6_route_del_cnt;
+  u_int32_t v6_route_upd8_cnt;
+  u_int32_t connected_rt_add_cnt;
+  u_int32_t connected_rt_del_cnt;
+  u_int32_t ifup_cnt;
+  u_int32_t ifdown_cnt;
+  u_int32_t ifadd_cnt;
+  u_int32_t ifdel_cnt;
+
+  time_t connect_time;
+  time_t last_read_time;
+  time_t last_write_time;
+  time_t nh_reg_time;
+  time_t nh_dereg_time;
+  time_t nh_last_upd_time;
+
+  int last_read_cmd;
+  int last_write_cmd;
 };
 
 /* Zebra instance */
-- 
1.9.1


_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to