From 772beb7308a53558e153223bc42742f719ff4a40 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Wed, 13 Dec 2017 14:49:55 +0100 Subject: [PATCH 1/3] Lib: Minor fix --- lib/mempool.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/mempool.c b/lib/mempool.c index 5a8f2a69..758882ce 100644 --- a/lib/mempool.c +++ b/lib/mempool.c @@ -244,6 +244,7 @@ lp_restore(linpool *m, lp_state *p) while ((c = m->first_large) && (c != p->large)) { m->first_large = c->next; + m->total_large -= c->size; xfree(c); } } From 3e7923507b40b42c80dc621aff9d896106bae8c7 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Wed, 13 Dec 2017 15:26:29 +0100 Subject: [PATCH 2/3] Netlink: Use linpool instead of static buffer --- sysdep/linux/netlink.c | 39 +++++---------------------------------- 1 file changed, 5 insertions(+), 34 deletions(-) diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index bd3dbbd9..72ff13fa 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -645,13 +645,8 @@ nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af) } static struct nexthop * -nl_parse_multipath(struct krt_proto *p, struct rtattr *ra, int af) +nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, struct rtattr *ra, int af) { - /* Temporary buffer for multicast nexthops */ - static struct nexthop *nh_buffer; - static int nh_buf_size; /* in number of structures */ - static int nh_buf_used; - struct rtattr *a[BIRD_RTA_MAX]; struct rtnexthop *nh = RTA_DATA(ra); struct nexthop *rv, *first, **last; @@ -659,7 +654,6 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra, int af) first = NULL; last = &first; - nh_buf_used = 0; while (len) { @@ -667,18 +661,9 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra, int af) if ((len < sizeof(*nh)) || (len < nh->rtnh_len)) return NULL; - if (nh_buf_used == nh_buf_size) - { - nh_buf_size = nh_buf_size ? (nh_buf_size * 2) : 4; - nh_buffer = xrealloc(nh_buffer, nh_buf_size * NEXTHOP_MAX_SIZE); - } - /* FIXME: This is really ugly */ - *last = rv = (void *) (((byte *) nh_buffer) + (nh_buf_used++ * NEXTHOP_MAX_SIZE)); - memset(rv, 0, NEXTHOP_MAX_SIZE); - // rv->next = NULL; + *last = rv = lp_allocz(s->pool, NEXTHOP_MAX_SIZE); last = &(rv->next); - rv->flags = 0; rv->weight = nh->rtnh_hops; rv->iface = if_find_by_index(nh->rtnh_ifindex); if (!rv->iface) @@ -1395,20 +1380,6 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list n->n.flags &= ~KRF_SYNC_ERROR; } - -static inline struct nexthop * -nl_alloc_nexthop(struct nl_parse_state *s, ip_addr gw, struct iface *iface, byte weight) -{ - struct nexthop *nh = lp_alloc(s->pool, sizeof(struct nexthop)); - - nh->gw = gw; - nh->iface = iface; - nh->next = NULL; - nh->weight = weight; - - return nh; -} - static int nl_mergable_route(struct nl_parse_state *s, net *net, struct krt_proto *p, uint priority, uint krt_type) { @@ -1597,7 +1568,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if (a[RTA_MULTIPATH]) { - struct nexthop *nh = nl_parse_multipath(p, a[RTA_MULTIPATH], i->rtm_family); + struct nexthop *nh = nl_parse_multipath(s, p, a[RTA_MULTIPATH], i->rtm_family); if (!nh) { log(L_ERR "KRT: Received strange multipath route %N", net->n.addr); @@ -1784,8 +1755,8 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) * Ideally, now we would send the received route to the rest of kernel code. * But IPv6 ECMP routes before 4.11 are sent as a sequence of routes, so we * postpone it and merge next hops until the end of the sequence. Note that - * proper multipath updates are rejected by nl_mergable_route(), so it is - * always the first case for them. + * when doing merging of next hops, we expect the new route to be unipath. + * Otherwise, we ignore additional next hops in nexthop_insert(). */ if (!s->net) From d807ea087f8d60e25eaef8c10168a40ca6545c57 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Wed, 13 Dec 2017 15:57:44 +0100 Subject: [PATCH 3/3] BGP: Fix non-transitive ext communities --- nest/a-set.c | 7 +++++++ nest/attrs.h | 2 ++ proto/bgp/attrs.c | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/nest/a-set.c b/nest/a-set.c index a2fb6953..048e522d 100644 --- a/nest/a-set.c +++ b/nest/a-set.c @@ -536,6 +536,13 @@ ec_set_sort(struct linpool *pool, struct adata *src) return dst; } +void +ec_set_sort_x(struct adata *set) +{ + /* Sort in place */ + qsort(set->data, set->length / 8, 8, ec_set_cmp); +} + static int lc_set_cmp(const void *X, const void *Y) diff --git a/nest/attrs.h b/nest/attrs.h index f66d4f04..102f378a 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -197,4 +197,6 @@ struct adata *int_set_sort(struct linpool *pool, struct adata *src); struct adata *ec_set_sort(struct linpool *pool, struct adata *src); struct adata *lc_set_sort(struct linpool *pool, struct adata *src); +void ec_set_sort_x(struct adata *set); /* Sort in place */ + #endif diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index dea3c4a6..fdc981ca 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -550,10 +550,12 @@ bgp_decode_mp_unreach_nlri(struct bgp_parse_state *s, uint code UNUSED, uint fla static void bgp_export_ext_community(struct bgp_export_state *s, eattr *a) { + a->u.ptr = ec_set_del_nontrans(s->pool, a->u.ptr); + if (a->u.ptr->length == 0) UNSET(a); - a->u.ptr = ec_set_sort(s->pool, a->u.ptr); + ec_set_sort_x(a->u.ptr); } static void