summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_aspath.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_aspath.c')
-rw-r--r--bgpd/bgp_aspath.c176
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)))