From 3991d84e8fa9118a43149d4d3304726eb786bd46 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sat, 1 Apr 2000 10:19:47 +0000 Subject: 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. --- nest/proto.c | 25 ++++++++++++++++------ nest/protocol.h | 10 ++++++--- nest/route.h | 3 +++ nest/rt-attr.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- nest/rt-table.c | 6 +----- 5 files changed, 94 insertions(+), 16 deletions(-) (limited to 'nest') diff --git a/nest/proto.c b/nest/proto.c index c6a3d7d..abf4a3c 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -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); diff --git a/nest/protocol.h b/nest/protocol.h index b02ea02..2e64112 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -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); diff --git a/nest/route.h b/nest/route.h index f180d5e..96ee580 100644 --- a/nest/route.h +++ b/nest/route.h @@ -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 */ diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 63f596e..57c98b2 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -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; idata[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, "", 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; icount; i++) + { + ea_format(&eal->attrs[i], buf); + cli_printf(c, -1012, "\t%s", buf); + } } void diff --git a/nest/rt-table.c b/nest/rt-table.c index 3daa836..6ad5b06 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -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 -- cgit v1.2.3