summaryrefslogtreecommitdiff
path: root/bgpd/bgp_aspath.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_aspath.c')
-rw-r--r--bgpd/bgp_aspath.c82
1 files changed, 81 insertions, 1 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index d7e985d4..38c9caa6 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1225,6 +1225,81 @@ aspath_prepend (struct aspath *as1, struct aspath *as2)
/* Not reached */
}
+/* Iterate over AS_PATH segments and wipe all occurences of the
+ * listed AS numbers. Hence some segments may lose some or even
+ * all data on the way, the operation is implemented as a smarter
+ * version of aspath_dup(), which allocates memory to hold the new
+ * data, not the original. The new AS path is returned.
+ */
+struct aspath *
+aspath_filter_exclude (struct aspath * source, struct aspath * exclude_list)
+{
+ struct assegment * srcseg, * exclseg, * lastseg;
+ struct aspath * newpath;
+
+ newpath = aspath_new();
+ lastseg = NULL;
+
+ for (srcseg = source->segments; srcseg; srcseg = srcseg->next)
+ {
+ unsigned i, y, newlen = 0, done = 0, skip_as;
+ struct assegment * newseg;
+
+ /* Find out, how much ASns are we going to pick from this segment.
+ * We can't perform filtering right inline, because the size of
+ * the new segment isn't known at the moment yet.
+ */
+ for (i = 0; i < srcseg->length; i++)
+ {
+ skip_as = 0;
+ for (exclseg = exclude_list->segments; exclseg && !skip_as; exclseg = exclseg->next)
+ for (y = 0; y < exclseg->length; y++)
+ if (srcseg->as[i] == exclseg->as[y])
+ {
+ skip_as = 1;
+ // There's no sense in testing the rest of exclusion list, bail out.
+ break;
+ }
+ if (!skip_as)
+ newlen++;
+ }
+ /* newlen is now the number of ASns to copy */
+ if (!newlen)
+ continue;
+
+ /* Actual copying. Allocate memory and iterate once more, performing filtering. */
+ newseg = assegment_new (srcseg->type, newlen);
+ for (i = 0; i < srcseg->length; i++)
+ {
+ skip_as = 0;
+ for (exclseg = exclude_list->segments; exclseg && !skip_as; exclseg = exclseg->next)
+ for (y = 0; y < exclseg->length; y++)
+ if (srcseg->as[i] == exclseg->as[y])
+ {
+ skip_as = 1;
+ break;
+ }
+ if (skip_as)
+ continue;
+ newseg->as[done++] = srcseg->as[i];
+ }
+ /* At his point newlen must be equal to done, and both must be positive. Append
+ * the filtered segment to the gross result. */
+ if (!lastseg)
+ newpath->segments = newseg;
+ else
+ lastseg->next = newseg;
+ lastseg = newseg;
+ }
+ aspath_str_update (newpath);
+ /* We are happy returning even an empty AS_PATH, because the administrator
+ * might expect this very behaviour. There's a mean to avoid this, if necessary,
+ * by having a match rule against certain AS_PATH regexps in the route-map index.
+ */
+ aspath_free (source);
+ return newpath;
+}
+
/* Add specified AS to the leftmost of aspath. */
static struct aspath *
aspath_add_one_as (struct aspath *aspath, as_t asno, u_char type)
@@ -1741,11 +1816,16 @@ aspath_print (struct aspath *as)
}
/* Printing functions */
+/* Feed the AS_PATH to the vty; the suffix string follows it only in case
+ * AS_PATH wasn't empty.
+ */
void
-aspath_print_vty (struct vty *vty, const char *format, struct aspath *as)
+aspath_print_vty (struct vty *vty, const char *format, struct aspath *as, const char * suffix)
{
assert (format);
vty_out (vty, format, as->str);
+ if (strlen (as->str) && strlen (suffix))
+ vty_out (vty, "%s", suffix);
}
static void