From 3734642218ef4af4236be3ff2d9427716396eb94 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 22 Jun 2018 07:46:03 -0400 Subject: [PATCH] zebra: Gather up output data and push in buffer to send This commit gathers data from the client->obuf_fifo and puts it all into the buffer for writing. This will address the fact that the multiple events created caused the memory of zebra to grow to unrealistic levels of usage when we are redistributing data to other protocols. Recreate Memory: robot# show memory Memory statistics for zebra: System allocator statistics: Total heap allocated: 1930 MiB Holding block headers: 16 MiB Used small blocks: 0 bytes Used ordinary blocks: 1911 MiB Free small blocks: 1968 bytes Free ordinary blocks: 19 MiB Ordinary blocks: 5210 Small blocks: 58 Holding blocks: 1 New Zebra Memory: Memory statistics for zebra: System allocator statistics: Total heap allocated: 478 MiB Holding block headers: 16 MiB Used small blocks: 0 bytes Used ordinary blocks: 415 MiB Free small blocks: 1968 bytes Free ordinary blocks: 63 MiB Ordinary blocks: 4909 Small blocks: 58 Holding blocks: 1 New show threads cpu for Zebra: robot# show thread cpu Thread statistics for zebra: Showing statistics for pthread main ----------------------------------- CPU (user+system): Real (wall-clock): Active Runtime(ms) Invoked Avg uSec Max uSecs Avg uSec Max uSecs Type Thread 0 6465.766 801 8072 54775 10810 225356 T work_queue_run 1 0.096 4 24 37 24 38 R vtysh_accept 0 8.690 533 16 54 154 6286 W zserv_flush_data 0 254.102 290 876 2224 971 6958 W zserv_write 0 1992.936 7854 253 115333 266 116288 E &zserv_process_messages 1 1.351 6 225 245 226 249 R zebra_accept 1 0.152 8 19 22 19 23 T zebra_ptm_connect 1 0.124 7 17 24 18 24 R kernel_read 1 121.460 122 995 107273 1021 108707 R vtysh_read 6 686.460 7854 87 150 93 6006 R zserv_read 0 0.040 1 40 40 39 39 T zebra_route_map_update_timer 0 0.412 6 68 170 499 1520 T if_zebra_speed_update Fixes: #2527 Signed-off-by: Donald Sharp --- zebra/zserv.c | 65 +++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/zebra/zserv.c b/zebra/zserv.c index 7dcd654240..764880372b 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -257,6 +257,7 @@ static int zserv_flush_data(struct thread *thread) static int zserv_write(struct thread *thread) { struct zserv *client = THREAD_ARG(thread); + bool pending = false; struct stream *msg; int writerv; @@ -267,37 +268,45 @@ static int zserv_write(struct thread *thread) return 0; msg = stream_fifo_pop(client->obuf_fifo); - stream_set_getp(msg, 0); - client->last_write_cmd = stream_getw_from(msg, 6); - - writerv = buffer_write(client->wb, client->sock, STREAM_DATA(msg), - stream_get_endp(msg)); - - stream_free(msg); + while (msg) { + stream_set_getp(msg, 0); + client->last_write_cmd = stream_getw_from(msg, 6); + + writerv = buffer_write(client->wb, client->sock, + STREAM_DATA(msg), stream_get_endp(msg)); + + stream_free(msg); + msg = NULL; + switch (writerv) { + case BUFFER_ERROR: + zlog_warn( + "%s: buffer_write failed to zserv client fd %d, closing", + __func__, client->sock); + /* + * Schedule a delayed close since many of the + * functions that call this one do not check the + * return code. They do not allow for the possibility + * that an I/O error may have caused the client to + * be deleted. + */ + client->t_suicide = NULL; + thread_add_event(zebrad.master, zserv_delayed_close, + client, 0, &client->t_suicide); + return -1; + case BUFFER_PENDING: + pending = true; + /* Intentional Fall-Through */ + case BUFFER_EMPTY: + msg = stream_fifo_pop(client->obuf_fifo); + break; + break; + } + } - switch (writerv) { - case BUFFER_ERROR: - zlog_warn( - "%s: buffer_write failed to zserv client fd %d, closing", - __func__, client->sock); - /* - * Schedule a delayed close since many of the functions that - * call this one do not check the return code. They do not - * allow for the possibility that an I/O error may have caused - * the client to be deleted. - */ - client->t_suicide = NULL; - thread_add_event(zebrad.master, zserv_delayed_close, client, 0, - &client->t_suicide); - return -1; - case BUFFER_EMPTY: - THREAD_OFF(client->t_write); - break; - case BUFFER_PENDING: + if (pending) thread_add_write(zebrad.master, zserv_flush_data, client, client->sock, &client->t_write); - break; - } + if (client->obuf_fifo->count) zebra_event(client, ZEBRA_WRITE); -- 2.39.5