From 66dbdbd993115c57acafdb776d2165d0b4a90a45 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Sat, 1 Oct 2016 12:50:29 +0200 Subject: BGP: Support for large communities Add support for large communities (draft-ietf-idr-large-community), 96bit alternative to RFC 1997 communities. Thanks to Matt Griswold for the original patch. --- nest/a-set.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 2 deletions(-) (limited to 'nest/a-set.c') diff --git a/nest/a-set.c b/nest/a-set.c index a6116022..0484ab98 100644 --- a/nest/a-set.c +++ b/nest/a-set.c @@ -116,7 +116,7 @@ int ec_set_format(struct adata *set, int from, byte *buf, uint size) { u32 *z = int_set_get_data(set); - byte *end = buf + size - 24; + byte *end = buf + size - 64; int from2 = MAX(from, 0); int to = int_set_get_size(set); int i; @@ -141,6 +141,43 @@ ec_set_format(struct adata *set, int from, byte *buf, uint size) return 0; } +int +lc_format(byte *buf, lcomm lc) +{ + return bsprintf(buf, "(%d, %d, %d)", lc.asn, lc.ldp1, lc.ldp2); +} + +int +lc_set_format(struct adata *set, int from, byte *buf, uint bufsize) +{ + u32 *d = (u32 *) set->data; + byte *end = buf + bufsize - 64; + int from2 = MAX(from, 0); + int to = set->length / 4; + int i; + + for (i = from2; i < to; i += 3) + { + if (buf > end) + { + if (from < 0) + strcpy(buf, "..."); + else + buf[-1] = 0; + return i; + } + + buf += bsprintf(buf, "(%d, %d, %d)", d[i], d[i+1], d[i+2]); + *buf++ = ' '; + } + + if (i != from2) + buf--; + + *buf = 0; + return 0; +} + int int_set_contains(struct adata *list, u32 val) { @@ -177,6 +214,24 @@ ec_set_contains(struct adata *list, u64 val) return 0; } +int +lc_set_contains(struct adata *list, lcomm val) +{ + if (!list) + return 0; + + u32 *l = int_set_get_data(list); + int len = int_set_get_size(list); + int i; + + for (i = 0; i < len; i += 3) + if (lc_match(l, i, val)) + return 1; + + return 0; +} + + struct adata * int_set_add(struct linpool *pool, struct adata *list, u32 val) { @@ -208,13 +263,30 @@ ec_set_add(struct linpool *pool, struct adata *list, u64 val) if (list) memcpy(res->data, list->data, list->length); - u32 *l = (u32 *) (res->data + res->length - 8); + u32 *l = (u32 *) (res->data + olen); l[0] = ec_hi(val); l[1] = ec_lo(val); return res; } +struct adata * +lc_set_add(struct linpool *pool, struct adata *list, lcomm val) +{ + if (lc_set_contains(list, val)) + return list; + + int olen = list ? list->length : 0; + struct adata *res = lp_alloc(pool, sizeof(struct adata) + olen + LCOMM_LENGTH); + res->length = olen + LCOMM_LENGTH; + + if (list) + memcpy(res->data, list->data, list->length); + + lc_put((u32 *) (res->data + olen), val); + + return res; +} struct adata * int_set_del(struct linpool *pool, struct adata *list, u32 val) @@ -265,6 +337,27 @@ ec_set_del(struct linpool *pool, struct adata *list, u64 val) return res; } +struct adata * +lc_set_del(struct linpool *pool, struct adata *list, lcomm val) +{ + if (!lc_set_contains(list, val)) + return list; + + struct adata *res; + res = lp_alloc(pool, sizeof(struct adata) + list->length - LCOMM_LENGTH); + res->length = list->length - LCOMM_LENGTH; + + u32 *l = int_set_get_data(list); + u32 *k = int_set_get_data(res); + int len = int_set_get_size(list); + int i; + + for (i=0; i < len; i += 3) + if (! lc_match(l, i, val)) + k = lc_copy(k, l+i); + + return res; +} struct adata * int_set_union(struct linpool *pool, struct adata *l1, struct adata *l2) @@ -328,3 +421,33 @@ ec_set_union(struct linpool *pool, struct adata *l1, struct adata *l2) memcpy(res->data + l1->length, tmp, len); return res; } + +struct adata * +lc_set_union(struct linpool *pool, struct adata *l1, struct adata *l2) +{ + if (!l1) + return l2; + if (!l2) + return l1; + + struct adata *res; + int len = int_set_get_size(l2); + u32 *l = int_set_get_data(l2); + u32 tmp[len]; + u32 *k = tmp; + int i; + + for (i = 0; i < len; i += 3) + if (!lc_set_contains(l1, lc_get(l, i))) + k = lc_copy(k, l+i); + + if (k == tmp) + return l1; + + len = (k - tmp) * 4; + res = lp_alloc(pool, sizeof(struct adata) + l1->length + len); + res->length = l1->length + len; + memcpy(res->data, l1->data, l1->length); + memcpy(res->data + l1->length, tmp, len); + return res; +} -- cgit v1.2.3 From a46e01eeef17a7efe876618623397f60e62afe37 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 4 Oct 2016 12:45:39 +0200 Subject: Nest: Fix signedness of large communities --- nest/a-set.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nest/a-set.c') diff --git a/nest/a-set.c b/nest/a-set.c index 0484ab98..fde34cab 100644 --- a/nest/a-set.c +++ b/nest/a-set.c @@ -144,7 +144,7 @@ ec_set_format(struct adata *set, int from, byte *buf, uint size) int lc_format(byte *buf, lcomm lc) { - return bsprintf(buf, "(%d, %d, %d)", lc.asn, lc.ldp1, lc.ldp2); + return bsprintf(buf, "(%u, %u, %u)", lc.asn, lc.ldp1, lc.ldp2); } int @@ -167,7 +167,7 @@ lc_set_format(struct adata *set, int from, byte *buf, uint bufsize) return i; } - buf += bsprintf(buf, "(%d, %d, %d)", d[i], d[i+1], d[i+2]); + buf += bsprintf(buf, "(%u, %u, %u)", d[i], d[i+1], d[i+2]); *buf++ = ' '; } -- cgit v1.2.3 From 3c09af416939d26c252aa1b339b52fd8f9f8e774 Mon Sep 17 00:00:00 2001 From: Pavel Tvrdik Date: Thu, 13 Oct 2016 16:57:21 +0200 Subject: Clist: The add() function will append a new value The add() function used to prepend a new community to clist, but after this fix the add() function appends new community. --- nest/a-set.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'nest/a-set.c') diff --git a/nest/a-set.c b/nest/a-set.c index fde34cab..bd244e2e 100644 --- a/nest/a-set.c +++ b/nest/a-set.c @@ -244,9 +244,13 @@ int_set_add(struct linpool *pool, struct adata *list, u32 val) len = list ? list->length : 0; res = lp_alloc(pool, sizeof(struct adata) + len + 4); res->length = len + 4; - * (u32 *) res->data = val; + if (list) - memcpy((char *) res->data + 4, list->data, list->length); + memcpy(res->data, list->data, list->length); + + u32 *c = (u32 *) (res->data + len); + *c = val; + return res; } -- cgit v1.2.3