diff options
Diffstat (limited to 'bgpd/bgp_aspath.c')
-rw-r--r-- | bgpd/bgp_aspath.c | 82 |
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 |