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.
This commit is contained in:
Donald Sharp 2015-05-19 17:47:22 -07:00
parent 6e26278cba
commit 04b02fda9f
5 changed files with 273 additions and 22 deletions

View File

@ -156,7 +156,10 @@ zebra_redistribute (struct zserv *client, int type)
&& newrib->type == type && newrib->type == type
&& newrib->distance != DISTANCE_INFINITY && newrib->distance != DISTANCE_INFINITY
&& zebra_check_addr (&rn->p)) && 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 #ifdef HAVE_IPV6
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
@ -167,7 +170,10 @@ zebra_redistribute (struct zserv *client, int type)
&& newrib->type == type && newrib->type == type
&& newrib->distance != DISTANCE_INFINITY && newrib->distance != DISTANCE_INFINITY
&& zebra_check_addr (&rn->p)) && 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 */ #endif /* HAVE_IPV6 */
} }
@ -184,20 +190,32 @@ redistribute_add (struct prefix *p, struct rib *rib)
if (client->redist_default || client->redist[rib->type]) if (client->redist_default || client->redist[rib->type])
{ {
if (p->family == AF_INET) 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 #ifdef HAVE_IPV6
if (p->family == AF_INET6) 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 */ #endif /* HAVE_IPV6 */
} }
} }
else if (client->redist[rib->type]) else if (client->redist[rib->type])
{ {
if (p->family == AF_INET) 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 #ifdef HAVE_IPV6
if (p->family == AF_INET6) 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 */ #endif /* HAVE_IPV6 */
} }
} }
@ -297,7 +315,9 @@ zebra_interface_up_update (struct interface *ifp)
if (ifp->ptm_status || !ifp->ptm_enable) { if (ifp->ptm_status || !ifp->ptm_enable) {
for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) 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); zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name);
for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) 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. */ /* Interface information update. */
@ -327,7 +349,10 @@ zebra_interface_add_update (struct interface *ifp)
for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
if (client->ifinfo) if (client->ifinfo)
zsend_interface_add (client, ifp); {
client->ifadd_cnt++;
zsend_interface_add (client, ifp);
}
} }
void void
@ -341,7 +366,10 @@ zebra_interface_delete_update (struct interface *ifp)
for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
if (client->ifinfo) if (client->ifinfo)
zsend_interface_delete (client, ifp); {
client->ifdel_cnt++;
zsend_interface_delete (client, ifp);
}
} }
/* Interface address addition. */ /* 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)) for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) 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. */ /* 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)) for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
if (client->ifinfo && CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) 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);
}
} }

View File

@ -2258,6 +2258,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
struct route_node *rn; struct route_node *rn;
struct rib *same; struct rib *same;
struct nexthop *nexthop; struct nexthop *nexthop;
int ret = 0;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (AFI_IP, safi, 0); 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.*/ /* Link new rib to node.*/
rib_addnode (rn, rib); rib_addnode (rn, rib);
ret = 1;
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
{ {
zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry", 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_dump (p, same);
} }
rib_delnode (rn, same); rib_delnode (rn, same);
ret = -1;
} }
route_unlock_node (rn); route_unlock_node (rn);
return 0; return ret;
} }
/* XXX factor with rib_delete_ipv6 */ /* XXX factor with rib_delete_ipv6 */

View File

@ -657,6 +657,9 @@ send_client (struct rnh *rnh, struct zserv *client)
stream_putc (s, 0); stream_putc (s, 0);
} }
stream_putw_at (s, 0, stream_get_endp (s)); 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); return zebra_server_send_message(client);
} }

View File

