mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Merge commit 'd85fa48e' into thread-next
The resource dumping routines needed to be updated in v3 to use the new API introduced in v2. Conflicts: filter/f-util.c filter/filter.c lib/birdlib.h lib/event.c lib/mempool.c lib/resource.c lib/resource.h lib/slab.c lib/timer.c nest/config.Y nest/iface.c nest/iface.h nest/locks.c nest/neighbor.c nest/proto.c nest/route.h nest/rt-attr.c nest/rt-table.c proto/bfd/bfd.c proto/bmp/bmp.c sysdep/unix/io.c sysdep/unix/krt.c sysdep/unix/main.c sysdep/unix/unix.h
This commit is contained in:
commit
731593685b
@ -1507,8 +1507,12 @@ This argument can be omitted if there exists only a single instance.
|
||||
<tag><label id="cli-debug">debug <m/protocol/|<m/pattern/|all all|off|{ states|routes|filters|events|packets [, <m/.../] }</tag>
|
||||
Control protocol debugging.
|
||||
|
||||
<tag><label id="cli-dump">dump resources|sockets|interfaces|neighbors|attributes|routes|protocols</tag>
|
||||
Dump contents of internal data structures to the debugging output.
|
||||
<tag><label id="cli-dump">dump resources|sockets|interfaces|neighbors|attributes|routes|protocols "<m/file/"</tag>
|
||||
Truncates the given file and dumps contents of internal data structures
|
||||
there. By sending SIGUSR1, you get all of these concatenated to
|
||||
<cf/bird.dump/ in the current directory. The file is only readable for
|
||||
the user running the daemon. The format of dump files is internal and
|
||||
could change in the future.
|
||||
|
||||
<tag><label id="cli-echo">echo all|off|{ <m/list of log classes/ } [ <m/buffer-size/ ]</tag>
|
||||
Control echoing of log messages to the command-line output.
|
||||
|
@ -73,6 +73,7 @@ Reply codes of BIRD command-line interface
|
||||
8006 Reload failed
|
||||
8007 Access denied
|
||||
8008 Evaluation runtime error
|
||||
8009 Failed to open file
|
||||
|
||||
9000 Command too long
|
||||
9001 Parse error
|
||||
|
@ -97,7 +97,7 @@ if ($3) return 0;
|
||||
]])
|
||||
m4_ifelse($4,,,[[
|
||||
FID_DUMP_BODY()m4_dnl
|
||||
debug("%s" $4 "\n", INDENT, $5);
|
||||
RDUMP("%s" $4 "\n", INDENT, $5);
|
||||
]])
|
||||
FID_INTERPRET_EXEC()m4_dnl
|
||||
$1 $2 = whati->$2
|
||||
@ -168,7 +168,7 @@ FID_LINEARIZE_BODY()m4_dnl
|
||||
pos = linearize(dest, whati->fvar, pos);
|
||||
item->varcount = whati->varcount;
|
||||
FID_DUMP_BODY()m4_dnl
|
||||
debug("%snumber of varargs %u\n", INDENT, item->varcount);
|
||||
RDUMP("%snumber of varargs %u\n", INDENT, item->varcount);
|
||||
FID_SAME_BODY()m4_dnl
|
||||
if (f1->varcount != f2->varcount) return 0;
|
||||
FID_INTERPRET_BODY()
|
||||
@ -241,7 +241,7 @@ FID_NEW_METHOD()m4_dnl
|
||||
args = NULL; /* The rest is the line itself */
|
||||
FID_METHOD_CALL() , arg$1
|
||||
FID_DUMP_BODY()m4_dnl
|
||||
f_dump_line(item->fl$1, indent + 1);
|
||||
f_dump_line(dreq, item->fl$1, indent + 1);
|
||||
FID_LINEARIZE_BODY()m4_dnl
|
||||
item->fl$1 = f_linearize(whati->f$1, $2);
|
||||
FID_SAME_BODY()m4_dnl
|
||||
@ -434,13 +434,13 @@ m4_undivert(113)
|
||||
|
||||
]])m4_dnl
|
||||
|
||||
FID_DUMP_CALLER()m4_dnl Case in another big switch used in instruction dumping (debug)
|
||||
case INST_NAME(): f_dump_line_item_]]INST_NAME()[[(item, indent + 1); break;
|
||||
FID_DUMP_CALLER()m4_dnl Case in another big switch used in instruction dumping
|
||||
case INST_NAME(): f_dump_line_item_]]INST_NAME()[[(dreq, item, indent + 1); break;
|
||||
|
||||
FID_DUMP()m4_dnl The dumper itself
|
||||
m4_ifdef([[FID_DUMP_BODY_EXISTS]],
|
||||
[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item_, const int indent)]],
|
||||
[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item UNUSED, const int indent UNUSED)]])
|
||||
[[static inline void f_dump_line_item_]]INST_NAME()[[(struct dump_request *dreq, const struct f_line_item *item_, const int indent)]],
|
||||
[[static inline void f_dump_line_item_]]INST_NAME()[[(struct dump_request *dreq UNUSED, const struct f_line_item *item UNUSED, const int indent UNUSED)]])
|
||||
m4_undefine([[FID_DUMP_BODY_EXISTS]])
|
||||
{
|
||||
#define item (&(item_->i_]]INST_NAME()[[))
|
||||
@ -681,22 +681,22 @@ static const char f_dump_line_indent_str[] = " ";
|
||||
|
||||
FID_WR_PUT(6)
|
||||
|
||||
void f_dump_line(const struct f_line *dest, uint indent)
|
||||
void f_dump_line(struct dump_request *dreq, const struct f_line *dest, uint indent)
|
||||
{
|
||||
if (!dest) {
|
||||
debug("%sNo filter line (NULL)\n", INDENT);
|
||||
RDUMP("%sNo filter line (NULL)\n", INDENT);
|
||||
return;
|
||||
}
|
||||
debug("%sFilter line %p (len=%u)\n", INDENT, dest, dest->len);
|
||||
RDUMP("%sFilter line %p (len=%u)\n", INDENT, dest, dest->len);
|
||||
for (uint i=0; i<dest->len; i++) {
|
||||
const struct f_line_item *item = &dest->items[i];
|
||||
debug("%sInstruction %s at line %u\n", INDENT, f_instruction_name_(item->fi_code), item->lineno);
|
||||
RDUMP("%sInstruction %s at line %u\n", INDENT, f_instruction_name_(item->fi_code), item->lineno);
|
||||
switch (item->fi_code) {
|
||||
FID_WR_PUT(7)
|
||||
default: bug("Unknown instruction %x in f_dump_line", item->fi_code);
|
||||
}
|
||||
}
|
||||
debug("%sFilter line %p dump done\n", INDENT, dest);
|
||||
RDUMP("%sFilter line %p dump done\n", INDENT, dest);
|
||||
}
|
||||
|
||||
/* Linearize */
|
||||
@ -726,10 +726,6 @@ f_linearize_concat(const struct f_inst * const inst[], uint count, uint results)
|
||||
out->len = linearize(out, inst[i], out->len);
|
||||
|
||||
out->results = results;
|
||||
|
||||
#ifdef LOCAL_DEBUG
|
||||
f_dump_line(out, 0);
|
||||
#endif
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -181,11 +181,11 @@
|
||||
* m4_dnl This structure is returned from the linearizer (105).
|
||||
* m4_dnl For writing directly to this structure, use FID_LINE_IN.
|
||||
*
|
||||
* m4_dnl f_dump_line_item_FI_EXAMPLE(const struct f_line_item *item, const int indent)
|
||||
* m4_dnl f_dump_line_item_FI_EXAMPLE(struct dump_request *dreq, const struct f_line_item *item, const int indent)
|
||||
* m4_dnl {
|
||||
* m4_dnl (104) [[ put it here ]]
|
||||
* m4_dnl }
|
||||
* m4_dnl This code dumps the instruction on debug. Note that the argument
|
||||
* m4_dnl This code dumps the instruction via RDUMP. Note that the argument
|
||||
* m4_dnl is the linearized instruction; if the instruction has arguments,
|
||||
* m4_dnl their code has already been linearized and their value is taken
|
||||
* m4_dnl from the value stack.
|
||||
|
@ -68,7 +68,7 @@ struct f_line *f_linearize_concat(const struct f_inst * const inst[], uint count
|
||||
static inline struct f_line *f_linearize(const struct f_inst *root, uint results)
|
||||
{ return f_linearize_concat(&root, 1, results); }
|
||||
|
||||
void f_dump_line(const struct f_line *, uint indent);
|
||||
void f_dump_line(struct dump_request *, const struct f_line *, uint indent);
|
||||
|
||||
|
||||
/* Recursive iteration over filter instructions */
|
||||
|
@ -144,11 +144,6 @@ interpret(struct filter_state *fs, const struct f_line *line, uint argc, const s
|
||||
#define curline fstk->estk[fstk->ecnt-1]
|
||||
#define prevline fstk->estk[fstk->ecnt-2]
|
||||
|
||||
#ifdef LOCAL_DEBUG
|
||||
debug("Interpreting line.");
|
||||
f_dump_line(line, 1);
|
||||
#endif
|
||||
|
||||
while (fstk->ecnt > 0) {
|
||||
while (curline.pos < curline.line->len) {
|
||||
const struct f_line_item *what = &(curline.line->items[curline.pos++]);
|
||||
@ -393,46 +388,46 @@ filter_commit(struct config *new, struct config *old)
|
||||
}
|
||||
}
|
||||
|
||||
void channel_filter_dump(const struct filter *f)
|
||||
void channel_filter_dump(struct dump_request *dreq, const struct filter *f)
|
||||
{
|
||||
if (f == FILTER_ACCEPT)
|
||||
debug(" ALL");
|
||||
RDUMP(" ALL");
|
||||
else if (f == FILTER_REJECT)
|
||||
debug(" NONE");
|
||||
RDUMP(" NONE");
|
||||
else if (f == FILTER_UNDEF)
|
||||
debug(" UNDEF");
|
||||
RDUMP(" UNDEF");
|
||||
else if (f->sym) {
|
||||
ASSERT(f->sym->filter == f);
|
||||
debug(" named filter %s", f->sym->name);
|
||||
RDUMP(" named filter %s", f->sym->name);
|
||||
} else {
|
||||
debug("\n");
|
||||
f_dump_line(f->root, 2);
|
||||
RDUMP("\n");
|
||||
f_dump_line(dreq, f->root, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void filters_dump_all(void)
|
||||
void filters_dump_all(struct dump_request *dreq)
|
||||
{
|
||||
struct symbol *sym;
|
||||
WALK_LIST(sym, OBSREF_GET(config)->symbols) {
|
||||
switch (sym->class) {
|
||||
case SYM_FILTER:
|
||||
debug("Named filter %s:\n", sym->name);
|
||||
f_dump_line(sym->filter->root, 1);
|
||||
RDUMP("Named filter %s:\n", sym->name);
|
||||
f_dump_line(dreq, sym->filter->root, 1);
|
||||
break;
|
||||
case SYM_FUNCTION:
|
||||
debug("Function %s:\n", sym->name);
|
||||
f_dump_line(sym->function, 1);
|
||||
RDUMP("Function %s:\n", sym->name);
|
||||
f_dump_line(dreq, sym->function, 1);
|
||||
break;
|
||||
case SYM_PROTO:
|
||||
{
|
||||
debug("Protocol %s:\n", sym->name);
|
||||
RDUMP("Protocol %s:\n", sym->name);
|
||||
struct channel *c;
|
||||
WALK_LIST(c, sym->proto->proto->channels) {
|
||||
debug(" Channel %s (%s) IMPORT", c->name, net_label[c->net_type]);
|
||||
channel_filter_dump(c->in_filter);
|
||||
debug(" EXPORT", c->name, net_label[c->net_type]);
|
||||
channel_filter_dump(c->out_filter);
|
||||
debug("\n");
|
||||
RDUMP(" Channel %s (%s) IMPORT", c->name, net_label[c->net_type]);
|
||||
channel_filter_dump(dreq, c->in_filter);
|
||||
RDUMP(" EXPORT", c->name, net_label[c->net_type]);
|
||||
channel_filter_dump(dreq, c->out_filter);
|
||||
RDUMP("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ int f_same(const struct f_line *f1, const struct f_line *f2);
|
||||
void filter_preconfig(struct config *new);
|
||||
void filter_commit(struct config *new, struct config *old);
|
||||
|
||||
void filters_dump_all(void);
|
||||
void filters_dump_all(struct dump_request *);
|
||||
|
||||
#define FILTER_ACCEPT NULL
|
||||
#define FILTER_REJECT ((struct filter *) 1)
|
||||
|
@ -310,4 +310,15 @@ static inline u32 u64_hash(u64 v)
|
||||
void birdloop_yield(void);
|
||||
|
||||
|
||||
/* Dumping */
|
||||
struct dump_request {
|
||||
u64 size;
|
||||
btime begin;
|
||||
uint indent, offset;
|
||||
void (*write)(struct dump_request *, const char *fmt, ...);
|
||||
void (*report)(struct dump_request *, int state, const char *fmt, ...);
|
||||
};
|
||||
|
||||
#define RDUMP(...) dreq->write(dreq, __VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
@ -173,11 +173,11 @@ ev_postpone(event *e)
|
||||
}
|
||||
|
||||
static void
|
||||
ev_dump(resource *r, unsigned indent UNUSED)
|
||||
ev_dump(struct dump_request *dreq, resource *r)
|
||||
{
|
||||
event *e = (event *) r;
|
||||
|
||||
debug("(code %p, data %p, %s)\n",
|
||||
RDUMP("(code %p, data %p, %s)\n",
|
||||
e->hook,
|
||||
e->data,
|
||||
atomic_load_explicit(&e->next, memory_order_relaxed) ? "scheduled" : "inactive");
|
||||
|
@ -46,7 +46,7 @@ struct linpool {
|
||||
|
||||
static void *lp_alloc_slow(struct linpool *, uint);
|
||||
static void lp_free(resource *);
|
||||
static void lp_dump(resource *, unsigned);
|
||||
static void lp_dump(struct dump_request *, resource *);
|
||||
static resource *lp_lookup(resource *, unsigned long);
|
||||
static struct resmem lp_memsize(resource *r);
|
||||
|
||||
@ -278,30 +278,27 @@ lp_free(resource *r)
|
||||
}
|
||||
|
||||
static void
|
||||
lp_dump(resource *r, unsigned indent)
|
||||
lp_dump(struct dump_request *dreq, resource *r)
|
||||
{
|
||||
linpool *m = (linpool *) r;
|
||||
struct lp_chunk *c;
|
||||
int cnt, cntl;
|
||||
char x[32];
|
||||
|
||||
for(cnt=0, c=m->first; c; c=c->next, cnt++)
|
||||
;
|
||||
for(cntl=0, c=m->first_large; c; c=c->next, cntl++)
|
||||
;
|
||||
debug("(count=%d+%d total=%d+%d)\n",
|
||||
cnt,
|
||||
cntl,
|
||||
m->total,
|
||||
m->total_large);
|
||||
int chunks = 0, large = 0;
|
||||
|
||||
bsprintf(x, "%%%dschunk %%p\n", indent + 2);
|
||||
for (c=m->first; c; c=c->next)
|
||||
debug(x, "", c);
|
||||
RDUMP("\n%*schunks:\n", dreq->indent+3, "");
|
||||
for (struct lp_chunk *c = m->first; c; c = c->next)
|
||||
{
|
||||
RDUMP("%*s%p\n", dreq->indent+6, "", c);
|
||||
chunks++;
|
||||
}
|
||||
RDUMP("%*scount=%d total=%d\n", dreq->indent+3, "", chunks, m->total);
|
||||
|
||||
bsprintf(x, "%%%dslarge %%p\n", indent + 2);
|
||||
for (c=m->first_large; c; c=c->next)
|
||||
debug(x, "", c);
|
||||
RDUMP("%*slarge:\n", dreq->indent+3, "");
|
||||
for (struct lp_chunk *c = m->first_large; c; c = c->next)
|
||||
{
|
||||
RDUMP("%*s%p\n", dreq->indent+6, "", c);
|
||||
large++;
|
||||
}
|
||||
RDUMP("%*scount=%d total=%d\n", dreq->indent+3, "", large, m->total_large);
|
||||
}
|
||||
|
||||
static struct resmem
|
||||
|
@ -30,7 +30,7 @@
|
||||
* is freed upon shutdown of the module.
|
||||
*/
|
||||
|
||||
static void pool_dump(resource *, unsigned);
|
||||
static void pool_dump(struct dump_request *, resource *);
|
||||
static void pool_free(resource *);
|
||||
static resource *pool_lookup(resource *, unsigned long);
|
||||
static struct resmem pool_memsize(resource *P);
|
||||
@ -135,17 +135,18 @@ pool_free(resource *P)
|
||||
POOL_UNLOCK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pool_dump(resource *P, unsigned indent)
|
||||
pool_dump(struct dump_request *dreq, resource *P)
|
||||
{
|
||||
pool *p = (pool *) P;
|
||||
|
||||
POOL_LOCK;
|
||||
|
||||
debug("%s\n", p->name);
|
||||
RDUMP("%s\n", p->name);
|
||||
dreq->indent += 3;
|
||||
WALK_TLIST_DELSAFE(resource, r, &p->inside)
|
||||
rdump(r, indent + 3);
|
||||
rdump(dreq, r);
|
||||
dreq->indent -= 3;
|
||||
|
||||
POOL_UNLOCK;
|
||||
}
|
||||
@ -246,20 +247,28 @@ rfree(void *res)
|
||||
* It works by calling a class-specific dump function.
|
||||
*/
|
||||
void
|
||||
rdump(void *res, unsigned indent)
|
||||
rdump(struct dump_request *dreq, void *res)
|
||||
{
|
||||
char x[16];
|
||||
resource *r = res;
|
||||
|
||||
bsprintf(x, "%%%ds%%p ", indent);
|
||||
debug(x, "", r);
|
||||
bsprintf(x, "%%%ds%%p ", dreq->indent);
|
||||
RDUMP(x, "", r);
|
||||
if (r)
|
||||
{
|
||||
debug("%s ", r->class->name);
|
||||
r->class->dump(r, indent);
|
||||
RDUMP("%s ", r->class->name);
|
||||
r->class->dump(dreq, r);
|
||||
}
|
||||
else
|
||||
debug("NULL\n");
|
||||
RDUMP("NULL\n");
|
||||
}
|
||||
|
||||
void page_dump(struct dump_request *req);
|
||||
|
||||
void resource_dump(struct dump_request *req)
|
||||
{
|
||||
rdump(req, &root_pool);
|
||||
page_dump(req);
|
||||
}
|
||||
|
||||
struct resmem
|
||||
@ -300,6 +309,7 @@ ralloc(pool *p, struct resclass *c)
|
||||
return r;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* rlookup - look up a memory location
|
||||
* @a: memory address
|
||||
@ -322,6 +332,7 @@ rlookup(unsigned long a)
|
||||
else
|
||||
debug("Not found.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* resource_init - initialize the resource manager
|
||||
@ -384,11 +395,11 @@ static void mbl_free(resource *r UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
static void mbl_debug(resource *r, unsigned indent UNUSED)
|
||||
static void mbl_debug(struct dump_request *dreq, resource *r)
|
||||
{
|
||||
struct mblock *m = (struct mblock *) r;
|
||||
|
||||
debug("(size=%d)\n", m->size);
|
||||
RDUMP("(size=%d)\n", m->size);
|
||||
}
|
||||
|
||||
static resource *
|
||||
|
@ -42,7 +42,7 @@ struct resclass {
|
||||
char *name; /* Resource class name */
|
||||
unsigned size; /* Standard size of single resource */
|
||||
void (*free)(resource *); /* Freeing function */
|
||||
void (*dump)(resource *, unsigned indent); /* Dump to debug output */
|
||||
void (*dump)(struct dump_request *, resource *); /* Dump to debug output */
|
||||
resource *(*lookup)(resource *, unsigned long); /* Look up address (only for debugging) */
|
||||
struct resmem (*memsize)(resource *); /* Return size of memory used by the resource, may be NULL */
|
||||
};
|
||||
@ -62,7 +62,10 @@ typedef struct pool {
|
||||
|
||||
void resource_init(void);
|
||||
void rfree(void *); /* Free single resource */
|
||||
void rdump(void *, unsigned indent); /* Dump to debug output */
|
||||
|
||||
struct dump_request;
|
||||
void rdump(struct dump_request *, void *); /* Dump to debug output */
|
||||
void resource_dump(struct dump_request *); /* Dump the root pool */
|
||||
struct resmem 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 */
|
||||
|
@ -134,7 +134,7 @@ static inline void rt_unlock_source(struct rte_src *src)
|
||||
void rt_init_sources(struct rte_owner *, const char *name, event_list *list);
|
||||
void rt_destroy_sources(struct rte_owner *, event *);
|
||||
|
||||
void rt_dump_sources(struct rte_owner *);
|
||||
void rt_dump_sources(struct dump_request *, struct rte_owner *);
|
||||
|
||||
/*
|
||||
* Route Attributes
|
||||
@ -350,7 +350,6 @@ static inline eattr *ea_find_by_name(ea_list *l, const char *name)
|
||||
})
|
||||
|
||||
eattr *ea_walk(struct ea_walk_state *s, uint id, uint max);
|
||||
void ea_dump(ea_list *);
|
||||
int ea_same(ea_list *x, ea_list *y); /* Test whether two ea_lists are identical */
|
||||
uint ea_hash(ea_list *e); /* Calculate attributes hash value */
|
||||
ea_list *ea_append(ea_list *to, ea_list *what);
|
||||
@ -639,8 +638,8 @@ static inline ea_list *ea_strip_to(ea_list *r, u32 strip_to)
|
||||
return r;
|
||||
}
|
||||
|
||||
void ea_dump(ea_list *);
|
||||
void ea_dump_all(void);
|
||||
void ea_dump(struct dump_request *, ea_list *);
|
||||
void ea_dump_all(struct dump_request *);
|
||||
void ea_show_list(struct cli *, ea_list *);
|
||||
|
||||
#endif
|
||||
|
43
lib/slab.c
43
lib/slab.c
@ -41,7 +41,7 @@
|
||||
#endif
|
||||
|
||||
static void slab_free(resource *r);
|
||||
static void slab_dump(resource *r, unsigned indent);
|
||||
static void slab_dump(struct dump_request *dreq, resource *r);
|
||||
static resource *slab_lookup(resource *r, unsigned long addr);
|
||||
static struct resmem slab_memsize(resource *r);
|
||||
|
||||
@ -393,27 +393,38 @@ slab_free(resource *r)
|
||||
}
|
||||
|
||||
static void
|
||||
slab_dump(resource *r, unsigned indent UNUSED)
|
||||
slab_dump(struct dump_request *dreq, resource *r)
|
||||
{
|
||||
slab *s = (slab *) r;
|
||||
int ec=0, pc=0, fc=0;
|
||||
|
||||
WALK_TLIST(sl_head, h, &s->empty_heads)
|
||||
ec++;
|
||||
WALK_TLIST(sl_head, h, &s->partial_heads)
|
||||
pc++;
|
||||
WALK_TLIST(sl_head, h, &s->full_heads)
|
||||
fc++;
|
||||
debug("(%de+%dp+%df blocks per %d objs per %d bytes)\n", ec, pc, fc, s->objs_per_slab, s->obj_size);
|
||||
RDUMP("(%d objs per %d bytes in page)\n",
|
||||
s->objs_per_slab, s->obj_size);
|
||||
|
||||
char x[16];
|
||||
bsprintf(x, "%%%ds%%s %%p\n", indent + 2);
|
||||
WALK_TLIST(sl_head, h, &s->full_heads)
|
||||
debug(x, "", "full", h);
|
||||
WALK_TLIST(sl_head, h, &s->partial_heads)
|
||||
debug(x, "", "partial", h);
|
||||
RDUMP("%*sempty:\n", dreq->indent+3, "");
|
||||
WALK_TLIST(sl_head, h, &s->empty_heads)
|
||||
debug(x, "", "empty", h);
|
||||
{
|
||||
RDUMP("%*s%p\n", dreq->indent+6, "", h);
|
||||
ec++;
|
||||
}
|
||||
|
||||
RDUMP("%*spartial:\n", dreq->indent+3, "");
|
||||
WALK_TLIST(sl_head, h, &s->partial_heads)
|
||||
{
|
||||
RDUMP("%*s%p (", dreq->indent+6, "", h);
|
||||
for (uint i=1; i<=s->head_bitfield_len; i++)
|
||||
RDUMP("%08x", h->used_bits[s->head_bitfield_len-i]);
|
||||
RDUMP(")\n");
|
||||
pc++;
|
||||
}
|
||||
|
||||
RDUMP("%*sfull:\n", dreq->indent+3, "");
|
||||
WALK_TLIST(sl_head, h, &s->full_heads)
|
||||
{
|
||||
RDUMP("%*s%p\n", dreq->indent+6, "", h);
|
||||
fc++;
|
||||
}
|
||||
RDUMP("%*sempty=%d partial=%d total=%d\n", dreq->indent+3, "", ec, pc, fc);
|
||||
}
|
||||
|
||||
static struct resmem
|
||||
|
@ -100,7 +100,7 @@ void sk_resume_rx(struct birdloop *loop, sock *s, int (*hook)(sock *, uint));
|
||||
void sk_set_rbsize(sock *s, uint val); /* Resize RX buffer */
|
||||
void sk_set_tbsize(sock *s, uint val); /* Resize TX buffer, keeping content */
|
||||
void sk_set_tbuf(sock *s, void *tbuf); /* Switch TX buffer, NULL-> return to internal */
|
||||
void sk_dump_all(void);
|
||||
void sk_dump_all(struct dump_request *);
|
||||
|
||||
int sk_is_ipv4(sock *s); /* True if socket is IPv4 */
|
||||
int sk_is_ipv6(sock *s); /* True if socket is IPv6 */
|
||||
|
12
lib/timer.c
12
lib/timer.c
@ -60,19 +60,19 @@ tm_free(resource *r)
|
||||
}
|
||||
|
||||
static void
|
||||
tm_dump(resource *r, unsigned indent UNUSED)
|
||||
tm_dump(struct dump_request *dreq, resource *r)
|
||||
{
|
||||
timer *t = (void *) r;
|
||||
|
||||
debug("(code %p, data %p, ", t->hook, t->data);
|
||||
RDUMP("(code %p, data %p, ", t->hook, t->data);
|
||||
if (t->randomize)
|
||||
debug("rand %d, ", t->randomize);
|
||||
RDUMP("rand %d, ", t->randomize);
|
||||
if (t->recurrent)
|
||||
debug("recur %ld, ", t->recurrent);
|
||||
RDUMP("recur %ld, ", t->recurrent);
|
||||
if (t->expires)
|
||||
debug("in loop %p expires in %ld ms)\n", t->loop, (t->expires - current_time()) TO_MS);
|
||||
RDUMP("in loop %p expires in %ld ms)\n", t->loop, (t->expires - current_time()) TO_MS);
|
||||
else
|
||||
debug("inactive)\n");
|
||||
RDUMP("inactive)\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -932,28 +932,27 @@ sym_args:
|
||||
| sym_args CF_SYM_KNOWN { $$ = $1; $$->sym = $2; }
|
||||
;
|
||||
|
||||
|
||||
CF_CLI_HELP(DUMP, ..., [[Dump debugging information]])
|
||||
CF_CLI(DUMP RESOURCES,,, [[Dump all allocated resource]])
|
||||
{ rdump(&root_pool, 0); cli_msg(0, ""); } ;
|
||||
CF_CLI(DUMP SOCKETS,,, [[Dump open sockets]])
|
||||
{ sk_dump_all(); cli_msg(0, ""); } ;
|
||||
CF_CLI(DUMP EVENTS,,, [[Dump event log]])
|
||||
{ io_log_dump(); cli_msg(0, ""); } ;
|
||||
CF_CLI(DUMP INTERFACES,,, [[Dump interface information]])
|
||||
{ if_dump_all(); cli_msg(0, ""); } ;
|
||||
CF_CLI(DUMP NEIGHBORS,,, [[Dump neighbor cache]])
|
||||
{ neigh_dump_all(); cli_msg(0, ""); } ;
|
||||
CF_CLI(DUMP ATTRIBUTES,,, [[Dump attribute cache]])
|
||||
{ ea_dump_all(); cli_msg(0, ""); } ;
|
||||
CF_CLI(DUMP ROUTES,,, [[Dump routes]])
|
||||
{ rt_dump_all(); cli_msg(0, ""); } ;
|
||||
CF_CLI(DUMP TABLES,,, [[Dump table connections]])
|
||||
{ rt_dump_hooks_all(); cli_msg(0, ""); } ;
|
||||
CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
|
||||
{ protos_dump_all(); cli_msg(0, ""); } ;
|
||||
CF_CLI(DUMP FILTER ALL,,, [[Dump all filters in linearized form]])
|
||||
{ filters_dump_all(); cli_msg(0, ""); } ;
|
||||
CF_CLI_HELP(DUMP, ..., [[Dump debugging information to the given file]])
|
||||
CF_CLI(DUMP RESOURCES, text,, [[Dump all allocated resource]])
|
||||
{ cmd_dump_file(this_cli, $3, "resources", resource_dump); } ;
|
||||
CF_CLI(DUMP SOCKETS, text,, [[Dump open sockets]])
|
||||
{ cmd_dump_file(this_cli, $3, "sockets", sk_dump_all); } ;
|
||||
CF_CLI(DUMP EVENTS, text,, [[Dump event log]])
|
||||
{ cmd_dump_file(this_cli, $3, "event log", io_log_dump); } ;
|
||||
CF_CLI(DUMP INTERFACES, text,, [[Dump interface information]])
|
||||
{ cmd_dump_file(this_cli, $3, "interfaces", if_dump_all); } ;
|
||||
CF_CLI(DUMP NEIGHBORS, text,, [[Dump neighbor cache]])
|
||||
{ cmd_dump_file(this_cli, $3, "neighbor cache", neigh_dump_all); } ;
|
||||
CF_CLI(DUMP ATTRIBUTES, text,, [[Dump attribute cache]])
|
||||
{ cmd_dump_file(this_cli, $3, "attribute cache", ea_dump_all); } ;
|
||||
CF_CLI(DUMP ROUTES, text,, [[Dump routes]])
|
||||
{ cmd_dump_file(this_cli, $3, "routing tables", rt_dump_all); } ;
|
||||
CF_CLI(DUMP TABLES, text,, [[Dump table connections]])
|
||||
{ cmd_dump_file(this_cli, $3, "table connections", rt_dump_hooks_all); } ;
|
||||
CF_CLI(DUMP PROTOCOLS, text,, [[Dump protocol information]])
|
||||
{ cmd_dump_file(this_cli, $3, "protocols", protos_dump_all); } ;
|
||||
CF_CLI(DUMP FILTER ALL, text,, [[Dump all filters in linearized form]])
|
||||
{ cmd_dump_file(this_cli, $4, "filter bytecode", filters_dump_all); } ;
|
||||
|
||||
CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
|
||||
{ cmd_eval(f_linearize($2, 1)); } ;
|
||||
|
52
nest/iface.c
52
nest/iface.c
@ -52,8 +52,8 @@ static void if_recalc_preferred(struct iface *i);
|
||||
|
||||
static void ifa_delete_locked(struct ifa *a);
|
||||
|
||||
static void ifa_dump_locked(struct ifa *);
|
||||
static void if_dump_locked(struct iface *);
|
||||
static void ifa_dump_locked(struct dump_request *, struct ifa *);
|
||||
static void if_dump_locked(struct dump_request *, struct iface *);
|
||||
|
||||
struct iface *
|
||||
if_walk_first(void)
|
||||
@ -85,17 +85,17 @@ if_walk_done(void)
|
||||
* This function dumps contents of an &ifa to the debug output.
|
||||
*/
|
||||
void
|
||||
ifa_dump(struct ifa *a)
|
||||
ifa_dump(struct dump_request *dreq, struct ifa *a)
|
||||
{
|
||||
IFACE_LOCK;
|
||||
ifa_dump_locked(a);
|
||||
ifa_dump_locked(dreq, a);
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
|
||||
static void
|
||||
ifa_dump_locked(struct ifa *a)
|
||||
ifa_dump_locked(struct dump_request *dreq, struct ifa *a)
|
||||
{
|
||||
debug("\t%I, net %N bc %I -> %I%s%s%s%s\n", a->ip, &a->prefix, a->brd, a->opposite,
|
||||
RDUMP("\t%I, net %N bc %I -> %I%s%s%s%s\n", a->ip, &a->prefix, a->brd, a->opposite,
|
||||
(a->flags & IA_PRIMARY) ? " PRIMARY" : "",
|
||||
(a->flags & IA_SECONDARY) ? " SEC" : "",
|
||||
(a->flags & IA_HOST) ? " HOST" : "",
|
||||
@ -110,43 +110,43 @@ ifa_dump_locked(struct ifa *a)
|
||||
* network interface to the debug output.
|
||||
*/
|
||||
void
|
||||
if_dump(struct iface *i)
|
||||
if_dump(struct dump_request *dreq, struct iface *i)
|
||||
{
|
||||
IFACE_LOCK;
|
||||
if_dump_locked(i);
|
||||
if_dump_locked(dreq, i);
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
|
||||
static void
|
||||
if_dump_locked(struct iface *i)
|
||||
if_dump_locked(struct dump_request *dreq, struct iface *i)
|
||||
{
|
||||
struct ifa *a;
|
||||
|
||||
debug("IF%d: %s", i->index, i->name);
|
||||
RDUMP("IF%d: %s", i->index, i->name);
|
||||
if (i->flags & IF_SHUTDOWN)
|
||||
debug(" SHUTDOWN");
|
||||
RDUMP(" SHUTDOWN");
|
||||
if (i->flags & IF_UP)
|
||||
debug(" UP");
|
||||
RDUMP(" UP");
|
||||
else
|
||||
debug(" DOWN");
|
||||
RDUMP(" DOWN");
|
||||
if (i->flags & IF_ADMIN_UP)
|
||||
debug(" LINK-UP");
|
||||
RDUMP(" LINK-UP");
|
||||
if (i->flags & IF_MULTIACCESS)
|
||||
debug(" MA");
|
||||
RDUMP(" MA");
|
||||
if (i->flags & IF_BROADCAST)
|
||||
debug(" BC");
|
||||
RDUMP(" BC");
|
||||
if (i->flags & IF_MULTICAST)
|
||||
debug(" MC");
|
||||
RDUMP(" MC");
|
||||
if (i->flags & IF_LOOPBACK)
|
||||
debug(" LOOP");
|
||||
RDUMP(" LOOP");
|
||||
if (i->flags & IF_IGNORE)
|
||||
debug(" IGN");
|
||||
RDUMP(" IGN");
|
||||
if (i->flags & IF_TMP_DOWN)
|
||||
debug(" TDOWN");
|
||||
debug(" MTU=%d\n", i->mtu);
|
||||
RDUMP(" TDOWN");
|
||||
RDUMP(" MTU=%d\n", i->mtu);
|
||||
WALK_LIST(a, i->addrs)
|
||||
{
|
||||
ifa_dump_locked(a);
|
||||
ifa_dump_locked(dreq, a);
|
||||
ASSERT(!!(a->flags & IA_PRIMARY) ==
|
||||
((a == i->addr4) || (a == i->addr6) || (a == i->llv6)));
|
||||
}
|
||||
@ -159,13 +159,13 @@ if_dump_locked(struct iface *i)
|
||||
* interfaces to the debug output.
|
||||
*/
|
||||
void
|
||||
if_dump_all(void)
|
||||
if_dump_all(struct dump_request *dreq)
|
||||
{
|
||||
debug("Known network interfaces:\n");
|
||||
RDUMP("Known network interfaces:\n");
|
||||
IFACE_WALK(i)
|
||||
if_dump(i);
|
||||
if_dump_locked(dreq, i);
|
||||
rcu_read_lock();
|
||||
debug("Router ID: %08x\n", atomic_load_explicit(&global_runtime, memory_order_relaxed)->router_id);
|
||||
RDUMP("Router ID: %08x\n", atomic_load_explicit(&global_runtime, memory_order_relaxed)->router_id);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
@ -107,9 +107,9 @@ struct iface {
|
||||
#define IF_CHANGE_PREFERRED (IF_CHANGE_ADDR4 | IF_CHANGE_ADDR6 | IF_CHANGE_LLV6)
|
||||
|
||||
void if_init(void);
|
||||
void if_dump(struct iface *);
|
||||
void if_dump_all(void);
|
||||
void ifa_dump(struct ifa *);
|
||||
void if_dump(struct dump_request *dreq, struct iface *);
|
||||
void if_dump_all(struct dump_request *);
|
||||
void ifa_dump(struct dump_request *dreq, struct ifa *);
|
||||
void if_show(void);
|
||||
void if_show_summary(void);
|
||||
struct iface *if_update(struct iface *);
|
||||
@ -168,7 +168,7 @@ typedef struct neighbor {
|
||||
|
||||
neighbor *neigh_find(struct proto *p, ip_addr a, struct iface *ifa, uint flags);
|
||||
|
||||
void neigh_dump_all(void);
|
||||
void neigh_dump_all(struct dump_request *);
|
||||
void neigh_if_up(struct iface *);
|
||||
void neigh_if_down(struct iface *);
|
||||
void neigh_if_link(struct iface *);
|
||||
|
@ -107,14 +107,14 @@ olock_free(resource *r)
|
||||
}
|
||||
|
||||
static void
|
||||
olock_dump(resource *r, unsigned indent UNUSED)
|
||||
olock_dump(struct dump_request *dreq, resource *r)
|
||||
{
|
||||
struct object_lock *l = (struct object_lock *) r;
|
||||
static char *olock_states[] = { "free", "locked", "waiting", "event" };
|
||||
|
||||
debug("(%d:%s:%I:%I:%d:%d) [%s]\n", l->type, (l->iface ? l->iface->name : "?"), l->addr, l->addr_local, l->port, l->inst, olock_states[l->state]);
|
||||
RDUMP("(%d:%s:%I:%I:%d:%d) [%s]\n", l->type, (l->iface ? l->iface->name : "?"), l->addr, l->addr_local, l->port, l->inst, olock_states[l->state]);
|
||||
if (!EMPTY_LIST(l->waiters))
|
||||
debug(" [wanted]\n");
|
||||
RDUMP(" [wanted]\n");
|
||||
}
|
||||
|
||||
static struct resclass olock_class = {
|
||||
|
@ -302,17 +302,17 @@ bad:
|
||||
* This functions dumps the contents of a given neighbor entry to debug output.
|
||||
*/
|
||||
static void
|
||||
neigh_dump(neighbor *n)
|
||||
neigh_dump(struct dump_request *dreq, neighbor *n)
|
||||
{
|
||||
debug("%p %I %s %s ", n, n->addr,
|
||||
RDUMP("%p %I %s %s ", n, n->addr,
|
||||
n->iface ? n->iface->name : "[]",
|
||||
n->ifreq ? n->ifreq->name : "[]");
|
||||
debug("%s %p %08x scope %s", n->proto->name, n->data, n->aux, ip_scope_text(n->scope));
|
||||
RDUMP("%s %p %08x scope %s", n->proto->name, n->data, n->aux, ip_scope_text(n->scope));
|
||||
if (n->flags & NEF_STICKY)
|
||||
debug(" STICKY");
|
||||
RDUMP(" STICKY");
|
||||
if (n->flags & NEF_ONLINK)
|
||||
debug(" ONLINK");
|
||||
debug("\n");
|
||||
RDUMP(" ONLINK");
|
||||
RDUMP("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -321,18 +321,18 @@ neigh_dump(neighbor *n)
|
||||
* This function dumps the contents of the neighbor cache to debug output.
|
||||
*/
|
||||
void
|
||||
neigh_dump_all(void)
|
||||
neigh_dump_all(struct dump_request *dreq)
|
||||
{
|
||||
IFACE_LOCK;
|
||||
|
||||
neighbor *n;
|
||||
int i;
|
||||
|
||||
debug("Known neighbors:\n");
|
||||
RDUMP("Known neighbors:\n");
|
||||
for(i=0; i<NEIGH_HASH_SIZE; i++)
|
||||
WALK_LIST(n, neigh_hash_table[i])
|
||||
neigh_dump(n);
|
||||
debug("\n");
|
||||
neigh_dump(dreq, n);
|
||||
RDUMP("\n");
|
||||
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
|
21
nest/proto.c
21
nest/proto.c
@ -2053,14 +2053,14 @@ channel_graceful_restart_unlock(struct channel *c)
|
||||
* the internals.
|
||||
*/
|
||||
void
|
||||
protos_dump_all(void)
|
||||
protos_dump_all(struct dump_request *dreq)
|
||||
{
|
||||
debug("Protocols:\n");
|
||||
RDUMP("Protocols:\n");
|
||||
|
||||
WALK_TLIST(proto, p, &global_proto_list) PROTO_LOCKED_FROM_MAIN(p)
|
||||
{
|
||||
#define DPF(x) (p->x ? " " #x : "")
|
||||
debug(" protocol %s (%p) state %s with %d active channels flags: %s%s%s\n",
|
||||
RDUMP(" protocol %s (%p) state %s with %d active channels flags: %s%s%s\n",
|
||||
p->name, p, p_states[p->proto_state], p->active_channels,
|
||||
DPF(disabled), DPF(do_stop), DPF(reconfiguring));
|
||||
#undef DPF
|
||||
@ -2068,23 +2068,24 @@ protos_dump_all(void)
|
||||
struct channel *c;
|
||||
WALK_LIST(c, p->channels)
|
||||
{
|
||||
debug("\tTABLE %s\n", c->table->name);
|
||||
RDUMP("\tTABLE %s\n", c->table->name);
|
||||
if (c->in_filter)
|
||||
debug("\tInput filter: %s\n", filter_name(c->in_filter));
|
||||
RDUMP("\tInput filter: %s\n", filter_name(c->in_filter));
|
||||
if (c->out_filter)
|
||||
debug("\tOutput filter: %s\n", filter_name(c->out_filter));
|
||||
debug("\tChannel state: %s/%s/%s\n", c_states[c->channel_state],
|
||||
RDUMP("\tOutput filter: %s\n", filter_name(c->out_filter));
|
||||
RDUMP("\tChannel state: %s/%s/%s\n", c_states[c->channel_state],
|
||||
c->in_req.hook ? rt_import_state_name(rt_import_get_state(c->in_req.hook)) : "-",
|
||||
rt_export_state_name(rt_export_get_state(&c->out_req)));
|
||||
}
|
||||
|
||||
debug("\tSOURCES\n");
|
||||
rt_dump_sources(&p->sources);
|
||||
RDUMP("\tSOURCES\n");
|
||||
if (p->proto_state != PS_DOWN_XX)
|
||||
rt_dump_sources(dreq, &p->sources);
|
||||
|
||||
if (p->proto->dump &&
|
||||
(p->proto_state != PS_DOWN_XX) &&
|
||||
(p->proto_state != PS_FLUSH))
|
||||
p->proto->dump(p);
|
||||
p->proto->dump(p, dreq);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ struct protocol {
|
||||
void (*postconfig)(struct proto_config *); /* After configuring each instance */
|
||||
struct proto * (*init)(struct proto_config *); /* Create new instance */
|
||||
int (*reconfigure)(struct proto *, struct proto_config *); /* Try to reconfigure instance, returns success */
|
||||
void (*dump)(struct proto *); /* Debugging dump */
|
||||
void (*dump)(struct proto *, struct dump_request *); /* Debugging dump */
|
||||
int (*start)(struct proto *); /* Start the instance */
|
||||
int (*shutdown)(struct proto *); /* Stop the instance */
|
||||
void (*cleanup)(struct proto *); /* Cleanup the instance right before tearing it all down */
|
||||
@ -78,7 +78,7 @@ void proto_build(struct protocol *); /* Called from protocol to register itself
|
||||
void protos_preconfig(struct config *);
|
||||
void protos_commit(struct config *new, struct config *old, int type);
|
||||
struct proto * proto_spawn(struct proto_config *cf, uint disabled);
|
||||
void protos_dump_all(void);
|
||||
void protos_dump_all(struct dump_request *);
|
||||
|
||||
#define GA_UNKNOWN 0 /* Attribute not recognized */
|
||||
#define GA_NAME 1 /* Result = name */
|
||||
|
10
nest/route.h
10
nest/route.h
@ -809,11 +809,11 @@ rte *rt_export_merged(struct channel *c, const struct rt_export_feed *feed, linp
|
||||
void rt_refresh_begin(struct rt_import_request *);
|
||||
void rt_refresh_end(struct rt_import_request *);
|
||||
void rt_schedule_prune(struct rtable_private *t);
|
||||
void rte_dump(struct rte_storage *);
|
||||
void rt_dump(rtable *);
|
||||
void rt_dump_all(void);
|
||||
void rt_dump_hooks(rtable *);
|
||||
void rt_dump_hooks_all(void);
|
||||
void rte_dump(struct dump_request *, struct rte_storage *);
|
||||
void rt_dump(struct dump_request *, rtable *);
|
||||
void rt_dump_all(struct dump_request *);
|
||||
void rt_dump_hooks(struct dump_request *, rtable *);
|
||||
void rt_dump_hooks_all(struct dump_request *);
|
||||
int rt_reload_channel(struct channel *c);
|
||||
void rt_reload_channel_abort(struct channel *c);
|
||||
void rt_prune_sync(rtable *t, int all);
|
||||
|
@ -390,18 +390,18 @@ rt_prune_sources(void *data)
|
||||
}
|
||||
|
||||
void
|
||||
rt_dump_sources(struct rte_owner *o)
|
||||
rt_dump_sources(struct dump_request *dreq, struct rte_owner *o)
|
||||
{
|
||||
debug("\t%s: hord=%u, uc=%u, cnt=%u prune=%p, stop=%p\n",
|
||||
RDUMP("\t%s: hord=%u, uc=%u, cnt=%u prune=%p, stop=%p\n",
|
||||
o->name, o->hash.order, o->uc, o->hash.count, o->prune, o->stop);
|
||||
debug("\tget_route_info=%p, better=%p, mergable=%p, igp_metric=%p, recalculate=%p",
|
||||
RDUMP("\tget_route_info=%p, better=%p, mergable=%p, igp_metric=%p, recalculate=%p",
|
||||
o->class->get_route_info, o->class->rte_better, o->class->rte_mergable,
|
||||
o->class->rte_igp_metric, o->rte_recalculate);
|
||||
|
||||
int splitting = 0;
|
||||
HASH_WALK(o->hash, next, src)
|
||||
{
|
||||
debug("%c%c%uL %uG %luU",
|
||||
RDUMP("%c%c%uL %uG %luU",
|
||||
(splitting % 8) ? ',' : '\n',
|
||||
(splitting % 8) ? ' ' : '\t',
|
||||
src->private_id, src->global_id,
|
||||
@ -410,7 +410,7 @@ rt_dump_sources(struct rte_owner *o)
|
||||
splitting++;
|
||||
}
|
||||
HASH_WALK_END;
|
||||
debug("\n");
|
||||
RDUMP("\n");
|
||||
}
|
||||
|
||||
static struct rte_owner_class default_rte_owner_class;
|
||||
@ -653,10 +653,10 @@ ea_class_ref_free(resource *r)
|
||||
}
|
||||
|
||||
static void
|
||||
ea_class_ref_dump(resource *r, unsigned indent UNUSED)
|
||||
ea_class_ref_dump(struct dump_request *dreq, resource *r)
|
||||
{
|
||||
SKIP_BACK_DECLARE(struct ea_class_ref, ref, r, r);
|
||||
debug("name \"%s\", type=%d\n", ref->class->name, ref->class->type);
|
||||
RDUMP("name \"%s\", type=%d\n", ref->class->name, ref->class->type);
|
||||
}
|
||||
|
||||
static struct resclass ea_class_ref_class = {
|
||||
@ -1348,27 +1348,27 @@ ea_show(struct cli *c, const eattr *e)
|
||||
}
|
||||
|
||||
static void
|
||||
nexthop_dump(const struct adata *ad)
|
||||
nexthop_dump(struct dump_request *dreq, const struct adata *ad)
|
||||
{
|
||||
struct nexthop_adata *nhad = (struct nexthop_adata *) ad;
|
||||
|
||||
debug(":");
|
||||
RDUMP(":");
|
||||
|
||||
if (!NEXTHOP_IS_REACHABLE(nhad))
|
||||
{
|
||||
const char *name = rta_dest_name(nhad->dest);
|
||||
if (name)
|
||||
debug(" %s", name);
|
||||
RDUMP(" %s", name);
|
||||
else
|
||||
debug(" D%d", nhad->dest);
|
||||
RDUMP(" D%d", nhad->dest);
|
||||
}
|
||||
else NEXTHOP_WALK(nh, nhad)
|
||||
{
|
||||
if (ipa_nonzero(nh->gw)) debug(" ->%I", nh->gw);
|
||||
if (nh->labels) debug(" L %d", nh->label[0]);
|
||||
if (ipa_nonzero(nh->gw)) RDUMP(" ->%I", nh->gw);
|
||||
if (nh->labels) RDUMP(" L %d", nh->label[0]);
|
||||
for (int i=1; i<nh->labels; i++)
|
||||
debug("/%d", nh->label[i]);
|
||||
debug(" [%s]", nh->iface ? nh->iface->name : "???");
|
||||
RDUMP("/%d", nh->label[i]);
|
||||
RDUMP(" [%s]", nh->iface ? nh->iface->name : "???");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1380,19 +1380,19 @@ nexthop_dump(const struct adata *ad)
|
||||
* the debug output.
|
||||
*/
|
||||
void
|
||||
ea_dump(ea_list *e)
|
||||
ea_dump(struct dump_request *dreq, ea_list *e)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!e)
|
||||
{
|
||||
debug("NONE");
|
||||
RDUMP("NONE");
|
||||
return;
|
||||
}
|
||||
while (e)
|
||||
{
|
||||
struct ea_storage *s = e->stored ? ea_get_storage(e) : NULL;
|
||||
debug("[%c%c] overlay=%d uc=%d h=%08x",
|
||||
RDUMP("[%c%c] overlay=%d uc=%d h=%08x",
|
||||
(e->flags & EALF_SORTED) ? 'S' : 's',
|
||||
(e->flags & EALF_BISECT) ? 'B' : 'b',
|
||||
e->stored,
|
||||
@ -1403,34 +1403,34 @@ ea_dump(ea_list *e)
|
||||
eattr *a = &e->attrs[i];
|
||||
struct ea_class *clp = (a->id < ea_class_max) ? ea_class_global[a->id] : NULL;
|
||||
if (clp)
|
||||
debug(" %s", clp->name);
|
||||
RDUMP(" %s", clp->name);
|
||||
else
|
||||
debug(" 0x%x", a->id);
|
||||
RDUMP(" 0x%x", a->id);
|
||||
|
||||
debug(".%02x", a->flags);
|
||||
debug("=%c",
|
||||
RDUMP(".%02x", a->flags);
|
||||
RDUMP("=%c",
|
||||
"?iO?IRP???S??pE?"
|
||||
"??L???N?????????"
|
||||
"?o???r??????????" [a->type]);
|
||||
if (a->originated)
|
||||
debug("o");
|
||||
RDUMP("o");
|
||||
if (a->undef)
|
||||
debug(":undef");
|
||||
RDUMP(":undef");
|
||||
else if (a->type & EAF_EMBEDDED)
|
||||
debug(":%08x", a->u.data);
|
||||
RDUMP(":%08x", a->u.data);
|
||||
else if (a->id == ea_gen_nexthop.id)
|
||||
nexthop_dump(a->u.ptr);
|
||||
nexthop_dump(dreq, a->u.ptr);
|
||||
else
|
||||
{
|
||||
int j, len = a->u.ptr->length;
|
||||
debug("[%d]:", len);
|
||||
RDUMP("[%d]:", len);
|
||||
for(j=0; j<len; j++)
|
||||
debug("%02x", a->u.ptr->data[j]);
|
||||
RDUMP("%02x", a->u.ptr->data[j]);
|
||||
}
|
||||
debug(" ");
|
||||
RDUMP(" ");
|
||||
}
|
||||
if (e = e->next)
|
||||
debug(" | ");
|
||||
RDUMP(" | ");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1681,20 +1681,20 @@ ea_free_deferred(struct deferred_call *dc)
|
||||
* to the debug output.
|
||||
*/
|
||||
void
|
||||
ea_dump_all(void)
|
||||
ea_dump_all(struct dump_request *dreq)
|
||||
{
|
||||
debug("Route attribute cache (%d entries, order %d):\n",
|
||||
RDUMP("Route attribute cache (%d entries, order %d):\n",
|
||||
atomic_load_explicit(&rta_hash_table.count, memory_order_relaxed),
|
||||
atomic_load_explicit(&rta_hash_table.cur, memory_order_relaxed)->order);
|
||||
|
||||
SPINHASH_WALK(rta_hash_table, RTAH, a)
|
||||
{
|
||||
debug("%p ", a);
|
||||
ea_dump(a->l);
|
||||
debug("\n");
|
||||
RDUMP("%p ", a);
|
||||
ea_dump(dreq, a->l);
|
||||
RDUMP("\n");
|
||||
}
|
||||
SPINHASH_WALK_END;
|
||||
debug("\n");
|
||||
RDUMP("\n");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2749,15 +2749,15 @@ rt_refresh_trace(struct rtable_private *tab, struct rt_import_hook *ih, const ch
|
||||
* This functions dumps contents of a &rte to debug output.
|
||||
*/
|
||||
void
|
||||
rte_dump(struct rte_storage *e)
|
||||
rte_dump(struct dump_request *dreq, struct rte_storage *e)
|
||||
{
|
||||
debug("(%u) %-1N", NET_TO_INDEX(e->rte.net)->index, e->rte.net);
|
||||
debug("ID=%d ", e->rte.id);
|
||||
debug("SENDER=%s ", e->rte.sender->req->name);
|
||||
debug("PF=%02x ", e->rte.pflags);
|
||||
debug("SRC=%uG ", e->rte.src->global_id);
|
||||
ea_dump(e->rte.attrs);
|
||||
debug("\n");
|
||||
RDUMP("(%u) %-1N", NET_TO_INDEX(e->rte.net)->index, e->rte.net);
|
||||
RDUMP("ID=%d ", e->rte.id);
|
||||
RDUMP("SENDER=%s ", e->rte.sender->req->name);
|
||||
RDUMP("PF=%02x ", e->rte.pflags);
|
||||
RDUMP("SRC=%uG ", e->rte.src->global_id);
|
||||
ea_dump(dreq, e->rte.attrs);
|
||||
RDUMP("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2767,20 +2767,20 @@ rte_dump(struct rte_storage *e)
|
||||
* This function dumps contents of a given routing table to debug output.
|
||||
*/
|
||||
void
|
||||
rt_dump(rtable *tab)
|
||||
rt_dump(struct dump_request *dreq, rtable *tab)
|
||||
{
|
||||
RT_READ(tab, tp);
|
||||
|
||||
/* Looking at priv.deleted is technically unsafe but we don't care */
|
||||
debug("Dump of routing table <%s>%s\n", tab->name, OBSREF_GET(tab->priv.deleted) ? " (deleted)" : "");
|
||||
RDUMP("Dump of routing table <%s>%s\n", tab->name, OBSREF_GET(tab->priv.deleted) ? " (deleted)" : "");
|
||||
|
||||
u32 bs = atomic_load_explicit(&tp->t->routes_block_size, memory_order_relaxed);
|
||||
net *routes = atomic_load_explicit(&tp->t->routes, memory_order_relaxed);
|
||||
for (u32 i = 0; i < bs; i++)
|
||||
NET_READ_WALK_ROUTES(tp, &routes[i], ep, e)
|
||||
rte_dump(e);
|
||||
rte_dump(dreq, e);
|
||||
|
||||
debug("\n");
|
||||
RDUMP("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2789,35 +2789,35 @@ rt_dump(rtable *tab)
|
||||
* This function dumps contents of all routing tables to debug output.
|
||||
*/
|
||||
void
|
||||
rt_dump_all(void)
|
||||
rt_dump_all(struct dump_request *dreq)
|
||||
{
|
||||
rtable *t;
|
||||
node *n;
|
||||
|
||||
WALK_LIST2(t, n, routing_tables, n)
|
||||
rt_dump(t);
|
||||
rt_dump(dreq, t);
|
||||
|
||||
WALK_LIST2(t, n, deleted_routing_tables, n)
|
||||
rt_dump(t);
|
||||
rt_dump(dreq, t);
|
||||
}
|
||||
|
||||
void
|
||||
rt_dump_hooks(rtable *tp)
|
||||
rt_dump_hooks(struct dump_request *dreq, rtable *tp)
|
||||
{
|
||||
RT_LOCKED(tp, tab)
|
||||
{
|
||||
|
||||
debug("Dump of hooks in routing table <%s>%s\n", tab->name, OBSREF_GET(tab->deleted) ? " (deleted)" : "");
|
||||
debug(" nhu_state=%u use_count=%d rt_count=%u\n",
|
||||
RDUMP("Dump of hooks in routing table <%s>%s\n", tab->name, OBSREF_GET(tab->deleted) ? " (deleted)" : "");
|
||||
RDUMP(" nhu_state=%u use_count=%d rt_count=%u\n",
|
||||
tab->nhu_state, tab->use_count, tab->rt_count);
|
||||
debug(" last_rt_change=%t gc_time=%t gc_counter=%d prune_state=%u\n",
|
||||
RDUMP(" last_rt_change=%t gc_time=%t gc_counter=%d prune_state=%u\n",
|
||||
tab->last_rt_change, tab->gc_time, tab->gc_counter, tab->prune_state);
|
||||
|
||||
struct rt_import_hook *ih;
|
||||
WALK_LIST(ih, tab->imports)
|
||||
{
|
||||
ih->req->dump_req(ih->req);
|
||||
debug(" Import hook %p requested by %p: pref=%u"
|
||||
RDUMP(" Import hook %p requested by %p: pref=%u"
|
||||
" last_state_change=%t import_state=%u stopped=%p\n",
|
||||
ih, ih->req, ih->stats.pref,
|
||||
ih->last_state_change, ih->import_state, ih->stopped);
|
||||
@ -2829,30 +2829,30 @@ rt_dump_hooks(rtable *tp)
|
||||
{
|
||||
SKIP_BACK_DECLARE(struct rt_export_hook, eh, recipient, r);
|
||||
eh->req->dump_req(eh->req);
|
||||
debug(" Export hook %p requested by %p:"
|
||||
RDUMP(" Export hook %p requested by %p:"
|
||||
" refeed_pending=%u last_state_change=%t export_state=%u\n",
|
||||
eh, eh->req, eh->refeed_pending, eh->last_state_change,
|
||||
atomic_load_explicit(&eh->export_state, memory_order_relaxed));
|
||||
}
|
||||
#endif
|
||||
debug("\n");
|
||||
RDUMP("\n");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rt_dump_hooks_all(void)
|
||||
rt_dump_hooks_all(struct dump_request *dreq)
|
||||
{
|
||||
rtable *t;
|
||||
node *n;
|
||||
|
||||
debug("Dump of all table hooks\n");
|
||||
RDUMP("Dump of all table hooks\n");
|
||||
|
||||
WALK_LIST2(t, n, routing_tables, n)
|
||||
rt_dump_hooks(t);
|
||||
rt_dump_hooks(dreq, t);
|
||||
|
||||
WALK_LIST2(t, n, deleted_routing_tables, n)
|
||||
rt_dump_hooks(t);
|
||||
rt_dump_hooks(dreq, t);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -3209,11 +3209,11 @@ rt_free(resource *_r)
|
||||
}
|
||||
|
||||
static void
|
||||
rt_res_dump(resource *_r, unsigned indent UNUSED)
|
||||
rt_res_dump(struct dump_request *dreq, resource *_r)
|
||||
{
|
||||
SKIP_BACK_DECLARE(struct rtable_private, r, r, _r);
|
||||
|
||||
debug("name \"%s\", addr_type=%s, rt_count=%u, use_count=%d\n",
|
||||
RDUMP("name \"%s\", addr_type=%s, rt_count=%u, use_count=%d\n",
|
||||
r->name, net_label[r->addr_type], r->rt_count, r->use_count);
|
||||
|
||||
#if 0
|
||||
|
@ -2103,82 +2103,82 @@ babel_reconfigure_ifaces(struct babel_proto *p, struct babel_config *cf)
|
||||
*/
|
||||
|
||||
static void
|
||||
babel_dump_source(struct babel_source *s)
|
||||
babel_dump_source(struct dump_request *dreq, struct babel_source *s)
|
||||
{
|
||||
debug("Source router_id %lR seqno %d metric %d expires %t\n",
|
||||
RDUMP("Source router_id %lR seqno %d metric %d expires %t\n",
|
||||
s->router_id, s->seqno, s->metric,
|
||||
s->expires ? s->expires - current_time() : 0);
|
||||
}
|
||||
|
||||
static void
|
||||
babel_dump_route(struct babel_route *r)
|
||||
babel_dump_route(struct dump_request *dreq, struct babel_route *r)
|
||||
{
|
||||
debug("Route neigh %I if %s seqno %d metric %d/%d router_id %lR expires %t\n",
|
||||
RDUMP("Route neigh %I if %s seqno %d metric %d/%d router_id %lR expires %t\n",
|
||||
r->neigh->addr, r->neigh->ifa->ifname, r->seqno, r->advert_metric, r->metric,
|
||||
r->router_id, r->expires ? r->expires - current_time() : 0);
|
||||
}
|
||||
|
||||
static void
|
||||
babel_dump_entry(struct babel_entry *e)
|
||||
babel_dump_entry(struct dump_request *dreq, struct babel_entry *e)
|
||||
{
|
||||
struct babel_source *s;
|
||||
struct babel_route *r;
|
||||
|
||||
debug("Babel: Entry %N:\n", e->n.addr);
|
||||
RDUMP("Babel: Entry %N:\n", e->n.addr);
|
||||
|
||||
WALK_LIST(s,e->sources)
|
||||
{ debug(" "); babel_dump_source(s); }
|
||||
{ RDUMP(" "); babel_dump_source(dreq, s); }
|
||||
|
||||
WALK_LIST(r,e->routes)
|
||||
{
|
||||
debug(" ");
|
||||
if (r == e->selected) debug("*");
|
||||
babel_dump_route(r);
|
||||
RDUMP(" ");
|
||||
if (r == e->selected) RDUMP("*");
|
||||
babel_dump_route(dreq, r);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
babel_dump_neighbor(struct babel_neighbor *n)
|
||||
babel_dump_neighbor(struct dump_request *dreq, struct babel_neighbor *n)
|
||||
{
|
||||
debug("Neighbor %I txcost %d hello_map %x next seqno %d expires %t/%t\n",
|
||||
RDUMP("Neighbor %I txcost %d hello_map %x next seqno %d expires %t/%t\n",
|
||||
n->addr, n->txcost, n->hello_map, n->next_hello_seqno,
|
||||
n->hello_expiry ? n->hello_expiry - current_time() : 0,
|
||||
n->ihu_expiry ? n->ihu_expiry - current_time() : 0);
|
||||
}
|
||||
|
||||
static void
|
||||
babel_dump_iface(struct babel_iface *ifa)
|
||||
babel_dump_iface(struct dump_request *dreq, struct babel_iface *ifa)
|
||||
{
|
||||
struct babel_neighbor *n;
|
||||
|
||||
debug("Babel: Interface %s addr %I rxcost %d type %d hello seqno %d intervals %t %t",
|
||||
RDUMP("Babel: Interface %s addr %I rxcost %d type %d hello seqno %d intervals %t %t",
|
||||
ifa->ifname, ifa->addr, ifa->cf->rxcost, ifa->cf->type, ifa->hello_seqno,
|
||||
ifa->cf->hello_interval, ifa->cf->update_interval);
|
||||
debug(" next hop v4 %I next hop v6 %I\n", ifa->next_hop_ip4, ifa->next_hop_ip6);
|
||||
RDUMP(" next hop v4 %I next hop v6 %I\n", ifa->next_hop_ip4, ifa->next_hop_ip6);
|
||||
|
||||
WALK_LIST(n, ifa->neigh_list)
|
||||
{ debug(" "); babel_dump_neighbor(n); }
|
||||
{ RDUMP(" "); babel_dump_neighbor(dreq, n); }
|
||||
}
|
||||
|
||||
static void
|
||||
babel_dump(struct proto *P)
|
||||
babel_dump(struct proto *P, struct dump_request *dreq)
|
||||
{
|
||||
struct babel_proto *p = (struct babel_proto *) P;
|
||||
struct babel_iface *ifa;
|
||||
|
||||
debug("Babel: router id %lR update seqno %d\n", p->router_id, p->update_seqno);
|
||||
RDUMP("Babel: router id %lR update seqno %d\n", p->router_id, p->update_seqno);
|
||||
|
||||
WALK_LIST(ifa, p->interfaces)
|
||||
babel_dump_iface(ifa);
|
||||
babel_dump_iface(dreq, ifa);
|
||||
|
||||
FIB_WALK(&p->ip4_rtable, struct babel_entry, e)
|
||||
{
|
||||
babel_dump_entry(e);
|
||||
babel_dump_entry(dreq, e);
|
||||
}
|
||||
FIB_WALK_END;
|
||||
FIB_WALK(&p->ip6_rtable, struct babel_entry, e)
|
||||
{
|
||||
babel_dump_entry(e);
|
||||
babel_dump_entry(dreq, e);
|
||||
}
|
||||
FIB_WALK_END;
|
||||
}
|
||||
|
@ -929,11 +929,11 @@ bfd_request_free(resource *r)
|
||||
}
|
||||
|
||||
static void
|
||||
bfd_request_dump(resource *r, unsigned indent UNUSED)
|
||||
bfd_request_dump(struct dump_request *dreq, resource *r)
|
||||
{
|
||||
struct bfd_request *req = (struct bfd_request *) r;
|
||||
|
||||
debug("(code %p, data %p)\n", req->hook, req->data);
|
||||
RDUMP("(code %p, data %p)\n", req->hook, req->data);
|
||||
}
|
||||
|
||||
static struct resclass bfd_request_class = {
|
||||
|
@ -236,7 +236,7 @@ static void
|
||||
bmp_tx_resource_free(resource *r UNUSED) {}
|
||||
|
||||
static void
|
||||
bmp_tx_resource_dump(resource *r UNUSED, uint indent UNUSED) {}
|
||||
bmp_tx_resource_dump(struct dump_request *dreq UNUSED, resource *r UNUSED) {}
|
||||
|
||||
static struct resmem
|
||||
bmp_tx_resource_memsize(resource *r)
|
||||
|
@ -334,32 +334,31 @@ ospf_start(struct proto *P)
|
||||
}
|
||||
|
||||
static void
|
||||
ospf_dump(struct proto *P)
|
||||
ospf_dump(struct proto *P, struct dump_request *dreq)
|
||||
{
|
||||
struct ospf_proto *p = (struct ospf_proto *) P;
|
||||
struct ospf_iface *ifa;
|
||||
struct ospf_neighbor *n;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Area number: %d", p->areano);
|
||||
RDUMP("Area number: %d\n", p->areano);
|
||||
|
||||
WALK_LIST(ifa, p->iface_list)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Interface: %s", ifa->ifname);
|
||||
OSPF_TRACE(D_EVENTS, "state: %u", ifa->state);
|
||||
OSPF_TRACE(D_EVENTS, "DR: %R", ifa->drid);
|
||||
OSPF_TRACE(D_EVENTS, "BDR: %R", ifa->bdrid);
|
||||
RDUMP("Interface: %s\n", ifa->ifname);
|
||||
RDUMP("state: %u\n", ifa->state);
|
||||
RDUMP("DR: %R\n", ifa->drid);
|
||||
RDUMP("BDR: %R\n", ifa->bdrid);
|
||||
WALK_LIST(n, ifa->neigh_list)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, " neighbor %R in state %u", n->rid, n->state);
|
||||
RDUMP(" neighbor %R in state %u\n", n->rid, n->state);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
OSPF_TRACE(D_EVENTS, "LSA graph dump start:");
|
||||
RDUMP("LSA graph dump start:");
|
||||
ospf_top_dump(p->gr, p);
|
||||
OSPF_TRACE(D_EVENTS, "LSA graph dump finished");
|
||||
RDUMP("LSA graph dump finished");
|
||||
*/
|
||||
neigh_dump_all();
|
||||
}
|
||||
|
||||
static struct proto *
|
||||
|
@ -1351,7 +1351,7 @@ rip_show_neighbors(struct proto *P, const char *iff)
|
||||
}
|
||||
|
||||
static void
|
||||
rip_dump(struct proto *P)
|
||||
rip_dump(struct proto *P, struct dump_request *dreq)
|
||||
{
|
||||
struct rip_proto *p = (struct rip_proto *) P;
|
||||
struct rip_iface *ifa;
|
||||
@ -1360,12 +1360,12 @@ rip_dump(struct proto *P)
|
||||
i = 0;
|
||||
FIB_WALK(&p->rtable, struct rip_entry, en)
|
||||
{
|
||||
debug("RIP: entry #%d: %N via %I dev %s valid %d metric %d age %t\n",
|
||||
RDUMP("RIP: entry #%d: %N via %I dev %s valid %d metric %d age %t\n",
|
||||
i++, en->n.addr, en->next_hop, en->iface ? en->iface->name : "(null)",
|
||||
en->valid, en->metric, current_time() - en->changed);
|
||||
|
||||
for (struct rip_rte *e = en->routes; e; e = e->next)
|
||||
debug("RIP: via %I metric %d expires %t\n",
|
||||
RDUMP("RIP: via %I metric %d expires %t\n",
|
||||
e->next_hop, e->metric, e->expires - current_time());
|
||||
}
|
||||
FIB_WALK_END;
|
||||
@ -1373,7 +1373,7 @@ rip_dump(struct proto *P)
|
||||
i = 0;
|
||||
WALK_LIST(ifa, p->iface_list)
|
||||
{
|
||||
debug("RIP: interface #%d: %s, %I, up = %d, busy = %d\n",
|
||||
RDUMP("RIP: interface #%d: %s, %I, up = %d, busy = %d\n",
|
||||
i++, ifa->iface->name, ifa->sk ? ifa->sk->daddr : IPA_NONE,
|
||||
ifa->up, ifa->tx_active);
|
||||
}
|
||||
|
@ -606,27 +606,27 @@ static_cleanup(struct proto *P)
|
||||
}
|
||||
|
||||
static void
|
||||
static_dump_rte(struct static_route *r)
|
||||
static_dump_rte(struct dump_request *dreq, struct static_route *r)
|
||||
{
|
||||
debug("%-1N (%u): ", r->net, r->index);
|
||||
RDUMP("%-1N (%u): ", r->net, r->index);
|
||||
if (r->dest == RTD_UNICAST)
|
||||
if (r->iface && ipa_zero(r->via))
|
||||
debug("dev %s\n", r->iface->name);
|
||||
RDUMP("dev %s\n", r->iface->name);
|
||||
else
|
||||
debug("via %I%J\n", r->via, r->iface);
|
||||
RDUMP("via %I%J\n", r->via, r->iface);
|
||||
else
|
||||
debug("rtd %d\n", r->dest);
|
||||
RDUMP("rtd %d\n", r->dest);
|
||||
}
|
||||
|
||||
static void
|
||||
static_dump(struct proto *P)
|
||||
static_dump(struct proto *P, struct dump_request *dreq)
|
||||
{
|
||||
struct static_config *c = (void *) P->cf;
|
||||
struct static_route *r;
|
||||
|
||||
debug("Static routes:\n");
|
||||
RDUMP("Static routes:\n");
|
||||
WALK_LIST(r, c->routes)
|
||||
static_dump_rte(r);
|
||||
static_dump_rte(dreq, r);
|
||||
}
|
||||
|
||||
#define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL )
|
||||
|
@ -431,6 +431,30 @@ page_cleanup(void *_ UNUSED)
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
page_dump(struct dump_request *dreq)
|
||||
{
|
||||
#ifdef HAVE_MMAP
|
||||
RDUMP("Hot pages:\n");
|
||||
struct free_page *fptop = PAGE_STACK_GET;
|
||||
for (struct free_page *fp = fptop; fp; fp = atomic_load_explicit(&fp->next, memory_order_relaxed))
|
||||
RDUMP(" %p\n", fp);
|
||||
|
||||
PAGE_STACK_PUT(fptop);
|
||||
|
||||
RDUMP("Cold pages:\n");
|
||||
|
||||
LOCK_DOMAIN(resource, empty_pages_domain);
|
||||
for (struct empty_pages *ep = empty_pages; ep; ep = ep->next)
|
||||
{
|
||||
RDUMP(" %p (index)\n", ep);
|
||||
for (uint i=0; i<ep->pos; i++)
|
||||
RDUMP(" %p\n", ep->pages[i]);
|
||||
}
|
||||
UNLOCK_DOMAIN(resource, empty_pages_domain);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
resource_sys_init(void)
|
||||
{
|
||||
|
169
sysdep/unix/io.c
169
sysdep/unix/io.c
@ -21,6 +21,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <poll.h>
|
||||
@ -43,6 +44,7 @@
|
||||
#include "lib/timer.h"
|
||||
#include "lib/string.h"
|
||||
#include "nest/iface.h"
|
||||
#include "nest/cli.h"
|
||||
#include "conf/conf.h"
|
||||
|
||||
#include "sysdep/unix/unix.h"
|
||||
@ -90,11 +92,11 @@ rf_free(resource *r)
|
||||
}
|
||||
|
||||
static void
|
||||
rf_dump(resource *r, unsigned indent UNUSED)
|
||||
rf_dump(struct dump_request *dreq, resource *r)
|
||||
{
|
||||
struct rfile *a = (struct rfile *) r;
|
||||
|
||||
debug("(fd %d)\n", a->fd);
|
||||
RDUMP("(fd %d)\n", a->fd);
|
||||
}
|
||||
|
||||
static struct resclass rf_class = {
|
||||
@ -285,6 +287,147 @@ rf_writev(struct rfile *r, struct iovec *iov, int iov_count)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Dumping to files
|
||||
*/
|
||||
|
||||
struct dump_request_file {
|
||||
struct dump_request dr;
|
||||
uint pos, max; int fd;
|
||||
uint last_progress_info;
|
||||
char data[0];
|
||||
};
|
||||
|
||||
static void
|
||||
dump_to_file_flush(struct dump_request_file *req)
|
||||
{
|
||||
if (req->fd < 0)
|
||||
return;
|
||||
|
||||
for (uint sent = 0; sent < req->pos; )
|
||||
{
|
||||
int e = write(req->fd, &req->data[sent], req->pos - sent);
|
||||
if (e <= 0)
|
||||
{
|
||||
req->dr.report(&req->dr, 8009, "Failed to write data: %m");
|
||||
close(req->fd);
|
||||
req->fd = -1;
|
||||
return;
|
||||
}
|
||||
sent += e;
|
||||
}
|
||||
|
||||
req->dr.size += req->pos;
|
||||
req->pos = 0;
|
||||
|
||||
for (uint reported = 0; req->dr.size >> req->last_progress_info; req->last_progress_info++)
|
||||
if (!reported++)
|
||||
req->dr.report(&req->dr, -13, "... dumped %lu bytes in %t s",
|
||||
req->dr.size, current_time_now() - req->dr.begin);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_to_file_write(struct dump_request *dr, const char *fmt, ...)
|
||||
{
|
||||
struct dump_request_file *req = SKIP_BACK(struct dump_request_file, dr, dr);
|
||||
|
||||
for (uint phase = 0; (req->fd >= 0) && (phase < 2); phase++)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int i = bvsnprintf(&req->data[req->pos], req->max - req->pos, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (i >= 0)
|
||||
{
|
||||
req->pos += i;
|
||||
return;
|
||||
}
|
||||
else
|
||||
dump_to_file_flush(req);
|
||||
}
|
||||
|
||||
bug("Too long dump call");
|
||||
}
|
||||
|
||||
struct dump_request *
|
||||
dump_to_file_init(off_t offset)
|
||||
{
|
||||
ASSERT_DIE(offset + sizeof(struct dump_request_file) + 1024 < (unsigned long) page_size);
|
||||
|
||||
struct dump_request_file *req = alloc_page() + offset;
|
||||
*req = (struct dump_request_file) {
|
||||
.dr = {
|
||||
.write = dump_to_file_write,
|
||||
.begin = current_time_now(),
|
||||
.offset = offset,
|
||||
},
|
||||
.max = page_size - offset - OFFSETOF(struct dump_request_file, data[0]),
|
||||
.fd = -1,
|
||||
};
|
||||
|
||||
return &req->dr;
|
||||
}
|
||||
|
||||
void
|
||||
dump_to_file_run(struct dump_request *dr, const char *file, const char *what, void (*dump)(struct dump_request *))
|
||||
{
|
||||
struct dump_request_file *req = SKIP_BACK(struct dump_request_file, dr, dr);
|
||||
req->fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR);
|
||||
|
||||
if (req->fd < 0)
|
||||
{
|
||||
dr->report(dr, 8009, "Failed to open file %s: %m", file);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dr->report(dr, -13, "Dumping %s to %s", what, file);
|
||||
|
||||
dump(dr);
|
||||
|
||||
if (req->fd >= 0)
|
||||
{
|
||||
dump_to_file_flush(req);
|
||||
close(req->fd);
|
||||
}
|
||||
|
||||
btime end = current_time_now();
|
||||
dr->report(dr, 13, "Dumped %lu bytes in %t s", dr->size, end - dr->begin);
|
||||
|
||||
cleanup:
|
||||
free_page(((void *) req) - dr->offset);
|
||||
}
|
||||
|
||||
struct dump_request_cli {
|
||||
cli *cli;
|
||||
struct dump_request dr;
|
||||
};
|
||||
|
||||
static void
|
||||
cmd_dump_report(struct dump_request *dr, int state, const char *fmt, ...)
|
||||
{
|
||||
struct dump_request_cli *req = SKIP_BACK(struct dump_request_cli, dr, dr);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
cli_vprintf(req->cli, state, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_dump_file(struct cli *cli, const char *file, const char *what, void (*dump)(struct dump_request *))
|
||||
{
|
||||
if (cli->restricted)
|
||||
return cli_printf(cli, 8007, "Access denied");
|
||||
|
||||
struct dump_request_cli *req = SKIP_BACK(struct dump_request_cli, dr,
|
||||
dump_to_file_init(OFFSETOF(struct dump_request_cli, dr)));
|
||||
|
||||
req->cli = cli;
|
||||
req->dr.report = cmd_dump_report;
|
||||
|
||||
dump_to_file_run(&req->dr, file, what, dump);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Time clock
|
||||
@ -1069,12 +1212,12 @@ sk_reallocate(sock *s)
|
||||
}
|
||||
|
||||
static void
|
||||
sk_dump(resource *r, unsigned indent UNUSED)
|
||||
sk_dump(struct dump_request *dreq, resource *r)
|
||||
{
|
||||
sock *s = (sock *) r;
|
||||
static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", NULL, "IP", NULL, "MAGIC", "UNIX<", "UNIX", "SSH>", "SSH", "DEL!" };
|
||||
|
||||
debug("(%s, ud=%p, sa=%I, sp=%d, da=%I, dp=%d, tos=%d, ttl=%d, if=%s)\n",
|
||||
RDUMP("(%s, ud=%p, sa=%I, sp=%d, da=%I, dp=%d, tos=%d, ttl=%d, if=%s)\n",
|
||||
sk_type_names[s->type],
|
||||
s->data,
|
||||
s->saddr,
|
||||
@ -2253,19 +2396,21 @@ sk_err(sock *s, int revents)
|
||||
}
|
||||
|
||||
void
|
||||
sk_dump_all(void)
|
||||
sk_dump_all(struct dump_request *dreq)
|
||||
{
|
||||
node *n;
|
||||
sock *s;
|
||||
|
||||
debug("Open sockets:\n");
|
||||
RDUMP("Open sockets:\n");
|
||||
dreq->indent += 3;
|
||||
WALK_LIST(n, main_birdloop.sock_list)
|
||||
{
|
||||
s = SKIP_BACK(sock, n, n);
|
||||
debug("%p ", s);
|
||||
sk_dump(&s->r, 3);
|
||||
RDUMP("%p ", s);
|
||||
sk_dump(dreq, &s->r);
|
||||
}
|
||||
debug("\n");
|
||||
dreq->indent -= 3;
|
||||
RDUMP("\n");
|
||||
}
|
||||
|
||||
|
||||
@ -2345,16 +2490,16 @@ io_close_event(void)
|
||||
}
|
||||
|
||||
void
|
||||
io_log_dump(void)
|
||||
io_log_dump(struct dump_request *dreq)
|
||||
{
|
||||
int i;
|
||||
|
||||
log(L_DEBUG "Event log:");
|
||||
RDUMP("Event log:\n");
|
||||
for (i = 0; i < EVENT_LOG_LENGTH; i++)
|
||||
{
|
||||
struct event_log_entry *en = event_log + (event_log_pos + i) % EVENT_LOG_LENGTH;
|
||||
if (en->hook)
|
||||
log(L_DEBUG " Event 0x%p 0x%p at %8d for %d ms", en->hook, en->data,
|
||||
RDUMP(" Event 0x%p 0x%p at %8d for %d ms\n", en->hook, en->data,
|
||||
(int) ((last_io_time - en->timestamp) TO_MS), (int) (en->duration TO_MS));
|
||||
}
|
||||
}
|
||||
|
@ -49,21 +49,38 @@
|
||||
* Debugging
|
||||
*/
|
||||
|
||||
static void
|
||||
async_dump_report(struct dump_request *dr UNUSED, int state, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vlog(((state > 1000) ? L_ERR : L_INFO)[0], fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void
|
||||
async_dump_run(struct dump_request *dreq)
|
||||
{
|
||||
RDUMP("ASYNC STATE DUMP\n");
|
||||
|
||||
rdump(dreq, &root_pool);
|
||||
sk_dump_all(dreq);
|
||||
// XXXX tm_dump_all();
|
||||
if_dump_all(dreq);
|
||||
neigh_dump_all(dreq);
|
||||
ea_dump_all(dreq);
|
||||
rt_dump_all(dreq);
|
||||
protos_dump_all(dreq);
|
||||
|
||||
debug("\n");
|
||||
}
|
||||
|
||||
void
|
||||
async_dump(void)
|
||||
{
|
||||
debug("INTERNAL STATE DUMP\n\n");
|
||||
|
||||
rdump(&root_pool, 0);
|
||||
sk_dump_all();
|
||||
// XXXX tm_dump_all();
|
||||
if_dump_all();
|
||||
neigh_dump_all();
|
||||
ea_dump_all();
|
||||
rt_dump_all();
|
||||
protos_dump_all();
|
||||
|
||||
debug("\n");
|
||||
struct dump_request *dr = dump_to_file_init(0);
|
||||
dr->report = async_dump_report;
|
||||
dump_to_file_run(dr, "bird.dump", "async dump", async_dump_run);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -20,6 +20,7 @@ struct pool;
|
||||
struct iface;
|
||||
struct birdsock;
|
||||
struct rfile;
|
||||
struct cli;
|
||||
struct config;
|
||||
|
||||
/* main.c */
|
||||
@ -113,7 +114,7 @@ extern volatile sig_atomic_t async_shutdown_flag;
|
||||
|
||||
void io_init(void);
|
||||
void io_loop(void);
|
||||
void io_log_dump(void);
|
||||
void io_log_dump(struct dump_request *);
|
||||
int sk_open_unix(struct birdsock *s, struct birdloop *, const char *name);
|
||||
|
||||
enum rf_mode {
|
||||
@ -133,6 +134,11 @@ extern struct rfile rf_stderr;
|
||||
void test_old_bird(const char *path);
|
||||
ip_addr resolve_hostname(const char *host, int type, const char **err_msg);
|
||||
|
||||
struct dump_request *dump_to_file_init(off_t offset);
|
||||
void dump_to_file_run(struct dump_request *dr, const char *file, const char *what, void (*dump)(struct dump_request *));
|
||||
|
||||
void cmd_dump_file(struct cli *cli, const char *file, const char *what, void (*dump)(struct dump_request *));
|
||||
|
||||
/* krt.c bits */
|
||||
|
||||
void krt_io_init(void);
|
||||
|
Loading…
Reference in New Issue
Block a user