Commit 3991d84e authored by Martin Mareš's avatar Martin Mareš

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.
parent f8809249
......@@ -24,6 +24,8 @@ Documentation
Globals
~~~~~~~
- right usage of DBG vs. debug
- kill preconfigs?
- check dump functions
- cleanup debugging calls
- logging and tracing; use appropriate log levels
- check incoming packets and log errors!!
......
......@@ -35,6 +35,7 @@ Reply codes of BIRD command-line interface
1009 Static route list
1010 Symbol list
1011 Uptime
1012 Route extended attribute list
8000 Reply too long
8001 Route not found
......
......@@ -22,7 +22,7 @@
static pool *proto_pool;
list protocol_list;
static list protocol_list;
static list proto_list;
#define WALK_PROTO_LIST(p) do { \
......@@ -343,6 +343,17 @@ protos_dump_all(void)
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
protos_build(void)
{
......@@ -352,21 +363,21 @@ protos_build(void)
init_list(&inactive_proto_list);
init_list(&initial_proto_list);
init_list(&flush_proto_list);
add_tail(&protocol_list, &proto_device.n);
proto_build(&proto_device);
#ifdef CONFIG_RIP
add_tail(&protocol_list, &proto_rip.n);
proto_build(&proto_rip);
#endif
#ifdef CONFIG_STATIC
add_tail(&protocol_list, &proto_static.n);
proto_build(&proto_static);
#endif
#ifdef CONFIG_OSPF
add_tail(&protocol_list, &proto_ospf.n);
proto_build(&proto_ospf);
#endif
#ifdef CONFIG_PIPE
add_tail(&protocol_list, &proto_pipe.n);
proto_build(&proto_pipe);
#endif
#ifdef CONFIG_BGP
add_tail(&protocol_list, &proto_bgp.n);
proto_build(&proto_bgp);
#endif
proto_pool = rp_new(&root_pool, "Protocols");
proto_flush_event = ev_new(proto_pool);
......
......@@ -24,6 +24,7 @@ struct config;
struct proto;
struct event;
struct ea_list;
struct eattr;
struct symbol;
/*
......@@ -35,6 +36,7 @@ struct protocol {
char *name;
char *template; /* Template for automatic generation of names */
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 (*postconfig)(struct proto_config *); /* After configuring each instance */
......@@ -46,16 +48,19 @@ struct protocol {
int (*shutdown)(struct proto *); /* Stop the instance */
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 (*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 proto_build(struct protocol *);
void protos_preconfig(struct config *);
void protos_postconfig(struct config *);
void protos_commit(struct config *new, struct config *old, int force_restart);
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
......@@ -146,7 +151,6 @@ struct proto {
/* Hic sunt protocol-specific data */
};
void proto_build(struct proto_config *);
void *proto_new(struct proto_config *, unsigned size);
void *proto_config_new(struct protocol *, unsigned size);
......
......@@ -283,6 +283,7 @@ typedef struct eattr {
#define EAP_GENERIC 0 /* Generic attributes */
#define EAP_BGP 1 /* BGP attributes */
#define EAP_RIP 2 /* RIP */
#define EAP_MAX 3
#define EA_CODE(proto,id) (((proto) << 8) | (id))
#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); }
void rta_show(struct cli *, rta *);
extern struct protocol *attr_class_to_protocol[EAP_MAX];
/*
* Default protocol preferences
*/
......
......@@ -19,6 +19,8 @@
static slab *rta_slab;
static pool *rta_pool;
struct protocol *attr_class_to_protocol[EAP_MAX];
/*
* Extended Attributes
*/
......@@ -233,6 +235,60 @@ ea_list_copy(ea_list *o)
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
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",
"BGP" };
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));
/* 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
......
......@@ -675,11 +675,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
bsprintf(info, " (%d)", e->pref);
cli_printf(c, -1007, "%-18s %s [%s %s%s]%s", ia, via, a->proto->name, tm, from, info);
if (d->verbose)
{
rta_show(c, a);
if (a->proto->proto->show_route_data)
a->proto->proto->show_route_data(e);
}
rta_show(c, a);
}
static void
......
......@@ -400,8 +400,8 @@ main(int argc, char **argv)
if_init();
protos_build();
add_tail(&protocol_list, &proto_unix_kernel.n);
add_tail(&protocol_list, &proto_unix_iface.n);
proto_build(&proto_unix_kernel);
proto_build(&proto_unix_iface);
read_config();
......
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