summaryrefslogtreecommitdiffstats
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/a-set.c50
-rw-r--r--nest/attrs.h2
-rw-r--r--nest/cli.c2
-rw-r--r--nest/cli.h3
-rw-r--r--nest/route.h2
-rw-r--r--nest/rt-attr.c102
6 files changed, 101 insertions, 60 deletions
diff --git a/nest/a-set.c b/nest/a-set.c
index f41b163..3cbd635 100644
--- a/nest/a-set.c
+++ b/nest/a-set.c
@@ -13,33 +13,53 @@
#include "lib/resource.h"
#include "lib/string.h"
-void
-int_set_format(struct adata *set, int way, byte *buf, unsigned int size)
+/**
+ * int_set_format - format an &set for printing
+ * @set: set attribute to be formatted
+ * @way: style of format (0 for router ID list, 1 for community list)
+ * @from: starting position in set
+ * @buf: destination buffer
+ * @size: size of buffer
+ *
+ * This function takes a set attribute and formats it. @way specifies
+ * the style of format (router ID / community). @from argument can be
+ * used to specify the first printed value for the purpose of printing
+ * untruncated sets even with smaller buffers. If the output fits in
+ * the buffer, 0 is returned, otherwise the position of the first not
+ * printed item is returned. This value can be used as @from argument
+ * in subsequent calls. If truncated output suffices, -1 can be
+ * instead used as @from, in that case " ..." is eventually added at
+ * the buffer to indicate truncation.
+ */
+int
+int_set_format(struct adata *set, int way, int from, byte *buf, unsigned int size)
{
u32 *z = (u32 *) set->data;
- int l = set->length / 4;
- int sp = 1;
- byte *end = buf + size - 16;
+ byte *end = buf + size - 24;
+ int to = set->length / 4;
+ int i;
- while (l--)
+ for (i = MAX(from, 0); i < to; i++)
{
- if (!sp)
- *buf++ = ' ';
if (buf > end)
{
- strcpy(buf, "...");
- return;
+ if (from < 0)
+ strcpy(buf, " ...");
+ else
+ *buf = 0;
+ return i;
}
+ if (i > from)
+ *buf++ = ' ';
+
if (way)
- buf += bsprintf(buf, "(%d,%d)", *z >> 16, *z & 0xffff);
+ buf += bsprintf(buf, "(%d,%d)", z[i] >> 16, z[i] & 0xffff);
else
- buf += bsprintf(buf, "%R", *z);
-
- z++;
- sp = 0;
+ buf += bsprintf(buf, "%R", z[i]);
}
*buf = 0;
+ return 0;
}
int
diff --git a/nest/attrs.h b/nest/attrs.h
index 16fb35a..6ce5755 100644
--- a/nest/attrs.h
+++ b/nest/attrs.h
@@ -50,7 +50,7 @@ int as_path_match(struct adata *path, struct f_path_mask *mask);
/* a-set.c */
-void int_set_format(struct adata *set, int way, byte *buf, unsigned int size);
+int int_set_format(struct adata *set, int way, int from, byte *buf, unsigned int size);
struct adata *int_set_add(struct linpool *pool, struct adata *list, u32 val);
int int_set_contains(struct adata *list, u32 val);
struct adata *int_set_del(struct linpool *pool, struct adata *list, u32 val);
diff --git a/nest/cli.c b/nest/cli.c
index 4d2b8fd..a61518b 100644
--- a/nest/cli.c
+++ b/nest/cli.c
@@ -120,7 +120,7 @@ void
cli_printf(cli *c, int code, char *msg, ...)
{
va_list args;
- byte buf[1024];
+ byte buf[CLI_LINE_SIZE];
int cd = code;
int size, cnt;
diff --git a/nest/cli.h b/nest/cli.h
index 57414a2..ea64680 100644
--- a/nest/cli.h
+++ b/nest/cli.h
@@ -16,6 +16,9 @@
#define CLI_TX_BUF_SIZE 4096
#define CLI_MAX_ASYNC_QUEUE 4096
+#define CLI_MSG_SIZE 500
+#define CLI_LINE_SIZE 512
+
struct cli_out {
struct cli_out *next;
byte *wpos, *outpos, *end;
diff --git a/nest/route.h b/nest/route.h
index 236882e..c77fe41 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -394,8 +394,6 @@ unsigned ea_scan(ea_list *); /* How many bytes do we need for merged ea_list */
void ea_merge(ea_list *from, ea_list *to); /* Merge sub-lists to allocated buffer */
int ea_same(ea_list *x, ea_list *y); /* Test whether two ea_lists are identical */
unsigned int ea_hash(ea_list *e); /* Calculate 16-bit hash value */
-void ea_format(eattr *e, byte *buf);
-#define EA_FORMAT_BUF_SIZE 256
ea_list *ea_append(ea_list *to, ea_list *what);
int mpnh__same(struct mpnh *x, struct mpnh *y); /* Compare multipath nexthops */
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index 5a7dd09..486a543 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -430,81 +430,105 @@ get_generic_attr(eattr *a, byte **buf, int buflen UNUSED)
return GA_UNKNOWN;
}
+static inline void
+opaque_format(struct adata *ad, byte *buf, unsigned int size)
+{
+ byte *bound = buf + size - 10;
+ int i;
+
+ for(i = 0; i < ad->length; i++)
+ {
+ if (buf > bound)
+ {
+ strcpy(buf, " ...");
+ return;
+ }
+ if (i)
+ *buf++ = ' ';
+
+ buf += bsprintf(buf, "%02x", ad->data[i]);
+ }
+
+ *buf = 0;
+ return;
+}
+
+static inline void
+ea_show_int_set(struct cli *c, struct adata *ad, int way, byte *pos, byte *buf, byte *end)
+{
+ int i = int_set_format(ad, way, 0, pos, end - pos);
+ cli_printf(c, -1012, "%s", buf);
+ while (i)
+ {
+ i = int_set_format(ad, way, i, buf, end - buf - 1);
+ cli_printf(c, -1012, "\t%s", buf);
+ }
+}
+
/**
- * ea_format - format an &eattr for printing
- * @e: attribute to be formatted
- * @buf: destination buffer of size %EA_FORMAT_BUF_SIZE
+ * ea_show - print an &eattr to CLI
+ * @c: destination CLI
+ * @e: attribute to be printed
*
- * This function takes an extended attribute represented by its
- * &eattr structure and formats it nicely for printing according
- * to the type information.
+ * This function takes an extended attribute represented by its &eattr
+ * structure and prints it to the CLI according to the type information.
*
* If the protocol defining the attribute provides its own
* get_attr() hook, it's consulted first.
*/
void
-ea_format(eattr *e, byte *buf)
+ea_show(struct cli *c, eattr *e)
{
struct protocol *p;
int status = GA_UNKNOWN;
- unsigned int i;
struct adata *ad = (e->type & EAF_EMBEDDED) ? NULL : e->u.ptr;
- byte *end = buf + EA_FORMAT_BUF_SIZE - 1;
+ byte buf[CLI_MSG_SIZE];
+ byte *pos = buf, *end = buf + sizeof(buf);
if (p = attr_class_to_protocol[EA_PROTO(e->id)])
{
- buf += bsprintf(buf, "%s.", p->name);
+ pos += bsprintf(pos, "%s.", p->name);
if (p->get_attr)
- status = p->get_attr(e, buf, end - buf);
- buf += strlen(buf);
+ status = p->get_attr(e, pos, end - pos);
+ pos += strlen(pos);
}
else if (EA_PROTO(e->id))
- buf += bsprintf(buf, "%02x.", EA_PROTO(e->id));
+ pos += bsprintf(pos, "%02x.", EA_PROTO(e->id));
else
- status = get_generic_attr(e, &buf, end - buf);
+ status = get_generic_attr(e, &pos, end - pos);
if (status < GA_NAME)
- buf += bsprintf(buf, "%02x", EA_ID(e->id));
+ pos += bsprintf(pos, "%02x", EA_ID(e->id));
if (status < GA_FULL)
{
- *buf++ = ':';
- *buf++ = ' ';
+ *pos++ = ':';
+ *pos++ = ' ';
switch (e->type & EAF_TYPE_MASK)
{
case EAF_TYPE_INT:
- bsprintf(buf, "%u", e->u.data);
+ bsprintf(pos, "%u", e->u.data);
break;
case EAF_TYPE_OPAQUE:
- *buf = 0;
- for(i=0; i<ad->length; i++)
- {
- if (buf > end - 8)
- {
- strcpy(buf, " ...");
- break;
- }
- if (i)
- *buf++ = ' ';
- buf += bsprintf(buf, "%02x", ad->data[i]);
- }
+ opaque_format(ad, pos, end - pos);
break;
case EAF_TYPE_IP_ADDRESS:
- bsprintf(buf, "%I", *(ip_addr *) ad->data);
+ bsprintf(pos, "%I", *(ip_addr *) ad->data);
break;
case EAF_TYPE_ROUTER_ID:
- bsprintf(buf, "%R", e->u.data);
+ bsprintf(pos, "%R", e->u.data);
break;
case EAF_TYPE_AS_PATH:
- as_path_format(ad, buf, end - buf);
+ as_path_format(ad, pos, end - pos);
break;
case EAF_TYPE_INT_SET:
- int_set_format(ad, 1, buf, end - buf);
- break;
+ ea_show_int_set(c, ad, 1, pos, buf, end);
+ return;
case EAF_TYPE_UNDEF:
default:
- bsprintf(buf, "<type %02x>", e->type);
+ bsprintf(pos, "<type %02x>", e->type);
}
}
+ cli_printf(c, -1012, "%s", buf);
}
/**
@@ -834,17 +858,13 @@ rta_show(struct cli *c, rta *a, ea_list *eal)
"RIP", "OSPF", "OSPF-IA", "OSPF-E1", "OSPF-E2", "BGP", "pipe" };
static char *cast_names[] = { "unicast", "broadcast", "multicast", "anycast" };
int i;
- byte buf[EA_FORMAT_BUF_SIZE];
cli_printf(c, -1008, "\tType: %s %s %s", src_names[a->source], cast_names[a->cast], ip_scope_text(a->scope));
if (!eal)
eal = a->eattrs;
for(; eal; eal=eal->next)
for(i=0; i<eal->count; i++)
- {
- ea_format(&eal->attrs[i], buf);
- cli_printf(c, -1012, "\t%s", buf);
- }
+ ea_show(c, &eal->attrs[i]);
}
/**