From 11cb620266035ffbe17b21c4a174380cb8b6a521 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Sun, 26 Oct 2008 22:36:08 +0100 Subject: Implementation of 4B ASN support for BGP --- nest/a-path.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++---------- nest/attrs.h | 21 ++++-- 2 files changed, 191 insertions(+), 39 deletions(-) (limited to 'nest') diff --git a/nest/a-path.c b/nest/a-path.c index 1b08f80..f466691 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -14,38 +14,139 @@ #include "lib/unaligned.h" #include "lib/string.h" + +/* Global AS4 support, shared by all BGP instances. + * This specifies whether BA_AS_PATH attributes contain 2 or 4 B per ASN + */ + +int bgp_as4_support = 1; + +static void +put_as(byte *data, u32 as) +{ + if (bgp_as4_support) + put_u32(data, as); + else if (as <= 0xFFFF) + put_u16(data, as); + else + bug("put_as: Try to put 32bit AS to 16bit AS Path"); +} + +static inline u32 +get_as(byte *data) +{ + return bgp_as4_support ? get_u32(data) : get_u16(data); +} + struct adata * -as_path_prepend(struct linpool *pool, struct adata *olda, int as) +as_path_prepend(struct linpool *pool, struct adata *olda, u32 as) { + int bs = bgp_as4_support ? 4 : 2; struct adata *newa; - if (olda->length && olda->data[0] == AS_PATH_SEQUENCE && - olda->data[1] < 255) /* Starting with sequence => just prepend the AS number */ + if (olda->length && olda->data[0] == AS_PATH_SEQUENCE && olda->data[1] < 255) + /* Starting with sequence => just prepend the AS number */ { - newa = lp_alloc(pool, sizeof(struct adata) + olda->length + 2); - newa->length = olda->length + 2; - newa->data[0] = 2; + int nl = olda->length + bs; + newa = lp_alloc(pool, sizeof(struct adata) + nl); + newa->length = nl; + newa->data[0] = AS_PATH_SEQUENCE; newa->data[1] = olda->data[1] + 1; - memcpy(newa->data+4, olda->data+2, olda->length-2); + memcpy(newa->data + bs + 2, olda->data + 2, olda->length - 2); } - else /* Create new path segment */ + else /* Create new path segment */ { - newa = lp_alloc(pool, sizeof(struct adata) + olda->length + 4); - newa->length = olda->length + 4; - newa->data[0] = 2; + int nl = olda->length + bs + 2; + newa = lp_alloc(pool, sizeof(struct adata) + nl); + newa->length = nl; + newa->data[0] = AS_PATH_SEQUENCE; newa->data[1] = 1; - memcpy(newa->data+4, olda->data, olda->length); + memcpy(newa->data + bs + 2, olda->data, olda->length); } - put_u16(newa->data+2, as); + put_as(newa->data + 2, as); return newa; } +int +as_path_convert_to_old(struct adata *path, byte *dst, int *new_used) +{ + byte *src = path->data; + byte *src_end = src + path->length; + byte *dst_start = dst; + u32 as; + int i, n; + *new_used = 0; + + while (src < src_end) + { + n = src[1]; + *dst++ = *src++; + *dst++ = *src++; + + for(i=0; i 0xFFFF) + { + as = AS_TRANS; + *new_used = 1; + } + put_u16(dst, as); + src += 4; + dst += 2; + } + } + + return dst - dst_start; +} + +int +as_path_convert_to_new(struct adata *path, byte *dst, int req_as) +{ + byte *src = path->data; + byte *src_end = src + path->length; + byte *dst_start = dst; + u32 as; + int i, t, n; + + + while ((src < src_end) && (req_as > 0)) + { + t = *src++; + n = *src++; + + if (t == AS_PATH_SEQUENCE) + { + if (n > req_as) + n = req_as; + + req_as -= n; + } + else // t == AS_PATH_SET + req_as--; + + *dst++ = t; + *dst++ = n; + + for(i=0; idata; byte *e = p + path->length; - byte *end = buf + size - 8; + byte *end = buf + size - 16; int sp = 1; int l, isset; @@ -69,8 +170,8 @@ as_path_format(struct adata *path, byte *buf, unsigned int size) { if (!sp) *buf++ = ' '; - buf += bsprintf(buf, "%d", get_u16(p)); - p += 2; + buf += bsprintf(buf, "%u", get_as(p)); + p += bs; sp = 0; } if (isset) @@ -86,6 +187,7 @@ as_path_format(struct adata *path, byte *buf, unsigned int size) int as_path_getlen(struct adata *path) { + int bs = bgp_as4_support ? 4 : 2; int res = 0; u8 *p = path->data; u8 *q = p+path->length; @@ -95,8 +197,8 @@ as_path_getlen(struct adata *path) { switch (*p++) { - case AS_PATH_SET: len = *p++; res++; p += 2*len; break; - case AS_PATH_SEQUENCE: len = *p++; res+=len; p += 2*len; break; + case AS_PATH_SET: len = *p++; res++; p += bs * len; break; + case AS_PATH_SEQUENCE: len = *p++; res += len; p += bs * len; break; default: bug("as_path_getlen: Invalid path segment"); } } @@ -104,9 +206,11 @@ as_path_getlen(struct adata *path) } int -as_path_get_first(struct adata *path) +as_path_get_first(struct adata *path, u32 *orig_as) { - int res = -1; + int bs = bgp_as4_support ? 4 : 2; + int found = 0; + u32 res = 0; u8 *p = path->data; u8 *q = p+path->length; int len; @@ -117,36 +221,70 @@ as_path_get_first(struct adata *path) { case AS_PATH_SET: if (len = *p++) - res = get_u16(p); - p += 2*len; + { + found = 1; + res = get_as(p); + p += bs * len; + } break; case AS_PATH_SEQUENCE: if (len = *p++) - res = get_u16(p+2*(len-1)); - p += 2*len; + { + found = 1; + res = get_as(p + bs * (len - 1)); + p += bs * len; + } break; default: bug("as_path_get_first: Invalid path segment"); } } - return res; + + *orig_as = res; + return found; } +int +as_path_is_member(struct adata *path, u32 as) +{ + int bs = bgp_as4_support ? 4 : 2; + u8 *p = path->data; + u8 *q = p+path->length; + int i, n; + + while (pnext; if (!mask) return next == q; \ - asterisk = (mask->val == PM_ANY); \ + asterisk = mask->any; \ if (asterisk) { mask = mask->next; if (!mask) { return 1; } } \ } while(0) int as_path_match(struct adata *path, struct f_path_mask *mask) { + int bs = bgp_as4_support ? 4 : 2; int i; int asterisk = 0; u8 *p = path->data; u8 *q = p+path->length; int len; u8 *next; + u32 as; - asterisk = (mask->val == PM_ANY); + asterisk = mask->any; if (asterisk) { mask = mask->next; if (!mask) return 1; } @@ -156,20 +294,21 @@ as_path_match(struct adata *path, struct f_path_mask *mask) len = *p++; { u8 *p_save = p; - next = p_save + 2*len; + next = p_save + bs * len; retry: p = p_save; for (i=0; ival)) { + as = get_as(p); + if (asterisk && (as == mask->val)) { MASK_PLUS; goto retry; } - if (!asterisk && (get_u16(p) == mask->val)) { + if (!asterisk && (as == mask->val)) { p = next; MASK_PLUS; goto okay; } - p+=2; + p += bs; } if (!asterisk) return 0; @@ -180,15 +319,15 @@ as_path_match(struct adata *path, struct f_path_mask *mask) case AS_PATH_SEQUENCE: len = *p++; for (i=0; ival)) + as = get_as(p); + if (asterisk && (as == mask->val)) MASK_PLUS; else if (!asterisk) { - if (get_u16(p) != mask->val) + if (as != mask->val) return 0; MASK_PLUS; } - p+=2; + p += bs; } break; diff --git a/nest/attrs.h b/nest/attrs.h index abd6b9e..f63f2e4 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -14,16 +14,29 @@ #define AS_PATH_SET 1 /* Types of path segments */ #define AS_PATH_SEQUENCE 2 -struct adata *as_path_prepend(struct linpool *pool, struct adata *olda, int as); +#define AS_PATH_MAXLEN 10000 + +#define AS_TRANS 23456 +/* AS_TRANS is used when we need to store 32bit ASN larger than 0xFFFF + * to 16bit slot (like in 16bit AS_PATH). See RFC 4893 for details + */ + +struct adata *as_path_prepend(struct linpool *pool, struct adata *olda, u32 as); +int as_path_convert_to_old(struct adata *path, byte *dst, int *new_used); +int as_path_convert_to_new(struct adata *path, byte *dst, int req_as); void as_path_format(struct adata *path, byte *buf, unsigned int size); int as_path_getlen(struct adata *path); -int as_path_get_first(struct adata *path); +int as_path_get_first(struct adata *path, u32 *orig_as); +int as_path_is_member(struct adata *path, u32 as); + struct f_path_mask { struct f_path_mask *next; - int val; + u32 val; + int any; }; -#define PM_ANY -1 + +// #define PM_ANY -1 int as_path_match(struct adata *path, struct f_path_mask *mask); -- cgit v1.2.3 From 4847a894bf7d4852325c3f1ea4bb4890054a1f66 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Sun, 26 Oct 2008 22:45:09 +0100 Subject: Implementation of route reflection for BGP --- nest/a-set.c | 8 +++++--- nest/attrs.h | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'nest') diff --git a/nest/a-set.c b/nest/a-set.c index 4440714..69c090b 100644 --- a/nest/a-set.c +++ b/nest/a-set.c @@ -40,10 +40,12 @@ int_set_format(struct adata *set, byte *buf, unsigned int size) struct adata * int_set_add(struct linpool *pool, struct adata *list, u32 val) { - struct adata *res = lp_alloc(pool, list->length + sizeof(struct adata) + 4); - res->length = list->length+4; + int len = list ? list->length : 0; + struct adata *res = lp_alloc(pool, len + sizeof(struct adata) + 4); + res->length = len + 4; * (u32 *) res->data = val; - memcpy((char *) res->data + 4, list->data, list->length); + if (list) + memcpy((char *) res->data + 4, list->data, list->length); return res; } diff --git a/nest/attrs.h b/nest/attrs.h index f63f2e4..aaa5f4a 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -47,4 +47,7 @@ struct adata *int_set_add(struct linpool *pool, struct adata *list, u32 val); int int_set_contains(struct adata *list, u32 val); struct adata *int_set_del(struct linpool *pool, struct adata *list, u32 val); +static inline int int_set_get_size(struct adata *list) +{ return list->length / 4; } + #endif -- cgit v1.2.3 From b6bf284a905412cfe107b4967e55649e6194187e Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Sun, 26 Oct 2008 22:59:21 +0100 Subject: Bugfixes in MULIT_EXIT_DISC attribute handling. - Old MED handling was completely different from behavior specified in RFCs - for example they havn't been propagated to neighboring areas. - Update tie-breaking according to RFC 4271. - Change default value for 'default bgp_med' configuration option according to RFC 4271. --- nest/a-path.c | 14 ++++++++++++++ nest/attrs.h | 1 + 2 files changed, 15 insertions(+) (limited to 'nest') diff --git a/nest/a-path.c b/nest/a-path.c index f466691..5e3ecfd 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -243,6 +243,20 @@ as_path_get_first(struct adata *path, u32 *orig_as) return found; } +int +as_path_get_last(struct adata *path, u32 *last_as) +{ + u8 *p = path->data; + + if ((path->length == 0) || (p[0] != AS_PATH_SEQUENCE) || (p[1] == 0)) + return 0; + else + { + *last_as = get_as(p+2); + return 1; + } +} + int as_path_is_member(struct adata *path, u32 as) { diff --git a/nest/attrs.h b/nest/attrs.h index aaa5f4a..fee2c2c 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -27,6 +27,7 @@ int as_path_convert_to_new(struct adata *path, byte *dst, int req_as); void as_path_format(struct adata *path, byte *buf, unsigned int size); int as_path_getlen(struct adata *path); int as_path_get_first(struct adata *path, u32 *orig_as); +int as_path_get_last(struct adata *path, u32 *last_as); int as_path_is_member(struct adata *path, u32 as); -- cgit v1.2.3