]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: Gather up output data and push in buffer to send
authorDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 22 Jun 2018 11:46:03 +0000 (07:46 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 22 Jun 2018 16:46:51 +0000 (12:46 -0400)
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 <sharpd@cumulusnetworks.com>
zebra/zserv.c

index 7dcd654240d50eb5927101883a33365a846b1348..764880372ba299cbb34660963fcbca88058d6088 100644 (file)
@@ -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);