summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2015-05-20 02:47:22 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2015-05-20 02:47:22 +0200
commit04b02fda9ff706fd53fbd17fe1700f567b1575b0 (patch)
tree75206948c794b94f9591fd5598abaa48a20d78cb /zebra
parentzebra: zebra-static-route-nht.patch (diff)
downloadfrr-04b02fda9ff706fd53fbd17fe1700f567b1575b0.tar.xz
frr-04b02fda9ff706fd53fbd17fe1700f567b1575b0.zip
zebra: zebra-client-info-detail.patch
Zebra: Gather and display detailed info about clients of Zebra 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.
Diffstat (limited to 'zebra')
-rw-r--r--zebra/redistribute.c58
-rw-r--r--zebra/zebra_rib.c5
-rw-r--r--zebra/zebra_rnh.c3
-rw-r--r--zebra/zserv.c201
-rw-r--r--zebra/zserv.h28
5 files changed, 273 insertions, 22 deletions
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 4767d9dbf..19176db7f 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -156,7 +156,10 @@ zebra_redistribute (struct zserv *client, int type)
&& 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 = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
@@ -167,7 +170,10 @@ zebra_redistribute (struct zserv *client, int type)
&& 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 */
}
@@ -184,20 +190,32 @@ redistribute_add (struct prefix *p, struct rib *rib)
if (client->redist_default || client->redist[rib->type])
{
if (p->family == AF_INET)
- zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
+ {
+ client->redist_v4_add_cnt++;
+ zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
+ }
#ifdef HAVE_IPV6
if (p->family == AF_INET6)
- zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
+ {
+ client->redist_v6_add_cnt++;
+ zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
+ }
#endif /* HAVE_IPV6 */
}
}
else if (client->redist[rib->type])
{
if (p->family == AF_INET)
- zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
+ {
+ client->redist_v4_add_cnt++;
+ zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib);
+ }
#ifdef HAVE_IPV6
if (p->family == AF_INET6)
- zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
+ {
+ client->redist_v6_add_cnt++;
+ zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
+ }
#endif /* HAVE_IPV6 */
}
}
@@ -297,7 +315,9 @@ zebra_interface_up_update (struct interface *ifp)
if (ifp->ptm_status || !ifp->ptm_enable) {
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);
+ }
}
}
@@ -312,7 +332,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. */
@@ -327,7 +349,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
@@ -341,7 +366,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. */
@@ -370,7 +398,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. */
@@ -396,5 +427,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 9499e8042..a9f31b1a0 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -2258,6 +2258,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 = vrf_table (AFI_IP, safi, 0);
@@ -2300,6 +2301,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",
@@ -2317,10 +2319,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 67d27c882..ed661d1d9 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -657,6 +657,9 @@ send_client (struct rnh *rnh, struct zserv *client)
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 4fc9a80d9..059fede6e 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -100,6 +100,8 @@ zserv_flush_data(struct thread *thread)
case BUFFER_EMPTY:
break;
}
+
+ client->last_write_time = quagga_time(NULL);
return 0;
}
@@ -108,6 +110,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)))
{
@@ -129,6 +134,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);
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);
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);
zserv_encode_interface (s, ifp);
+ if (cmd == ZEBRA_INTERFACE_UP)
+ client->ifup_cnt++;
+ else
+ client->ifdown_cnt++;
+
return zebra_server_send_message(client);
}
@@ -673,7 +688,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 */
@@ -775,6 +790,7 @@ zserv_nexthop_register (struct zserv *client, int sock, u_short length)
if (connected)
SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
+ client->nh_reg_time = quagga_time(NULL);
zebra_add_rnh_client(rnh, client);
}
zebra_evaluate_rnh_table(0, AF_INET, 0);
@@ -808,7 +824,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;
}
@@ -872,7 +891,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);
}
@@ -973,7 +992,7 @@ zread_ipv4_add (struct zserv *client, u_short length)
unsigned int ifindex;
u_char ifname_len;
safi_t safi;
-
+ int ret;
/* Get input stream. */
s = client->ibuf;
@@ -1048,7 +1067,13 @@ zread_ipv4_add (struct zserv *client, u_short length)
/* 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;
}
@@ -1137,6 +1162,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex,
client->rtm_table, api.safi);
+ client->v4_route_del_cnt++;
return 0;
}
@@ -1185,6 +1211,7 @@ zread_ipv6_add (struct zserv *client, u_short length)
safi_t safi;
static struct in6_addr nexthops[MULTIPATH_NUM];
static unsigned int ifindices[MULTIPATH_NUM];
+ int ret;
/* Get input stream. */
s = client->ibuf;
@@ -1283,7 +1310,13 @@ zread_ipv6_add (struct zserv *client, u_short length)
/* Table */
rib->table=zebrad.rtm_table_default;
- rib_add_ipv6_multipath (&p, rib, safi, ifindex);
+ ret = rib_add_ipv6_multipath (&p, rib, safi, ifindex);
+ /* Stats */
+ if (ret > 0)
+ client->v6_route_add_cnt++;
+ else if (ret < 0)
+ client->v6_route_upd8_cnt++;
+
return 0;
}
@@ -1358,6 +1391,8 @@ zread_ipv6_delete (struct zserv *client, u_short length)
rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi);
else
rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi);
+
+ client->v6_route_del_cnt++;
return 0;
}
@@ -1495,6 +1530,8 @@ zebra_client_create (int sock)
/* Set table number. */
client->rtm_table = zebrad.rtm_table_default;
+ client->connect_time = quagga_time(NULL);
+
/* Add this client to linked list. */
listnode_add (zebrad.client_list, client);
@@ -1607,6 +1644,9 @@ zebra_client_read (struct thread *thread)
zlog_debug ("zebra message received [%s] %d",
zserv_command_string (command), length);
+ client->last_read_time = quagga_time(NULL);
+ client->last_read_cmd = command;
+
switch (command)
{
case ZEBRA_ROUTER_ID_ADD:
@@ -1863,6 +1903,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,
@@ -1940,10 +2101,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;
}
@@ -2102,6 +2284,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 c5236367f..589d2e56d 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -72,6 +72,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 */