diff options
Diffstat (limited to 'bgpd/bgp_aspath.c')
-rw-r--r-- | bgpd/bgp_aspath.c | 176 |
1 files changed, 166 insertions, 10 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 6ab29376..71d510ec 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "stream.h" #include "jhash.h" #include "filter.h" +#include "linklist.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_aspath.h" @@ -427,7 +428,7 @@ aspath_count_confeds (struct aspath *aspath) } unsigned int -aspath_count_hops (struct aspath *aspath) +aspath_count_hops (const struct aspath *aspath) { int count = 0; struct assegment *seg = aspath->segments; @@ -471,13 +472,11 @@ aspath_highest (struct aspath *aspath) struct assegment *seg = aspath->segments; as_t highest = 0; unsigned int i; - + while (seg) { for (i = 0; i < seg->length; i++) - if (seg->as[i] > highest - && (seg->as[i] < BGP_PRIVATE_AS_MIN - || seg->as[i] > BGP_PRIVATE_AS_MAX)) + if (seg->as[i] > highest && !BGP_AS_IS_PRIVATE(seg->as[i])) highest = seg->as[i]; seg = seg->next; } @@ -1065,6 +1064,9 @@ aspath_aggregate (struct aspath *as1, struct aspath *as2) if (match != minlen || match != seg1->length || seg1->length != seg2->length) break; + /* We are moving on to the next segment to reset match */ + else + match = 0; seg1 = seg1->next; seg2 = seg2->next; @@ -1146,20 +1148,44 @@ int aspath_private_as_check (struct aspath *aspath) { struct assegment *seg; - + if ( !(aspath && aspath->segments) ) return 0; - + seg = aspath->segments; while (seg) { int i; - + + for (i = 0; i < seg->length; i++) + { + if (!BGP_AS_IS_PRIVATE(seg->as[i])) + return 0; + } + seg = seg->next; + } + return 1; +} + +/* Return True if the entire ASPATH consist of the specified ASN */ +int +aspath_single_asn_check (struct aspath *aspath, as_t asn) +{ + struct assegment *seg; + + if ( !(aspath && aspath->segments) ) + return 0; + + seg = aspath->segments; + + while (seg) + { + int i; + for (i = 0; i < seg->length; i++) { - if ( (seg->as[i] < BGP_PRIVATE_AS_MIN) - || (seg->as[i] > BGP_PRIVATE_AS_MAX) ) + if (seg->as[i] != asn) return 0; } seg = seg->next; @@ -1167,6 +1193,132 @@ aspath_private_as_check (struct aspath *aspath) return 1; } +/* Replace all instances of the target ASN with our own ASN */ +struct aspath * +aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, + as_t our_asn) +{ + struct aspath *new; + struct assegment *seg; + + new = aspath_dup(aspath); + seg = new->segments; + + while (seg) + { + int i; + + for (i = 0; i < seg->length; i++) + { + if (seg->as[i] == target_asn) + seg->as[i] = our_asn; + } + seg = seg->next; + } + + aspath_str_update(new); + return new; +} + +/* Replace all private ASNs with our own ASN */ +struct aspath * +aspath_replace_private_asns (struct aspath *aspath, as_t asn) +{ + struct aspath *new; + struct assegment *seg; + + new = aspath_dup(aspath); + seg = new->segments; + + while (seg) + { + int i; + + for (i = 0; i < seg->length; i++) + { + if (BGP_AS_IS_PRIVATE(seg->as[i])) + seg->as[i] = asn; + } + seg = seg->next; + } + + aspath_str_update(new); + return new; +} + +/* Remove all private ASNs */ +struct aspath * +aspath_remove_private_asns (struct aspath *aspath) +{ + struct aspath *new; + struct assegment *seg; + struct assegment *new_seg; + struct assegment *last_new_seg; + int i; + int j; + int public = 0; + + new = XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath)); + + new_seg = NULL; + last_new_seg = NULL; + seg = aspath->segments; + while (seg) + { + public = 0; + for (i = 0; i < seg->length; i++) + { + // ASN is public + if (!BGP_AS_IS_PRIVATE(seg->as[i])) + { + public++; + } + } + + // The entire segment is private so skip it + if (!public) + { + seg = seg->next; + continue; + } + + // The entire segment is public so copy it + else if (public == seg->length) + { + new_seg = assegment_dup (seg); + } + + // The segment is a mix of public and private ASNs. Copy as many spots as + // there are public ASNs then come back and fill in only the public ASNs. + else + { + new_seg = assegment_new (seg->type, public); + j = 0; + for (i = 0; i < seg->length; i++) + { + // ASN is public + if (!BGP_AS_IS_PRIVATE(seg->as[i])) + { + new_seg->as[j] = seg->as[i]; + j++; + } + } + } + + // This is the first segment so set the aspath segments pointer to this one + if (!last_new_seg) + new->segments = new_seg; + else + last_new_seg->next = new_seg; + + last_new_seg = new_seg; + seg = seg->next; + } + + aspath_str_update(new); + return new; +} + /* AS path confed check. If aspath contains confed set or sequence then return 1. */ int aspath_confed_check (struct aspath *aspath) @@ -1443,6 +1595,10 @@ aspath_cmp_left (const struct aspath *aspath1, const struct aspath *aspath2) seg1 = aspath1->segments; seg2 = aspath2->segments; + /* If both paths are originated in this AS then we do want to compare MED */ + if (!seg1 && !seg2) + return 1; + /* find first non-confed segments for each */ while (seg1 && ((seg1->type == AS_CONFED_SEQUENCE) || (seg1->type == AS_CONFED_SET))) |