Implements command that shows memory usage.
This commit is contained in:
parent
4461b89791
commit
acb60628f5
13 changed files with 143 additions and 9 deletions
|
@ -44,6 +44,7 @@ Reply codes of BIRD command-line interface
|
||||||
1015 Show ospf interface
|
1015 Show ospf interface
|
||||||
1016 Show ospf state/topology
|
1016 Show ospf state/topology
|
||||||
1017 Show ospf lsadb
|
1017 Show ospf lsadb
|
||||||
|
1018 Show memory
|
||||||
|
|
||||||
8000 Reply too long
|
8000 Reply too long
|
||||||
8001 Route not found
|
8001 Route not found
|
||||||
|
|
|
@ -50,6 +50,7 @@ static struct resclass ev_class = {
|
||||||
sizeof(event),
|
sizeof(event),
|
||||||
(void (*)(resource *)) ev_postpone,
|
(void (*)(resource *)) ev_postpone,
|
||||||
ev_dump,
|
ev_dump,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -43,13 +43,15 @@ struct linpool {
|
||||||
static void lp_free(resource *);
|
static void lp_free(resource *);
|
||||||
static void lp_dump(resource *);
|
static void lp_dump(resource *);
|
||||||
static resource *lp_lookup(resource *, unsigned long);
|
static resource *lp_lookup(resource *, unsigned long);
|
||||||
|
static size_t lp_memsize(resource *r);
|
||||||
|
|
||||||
static struct resclass lp_class = {
|
static struct resclass lp_class = {
|
||||||
"LinPool",
|
"LinPool",
|
||||||
sizeof(struct linpool),
|
sizeof(struct linpool),
|
||||||
lp_free,
|
lp_free,
|
||||||
lp_dump,
|
lp_dump,
|
||||||
lp_lookup
|
lp_lookup,
|
||||||
|
lp_memsize
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -235,6 +237,24 @@ lp_dump(resource *r)
|
||||||
m->total_large);
|
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 *
|
static resource *
|
||||||
lp_lookup(resource *r, unsigned long a)
|
lp_lookup(resource *r, unsigned long a)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,13 +37,15 @@ struct pool {
|
||||||
static void pool_dump(resource *);
|
static void pool_dump(resource *);
|
||||||
static void pool_free(resource *);
|
static void pool_free(resource *);
|
||||||
static resource *pool_lookup(resource *, unsigned long);
|
static resource *pool_lookup(resource *, unsigned long);
|
||||||
|
static size_t pool_memsize(resource *P);
|
||||||
|
|
||||||
static struct resclass pool_class = {
|
static struct resclass pool_class = {
|
||||||
"Pool",
|
"Pool",
|
||||||
sizeof(pool),
|
sizeof(pool),
|
||||||
pool_free,
|
pool_free,
|
||||||
pool_dump,
|
pool_dump,
|
||||||
pool_lookup
|
pool_lookup,
|
||||||
|
pool_memsize
|
||||||
};
|
};
|
||||||
|
|
||||||
pool root_pool;
|
pool root_pool;
|
||||||
|
@ -95,6 +97,19 @@ pool_dump(resource *P)
|
||||||
indent -= 3;
|
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 *
|
static resource *
|
||||||
pool_lookup(resource *P, unsigned long a)
|
pool_lookup(resource *P, unsigned long a)
|
||||||
{
|
{
|
||||||
|
@ -177,6 +192,17 @@ rdump(void *res)
|
||||||
debug("NULL\n");
|
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
|
* ralloc - create a resource
|
||||||
* @p: pool to create the resource in
|
* @p: pool to create the resource in
|
||||||
|
@ -277,12 +303,20 @@ mbl_lookup(resource *r, unsigned long a)
|
||||||
return NULL;
|
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 = {
|
static struct resclass mb_class = {
|
||||||
"Memory",
|
"Memory",
|
||||||
0,
|
0,
|
||||||
mbl_free,
|
mbl_free,
|
||||||
mbl_debug,
|
mbl_debug,
|
||||||
mbl_lookup
|
mbl_lookup,
|
||||||
|
mbl_memsize
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,8 +26,12 @@ struct resclass {
|
||||||
void (*free)(resource *); /* Freeing function */
|
void (*free)(resource *); /* Freeing function */
|
||||||
void (*dump)(resource *); /* Dump to debug output */
|
void (*dump)(resource *); /* Dump to debug output */
|
||||||
resource *(*lookup)(resource *, unsigned long); /* Look up address (only for debugging) */
|
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 */
|
/* Generic resource manipulation */
|
||||||
|
|
||||||
typedef struct pool pool;
|
typedef struct pool pool;
|
||||||
|
@ -36,6 +40,7 @@ void resource_init(void);
|
||||||
pool *rp_new(pool *, char *); /* Create new pool */
|
pool *rp_new(pool *, char *); /* Create new pool */
|
||||||
void rfree(void *); /* Free single resource */
|
void rfree(void *); /* Free single resource */
|
||||||
void rdump(void *); /* Dump to debug output */
|
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 rlookup(unsigned long); /* Look up address (only for debugging) */
|
||||||
void rmove(void *, pool *); /* Move to a different pool */
|
void rmove(void *, pool *); /* Move to a different pool */
|
||||||
|
|
||||||
|
|
38
lib/slab.c
38
lib/slab.c
|
@ -41,6 +41,7 @@
|
||||||
static void slab_free(resource *r);
|
static void slab_free(resource *r);
|
||||||
static void slab_dump(resource *r);
|
static void slab_dump(resource *r);
|
||||||
static resource *slab_lookup(resource *r, unsigned long addr);
|
static resource *slab_lookup(resource *r, unsigned long addr);
|
||||||
|
static size_t slab_memsize(resource *r);
|
||||||
|
|
||||||
#ifdef FAKE_SLAB
|
#ifdef FAKE_SLAB
|
||||||
|
|
||||||
|
@ -58,7 +59,8 @@ static struct resclass sl_class = {
|
||||||
"FakeSlab",
|
"FakeSlab",
|
||||||
sizeof(struct slab),
|
sizeof(struct slab),
|
||||||
slab_free,
|
slab_free,
|
||||||
slab_dump
|
slab_dump,
|
||||||
|
slab_memsize
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sl_obj {
|
struct sl_obj {
|
||||||
|
@ -116,6 +118,20 @@ slab_dump(resource *r)
|
||||||
debug("(%d objects per %d bytes)\n", cnt, s->size);
|
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
|
#else
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -136,7 +152,8 @@ static struct resclass sl_class = {
|
||||||
sizeof(struct slab),
|
sizeof(struct slab),
|
||||||
slab_free,
|
slab_free,
|
||||||
slab_dump,
|
slab_dump,
|
||||||
slab_lookup
|
slab_lookup,
|
||||||
|
slab_memsize
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sl_head {
|
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);
|
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 *
|
static resource *
|
||||||
slab_lookup(resource *r, unsigned long a)
|
slab_lookup(resource *r, unsigned long a)
|
||||||
{
|
{
|
||||||
|
|
30
nest/cmds.c
30
nest/cmds.c
|
@ -11,6 +11,7 @@
|
||||||
#include "conf/conf.h"
|
#include "conf/conf.h"
|
||||||
#include "nest/cmds.h"
|
#include "nest/cmds.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
#include "lib/resource.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
cmd_show_status(void)
|
cmd_show_status(void)
|
||||||
|
@ -47,3 +48,32 @@ cmd_show_symbols(struct symbol *sym)
|
||||||
cli_msg(0, "");
|
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_status(void);
|
||||||
void cmd_show_symbols(struct symbol *sym);
|
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(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
|
||||||
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE)
|
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE)
|
||||||
CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION)
|
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,
|
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
|
||||||
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE)
|
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]])
|
CF_CLI(SHOW STATUS,,, [[Show router status]])
|
||||||
{ cmd_show_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]])
|
CF_CLI(SHOW PROTOCOLS, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocols]])
|
||||||
{ proto_apply_cmd($3, proto_cmd_show, 0, 0); } ;
|
{ proto_apply_cmd($3, proto_cmd_show, 0, 0); } ;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "nest/cli.h"
|
#include "nest/cli.h"
|
||||||
#include "filter/filter.h"
|
#include "filter/filter.h"
|
||||||
|
|
||||||
static pool *proto_pool;
|
pool *proto_pool;
|
||||||
|
|
||||||
static list protocol_list;
|
static list protocol_list;
|
||||||
static list proto_list;
|
static list proto_list;
|
||||||
|
|
|
@ -54,8 +54,9 @@
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
|
||||||
|
pool *rta_pool;
|
||||||
|
|
||||||
static slab *rta_slab;
|
static slab *rta_slab;
|
||||||
static pool *rta_pool;
|
|
||||||
|
|
||||||
struct protocol *attr_class_to_protocol[EAP_MAX];
|
struct protocol *attr_class_to_protocol[EAP_MAX];
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,11 @@
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
#include "lib/alloca.h"
|
#include "lib/alloca.h"
|
||||||
|
|
||||||
|
pool *rt_table_pool;
|
||||||
|
|
||||||
static slab *rte_slab;
|
static slab *rte_slab;
|
||||||
static linpool *rte_update_pool;
|
static linpool *rte_update_pool;
|
||||||
|
|
||||||
static pool *rt_table_pool;
|
|
||||||
static list routing_tables;
|
static list routing_tables;
|
||||||
|
|
||||||
static void rt_format_via(rte *e, byte *via);
|
static void rt_format_via(rte *e, byte *via);
|
||||||
|
|
|
@ -76,6 +76,7 @@ static struct resclass rf_class = {
|
||||||
sizeof(struct rfile),
|
sizeof(struct rfile),
|
||||||
rf_free,
|
rf_free,
|
||||||
rf_dump,
|
rf_dump,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -203,6 +204,7 @@ static struct resclass tm_class = {
|
||||||
sizeof(timer),
|
sizeof(timer),
|
||||||
tm_free,
|
tm_free,
|
||||||
tm_dump,
|
tm_dump,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -573,6 +575,7 @@ static struct resclass sk_class = {
|
||||||
sizeof(sock),
|
sizeof(sock),
|
||||||
sk_free,
|
sk_free,
|
||||||
sk_dump,
|
sk_dump,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue