From 1187627a1dded6a3673c0d43033f431f15cd1b8f Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 2 Jul 2019 16:30:36 +0200 Subject: Netlink: Do unified scan for both IPv4 and IPv6 Instead of separate scans for IPv4, IPv6 and MPLS, do one AF_UNSPEC scan. This also avoids kernel issue when kernel reported IPv4 and IPv6 routes during MPLS scan if MPLS is not active. --- sysdep/linux/netlink.c | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) (limited to 'sysdep/linux/netlink.c') diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index d773743d..5a0b4d0c 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -1393,10 +1393,10 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old) } static int -nl_mergable_route(struct nl_parse_state *s, net *net, struct krt_proto *p, uint priority, uint krt_type) +nl_mergable_route(struct nl_parse_state *s, net *net, struct krt_proto *p, uint priority, uint krt_type, uint rtm_family) { - /* Route merging must be active */ - if (!s->merge) + /* Route merging is used for IPv6 scans */ + if (!s->scan || (rtm_family != AF_INET6)) return 0; /* Saved and new route must have same network, proto/table, and priority */ @@ -1433,12 +1433,11 @@ nl_announce_route(struct nl_parse_state *s) } static inline void -nl_parse_begin(struct nl_parse_state *s, int scan, int merge) +nl_parse_begin(struct nl_parse_state *s, int scan) { memset(s, 0, sizeof (struct nl_parse_state)); s->pool = nl_linpool; s->scan = scan; - s->merge = merge; } static inline void @@ -1581,7 +1580,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) net *net = net_get(p->p.main_channel->table, n); - if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type)) + if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type, i->rtm_family)) nl_announce_route(s); rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE); @@ -1814,34 +1813,14 @@ krt_do_scan(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NUL struct nlmsghdr *h; struct nl_parse_state s; - nl_parse_begin(&s, 1, 0); - nl_request_dump(AF_INET, RTM_GETROUTE); + nl_parse_begin(&s, 1); + nl_request_dump(AF_UNSPEC, RTM_GETROUTE); while (h = nl_get_scan()) if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE) nl_parse_route(&s, h); else log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type); nl_parse_end(&s); - - nl_parse_begin(&s, 1, 1); - nl_request_dump(AF_INET6, RTM_GETROUTE); - while (h = nl_get_scan()) - if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE) - nl_parse_route(&s, h); - else - log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type); - nl_parse_end(&s); - -#ifdef HAVE_MPLS_KERNEL - nl_parse_begin(&s, 1, 1); - nl_request_dump(AF_MPLS, RTM_GETROUTE); - while (h = nl_get_scan()) - if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE) - nl_parse_route(&s, h); - else - log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type); - nl_parse_end(&s); -#endif } /* @@ -1861,7 +1840,7 @@ nl_async_msg(struct nlmsghdr *h) case RTM_NEWROUTE: case RTM_DELROUTE: DBG("KRT: Received async route notification (%d)\n", h->nlmsg_type); - nl_parse_begin(&s, 0, 0); + nl_parse_begin(&s, 0); nl_parse_route(&s, h); nl_parse_end(&s); break; -- cgit v1.2.3 From 59d3a3611f05c05040cec4bf09f31c26ade0fa0a Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 2 Jul 2019 18:23:06 +0200 Subject: Netlink: Handle alien routes with unsorted nexthops Nest requires that nexthops are sorted, the kernel protocol have to ensure that for alien routes. --- nest/route.h | 1 + nest/rt-attr.c | 20 +++++++++++++++++++- sysdep/linux/netlink.c | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) (limited to 'sysdep/linux/netlink.c') diff --git a/nest/route.h b/nest/route.h index 15aac8f6..e356f686 100644 --- a/nest/route.h +++ b/nest/route.h @@ -628,6 +628,7 @@ int nexthop__same(struct nexthop *x, struct nexthop *y); /* Compare multipath ne static inline int nexthop_same(struct nexthop *x, struct nexthop *y) { return (x == y) || nexthop__same(x, y); } struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp); +struct nexthop *nexthop_sort(struct nexthop *x); static inline void nexthop_link(struct rta *a, struct nexthop *from) { memcpy(&a->nh, from, nexthop_size(from)); } void nexthop_insert(struct nexthop **n, struct nexthop *y); diff --git a/nest/rt-attr.c b/nest/rt-attr.c index cc362cab..1803db92 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -200,7 +200,7 @@ nexthop__same(struct nexthop *x, struct nexthop *y) } static int -nexthop_compare_node(struct nexthop *x, struct nexthop *y) +nexthop_compare_node(const struct nexthop *x, const struct nexthop *y) { int r; @@ -318,6 +318,24 @@ nexthop_insert(struct nexthop **n, struct nexthop *x) *n = x; } +struct nexthop * +nexthop_sort(struct nexthop *x) +{ + struct nexthop *s = NULL; + + /* Simple insert-sort */ + while (x) + { + struct nexthop *n = x; + x = n->next; + n->next = NULL; + + nexthop_insert(&s, n); + } + + return s; +} + int nexthop_is_sorted(struct nexthop *x) { diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 5a0b4d0c..6e3fe488 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -725,6 +725,10 @@ nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, struct rtattr nh = RTNH_NEXT(nh); } + /* Ensure nexthops are sorted to satisfy nest invariant */ + if (!nexthop_is_sorted(first)) + first = nexthop_sort(first); + return first; } -- cgit v1.2.3