1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
From de9dbee796876f5b621e40e0082612aad746cac1 Mon Sep 17 00:00:00 2001
From: Maria Matejka <mq@ucw.cz>
Date: Sun, 22 Dec 2024 22:10:38 +0100
Subject: [PATCH] CLI: allocate TX buffers as pages, not by malloc
Every malloc risks heap bloating and these blocks are already
the same size as pages.
---
nest/cli.c | 59 ++++++++++++++++++++++++++++++++++++++++++------------
nest/cli.h | 2 +-
2 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/nest/cli.c b/nest/cli.c
index 3b8e6f468..b33ffd437 100644
--- nest/cli.c
+++ nest/cli.c
@@ -81,13 +81,14 @@ cli_alloc_out(cli *c, int size)
o = c->tx_buf;
else
{
- o = mb_alloc(c->pool, sizeof(struct cli_out) + CLI_TX_BUF_SIZE);
+ o = alloc_page();
+ c->tx_pending_count++;
if (c->tx_write)
c->tx_write->next = o;
else
c->tx_buf = o;
o->wpos = o->outpos = o->buf;
- o->end = o->buf + CLI_TX_BUF_SIZE;
+ o->end = (void *) o + page_size;
}
c->tx_write = o;
if (!c->tx_pos)
@@ -167,19 +168,18 @@ cli_hello(cli *c)
static void
cli_free_out(cli *c)
{
- struct cli_out *o, *p;
+ for (struct cli_out *o = c->tx_buf, *n; o; o = n)
+ {
+ n = o->next;
+ free_page(o);
+ c->tx_pending_count--;
+ }
- if (o = c->tx_buf)
- {
- o->wpos = o->outpos = o->buf;
- while (p = o->next)
- {
- o->next = p->next;
- mb_free(p);
- }
- }
+ c->tx_buf = NULL;
c->tx_write = c->tx_pos = NULL;
c->async_msg_size = 0;
+
+ ASSERT_DIE(c->tx_pending_count == 0);
}
void
@@ -189,6 +189,38 @@ cli_written(cli *c)
ev_schedule(c->event);
}
+/* A dummy resource to show and free memory pages allocated for pending TX */
+struct cli_tx_resource {
+ resource r;
+ struct cli *c;
+};
+
+static void
+cli_tx_resource_free(resource *r)
+{
+ cli_free_out(SKIP_BACK(struct cli_tx_resource, r, r)->c);
+}
+
+static void
+cli_tx_resource_dump(struct dump_request *dreq UNUSED, resource *r UNUSED) {}
+
+static struct resmem
+cli_tx_resource_memsize(resource *r)
+{
+ return (struct resmem) {
+ .effective = SKIP_BACK(struct cli_tx_resource, r, r)->c->tx_pending_count * page_size,
+ .overhead = sizeof(struct cli_tx_resource),
+ };
+}
+
+static struct resclass cli_tx_resource_class = {
+ .name = "CLI TX buffers",
+ .size = sizeof (struct cli_tx_resource),
+ .free = cli_tx_resource_free,
+ .dump = cli_tx_resource_dump,
+ .memsize = cli_tx_resource_memsize,
+};
+
static byte *cli_rh_pos;
static uint cli_rh_len;
@@ -272,7 +304,8 @@ cli *
cli_new(struct birdsock *sock, struct cli_config *cf)
{
pool *p = rp_new(cli_pool, the_bird_domain.the_bird, "CLI");
- cli *c = mb_alloc(p, sizeof(cli));
+ struct cli_tx_resource *ctr = ralloc(p, &cli_tx_resource_class);
+ cli *c = ctr->c = mb_alloc(p, sizeof(cli));
bzero(c, sizeof(cli));
c->pool = p;
diff --git a/nest/cli.h b/nest/cli.h
index d86ec3801..671be04d8 100644
--- nest/cli.h
+++ nest/cli.h
@@ -17,7 +17,6 @@
#include "conf/conf.h"
#define CLI_RX_BUF_SIZE 4096
-#define CLI_TX_BUF_SIZE 4096
#define CLI_MAX_ASYNC_QUEUE 4096
#define CLI_MSG_SIZE 500
@@ -49,6 +48,7 @@ typedef struct cli {
uint log_mask; /* Mask of allowed message levels */
uint log_threshold; /* When free < log_threshold, store only important messages */
uint async_msg_size; /* Total size of async messages queued in tx_buf */
+ uint tx_pending_count; /* How many blocks are pending */
} cli;
struct cli_config {
--
GitLab
|