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->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);
}
}

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 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 */

View File

@ -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);
}

View File

@ -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,13 +2101,34 @@ 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;
}
/* Table configuration write function. */
static int
config_write_table (struct vty *vty)
@ -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);

View File

@ -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 */