]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Prints full community lists during 'show route all'.
authorOndrej Zajicek <santiago@crfreenet.org>
Sun, 3 Jul 2011 17:43:30 +0000 (19:43 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Sun, 3 Jul 2011 17:43:30 +0000 (19:43 +0200)
filter/filter.c
nest/a-set.c
nest/attrs.h
nest/cli.c
nest/cli.h
nest/route.h
nest/rt-attr.c
proto/bgp/attrs.c

index 913bd086113fa37e1a38d2920d0870832ae3b614..0f44a6eea7c03871b8c97e7846fd71e5b890a678 100644 (file)
@@ -401,7 +401,7 @@ val_print(struct f_val v)
   case T_SET: tree_print(v.val.t); return;
   case T_ENUM: logn("(enum %x)%d", v.type, v.val.i); return;
   case T_PATH: as_path_format(v.val.ad, buf2, 1000); logn("(path %s)", buf2); return;
-  case T_CLIST: int_set_format(v.val.ad, 1, buf2, 1000); logn("(clist %s)", buf2); return;
+  case T_CLIST: int_set_format(v.val.ad, 1, -1, buf2, 1000); logn("(clist %s)", buf2); return;
   case T_PATH_MASK: pm_format(v.val.path_mask, buf2, 1000); logn("(pathmask%s)", buf2); return;
   default: logn( "[unknown type %x]", v.type ); return;
   }
index f41b163d1e037f3b04a25358f56c057f1296c46e..3cbd63553f513e3a87f926b05b29ffd82f4a798c 100644 (file)
 #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
index 16fb35af273b40c943bf1c1213cf62bed6ab7a99..6ce5755fe04bd815dd1909c45d92dd0898360c9f 100644 (file)
@@ -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);
index 4d2b8fd06e6dbc735ed997ba835ce7d433a60a47..a61518b59cd2889dc4578f4a6f3565108688eb17 100644 (file)
@@ -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;
 
index 57414a29eb9cff81b5505586a41d459b4a122145..ea64680abdc40adb03cdb739169e022de3c706e8 100644 (file)
@@ -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;
index 236882ece3bd4c66e61a301d603431424b67331a..c77fe41735d49e9ebfe32bdc1853db8a7e431a6e 100644 (file)
@@ -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 */
index 5a7dd09a3d49ef570c8ba578c7cada1b13c7bfe9..486a543d3d555d11d012af32de3b91c91264329e 100644 (file)
@@ -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]);
 }
 
 /**
index 95eee9aa82b20b456bd83fd098b1c4f0e6bcb1a9..83ca24983f698cd21076400ca82561fa2aa87afe 100644 (file)
@@ -255,9 +255,10 @@ bgp_check_cluster_list(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
 }
 
 static void
-bgp_format_cluster_list(eattr *a, byte *buf, int buflen UNUSED)
+bgp_format_cluster_list(eattr *a, byte *buf, int buflen)
 {
-  int_set_format(a->u.ptr, 0, buf, buflen);
+  /* Truncates cluster lists larger than buflen, probably not a problem */
+  int_set_format(a->u.ptr, 0, -1, buf, buflen);
 }
 
 static int
@@ -735,13 +736,6 @@ bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate)
   for(i=0; i<cnt; i++)
     {
       a = &new->attrs[i];
-#ifdef LOCAL_DEBUG
-      {
-       byte buf[EA_FORMAT_BUF_SIZE];
-       ea_format(a, buf);
-       DBG("\t%s\n", buf);
-      }
-#endif
       if (EA_PROTO(a->id) != EAP_BGP)
        continue;
       code = EA_ID(a->id);