summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/reply_codes1
-rw-r--r--lib/event.c1
-rw-r--r--lib/mempool.c22
-rw-r--r--lib/resource.c38
-rw-r--r--lib/resource.h5
-rw-r--r--lib/slab.c38
-rw-r--r--nest/cmds.c30
-rw-r--r--nest/cmds.h1
-rw-r--r--nest/config.Y5
-rw-r--r--nest/proto.c2
-rw-r--r--nest/rt-attr.c3
-rw-r--r--nest/rt-table.c3
-rw-r--r--sysdep/unix/io.c3
13 files changed, 143 insertions, 9 deletions
diff --git a/doc/reply_codes b/doc/reply_codes
index 22e0fd2d..a0db2cad 100644
--- a/doc/reply_codes
+++ b/doc/reply_codes
@@ -44,6 +44,7 @@ Reply codes of BIRD command-line interface
1015 Show ospf interface
1016 Show ospf state/topology
1017 Show ospf lsadb
+1018 Show memory
8000 Reply too long
8001 Route not found
diff --git a/lib/event.c b/lib/event.c
index ce5e81c8..916cf55c 100644
--- a/lib/event.c
+++ b/lib/event.c
@@ -50,6 +50,7 @@ static struct resclass ev_class = {
sizeof(event),
(void (*)(resource *)) ev_postpone,
ev_dump,
+ NULL,
NULL
};
diff --git a/lib/mempool.c b/lib/mempool.c
index 0cb06b58..65072f9a 100644
--- a/lib/mempool.c
+++ b/lib/mempool.c
@@ -43,13 +43,15 @@ struct linpool {
static void lp_free(resource *);
static void lp_dump(resource *);
static resource *lp_lookup(resource *, unsigned long);
+static size_t lp_memsize(resource *r);
static struct resclass lp_class = {
"LinPool",
sizeof(struct linpool),
lp_free,
lp_dump,
- lp_lookup
+ lp_lookup,
+ lp_memsize
};
/**
@@ -235,6 +237,24 @@ lp_dump(resource *r)
m->total_large);
}
+static size_t
+lp_memsize(resource *r)
+{
+ linpool *m = (linpool *) r;
+ struct lp_chunk *c;
+ int cnt = 0;
+
+ for(c=m->first; c; c=c->next)
+ cnt++;
+ for(c=m->first_large; c; c=c->next)
+ cnt++;
+
+ return ALLOC_OVERHEAD + sizeof(struct linpool) +
+ cnt * (ALLOC_OVERHEAD + sizeof(sizeof(struct lp_chunk))) +
+ m->total + m->total_large;
+}
+
+
static resource *
lp_lookup(resource *r, unsigned long a)
{
diff --git a/lib/resource.c b/lib/resource.c
index 5ba23f18..24164ec2 100644
--- a/lib/resource.c
+++ b/lib/resource.c
@@ -37,13 +37,15 @@ struct pool {
static void pool_dump(resource *);
static void pool_free(resource *);
static resource *pool_lookup(resource *, unsigned long);
+static size_t pool_memsize(resource *P);
static struct resclass pool_class = {
"Pool",
sizeof(pool),
pool_free,
pool_dump,
- pool_lookup
+ pool_lookup,
+ pool_memsize
};
pool root_pool;
@@ -95,6 +97,19 @@ pool_dump(resource *P)
indent -= 3;
}
+static size_t
+pool_memsize(resource *P)
+{
+ pool *p = (pool *) P;
+ resource *r;
+ size_t sum = sizeof(pool) + ALLOC_OVERHEAD;
+
+ WALK_LIST(r, p->inside)
+ sum += rmemsize(r);
+
+ return sum;
+}
+
static resource *
pool_lookup(resource *P, unsigned long a)
{
@@ -177,6 +192,17 @@ rdump(void *res)
debug("NULL\n");
}
+size_t
+rmemsize(void *res)
+{
+ resource *r = res;
+ if (!r)
+ return 0;
+ if (!r->class->memsize)
+ return r->class->size + ALLOC_OVERHEAD;
+ return r->class->memsize(r);
+}
+
/**
* ralloc - create a resource
* @p: pool to create the resource in
@@ -277,12 +303,20 @@ mbl_lookup(resource *r, unsigned long a)
return NULL;
}
+static size_t
+mbl_memsize(resource *r)
+{
+ struct mblock *m = (struct mblock *) r;
+ return ALLOC_OVERHEAD + sizeof(struct mblock) + m->size;
+}
+
static struct resclass mb_class = {
"Memory",
0,
mbl_free,
mbl_debug,
- mbl_lookup
+ mbl_lookup,
+ mbl_memsize
};
/**
diff --git a/lib/resource.h b/lib/resource.h
index 8dd441f0..5cb5e274 100644
--- a/lib/resource.h
+++ b/lib/resource.h
@@ -26,8 +26,12 @@ struct resclass {
void (*free)(resource *); /* Freeing function */
void (*dump)(resource *); /* Dump to debug output */
resource *(*lookup)(resource *, unsigned long); /* Look up address (only for debugging) */
+ size_t (*memsize)(resource *); /* Return size of memory used by the resource, may be NULL */
};
+/* Estimate of system allocator overhead per item, for memory consumtion stats */
+#define ALLOC_OVERHEAD 8
+
/* Generic resource manipulation */
typedef struct pool pool;
@@ -36,6 +40,7 @@ void resource_init(void);
pool *rp_new(pool *, char *); /* Create new pool */
void rfree(void *); /* Free single resource */
void rdump(void *); /* Dump to debug output */
+size_t rmemsize(void *res); /* Return size of memory used by the resource */
void rlookup(unsigned long); /* Look up address (only for debugging) */
void rmove(void *, pool *); /* Move to a different pool */
diff --git a/lib/slab.c b/lib/slab.c
index 8cce52fe..af6b50b0 100644
--- a/lib/slab.c
+++ b/lib/slab.c
@@ -41,6 +41,7 @@
static void slab_free(resource *r);
static void slab_dump(resource *r);
static resource *slab_lookup(resource *r, unsigned long addr);
+static size_t slab_memsize(resource *r);
#ifdef FAKE_SLAB
@@ -58,7 +59,8 @@ static struct resclass sl_class = {
"FakeSlab",
sizeof(struct slab),
slab_free,
- slab_dump
+ slab_dump,
+ slab_memsize
};
struct sl_obj {
@@ -116,6 +118,20 @@ slab_dump(resource *r)
debug("(%d objects per %d bytes)\n", cnt, s->size);
}
+static size_t
+slab_memsize(resource *r)
+{
+ slab *s = (slab *) r;
+ int cnt = 0;
+ struct sl_obj *o;
+
+ WALK_LIST(o, s->objs)
+ cnt++;
+
+ return ALLOC_OVERHEAD + sizeof(struct slab) + cnt * (ALLOC_OVERHEAD + s->size);
+}
+
+
#else
/*
@@ -136,7 +152,8 @@ static struct resclass sl_class = {
sizeof(struct slab),
slab_free,
slab_dump,
- slab_lookup
+ slab_lookup,
+ slab_memsize
};
struct sl_head {
@@ -324,6 +341,23 @@ slab_dump(resource *r)
debug("(%de+%dp+%df blocks per %d objs per %d bytes)\n", ec, pc, fc, s->objs_per_slab, s->obj_size);
}
+static size_t
+slab_memsize(resource *r)
+{
+ slab *s = (slab *) r;
+ int heads = 0;
+ struct sl_head *h;
+
+ WALK_LIST(h, s->empty_heads)
+ heads++;
+ WALK_LIST(h, s->partial_heads)
+ heads++;
+ WALK_LIST(h, s->full_heads)
+ heads++;
+
+ return ALLOC_OVERHEAD + sizeof(struct slab) + heads * (ALLOC_OVERHEAD + SLAB_SIZE);
+}
+
static resource *
slab_lookup(resource *r, unsigned long a)
{
diff --git a/nest/cmds.c b/nest/cmds.c
index 16fbba61..8ac32096 100644
--- a/nest/cmds.c
+++ b/nest/cmds.c
@@ -11,6 +11,7 @@
#include "conf/conf.h"
#include "nest/cmds.h"
#include "lib/string.h"
+#include "lib/resource.h"
void
cmd_show_status(void)
@@ -47,3 +48,32 @@ cmd_show_symbols(struct symbol *sym)
cli_msg(0, "");
}
}
+
+static void
+print_size(char *dsc, size_t val)
+{
+ char *px = " kMG";
+ int i = 0;
+ while ((val >= 10000) && (i < 3))
+ {
+ val = (val + 512) / 1024;
+ i++;
+ }
+
+ cli_msg(-1018, "%-17s %4u %cB", dsc, (unsigned) val, px[i]);
+}
+
+extern pool *rt_table_pool;
+extern pool *rta_pool;
+extern pool *proto_pool;
+
+void
+cmd_show_memory(void)
+{
+ cli_msg(-1018, "BIRD memory usage");
+ print_size("Routing tables:", rmemsize(rt_table_pool));
+ print_size("Route attributes:", rmemsize(rta_pool));
+ print_size("Protocols:", rmemsize(proto_pool));
+ print_size("Total:", rmemsize(&root_pool));
+ cli_msg(0, "");
+}
diff --git a/nest/cmds.h b/nest/cmds.h
index ae1c9e2e..3b86a924 100644
--- a/nest/cmds.h
+++ b/nest/cmds.h
@@ -8,3 +8,4 @@
void cmd_show_status(void);
void cmd_show_symbols(struct symbol *sym);
+void cmd_show_memory(void);
diff --git a/nest/config.Y b/nest/config.Y
index 7bb05259..a8e6bf8c 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -45,7 +45,7 @@ CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILT
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE)
CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION)
-CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT)
+CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY)
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE)
@@ -324,6 +324,9 @@ CF_CLI_HELP(SHOW, ..., [[Show status information]])
CF_CLI(SHOW STATUS,,, [[Show router status]])
{ cmd_show_status(); } ;
+CF_CLI(SHOW MEMORY,,, [[Show memory usage]])
+{ cmd_show_memory(); } ;
+
CF_CLI(SHOW PROTOCOLS, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocols]])
{ proto_apply_cmd($3, proto_cmd_show, 0, 0); } ;
diff --git a/nest/proto.c b/nest/proto.c
index 46147a4e..c9e2f5c7 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -20,7 +20,7 @@
#include "nest/cli.h"
#include "filter/filter.h"
-static pool *proto_pool;
+pool *proto_pool;
static list protocol_list;
static list proto_list;
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index b553475a..abd49c70 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -54,8 +54,9 @@
#include "lib/resource.h"
#include "lib/string.h"
+pool *rta_pool;
+
static slab *rta_slab;
-static pool *rta_pool;
struct protocol *attr_class_to_protocol[EAP_MAX];
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 87365742..8cca42a7 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -43,10 +43,11 @@
#include "lib/string.h"
#include "lib/alloca.h"
+pool *rt_table_pool;
+
static slab *rte_slab;
static linpool *rte_update_pool;
-static pool *rt_table_pool;
static list routing_tables;
static void rt_format_via(rte *e, byte *via);
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 8058fa66..690c8fc9 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -76,6 +76,7 @@ static struct resclass rf_class = {
sizeof(struct rfile),
rf_free,
rf_dump,
+ NULL,
NULL
};
@@ -203,6 +204,7 @@ static struct resclass tm_class = {
sizeof(timer),
tm_free,
tm_dump,
+ NULL,
NULL
};
@@ -573,6 +575,7 @@ static struct resclass sk_class = {
sizeof(sock),
sk_free,
sk_dump,
+ NULL,
NULL
};