@ -100,6 +100,8 @@ zserv_flush_data(struct thread *thread)
case BUFFER_EMPTY: case BUFFER_EMPTY:
break; break;
} }
client->last_write_time = quagga_time(NULL);
return 0; return 0;
} }
@ -108,6 +110,9 @@ zebra_server_send_message(struct zserv *client)
{ {
if (client->t_suicide) if (client->t_suicide)
return -1; 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), switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf),
stream_get_endp(client->obuf))) stream_get_endp(client->obuf)))
{ {
@ -129,6 +134,8 @@ zebra_server_send_message(struct zserv *client)
zserv_flush_data, client, client->sock); zserv_flush_data, client, client->sock);
break; break;
} }
client->last_write_time = quagga_time(NULL);
return 0; return 0;
} }
@ -194,6 +201,7 @@ zsend_interface_add (struct zserv *client, struct interface *ifp)
zserv_create_header (s, ZEBRA_INTERFACE_ADD); zserv_create_header (s, ZEBRA_INTERFACE_ADD);
zserv_encode_interface (s, ifp); zserv_encode_interface (s, ifp);
client->ifadd_cnt++;
return zebra_server_send_message(client); 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_create_header (s, ZEBRA_INTERFACE_DELETE);
zserv_encode_interface (s, ifp); zserv_encode_interface (s, ifp);
client->ifdel_cnt++;
return zebra_server_send_message (client); return zebra_server_send_message (client);
} }
@ -298,6 +307,7 @@ zsend_interface_address (int cmd, struct zserv *client,
/* Write packet size. */ /* Write packet size. */
stream_putw_at (s, 0, stream_get_endp (s)); stream_putw_at (s, 0, stream_get_endp (s));
client->connected_rt_add_cnt++;
return zebra_server_send_message(client); 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_create_header (s, cmd);
zserv_encode_interface (s, ifp); zserv_encode_interface (s, ifp);
if (cmd == ZEBRA_INTERFACE_UP)
client->ifup_cnt++;
else
client->ifdown_cnt++;
return zebra_server_send_message(client); 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)); stream_putw_at (s, 0, stream_get_endp (s));
return zebra_server_send_message(client); return zebra_server_send_message(client);
} }
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -775,6 +790,7 @@ zserv_nexthop_register (struct zserv *client, int sock, u_short length)
if (connected) if (connected)
SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
client->nh_reg_time = quagga_time(NULL);
zebra_add_rnh_client(rnh, client); zebra_add_rnh_client(rnh, client);
} }
zebra_evaluate_rnh_table(0, AF_INET, 0); 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); l += PSIZE(p.prefixlen);
rnh = zebra_lookup_rnh(&p, 0); rnh = zebra_lookup_rnh(&p, 0);
if (rnh) if (rnh)
zebra_remove_rnh_client(rnh, client); {
client->nh_dereg_time = quagga_time(NULL);
zebra_remove_rnh_client(rnh, client);
}
} }
return 0; 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)); stream_putw_at (s, 0, stream_get_endp (s));
return zebra_server_send_message(client); return zebra_server_send_message(client);
} }
@ -973,7 +992,7 @@ zread_ipv4_add (struct zserv *client, u_short length)
unsigned int ifindex; unsigned int ifindex;
u_char ifname_len; u_char ifname_len;
safi_t safi; safi_t safi;
int ret;
/* Get input stream. */ /* Get input stream. */
s = client->ibuf; s = client->ibuf;
@ -1048,7 +1067,13 @@ zread_ipv4_add (struct zserv *client, u_short length)
/* Table */ /* Table */
rib->table=zebrad.rtm_table_default; 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; 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, rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex,
client->rtm_table, api.safi); client->rtm_table, api.safi);
client->v4_route_del_cnt++;
return 0; return 0;
} }
@ -1185,6 +1211,7 @@ zread_ipv6_add (struct zserv *client, u_short length)
safi_t safi; safi_t safi;
static struct in6_addr nexthops[MULTIPATH_NUM]; static struct in6_addr nexthops[MULTIPATH_NUM];
static unsigned int ifindices[MULTIPATH_NUM]; static unsigned int ifindices[MULTIPATH_NUM];
int ret;
/* Get input stream. */ /* Get input stream. */
s = client->ibuf; s = client->ibuf;
@ -1283,7 +1310,13 @@ zread_ipv6_add (struct zserv *client, u_short length)
/* Table */ /* Table */
rib->table=zebrad.rtm_table_default; 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; 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); rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi);
else else
rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi); rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi);
client->v6_route_del_cnt++;
return 0; return 0;
} }
@ -1495,6 +1530,8 @@ zebra_client_create (int sock)
/* Set table number. */ /* Set table number. */
client->rtm_table = zebrad.rtm_table_default; client->rtm_table = zebrad.rtm_table_default;
client->connect_time = quagga_time(NULL);
/* Add this client to linked list. */ /* Add this client to linked list. */
listnode_add (zebrad.client_list, client); listnode_add (zebrad.client_list, client);
@ -1607,6 +1644,9 @@ zebra_client_read (struct thread *thread)
zlog_debug ("zebra message received [%s] %d", zlog_debug ("zebra message received [%s] %d",
zserv_command_string (command), length); zserv_command_string (command), length);
client->last_read_time = quagga_time(NULL);
client->last_read_cmd = command;
switch (command) switch (command)
{ {
case ZEBRA_ROUTER_ID_ADD: 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. */ /* Display default rtm_table for all clients. */
DEFUN (show_table, DEFUN (show_table,
show_table_cmd, show_table_cmd,
@ -1940,13 +2101,34 @@ DEFUN (show_zebra_client,
struct zserv *client; struct zserv *client;
for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
vty_out (vty, "Client %s fd %d%s", zebra_show_client_detail(vty, client);
zebra_route_string(client->proto), client->sock,
VTY_NEWLINE);
return CMD_SUCCESS; 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;
}
/* Table configuration write function. */ /* Table configuration write function. */
static int static int
config_write_table (struct vty *vty) config_write_table (struct vty *vty)
@ -2102,6 +2284,7 @@ zebra_init (void)
install_element (CONFIG_NODE, &ip_forwarding_cmd); install_element (CONFIG_NODE, &ip_forwarding_cmd);
install_element (CONFIG_NODE, &no_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_cmd);
install_element (ENABLE_NODE, &show_zebra_client_summary_cmd);
#ifdef HAVE_NETLINK #ifdef HAVE_NETLINK
install_element (VIEW_NODE, &show_table_cmd); install_element (VIEW_NODE, &show_table_cmd);

View File

@ -72,6 +72,34 @@ struct zserv
/* client's protocol */ /* client's protocol */
u_char proto; 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 */ /* Zebra instance */