Commit acb60628 authored by Ondřej Zajíček's avatar Ondřej Zajíček

Implements command that shows memory usage.

parent 4461b897
......@@ -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
......
......@@ -50,6 +50,7 @@ static struct resclass ev_class = {
sizeof(event),
(void (*)(resource *)) ev_postpone,
ev_dump,
NULL,
NULL
};
......
......@@ -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)
{
......
......@@ -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
};
/**
......
......@@ -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 */
......
......@@ -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)
{
......
......@@ -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, "");
}
......@@ -8,3 +8,4 @@
void cmd_show_status(void);
void cmd_show_symbols(struct symbol *sym);
void cmd_show_memory(void);
......@@ -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); } ;
......
......@@ -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;
......
......@@ -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];
......
......@@ -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);
......
......@@ -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
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment