Changed initialization of protocol list -- now we call proto_build() instead

of calling the protocols manually.

Implemented printing of dynamic attributes in `show route all'.

Each protocol can now register its own attribute class (protocol->attr_class,
set to EAP_xxx) and also a callback for naming and formatting of attributes.
The callback can return one of the following results:

	GA_UNKNOWN	Attribute not recognized.
	GA_NAME		Attribute name recognized and put to the buffer,
			generic code should format the value.
	GA_FULL		Both attribute name and value put to the buffer.

Please update protocols generating dynamic attributes to provide
the attr_class and formatting hook.
This commit is contained in:
Martin Mares 2000-04-01 10:19:47 +00:00
parent f880924990
commit 3991d84e8f
8 changed files with 99 additions and 18 deletions

2
TODO
View file

@ -24,6 +24,8 @@ Documentation
Globals Globals
~~~~~~~ ~~~~~~~
- right usage of DBG vs. debug - right usage of DBG vs. debug
- kill preconfigs?
- check dump functions
- cleanup debugging calls - cleanup debugging calls
- logging and tracing; use appropriate log levels - logging and tracing; use appropriate log levels
- check incoming packets and log errors!! - check incoming packets and log errors!!

View file

@ -35,6 +35,7 @@ Reply codes of BIRD command-line interface
1009 Static route list 1009 Static route list
1010 Symbol list 1010 Symbol list
1011 Uptime 1011 Uptime
1012 Route extended attribute list
8000 Reply too long 8000 Reply too long
8001 Route not found 8001 Route not found

View file

@ -22,7 +22,7 @@
static pool *proto_pool; static pool *proto_pool;
list protocol_list; static list protocol_list;
static list proto_list; static list proto_list;
#define WALK_PROTO_LIST(p) do { \ #define WALK_PROTO_LIST(p) do { \
@ -343,6 +343,17 @@ protos_dump_all(void)
debug(" flushing %s\n", p->name); debug(" flushing %s\n", p->name);
} }
void
proto_build(struct protocol *p)
{
add_tail(&protocol_list, &p->n);
if (p->attr_class)
{
ASSERT(!attr_class_to_protocol[p->attr_class]);
attr_class_to_protocol[p->attr_class] = p;
}
}
void void
protos_build(void) protos_build(void)
{ {
@ -352,21 +363,21 @@ protos_build(void)
init_list(&inactive_proto_list); init_list(&inactive_proto_list);
init_list(&initial_proto_list); init_list(&initial_proto_list);
init_list(&flush_proto_list); init_list(&flush_proto_list);
add_tail(&protocol_list, &proto_device.n); proto_build(&proto_device);
#ifdef CONFIG_RIP #ifdef CONFIG_RIP
add_tail(&protocol_list, &proto_rip.n); proto_build(&proto_rip);
#endif #endif
#ifdef CONFIG_STATIC #ifdef CONFIG_STATIC
add_tail(&protocol_list, &proto_static.n); proto_build(&proto_static);
#endif #endif
#ifdef CONFIG_OSPF #ifdef CONFIG_OSPF
add_tail(&protocol_list, &proto_ospf.n); proto_build(&proto_ospf);
#endif #endif
#ifdef CONFIG_PIPE #ifdef CONFIG_PIPE
add_tail(&protocol_list, &proto_pipe.n); proto_build(&proto_pipe);
#endif #endif
#ifdef CONFIG_BGP #ifdef CONFIG_BGP
add_tail(&protocol_list, &proto_bgp.n); proto_build(&proto_bgp);
#endif #endif
proto_pool = rp_new(&root_pool, "Protocols"); proto_pool = rp_new(&root_pool, "Protocols");
proto_flush_event = ev_new(proto_pool); proto_flush_event = ev_new(proto_pool);

View file

@ -24,6 +24,7 @@ struct config;
struct proto; struct proto;
struct event; struct event;
struct ea_list; struct ea_list;
struct eattr;
struct symbol; struct symbol;
/* /*
@ -35,6 +36,7 @@ struct protocol {
char *name; char *name;
char *template; /* Template for automatic generation of names */ char *template; /* Template for automatic generation of names */
int name_counter; /* Counter for automatic name generation */ int name_counter; /* Counter for automatic name generation */
int attr_class; /* Attribute class known to this protocol */
void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */ void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */
void (*postconfig)(struct proto_config *); /* After configuring each instance */ void (*postconfig)(struct proto_config *); /* After configuring each instance */
@ -46,16 +48,19 @@ struct protocol {
int (*shutdown)(struct proto *); /* Stop the instance */ int (*shutdown)(struct proto *); /* Stop the instance */
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */ void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */ void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */
void (*show_route_data)(struct rte *); /* Print verbose route information (`show route' again) */ int (*get_attr)(struct eattr *, byte *buf); /* ASCIIfy dynamic attribute (returns GA_*) */
}; };
void protos_build(void); void protos_build(void);
void proto_build(struct protocol *);
void protos_preconfig(struct config *); void protos_preconfig(struct config *);
void protos_postconfig(struct config *); void protos_postconfig(struct config *);
void protos_commit(struct config *new, struct config *old, int force_restart); void protos_commit(struct config *new, struct config *old, int force_restart);
void protos_dump_all(void); void protos_dump_all(void);
extern list protocol_list; #define GA_UNKNOWN 0 /* Attribute not recognized */
#define GA_NAME 1 /* Result = name */
#define GA_FULL 2 /* Result = both name and value */
/* /*
* Known protocols * Known protocols
@ -146,7 +151,6 @@ struct proto {
/* Hic sunt protocol-specific data */ /* Hic sunt protocol-specific data */
}; };
void proto_build(struct proto_config *);
void *proto_new(struct proto_config *, unsigned size); void *proto_new(struct proto_config *, unsigned size);
void *proto_config_new(struct protocol *, unsigned size); void *proto_config_new(struct protocol *, unsigned size);

View file

@ -283,6 +283,7 @@ typedef struct eattr {
#define EAP_GENERIC 0 /* Generic attributes */ #define EAP_GENERIC 0 /* Generic attributes */
#define EAP_BGP 1 /* BGP attributes */ #define EAP_BGP 1 /* BGP attributes */
#define EAP_RIP 2 /* RIP */ #define EAP_RIP 2 /* RIP */
#define EAP_MAX 3
#define EA_CODE(proto,id) (((proto) << 8) | (id)) #define EA_CODE(proto,id) (((proto) << 8) | (id))
#define EA_PROTO(ea) ((ea) >> 8) #define EA_PROTO(ea) ((ea) >> 8)
@ -336,6 +337,8 @@ void rta_dump_all(void);
static inline eattr * rta_find(rta *a, unsigned ea) { return ea_find(a->eattrs, ea); } static inline eattr * rta_find(rta *a, unsigned ea) { return ea_find(a->eattrs, ea); }
void rta_show(struct cli *, rta *); void rta_show(struct cli *, rta *);
extern struct protocol *attr_class_to_protocol[EAP_MAX];
/* /*
* Default protocol preferences * Default protocol preferences
*/ */

View file

@ -19,6 +19,8 @@
static slab *rta_slab; static slab *rta_slab;
static pool *rta_pool; static pool *rta_pool;
struct protocol *attr_class_to_protocol[EAP_MAX];
/* /*
* Extended Attributes * Extended Attributes
*/ */
@ -233,6 +235,60 @@ ea_list_copy(ea_list *o)
return n; return n;
} }
void
ea_format(eattr *e, byte *buf)
{
struct protocol *p;
int status = GA_UNKNOWN;
unsigned int i, l;
struct adata *ad = (e->type & EAF_EMBEDDED) ? NULL : e->u.ptr;
if (p = attr_class_to_protocol[EA_PROTO(e->id)])
{
buf += bsprintf(buf, "%s.", p->name);
if (p->get_attr)
status = p->get_attr(e, buf);
buf += strlen(buf);
}
else if (EA_PROTO(e->id))
buf += bsprintf(buf, "%02x.", EA_PROTO(e->id));
if (status < GA_NAME)
buf += bsprintf(buf, "%02x", EA_ID(e->id));
if (status < GA_FULL)
{
*buf++ = ':';
*buf++ = ' ';
switch (e->type & EAF_TYPE_MASK)
{
case EAF_TYPE_INT:
bsprintf(buf, "%d", e->u.data);
break;
case EAF_TYPE_OPAQUE:
l = (ad->length < 16) ? ad->length : 16;
for(i=0; i<l; i++)
{
buf += bsprintf(buf, "%02x", ad->data[i]);
if (i < l)
*buf++ = ' ';
}
if (l < ad->length)
strcpy(buf, "...");
break;
case EAF_TYPE_IP_ADDRESS:
bsprintf(buf, "%I", *(ip_addr *) ad->data);
break;
case EAF_TYPE_ROUTER_ID:
bsprintf(buf, "%08x", e->u.data); /* FIXME: Better printing of router ID's */
break;
case EAF_TYPE_AS_PATH: /* FIXME */
case EAF_TYPE_INT_SET: /* FIXME */
case EAF_TYPE_UNDEF:
default:
bsprintf(buf, "<type %02x>", e->type);
}
}
}
void void
ea_dump(ea_list *e) ea_dump(ea_list *e)
{ {
@ -484,9 +540,17 @@ rta_show(struct cli *c, rta *a)
"RIP", "RIP-ext", "OSPF", "OSPF-ext", "OSPF-IA", "OSPF-boundary", "RIP", "RIP-ext", "OSPF", "OSPF-ext", "OSPF-IA", "OSPF-boundary",
"BGP" }; "BGP" };
static char *cast_names[] = { "unicast", "broadcast", "multicast", "anycast" }; static char *cast_names[] = { "unicast", "broadcast", "multicast", "anycast" };
ea_list *eal;
int i;
byte buf[256];
cli_printf(c, -1008, "\tType: %s %s %s", src_names[a->source], cast_names[a->cast], ip_scope_text(a->scope)); cli_printf(c, -1008, "\tType: %s %s %s", src_names[a->source], cast_names[a->cast], ip_scope_text(a->scope));
/* FIXME: Here we probably should print the dynamic attributes... */ for(eal=a->eattrs; eal; eal=eal->next)
for(i=0; i<eal->count; i++)
{
ea_format(&eal->attrs[i], buf);
cli_printf(c, -1012, "\t%s", buf);
}
} }
void void

View file

@ -675,11 +675,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
bsprintf(info, " (%d)", e->pref); bsprintf(info, " (%d)", e->pref);
cli_printf(c, -1007, "%-18s %s [%s %s%s]%s", ia, via, a->proto->name, tm, from, info); cli_printf(c, -1007, "%-18s %s [%s %s%s]%s", ia, via, a->proto->name, tm, from, info);
if (d->verbose) if (d->verbose)
{
rta_show(c, a); rta_show(c, a);
if (a->proto->proto->show_route_data)
a->proto->proto->show_route_data(e);
}
} }
static void static void

View file

@ -400,8 +400,8 @@ main(int argc, char **argv)
if_init(); if_init();
protos_build(); protos_build();
add_tail(&protocol_list, &proto_unix_kernel.n); proto_build(&proto_unix_kernel);
add_tail(&protocol_list, &proto_unix_iface.n); proto_build(&proto_unix_iface);
read_config(); read_config();