[RFC,PATCH 2/2] BGP: Implement skip_private_as_path_prefix.
Lennert Buytenhek
buytenh at wantstofly.org
Sat Aug 12 21:31:13 CEST 2017
When skip_private_as_path_prefix is enabled for a BGP peer, leading
private AS numbers will be skipped when computing the length of AS
paths learned from this peer for the purpose of comparing path
lengths of different BGP-learned routes.
---
nest/a-path.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
nest/attrs.h | 1 +
proto/bgp/attrs.c | 8 +++---
proto/bgp/bgp.h | 1 +
proto/bgp/config.Y | 3 ++-
5 files changed, 82 insertions(+), 5 deletions(-)
diff --git a/nest/a-path.c b/nest/a-path.c
index b453f702..c2d8bdf8 100644
--- a/nest/a-path.c
+++ b/nest/a-path.c
@@ -193,6 +193,80 @@ as_path_getlen_int(struct adata *path, int bs)
}
int
+as_is_private(u32 as)
+{
+ if (as >= 64512 && as <= 65534)
+ return 1;
+ if (as >= 4200000000 && as <= 4294967294)
+ return 1;
+ return 0;
+}
+
+int
+as_set_is_private(u32 *as, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (!as_is_private(get_u32(as + i)))
+ return 0;
+
+ return 1;
+}
+
+int
+as_sequence_private_prefix_length(u32 *as, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (!as_is_private(get_u32(as + i)))
+ break;
+
+ return i;
+}
+
+int
+as_path_getlen_ext(struct adata *path, int skip_private)
+{
+ int res = 0;
+ u8 *p = path->data;
+ u8 *q = p+path->length;
+ int len;
+ int i;
+
+ while (p<q)
+ {
+ switch (*p++)
+ {
+ case AS_PATH_SET:
+ len = *p++;
+ if (skip_private && !as_set_is_private((u32 *)p, len))
+ skip_private = 0;
+ if (!skip_private)
+ res++;
+ p += BS * len;
+ break;
+ case AS_PATH_SEQUENCE:
+ len = *p++;
+ i = 0;
+ if (skip_private)
+ {
+ i = as_sequence_private_prefix_length((u32 *)p, len);
+ if (i < len)
+ skip_private = 0;
+ }
+ res += len - i;
+ p += BS * len;
+ break;
+ default:
+ bug("as_path_getlen_ext: Invalid path segment");
+ }
+ }
+ return res;
+}
+
+int
as_path_get_last(struct adata *path, u32 *orig_as)
{
int found = 0;
diff --git a/nest/attrs.h b/nest/attrs.h
index a34e64d3..d0808cd6 100644
--- a/nest/attrs.h
+++ b/nest/attrs.h
@@ -33,6 +33,7 @@ int as_path_convert_to_new(struct adata *path, byte *dst, int req_as);
void as_path_format(struct adata *path, byte *buf, uint size);
int as_path_getlen(struct adata *path);
int as_path_getlen_int(struct adata *path, int bs);
+int as_path_getlen_ext(struct adata *path, int skip_private);
int as_path_get_first(struct adata *path, u32 *orig_as);
int as_path_get_last(struct adata *path, u32 *last_as);
u32 as_path_get_last_nonaggregated(struct adata *path);
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 478c805c..ec6db1e5 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -1280,8 +1280,8 @@ bgp_rte_better(rte *new, rte *old)
{
x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
- n = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN;
- o = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN;
+ n = x ? as_path_getlen_ext(x->u.ptr, new_bgp->cf->skip_private_as_path_prefix) : AS_PATH_MAXLEN;
+ o = y ? as_path_getlen_ext(y->u.ptr, old_bgp->cf->skip_private_as_path_prefix) : AS_PATH_MAXLEN;
if (n < o)
return 1;
if (n > o)
@@ -1401,8 +1401,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
{
x = ea_find(pri->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
y = ea_find(sec->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
- p = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN;
- s = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN;
+ p = x ? as_path_getlen_ext(x->u.ptr, pri_bgp->cf->skip_private_as_path_prefix) : AS_PATH_MAXLEN;
+ s = y ? as_path_getlen_ext(y->u.ptr, sec_bgp->cf->skip_private_as_path_prefix) : AS_PATH_MAXLEN;
if (p != s)
return 0;
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 8652fae8..10fdeeda 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -52,6 +52,7 @@ struct bgp_config {
int allow_local_as; /* Allow that number of local ASNs in incoming AS_PATHs */
int allow_local_pref; /* Allow LOCAL_PREF in EBGP sessions */
int iebgp_peer; /* Peer has different AS but should be treated as internal peer */
+ int skip_private_as_path_prefix; /* Skip leading private ASes when comparing AS path lengths */
int gr_mode; /* Graceful restart mode (BGP_GR_*) */
int setkey; /* Set MD5 password to system SA/SP database */
unsigned gr_time; /* Graceful restart timeout */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index f01a6fb6..153747c6 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -28,7 +28,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY, BGP_LARGE_COMMUNITY,
- IEBGP_PEER)
+ IEBGP_PEER, SKIP_PRIVATE_AS_PATH_PREFIX)
CF_GRAMMAR
@@ -135,6 +135,7 @@ bgp_proto:
| bgp_proto GRACEFUL RESTART AWARE ';' { BGP_CFG->gr_mode = BGP_GR_AWARE; }
| bgp_proto GRACEFUL RESTART TIME expr ';' { BGP_CFG->gr_time = $5; }
| bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
+ | bgp_proto SKIP_PRIVATE_AS_PATH_PREFIX bool ';' { BGP_CFG->skip_private_as_path_prefix = $3; }
| bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
| bgp_proto CHECK LINK bool ';' { BGP_CFG->check_link = $4; }
| bgp_proto BFD bool ';' { BGP_CFG->bfd = $3; cf_check_bfd($3); }
--
2.13.4
More information about the Bird-users
mailing list