summaryrefslogtreecommitdiff
path: root/zebra/zserv.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zserv.c')
-rw-r--r--zebra/zserv.c134
1 files changed, 127 insertions, 7 deletions
diff --git a/zebra/zserv.c b/zebra/zserv.c
index cca926f3b0..2a5352a1da 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -557,6 +557,9 @@ DEFINE_KOOH(zserv_client_close, (struct zserv *client), (client));
*/
static void zserv_client_free(struct zserv *client)
{
+ if (client == NULL)
+ return;
+
hook_call(zserv_client_close, client);
/* Close file descriptor. */
@@ -565,11 +568,14 @@ static void zserv_client_free(struct zserv *client)
close(client->sock);
- nroutes = rib_score_proto(client->proto, client->instance);
- zlog_notice(
- "client %d disconnected. %lu %s routes removed from the rib",
- client->sock, nroutes,
- zebra_route_string(client->proto));
+ if (!client->gr_instance_count) {
+ nroutes = rib_score_proto(client->proto,
+ client->instance);
+ zlog_notice(
+ "client %d disconnected %lu %s routes removed from the rib",
+ client->sock, nroutes,
+ zebra_route_string(client->proto));
+ }
client->sock = -1;
}
@@ -600,7 +606,25 @@ static void zserv_client_free(struct zserv *client)
}
vrf_bitmap_free(client->ridinfo);
- XFREE(MTYPE_TMP, client);
+ /*
+ * If any instance are graceful restart enabled,
+ * client is not deleted
+ */
+ if (!client->gr_instance_count) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s: Deleting client %s", __func__,
+ zebra_route_string(client->proto));
+ XFREE(MTYPE_TMP, client);
+ } else {
+ /* Handle cases where client has GR instance. */
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s: client %s restart enabled", __func__,
+ zebra_route_string(client->proto));
+ if (zebra_gr_client_disconnect(client) < 0)
+ zlog_err(
+ "%s: GR enabled but could not handle disconnect event",
+ __func__);
+ }
}
void zserv_close_client(struct zserv *client)
@@ -670,6 +694,7 @@ static struct zserv *zserv_client_create(int sock)
pthread_mutex_init(&client->ibuf_mtx, NULL);
pthread_mutex_init(&client->obuf_mtx, NULL);
client->wb = buffer_new(0);
+ TAILQ_INIT(&(client->gr_info_queue));
atomic_store_explicit(&client->connect_time, (uint32_t) monotime(NULL),
memory_order_relaxed);
@@ -861,12 +886,14 @@ static char *zserv_time_buf(time_t *time1, char *buf, int buflen)
return buf;
}
+/* Display client info details */
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];
time_t connect_time, last_read_time, last_write_time;
uint32_t last_read_cmd, last_write_cmd;
+ struct client_gr_info *info = NULL;
vty_out(vty, "Client: %s", zebra_route_string(client->proto));
if (client->instance)
@@ -945,12 +972,100 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
vty_out(vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt);
vty_out(vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt);
+ TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
+ vty_out(vty, "VRF : %s\n", vrf_id_to_name(info->vrf_id));
+ vty_out(vty, "Capabilities : ");
+ switch (info->capabilities) {
+ case ZEBRA_CLIENT_GR_CAPABILITIES:
+ vty_out(vty, "Graceful Restart\n");
+ break;
+ case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
+ case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
+ case ZEBRA_CLIENT_GR_DISABLE:
+ case ZEBRA_CLIENT_RIB_STALE_TIME:
+ vty_out(vty, "None\n");
+ break;
+ }
+ }
+
#if defined DEV_BUILD
vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n",
client->ibuf_fifo->count, client->ibuf_fifo->max_count,
client->obuf_fifo->count, client->obuf_fifo->max_count);
#endif
vty_out(vty, "\n");
+}
+
+/* Display stale client information */
+static void zebra_show_stale_client_detail(struct vty *vty,
+ struct zserv *client)
+{
+ char buf[PREFIX2STR_BUFFER];
+ struct tm *tm;
+ struct timeval tv;
+ time_t uptime;
+ struct client_gr_info *info = NULL;
+ struct zserv *s = NULL;
+
+ if (client->instance)
+ vty_out(vty, " Instance: %d", client->instance);
+
+ TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
+ vty_out(vty, "VRF : %s\n", vrf_id_to_name(info->vrf_id));
+ vty_out(vty, "Capabilities : ");
+ switch (info->capabilities) {
+ case ZEBRA_CLIENT_GR_CAPABILITIES:
+ vty_out(vty, "Graceful Restart\n");
+ break;
+ case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
+ case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
+ case ZEBRA_CLIENT_GR_DISABLE:
+ case ZEBRA_CLIENT_RIB_STALE_TIME:
+ vty_out(vty, "None\n");
+ break;
+ }
+
+ if (ZEBRA_CLIENT_GR_ENABLED(info->capabilities)) {
+ if (info->stale_client_ptr) {
+ s = (struct zserv *)(info->stale_client_ptr);
+ uptime = monotime(&tv);
+ uptime -= s->restart_time;
+ tm = gmtime(&uptime);
+ vty_out(vty, "Last restart time : ");
+ if (uptime < ONE_DAY_SECOND)
+ vty_out(vty, "%02d:%02d:%02d",
+ tm->tm_hour, tm->tm_min,
+ tm->tm_sec);
+ else if (uptime < ONE_WEEK_SECOND)
+ vty_out(vty, "%dd%02dh%02dm",
+ tm->tm_yday, tm->tm_hour,
+ tm->tm_min);
+ else
+ vty_out(vty, "%02dw%dd%02dh",
+ tm->tm_yday / 7,
+ tm->tm_yday - ((tm->tm_yday / 7)
+ * 7),
+ tm->tm_hour);
+ vty_out(vty, " ago\n");
+
+ vty_out(vty, "Stalepath removal time: %d sec\n",
+ info->stale_removal_time);
+ if (info->t_stale_removal) {
+ vty_out(vty,
+ "Stale delete timer: %ld sec\n",
+ thread_timer_remain_second(
+ info->t_stale_removal));
+ }
+ }
+ vty_out(vty, "Current AFI : %d\n", info->current_afi);
+ if (info->current_prefix) {
+ prefix2str(info->current_prefix, buf,
+ sizeof(buf));
+ vty_out(vty, "Current prefix : %s\n", buf);
+ }
+ }
+ }
+ vty_out(vty, "\n");
return;
}
@@ -1002,8 +1117,12 @@ DEFUN (show_zebra_client,
struct listnode *node;
struct zserv *client;
- for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client))
+ for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
zebra_show_client_detail(vty, client);
+ vty_out(vty, "Stale Client Information\n");
+ vty_out(vty, "------------------------\n");
+ zebra_show_stale_client_detail(vty, client);
+ }
return CMD_SUCCESS;
}
@@ -1047,6 +1166,7 @@ void zserv_init(void)
{
/* Client list init. */
zrouter.client_list = list_new();
+ zrouter.stale_client_list = list_new();
/* Misc init. */
zsock = -1;