summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--doc/reply_codes1
-rw-r--r--nest/proto.c25
-rw-r--r--nest/protocol.h10
-rw-r--r--nest/route.h3
-rw-r--r--nest/rt-attr.c66
-rw-r--r--nest/rt-table.c6
-rw-r--r--sysdep/unix/main.c4
8 files changed, 99 insertions, 18 deletions
diff --git a/TODO b/TODO
index d3290e8a..0a4a4822 100644
--- a/TODO
+++ b/TODO
@@ -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!!
diff --git a/doc/reply_codes b/doc/reply_codes
index 140de95a..91466bee 100644
--- a/doc/reply_codes
+++ b/doc/reply_codes
@@ -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
diff --git a/nest/proto.c b/nest/proto.c
index c6a3d7d4..abf4a3cf 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 { \
@@ -344,6 +344,17 @@ protos_dump_all(void)
}
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)
{
init_list(&protocol_list);
@@ -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 b02ea022..2e64112f 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 f180d5e3..96ee580b 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 63f596ef..57c98b2d 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
*/
@@ -234,6 +236,60 @@ ea_list_copy(ea_list *o)
}
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)
{
int i;
@@ -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
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 3daa836c..6ad5b06f 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
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 121ec9dc..39ac3521 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -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();