From 4e276a8920ed0496836f002f144943ab42f120f6 Mon Sep 17 00:00:00 2001 From: Jan Moskyto Matejka Date: Fri, 6 May 2016 15:48:35 +0200 Subject: Merged multipath and single-path data structures. Dropped struct mpnh and mpnh_*() Now struct nexthop exists, nexthop_*(), and also included struct nexthop into struct rta. Also converted RTD_DEVICE and RTD_ROUTER to RTD_UNICAST. If it is needed to distinguish between these two cases, RTD_DEVICE is equivalent to IPA_ZERO(a->nh.gw), RTD_ROUTER is then IPA_NONZERO(a->nh.gw). From now on, we also explicitely want C99 compatible compiler. We assume that this 20-year norm should be known almost everywhere. --- sysdep/bsd/krt-sock.c | 70 ++++++++++++++++---------------- sysdep/linux/netlink.c | 108 ++++++++++++++++++++++--------------------------- sysdep/unix/krt.c | 30 +++++++------- 3 files changed, 99 insertions(+), 109 deletions(-) (limited to 'sysdep') diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index d2372a3d..fbaa8e32 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -148,8 +148,7 @@ krt_capable(rte *e) return a->cast == RTC_UNICAST && - (a->dest == RTD_ROUTER - || a->dest == RTD_DEVICE + ((a->dest == RTD_UNICAST && !a->nh.next) /* No multipath support */ #ifdef RTF_REJECT || a->dest == RTD_UNREACHABLE #endif @@ -190,7 +189,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) net *net = e->net; rta *a = e->attrs; static int msg_seq; - struct iface *j, *i = a->iface; + struct iface *j, *i = a->nh.iface; int l; struct ks_msg msg; char *body = (char *)msg.buf; @@ -243,7 +242,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) } } - gw = a->gw; + gw = a->nh.gw; /* Embed interface ID to link-local address */ if (ipa_is_link_local(gw)) @@ -270,9 +269,28 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) switch (a->dest) { - case RTD_ROUTER: - msg.rtm.rtm_flags |= RTF_GATEWAY; - msg.rtm.rtm_addrs |= RTA_GATEWAY; + case RTD_UNICAST: + if (ipa_zero(gw)) + { + if(i) + { +#ifdef RTF_CLONING + if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */ + msg.rtm.rtm_flags |= RTF_CLONING; +#endif + + if(!i->addr) { + log(L_ERR "KRT: interface %s has no IP addess", i->name); + return -1; + } + + sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0); + msg.rtm.rtm_addrs |= RTA_GATEWAY; + } + } else { + msg.rtm.rtm_flags |= RTF_GATEWAY; + msg.rtm.rtm_addrs |= RTA_GATEWAY; + } break; #ifdef RTF_REJECT @@ -281,23 +299,6 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) #ifdef RTF_BLACKHOLE case RTD_BLACKHOLE: #endif - case RTD_DEVICE: - if(i) - { -#ifdef RTF_CLONING - if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */ - msg.rtm.rtm_flags |= RTF_CLONING; -#endif - - if(!i->addr) { - log(L_ERR "KRT: interface %s has no IP addess", i->name); - return -1; - } - - sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0); - msg.rtm.rtm_addrs |= RTA_GATEWAY; - } - break; default: bug("krt-sock: unknown flags, but not filtered"); } @@ -489,39 +490,40 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) } #endif - a.iface = if_find_by_index(msg->rtm.rtm_index); - if (!a.iface) + a.nh.iface = if_find_by_index(msg->rtm.rtm_index); + if (!a.nh.iface) { log(L_ERR "KRT: Received route %N with unknown ifindex %u", net->n.addr, msg->rtm.rtm_index); return; } + a.dest = RTD_UNICAST; + a.nh.next = NULL; if (flags & RTF_GATEWAY) { neighbor *ng; - a.dest = RTD_ROUTER; - a.gw = igate; + a.nh.gw = igate; /* Clean up embedded interface ID returned in link-local address */ - if (ipa_is_link_local(a.gw)) - _I0(a.gw) = 0xfe800000; + if (ipa_is_link_local(a.nh.gw)) + _I0(a.nh.gw) = 0xfe800000; - ng = neigh_find2(&p->p, &a.gw, a.iface, 0); + ng = neigh_find2(&p->p, &a.nh.gw, a.nh.iface, 0); if (!ng || (ng->scope == SCOPE_HOST)) { /* Ignore routes with next-hop 127.0.0.1, host routes with such next-hop appear on OpenBSD for address aliases. */ - if (ipa_classify(a.gw) == (IADDR_HOST | SCOPE_HOST)) + if (ipa_classify(a.nh.gw) == (IADDR_HOST | SCOPE_HOST)) return; log(L_ERR "KRT: Received route %N with strange next-hop %I", - net->n.addr, a.gw); + net->n.addr, a.nh.gw); return; } } else - a.dest = RTD_DEVICE; + a.nh.gw = IPA_NONE; done: e = rte_get_temp(&a); diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index ee2cd125..6e75ee53 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -20,6 +20,7 @@ #include "nest/route.h" #include "nest/protocol.h" #include "nest/iface.h" +#include "lib/alloca.h" #include "sysdep/unix/timer.h" #include "sysdep/unix/unix.h" #include "sysdep/unix/krt.h" @@ -303,7 +304,6 @@ static struct nl_want_attrs ifa_attr_want4[BIRD_IFA_MAX] = { [IFA_ADDRESS] = { 1, 1, sizeof(ip4_addr) }, [IFA_LOCAL] = { 1, 1, sizeof(ip4_addr) }, [IFA_BROADCAST] = { 1, 1, sizeof(ip4_addr) }, - [IFA_FLAGS] = { 1, 1, sizeof(u32) }, }; static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = { @@ -315,7 +315,7 @@ static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = { #define BIRD_RTA_MAX (RTA_TABLE+1) -static struct nl_want_attrs mpnh_attr_want4[BIRD_RTA_MAX] = { +static struct nl_want_attrs nexthop_attr_want4[BIRD_RTA_MAX] = { [RTA_GATEWAY] = { 1, 1, sizeof(ip4_addr) }, }; @@ -472,7 +472,7 @@ nl_close_nexthop(struct nlmsghdr *h, struct rtnexthop *nh) } static void -nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct mpnh *nh) +nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct nexthop *nh) { struct rtattr *a = nl_open_attr(h, bufsize, RTA_MULTIPATH); @@ -492,17 +492,17 @@ nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct mpnh *nh) nl_close_attr(h, a); } -static struct mpnh * +static struct nexthop * nl_parse_multipath(struct krt_proto *p, struct rtattr *ra) { /* Temporary buffer for multicast nexthops */ - static struct mpnh *nh_buffer; + 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 mpnh *rv, *first, **last; + struct nexthop *rv, *first, **last; unsigned len = RTA_PAYLOAD(ra); first = NULL; @@ -518,7 +518,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra) 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 * sizeof(struct mpnh)); + nh_buffer = xrealloc(nh_buffer, nh_buf_size * sizeof(struct nexthop)); } *last = rv = nh_buffer + nh_buf_used++; rv->next = NULL; @@ -531,7 +531,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra) /* Nonexistent RTNH_PAYLOAD ?? */ nl_attr_len = nh->rtnh_len - RTNH_LENGTH(0); - nl_parse_attrs(RTNH_DATA(nh), mpnh_attr_want4, a, sizeof(a)); + nl_parse_attrs(RTNH_DATA(nh), nexthop_attr_want4, a, sizeof(a)); if (a[RTA_GATEWAY]) { rv->gw = rta_get_ipa(a[RTA_GATEWAY]); @@ -957,14 +957,14 @@ krt_capable(rte *e) switch (a->dest) { - case RTD_ROUTER: - case RTD_DEVICE: - if (a->iface == NULL) - return 0; + case RTD_UNICAST: + for (struct nexthop *nh = &(a->nh); nh; nh = nh->next) + if (nh->iface) + return 1; + return 0; case RTD_BLACKHOLE: case RTD_UNREACHABLE: case RTD_PROHIBIT: - case RTD_MULTIPATH: break; default: return 0; @@ -973,7 +973,7 @@ krt_capable(rte *e) } static inline int -nh_bufsize(struct mpnh *nh) +nh_bufsize(struct nexthop *nh) { int rv = 0; for (; nh != NULL; nh = nh->next) @@ -982,12 +982,12 @@ nh_bufsize(struct mpnh *nh) } static int -nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int dest, ip_addr gw, struct iface *iface) +nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int dest, struct nexthop *nh) { eattr *ea; net *net = e->net; rta *a = e->attrs; - int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(a->nexthops); + int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(&(a->nh)); u32 priority = 0; struct { @@ -1043,7 +1043,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d if (ea = ea_find(eattrs, EA_KRT_SCOPE)) r->r.rtm_scope = ea->u.data; else - r->r.rtm_scope = (dest == RTD_DEVICE) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE; + r->r.rtm_scope = (dest == RTD_UNICAST && ipa_zero(nh->gw)) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE; if (ea = ea_find(eattrs, EA_KRT_PREFSRC)) nl_add_attr_ipa(&r->h, rsize, RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data); @@ -1071,14 +1071,17 @@ dest: /* a->iface != NULL checked in krt_capable() for router and device routes */ switch (dest) { - case RTD_ROUTER: - r->r.rtm_type = RTN_UNICAST; - nl_add_attr_u32(&r->h, rsize, RTA_OIF, iface->index); - nl_add_attr_ipa(&r->h, rsize, RTA_GATEWAY, gw); - break; - case RTD_DEVICE: + case RTD_UNICAST: r->r.rtm_type = RTN_UNICAST; - nl_add_attr_u32(&r->h, rsize, RTA_OIF, iface->index); + if (nh->next && !krt_ecmp6(p)) + nl_add_multipath(&r->h, rsize, nh); + else + { + nl_add_attr_u32(&r->h, rsize, RTA_OIF, nh->iface->index); + + if (ipa_nonzero(nh->gw)) + nl_add_attr_ipa(&r->h, rsize, RTA_GATEWAY, nh->gw); + } break; case RTD_BLACKHOLE: r->r.rtm_type = RTN_BLACKHOLE; @@ -1089,10 +1092,6 @@ dest: case RTD_PROHIBIT: r->r.rtm_type = RTN_PROHIBIT; break; - case RTD_MULTIPATH: - r->r.rtm_type = RTN_UNICAST; - nl_add_multipath(&r->h, rsize, a->nexthops); - break; case RTD_NONE: break; default: @@ -1109,21 +1108,21 @@ nl_add_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs) rta *a = e->attrs; int err = 0; - if (krt_ecmp6(p) && (a->dest == RTD_MULTIPATH)) + if (krt_ecmp6(p) && a->nh.next) { - struct mpnh *nh = a->nexthops; + struct nexthop *nh = &(a->nh); - err = nl_send_route(p, e, eattrs, NL_OP_ADD, RTD_ROUTER, nh->gw, nh->iface); + err = nl_send_route(p, e, eattrs, NL_OP_ADD, RTD_UNICAST, nh); if (err < 0) return err; for (nh = nh->next; nh; nh = nh->next) - err += nl_send_route(p, e, eattrs, NL_OP_APPEND, RTD_ROUTER, nh->gw, nh->iface); + err += nl_send_route(p, e, eattrs, NL_OP_APPEND, RTD_UNICAST, nh); return err; } - return nl_send_route(p, e, eattrs, NL_OP_ADD, a->dest, a->gw, a->iface); + return nl_send_route(p, e, eattrs, NL_OP_ADD, a->dest, &(a->nh)); } static inline int @@ -1133,7 +1132,7 @@ nl_delete_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs) /* For IPv6, we just repeatedly request DELETE until we get error */ do - err = nl_send_route(p, e, eattrs, NL_OP_DELETE, RTD_NONE, IPA_NONE, NULL); + err = nl_send_route(p, e, eattrs, NL_OP_DELETE, RTD_NONE, NULL); while (krt_ecmp6(p) && !err); return err; @@ -1168,10 +1167,10 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list } -static inline struct mpnh * -nl_alloc_mpnh(struct nl_parse_state *s, ip_addr gw, struct iface *iface, byte weight) +static inline struct nexthop * +nl_alloc_nexthop(struct nl_parse_state *s, ip_addr gw, struct iface *iface, byte weight) { - struct mpnh *nh = lp_alloc(s->pool, sizeof(struct mpnh)); + struct nexthop *nh = lp_alloc(s->pool, sizeof(struct nexthop)); nh->gw = gw; nh->iface = iface; @@ -1342,7 +1341,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type)) nl_announce_route(s); - rta *ra = lp_allocz(s->pool, sizeof(rta)); + rta *ra = lp_allocz(s->pool, sizeof(rta)); // TODO: fix alloc ra->src = p->p.main_source; ra->source = RTS_INHERIT; ra->scope = SCOPE_UNIVERSE; @@ -1354,19 +1353,19 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if (a[RTA_MULTIPATH] && (i->rtm_family == AF_INET)) { - ra->dest = RTD_MULTIPATH; - ra->nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH]); - if (!ra->nexthops) + struct nexthop *nh = nl_parse_multipath(p, a[RTA_MULTIPATH]); + if (!nh) { log(L_ERR "KRT: Received strange multipath route %N", net->n.addr); return; } + nexthop_link(ra, nh); break; } - ra->iface = if_find_by_index(oif); - if (!ra->iface) + ra->nh.iface = if_find_by_index(oif); + if (!ra->nh.iface) { log(L_ERR "KRT: Received route %N with unknown ifindex %u", net->n.addr, oif); return; @@ -1374,28 +1373,23 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if (a[RTA_GATEWAY]) { - ra->dest = RTD_ROUTER; - ra->gw = rta_get_ipa(a[RTA_GATEWAY]); + ra->nh.gw = rta_get_ipa(a[RTA_GATEWAY]); /* Silently skip strange 6to4 routes */ const net_addr_ip6 sit = NET_ADDR_IP6(IP6_NONE, 96); - if ((i->rtm_family == AF_INET6) && ipa_in_netX(ra->gw, (net_addr *) &sit)) + if ((i->rtm_family == AF_INET6) && ipa_in_netX(ra->nh.gw, (net_addr *) &sit)) return; neighbor *nbr; - nbr = neigh_find2(&p->p, &ra->gw, ra->iface, + nbr = neigh_find2(&p->p, &ra->nh.gw, ra->nh.iface, (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0); if (!nbr || (nbr->scope == SCOPE_HOST)) { - log(L_ERR "KRT: Received route %N with strange next-hop %I", net->n.addr, ra->gw); + log(L_ERR "KRT: Received route %N with strange next-hop %I", net->n.addr, + ra->nh.gw); return; } } - else - { - ra->dest = RTD_DEVICE; - def_scope = RT_SCOPE_LINK; - } break; case RTN_BLACKHOLE: @@ -1510,13 +1504,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) /* Merge next hops with the stored route */ rta *a = s->attrs; - if (a->dest != RTD_MULTIPATH) - { - a->dest = RTD_MULTIPATH; - a->nexthops = nl_alloc_mpnh(s, a->gw, a->iface, 0); - } - - mpnh_insert(&a->nexthops, nl_alloc_mpnh(s, ra->gw, ra->iface, 0)); + nexthop_insert(&a->nh, &ra->nh); } } diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index e899671d..9f66d2f4 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -645,17 +645,11 @@ krt_same_dest(rte *k, rte *e) if (ka->dest != ea->dest) return 0; - switch (ka->dest) - { - case RTD_ROUTER: - return ipa_equal(ka->gw, ea->gw); - case RTD_DEVICE: - return !strcmp(ka->iface->name, ea->iface->name); - case RTD_MULTIPATH: - return mpnh_same(ka->nexthops, ea->nexthops); - default: - return 1; - } + + if (ka->dest == RTD_UNICAST) + return nexthop_same(&(ka->nh), &(ea->nh)); + + return 1; } /* @@ -1011,10 +1005,16 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li return -1; } - if (!KRT_CF->devroutes && - (e->attrs->dest == RTD_DEVICE) && - (e->attrs->source != RTS_STATIC_DEVICE)) - return -1; + if (!KRT_CF->devroutes && (e->attrs->source != RTS_STATIC_DEVICE)) + { + struct nexthop *nh = &(e->attrs->nh); + for (; nh; nh = nh->next) + if (ipa_nonzero(nh->gw)) + break; + + if (!nh) /* Gone through all the nexthops and no explicit GW found */ + return -1; + } if (!krt_capable(e)) return -1; -- cgit v1.2.3 From 5b208e296fed0beddce16188478c5119df610d89 Mon Sep 17 00:00:00 2001 From: Jan Moskyto Matejka Date: Tue, 7 Jun 2016 11:46:07 +0200 Subject: Removing (struct rta)->cast. Never used. --- filter/config.Y | 3 +-- filter/filter.c | 1 - filter/filter.h | 7 +++---- nest/config.Y | 1 - nest/route.h | 11 ++++------- nest/rt-attr.c | 13 ++++++------- nest/rt-dev.c | 1 - proto/bgp/packets.c | 1 - proto/ospf/rt.c | 1 - proto/rip/rip.c | 1 - proto/rpki/rpki.c | 1 - proto/static/static.c | 11 +++++------ sysdep/bsd/krt-sock.c | 2 -- sysdep/linux/netlink.c | 4 ---- 14 files changed, 19 insertions(+), 39 deletions(-) (limited to 'sysdep') diff --git a/filter/config.Y b/filter/config.Y index 7b4178be..94a7e307 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -397,7 +397,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST, IF, THEN, ELSE, CASE, TRUE, FALSE, RT, RO, UNKNOWN, GENERIC, - FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX, + FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, PREFERENCE, ROA_CHECK, ASN, LEN, MAXLEN, @@ -854,7 +854,6 @@ static_attr: | PROTO { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_PROTO; } | SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = SA_SOURCE; } | SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = SA_SCOPE; $$->a1.i = 1; } - | CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = SA_CAST; } | DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = SA_DEST; $$->a1.i = 1; } | IFNAME { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_IFNAME; } | IFINDEX { $$ = f_new_inst(); $$->aux = T_INT; $$->a2.i = SA_IFINDEX; } diff --git a/filter/filter.c b/filter/filter.c index 926316ac..bc80997f 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -905,7 +905,6 @@ interpret(struct f_inst *what) case SA_PROTO: res.val.s = rta->src->proto->name; break; case SA_SOURCE: res.val.i = rta->source; break; case SA_SCOPE: res.val.i = rta->scope; break; - case SA_CAST: res.val.i = rta->cast; break; case SA_DEST: res.val.i = rta->dest; break; case SA_IFNAME: res.val.s = rta->nh.iface ? rta->nh.iface->name : ""; break; case SA_IFINDEX: res.val.i = rta->nh.iface ? rta->nh.iface->index : 0; break; diff --git a/filter/filter.h b/filter/filter.h index a4808731..0482b83b 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -174,10 +174,9 @@ void val_format(struct f_val v, buffer *buf); #define SA_PROTO 4 #define SA_SOURCE 5 #define SA_SCOPE 6 -#define SA_CAST 7 -#define SA_DEST 8 -#define SA_IFNAME 9 -#define SA_IFINDEX 10 +#define SA_DEST 8 +#define SA_IFNAME 9 +#define SA_IFINDEX 10 struct f_tree { diff --git a/nest/config.Y b/nest/config.Y index 95ce59cd..511936ef 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -78,7 +78,6 @@ CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS) CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL) CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE, UNDEFINED) -CF_ENUM(T_ENUM_RTC, RTC_, UNICAST, BROADCAST, MULTICAST, ANYCAST) CF_ENUM(T_ENUM_RTD, RTD_, UNICAST, BLACKHOLE, UNREACHABLE, PROHIBIT) CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID) diff --git a/nest/route.h b/nest/route.h index 37c9abfb..154e027e 100644 --- a/nest/route.h +++ b/nest/route.h @@ -358,13 +358,10 @@ typedef struct rta { struct hostentry *hostentry; /* Hostentry for recursive next-hops */ ip_addr from; /* Advertising router */ u32 igp_metric; /* IGP metric to next hop (for iBGP routes) */ - u32 bf[0]; - u32 source:6; /* Route source (RTS_...) */ - u32 scope:6; /* Route scope (SCOPE_... -- see ip.h) */ - u32 cast:6; /* Casting type (RTC_...) */ - u32 dest:6; /* Route destination type (RTD_...) */ -// u32 eflags:8; /* Flags (RTAF_...) */ - u32 aflags:8; + u8 source; /* Route source (RTS_...) */ + u8 scope; /* Route scope (SCOPE_... -- see ip.h) */ + u8 dest; /* Route destination type (RTD_...) */ + u8 aflags; struct nexthop nh; /* Next hop */ } rta; diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 0eacfe3f..e575ba4a 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -1008,7 +1008,9 @@ rta_hash(rta *a) MIX(hostentry); MIX(from); MIX(igp_metric); - mem_hash_mix(&h, a->bf, sizeof(u32)); + MIX(source); + MIX(scope); + MIX(dest); #undef MIX return mem_hash_value(&h) ^ nexthop_hash(&(a->nh)) ^ ea_hash(a->eattrs); @@ -1020,7 +1022,6 @@ rta_same(rta *x, rta *y) return (x->src == y->src && x->source == y->source && x->scope == y->scope && - x->cast == y->cast && x->dest == y->dest && x->igp_metric == y->igp_metric && ipa_equal(x->nh.gw, y->nh.gw) && @@ -1163,11 +1164,10 @@ rta_dump(rta *a) "RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP", "RTS_OSPF", "RTS_OSPF_IA", "RTS_OSPF_EXT1", "RTS_OSPF_EXT2", "RTS_BGP", "RTS_PIPE", "RTS_BABEL" }; - static char *rtc[] = { "", " BC", " MC", " AC" }; static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" }; - debug("p=%s uc=%d %s %s%s%s h=%04x", - a->src->proto->name, a->uc, rts[a->source], ip_scope_text(a->scope), rtc[a->cast], + debug("p=%s uc=%d %s %s%s h=%04x", + a->src->proto->name, a->uc, rts[a->source], ip_scope_text(a->scope), rtd[a->dest], a->hash_key); if (!(a->aflags & RTAF_CACHED)) debug(" !CACHED"); @@ -1213,10 +1213,9 @@ rta_show(struct cli *c, rta *a, ea_list *eal) { static char *src_names[] = { "dummy", "static", "inherit", "device", "static-device", "redirect", "RIP", "OSPF", "OSPF-IA", "OSPF-E1", "OSPF-E2", "BGP", "pipe" }; - static char *cast_names[] = { "unicast", "broadcast", "multicast", "anycast" }; int i; - cli_printf(c, -1008, "\tType: %s %s %s", src_names[a->source], cast_names[a->cast], ip_scope_text(a->scope)); + cli_printf(c, -1008, "\tType: %s %s", src_names[a->source], ip_scope_text(a->scope)); if (!eal) eal = a->eattrs; for(; eal; eal=eal->next) diff --git a/nest/rt-dev.c b/nest/rt-dev.c index 43628af8..5edd1c5d 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -78,7 +78,6 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad) .src = src, .source = RTS_DEVICE, .scope = SCOPE_UNIVERSE, - .cast = RTC_UNICAST, .dest = RTD_UNICAST, .nh = { .iface = ad->iface diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 0baa84c9..9c59e6d8 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1439,7 +1439,6 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis a->source = RTS_BGP; a->scope = SCOPE_UNIVERSE; - a->cast = RTC_UNICAST; a->dest = RTD_UNREACHABLE; a->from = s->proto->cf->remote_ip; a->eattrs = ea; diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 09cc5776..d28d463b 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -1951,7 +1951,6 @@ again1: .src = p->p.main_source, .source = nf->n.type, .scope = SCOPE_UNIVERSE, - .cast = RTC_UNICAST }; nexthop_link(&a0, nf->n.nhs); diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 8b09330c..9bed9249 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -147,7 +147,6 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) .src = p->p.main_source, .source = RTS_RIP, .scope = SCOPE_UNIVERSE, - .cast = RTC_UNICAST }; u8 rt_metric = rt->metric; diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c index 6360dbaf..81268e83 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -124,7 +124,6 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_ .src = p->p.main_source, .source = RTS_RPKI, .scope = SCOPE_UNIVERSE, - .cast = RTC_UNICAST, .dest = RTD_BLACKHOLE, }; diff --git a/proto/static/static.c b/proto/static/static.c index f3cfec01..a63d4d29 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -71,7 +71,6 @@ static_install(struct proto *p, struct static_route *r) a.src = p->main_source; a.source = ((r->dest == RTD_UNICAST) && ipa_zero(r->via)) ? RTS_STATIC_DEVICE : RTS_STATIC; a.scope = SCOPE_UNIVERSE; - a.cast = RTC_UNICAST; a.dest = r->dest; if (r->dest == RTD_UNICAST) { @@ -210,13 +209,13 @@ static_add(struct proto *p, struct static_config *cf, struct static_route *r) } if (count) - static_install(p, r, NULL); + static_install(p, r); break; } default: - static_install(p, r, NULL); + static_install(p, r); } } @@ -300,7 +299,7 @@ static_update_rte(struct proto *p, struct static_route *r) return; if (static_decide((struct static_config *) p->cf, r)) - static_install(p, r, r->neigh->iface); + static_install(p, r); else static_remove(p, r); } @@ -367,7 +366,7 @@ static_if_notify(struct proto *p, unsigned flags, struct iface *i) { WALK_LIST(r, c->iface_routes) if (!strcmp(r->if_name, i->name)) - static_install(p, r, i); + static_install(p, r); } else if (flags & IF_CHANGE_DOWN) { @@ -535,7 +534,7 @@ static_reconfigure(struct proto *p, struct proto_config *CF) { struct iface *ifa; if ((ifa = if_find_by_name(r->if_name)) && (ifa->flags & IF_UP)) - static_install(p, r, ifa); + static_install(p, r); } WALK_LIST(r, n->other_routes) static_add(p, n, r); diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index fbaa8e32..2e0f194b 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -147,7 +147,6 @@ krt_capable(rte *e) rta *a = e->attrs; return - a->cast == RTC_UNICAST && ((a->dest == RTD_UNICAST && !a->nh.next) /* No multipath support */ #ifdef RTF_REJECT || a->dest == RTD_UNREACHABLE @@ -470,7 +469,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) .src = p->p.main_source, .source = RTS_INHERIT, .scope = SCOPE_UNIVERSE, - .cast = RTC_UNICAST }; /* reject/blackhole routes have also set RTF_GATEWAY, diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 6e75ee53..c9a30719 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -952,9 +952,6 @@ krt_capable(rte *e) { rta *a = e->attrs; - if (a->cast != RTC_UNICAST) - return 0; - switch (a->dest) { case RTD_UNICAST: @@ -1345,7 +1342,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) ra->src = p->p.main_source; ra->source = RTS_INHERIT; ra->scope = SCOPE_UNIVERSE; - ra->cast = RTC_UNICAST; switch (i->rtm_type) { -- cgit v1.2.3 From d14f8c3c45f7e33a7e54ebc0d45bdb0295d70301 Mon Sep 17 00:00:00 2001 From: Jan Moskyto Matejka Date: Fri, 4 Mar 2016 12:55:50 +0100 Subject: Netlink: MPLS routes in kernel Anyway, Bird is now capable to insert both MPLS routes and MPLS encap routes into kernel. It was (among others) needed to define platform-specific AF_MPLS to 28 as this constant has been assigned in the linux kernel. No support for BSD now, it may be added in the future. --- conf/confbase.Y | 4 +- lib/ip.h | 22 +++++ lib/net.c | 3 +- lib/net.h | 8 ++ nest/route.h | 5 +- nest/rt-attr.c | 4 +- nest/rt-table.c | 2 +- sysdep/cf/linux.h | 4 + sysdep/linux/netlink.c | 247 +++++++++++++++++++++++++++++++++++++++++++++---- sysdep/unix/krt.c | 5 +- 10 files changed, 274 insertions(+), 30 deletions(-) (limited to 'sysdep') diff --git a/conf/confbase.Y b/conf/confbase.Y index 11393fe2..00e78232 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -270,7 +270,7 @@ net_or_ipa: label_stack_start: NUM { - $$ = cfg_allocz(sizeof(u32) * (NEXTHOP_MAX_LABEL_STACK+1)); + $$ = cfg_allocz(sizeof(u32) * (MPLS_MAX_LABEL_STACK+1)); $$[0] = 1; $$[1] = $1; }; @@ -278,7 +278,7 @@ label_stack_start: NUM label_stack: label_stack_start | label_stack '/' NUM { - if ($1[0] >= NEXTHOP_MAX_LABEL_STACK) + if ($1[0] >= MPLS_MAX_LABEL_STACK) cf_error("Too many labels in stack."); $1[++$1[0]] = $3; $$ = $1; diff --git a/lib/ip.h b/lib/ip.h index 86750675..ab90bee7 100644 --- a/lib/ip.h +++ b/lib/ip.h @@ -325,6 +325,28 @@ static inline ip6_addr ip6_hton(ip6_addr a) static inline ip6_addr ip6_ntoh(ip6_addr a) { return _MI6(ntohl(_I0(a)), ntohl(_I1(a)), ntohl(_I2(a)), ntohl(_I3(a))); } +#define MPLS_MAX_LABEL_STACK 8 +static inline int +mpls_get(const char *buf, int buflen, u32 *stack) +{ + for (int i=0; (i> 12; + if (s & 0x100) + return i+1; + } + return -1; +} + +static inline int +mpls_put(char *buf, int len, u32 *stack) +{ + for (int i=0; iip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6.prefix); - /* classify probably not needed for NET_MPLS */ + case NET_MPLS: + return IADDR_HOST | SCOPE_UNIVERSE; } return IADDR_INVALID; diff --git a/lib/net.h b/lib/net.h index 5fc4dab7..7c124fc0 100644 --- a/lib/net.h +++ b/lib/net.h @@ -259,6 +259,14 @@ static inline ip_addr net_prefix(const net_addr *a) } } +static inline u32 net_mpls(const net_addr *a) +{ + if (a->type == NET_MPLS) + return ((net_addr_mpls *) a)->label; + + bug("Can't call net_mpls on non-mpls net_addr"); +} + static inline uint net4_pxlen(const net_addr *a) { return a->pxlen; } diff --git a/nest/route.h b/nest/route.h index c293fbb1..a2fadf62 100644 --- a/nest/route.h +++ b/nest/route.h @@ -512,8 +512,7 @@ uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */ ea_list *ea_append(ea_list *to, ea_list *what); void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max); -#define NEXTHOP_MAX_LABEL_STACK 8 -#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK) +#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK) static inline size_t nexthop_size(const struct nexthop *nh) { return sizeof(struct nexthop) + sizeof(u32)*nh->labels; } @@ -528,7 +527,7 @@ int nexthop_is_sorted(struct nexthop *x); void rta_init(void); static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a->nh.labels; } -#define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK) +#define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK) rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */ static inline int rta_is_cached(rta *r) { return r->aflags & RTAF_CACHED; } static inline rta *rta_clone(rta *r) { r->uc++; return r; } diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 22a5cb14..120a8e24 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -1279,12 +1279,12 @@ rta_init(void) rta_slab_[0] = sl_new(rta_pool, sizeof(rta)); rta_slab_[1] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)); rta_slab_[2] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*2); - rta_slab_[3] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK); + rta_slab_[3] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK); nexthop_slab_[0] = sl_new(rta_pool, sizeof(struct nexthop)); nexthop_slab_[1] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)); nexthop_slab_[2] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*2); - nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK); + nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK); rta_alloc_hash(); rte_src_init(); diff --git a/nest/rt-table.c b/nest/rt-table.c index 92542ea8..73b838be 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -2487,7 +2487,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm tm, from, primary ? (sync_error ? " !" : " *") : "", info); for (nh = &(a->nh); nh; nh = nh->next) { - char ls[NEXTHOP_MAX_LABEL_STACK*8 + 5]; char *lsp = ls; + char ls[MPLS_MAX_LABEL_STACK*8 + 5]; char *lsp = ls; if (nh->labels) { lsp += bsprintf(lsp, " mpls %d", nh->label[0]); diff --git a/sysdep/cf/linux.h b/sysdep/cf/linux.h index cec9499c..3a3a15da 100644 --- a/sysdep/cf/linux.h +++ b/sysdep/cf/linux.h @@ -21,6 +21,10 @@ #define CONFIG_INCLUDE_SYSPRIV_H "sysdep/linux/syspriv.h" +#ifndef AF_MPLS +#define AF_MPLS 28 +#endif + /* Link: sysdep/linux Link: sysdep/unix diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index c9a30719..23431172 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -51,6 +52,21 @@ #define RTA_TABLE 15 #endif +#ifndef RTA_VIA +#define RTA_VIA 18 +#endif + +#ifndef RTA_NEWDST +#define RTA_NEWDST 19 +#endif + +#ifndef RTA_ENCAP_TYPE +#define RTA_ENCAP_TYPE 21 +#endif + +#ifndef RTA_ENCAP +#define RTA_ENCAP 22 +#endif #define krt_ecmp6(p) ((p)->af == AF_INET6) @@ -313,10 +329,16 @@ static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = { }; -#define BIRD_RTA_MAX (RTA_TABLE+1) +#define BIRD_RTA_MAX (RTA_ENCAP+1) static struct nl_want_attrs nexthop_attr_want4[BIRD_RTA_MAX] = { [RTA_GATEWAY] = { 1, 1, sizeof(ip4_addr) }, + [RTA_ENCAP_TYPE]= { 1, 1, sizeof(u16) }, + [RTA_ENCAP] = { 1, 0, 0 }, +}; + +static struct nl_want_attrs encap_mpls_want[BIRD_RTA_MAX] = { + [RTA_DST] = { 1, 0, 0 }, }; static struct nl_want_attrs rtm_attr_want4[BIRD_RTA_MAX] = { @@ -329,6 +351,8 @@ static struct nl_want_attrs rtm_attr_want4[BIRD_RTA_MAX] = { [RTA_MULTIPATH] = { 1, 0, 0 }, [RTA_FLOW] = { 1, 1, sizeof(u32) }, [RTA_TABLE] = { 1, 1, sizeof(u32) }, + [RTA_ENCAP_TYPE]= { 1, 1, sizeof(u16) }, + [RTA_ENCAP] = { 1, 0, 0 }, }; static struct nl_want_attrs rtm_attr_want6[BIRD_RTA_MAX] = { @@ -341,6 +365,20 @@ static struct nl_want_attrs rtm_attr_want6[BIRD_RTA_MAX] = { [RTA_METRICS] = { 1, 0, 0 }, [RTA_FLOW] = { 1, 1, sizeof(u32) }, [RTA_TABLE] = { 1, 1, sizeof(u32) }, + [RTA_ENCAP_TYPE]= { 1, 1, sizeof(u16) }, + [RTA_ENCAP] = { 1, 0, 0 }, +}; + +static struct nl_want_attrs rtm_attr_want_mpls[BIRD_RTA_MAX] = { + [RTA_DST] = { 1, 1, sizeof(u32) }, + [RTA_IIF] = { 1, 1, sizeof(u32) }, + [RTA_OIF] = { 1, 1, sizeof(u32) }, + [RTA_PRIORITY] = { 1, 1, sizeof(u32) }, + [RTA_METRICS] = { 1, 0, 0 }, + [RTA_FLOW] = { 1, 1, sizeof(u32) }, + [RTA_TABLE] = { 1, 1, sizeof(u32) }, + [RTA_VIA] = { 1, 0, 0 }, + [RTA_NEWDST] = { 1, 0, 0 }, }; @@ -373,6 +411,9 @@ nl_parse_attrs(struct rtattr *a, struct nl_want_attrs *want, struct rtattr **k, return 1; } +static inline u16 rta_get_u16(struct rtattr *a) +{ return *(u16 *) RTA_DATA(a); } + static inline u32 rta_get_u32(struct rtattr *a) { return *(u32 *) RTA_DATA(a); } @@ -390,6 +431,25 @@ static inline ip_addr rta_get_ipa(struct rtattr *a) return ipa_from_ip6(rta_get_ip6(a)); } +static inline ip_addr rta_get_via(struct rtattr *a) +{ + struct rtvia *v = RTA_DATA(a); + switch(v->rtvia_family) { + case AF_INET: return ipa_from_ip4(ip4_ntoh(*(ip4_addr *) v->rtvia_addr)); + case AF_INET6: return ipa_from_ip6(ip6_ntoh(*(ip6_addr *) v->rtvia_addr)); + } + return IPA_NONE; +} + +static u32 rta_mpls_stack[MPLS_MAX_LABEL_STACK]; +static inline int rta_get_mpls(struct rtattr *a, u32 *stack) +{ + if (RTA_PAYLOAD(a) % 4) + log(L_WARN "KRT: Strange length of received MPLS stack: %u", RTA_PAYLOAD(a)); + + return mpls_get(RTA_DATA(a), RTA_PAYLOAD(a) & ~0x3, stack); +} + struct rtattr * nl_add_attr(struct nlmsghdr *h, uint bufsize, uint code, const void *data, uint dlen) { @@ -410,6 +470,24 @@ nl_add_attr(struct nlmsghdr *h, uint bufsize, uint code, const void *data, uint return a; } +static inline struct rtattr * +nl_open_attr(struct nlmsghdr *h, uint bufsize, uint code) +{ + return nl_add_attr(h, bufsize, code, NULL, 0); +} + +static inline void +nl_close_attr(struct nlmsghdr *h, struct rtattr *a) +{ + a->rta_len = (void *)h + NLMSG_ALIGN(h->nlmsg_len) - (void *)a; +} + +static inline void +nl_add_attr_u16(struct nlmsghdr *h, uint bufsize, int code, u16 data) +{ + nl_add_attr(h, bufsize, code, &data, 2); +} + static inline void nl_add_attr_u32(struct nlmsghdr *h, uint bufsize, int code, u32 data) { @@ -439,16 +517,47 @@ nl_add_attr_ipa(struct nlmsghdr *h, uint bufsize, int code, ip_addr ipa) nl_add_attr_ip6(h, bufsize, code, ipa_to_ip6(ipa)); } -static inline struct rtattr * -nl_open_attr(struct nlmsghdr *h, uint bufsize, uint code) +static inline void +nl_add_attr_mpls(struct nlmsghdr *h, uint bufsize, int code, int len, u32 *stack) { - return nl_add_attr(h, bufsize, code, NULL, 0); + char buf[len*4]; + mpls_put(buf, len, stack); + nl_add_attr(h, bufsize, code, buf, len*4); } static inline void -nl_close_attr(struct nlmsghdr *h, struct rtattr *a) +nl_add_attr_mpls_encap(struct nlmsghdr *h, uint bufsize, int len, u32 *stack) { - a->rta_len = (void *)h + NLMSG_ALIGN(h->nlmsg_len) - (void *)a; + nl_add_attr_u16(h, bufsize, RTA_ENCAP_TYPE, LWTUNNEL_ENCAP_MPLS); + + struct rtattr *nest = nl_open_attr(h, bufsize, RTA_ENCAP); + nl_add_attr_mpls(h, bufsize, RTA_DST, len, stack); + nl_close_attr(h, nest); +} + +static inline void +nl_add_attr_via(struct nlmsghdr *h, uint bufsize, ip_addr ipa) +{ + struct rtattr *nest = nl_open_attr(h, bufsize, RTA_VIA); + struct rtvia *via = RTA_DATA(nest); + + h->nlmsg_len += sizeof(*via); + + if (ipa_is_ip4(ipa)) { + ip4_addr ip4 = ipa_to_ip4(ipa); + ip4 = ip4_hton(ip4); + via->rtvia_family = AF_INET; + memcpy(via->rtvia_addr, &ip4, sizeof(ip4)); + h->nlmsg_len += sizeof(ip4); + } else { + ip6_addr ip6 = ipa_to_ip6(ipa); + ip6 = ip6_hton(ip6); + via->rtvia_family = AF_INET6; + memcpy(via->rtvia_addr, &ip6, sizeof(ip6)); + h->nlmsg_len += sizeof(ip6); + } + + nl_close_attr(h, nest); } static inline struct rtnexthop * @@ -471,8 +580,24 @@ nl_close_nexthop(struct nlmsghdr *h, struct rtnexthop *nh) nh->rtnh_len = (void *)h + NLMSG_ALIGN(h->nlmsg_len) - (void *)nh; } +static inline void +nl_add_nexthop(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af) +{ + if (nh->labels > 0) + if (af == AF_MPLS) + nl_add_attr_mpls(h, bufsize, RTA_NEWDST, nh->labels, nh->label); + else + nl_add_attr_mpls_encap(h, bufsize, nh->labels, nh->label); + + if (ipa_nonzero(nh->gw)) + if (af == AF_MPLS) + nl_add_attr_via(h, bufsize, nh->gw); + else + nl_add_attr_ipa(h, bufsize, RTA_GATEWAY, nh->gw); +} + static void -nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct nexthop *nh) +nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af) { struct rtattr *a = nl_open_attr(h, bufsize, RTA_MULTIPATH); @@ -484,7 +609,7 @@ nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct nexthop *nh) rtnh->rtnh_hops = nh->weight; rtnh->rtnh_ifindex = nh->iface->index; - nl_add_attr_ipa(h, bufsize, RTA_GATEWAY, nh->gw); + nl_add_nexthop(h, bufsize, nh, af); nl_close_nexthop(h, rtnh); } @@ -518,7 +643,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra) 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 * sizeof(struct nexthop)); + nh_buffer = xrealloc(nh_buffer, nh_buf_size * NEXTHOP_MAX_SIZE); } *last = rv = nh_buffer + nh_buf_used++; rv->next = NULL; @@ -543,7 +668,21 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra) return NULL; } else - return NULL; + rv->gw = IPA_NONE; + if (a[RTA_ENCAP_TYPE]) + { + if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) { + log(L_WARN "KRT: Unknown encapsulation method %d in multipath", rta_get_u16(a[RTA_ENCAP_TYPE])); + return NULL; + } + + struct rtattr *enca[BIRD_RTA_MAX]; + nl_attr_len = RTA_PAYLOAD(a[RTA_ENCAP]); + nl_parse_attrs(RTA_DATA(a[RTA_ENCAP]), encap_mpls_want, enca, sizeof(enca)); + rv->labels = rta_get_mpls(enca[RTA_DST], rv->label); + break; + } + len -= NLMSG_ALIGN(nh->rtnh_len); nh = RTNH_NEXT(nh); @@ -1008,7 +1147,13 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d r->r.rtm_dst_len = net_pxlen(net->n.addr); r->r.rtm_protocol = RTPROT_BIRD; r->r.rtm_scope = RT_SCOPE_UNIVERSE; - nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(net->n.addr)); + if (p->af == AF_MPLS) + { + u32 label = net_mpls(net->n.addr); + nl_add_attr_mpls(&r->h, rsize, RTA_DST, 1, &label); + } + else + nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(net->n.addr)); /* * Strange behavior for RTM_DELROUTE: @@ -1071,13 +1216,11 @@ dest: case RTD_UNICAST: r->r.rtm_type = RTN_UNICAST; if (nh->next && !krt_ecmp6(p)) - nl_add_multipath(&r->h, rsize, nh); + nl_add_multipath(&r->h, rsize, nh, p->af); else { nl_add_attr_u32(&r->h, rsize, RTA_OIF, nh->iface->index); - - if (ipa_nonzero(nh->gw)) - nl_add_attr_ipa(&r->h, rsize, RTA_GATEWAY, nh->gw); + nl_add_nexthop(&r->h, rsize, nh, p->af); } break; case RTD_BLACKHOLE: @@ -1276,6 +1419,19 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) net_fill_ip6(&dst, IP6_NONE, 0); break; + case AF_MPLS: + if (!nl_parse_attrs(RTM_RTA(i), rtm_attr_want_mpls, a, sizeof(a))) + return; + + if (a[RTA_DST]) + if (rta_get_mpls(a[RTA_DST], rta_mpls_stack) == 1) + net_fill_mpls(&dst, rta_mpls_stack[0]); + else + log(L_WARN "KRT: Got multi-label MPLS RTA_DST"); + else + return; /* No support for MPLS routes without RTA_DST */ + break; + default: return; } @@ -1338,7 +1494,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type)) nl_announce_route(s); - rta *ra = lp_allocz(s->pool, sizeof(rta)); // TODO: fix alloc + rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE); ra->src = p->p.main_source; ra->source = RTS_INHERIT; ra->scope = SCOPE_UNIVERSE; @@ -1367,9 +1523,12 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; } - if (a[RTA_GATEWAY]) + if ((i->rtm_family != AF_MPLS) && a[RTA_GATEWAY] || (i->rtm_family == AF_MPLS) && a[RTA_VIA]) { - ra->nh.gw = rta_get_ipa(a[RTA_GATEWAY]); + if (i->rtm_family == AF_MPLS) + ra->nh.gw = rta_get_via(a[RTA_VIA]); + else + ra->nh.gw = rta_get_ipa(a[RTA_GATEWAY]); /* Silently skip strange 6to4 routes */ const net_addr_ip6 sit = NET_ADDR_IP6(IP6_NONE, 96); @@ -1377,7 +1536,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; neighbor *nbr; - nbr = neigh_find2(&p->p, &ra->nh.gw, ra->nh.iface, + nbr = neigh_find2(&p->p, &(ra->nh.gw), ra->nh.iface, (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0); if (!nbr || (nbr->scope == SCOPE_HOST)) { @@ -1403,6 +1562,44 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; } + int labels = 0; + if ((i->rtm_family == AF_MPLS) && a[RTA_NEWDST] && !ra->nh.next) + labels = rta_get_mpls(a[RTA_NEWDST], ra->nh.label); + + if (a[RTA_ENCAP] && a[RTA_ENCAP_TYPE] && !ra->nh.next) + { + switch (rta_get_u16(a[RTA_ENCAP_TYPE])) + { + case LWTUNNEL_ENCAP_MPLS: + { + struct rtattr *enca[BIRD_RTA_MAX]; + nl_attr_len = RTA_PAYLOAD(a[RTA_ENCAP]); + nl_parse_attrs(RTA_DATA(a[RTA_ENCAP]), encap_mpls_want, enca, sizeof(enca)); + labels = rta_get_mpls(enca[RTA_DST], ra->nh.label); + break; + } + default: + SKIP("unknown encapsulation method %d\n", rta_get_u16(a[RTA_ENCAP_TYPE])); + break; + } + } + + if (labels < 0) + { + log(L_WARN "KRT: Too long MPLS stack received, ignoring."); + ra->nh.labels = 0; + } + else + ra->nh.labels = labels; + + rte *e = rte_get_temp(ra); + e->net = net; + e->u.krt.src = src; + e->u.krt.proto = i->rtm_protocol; + e->u.krt.seen = 0; + e->u.krt.best = 0; + e->u.krt.metric = 0; + if (i->rtm_scope != def_scope) { ea_list *ea = lp_alloc(s->pool, sizeof(ea_list) + sizeof(eattr)); @@ -1416,6 +1613,9 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) ea->attrs[0].u.data = i->rtm_scope; } + if (a[RTA_PRIORITY]) + e->u.krt.metric = rta_get_u32(a[RTA_PRIORITY]); + if (a[RTA_PREFSRC]) { ip_addr ps = rta_get_ipa(a[RTA_PREFSRC]); @@ -1527,6 +1727,15 @@ krt_do_scan(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NUL 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_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); } /* diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 9f66d2f4..c273cb10 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -1153,7 +1153,8 @@ krt_start(struct proto *P) { case NET_IP4: p->af = AF_INET; break; case NET_IP6: p->af = AF_INET6; break; - default: ASSERT(0); + case NET_MPLS: p->af = AF_MPLS; break; + default: log(L_ERR "KRT: Tried to start with strange net type: %d", p->p.net_type); return PS_START; break; } add_tail(&krt_proto_list, &p->krt_node); @@ -1264,7 +1265,7 @@ struct protocol proto_unix_kernel = { .template = "kernel%d", .attr_class = EAP_KRT, .preference = DEF_PREF_INHERITED, - .channel_mask = NB_IP, + .channel_mask = NB_IP | NB_MPLS, .proto_size = sizeof(struct krt_proto), .config_size = sizeof(struct krt_config), .preconfig = krt_preconfig, -- cgit v1.2.3 From 62e64905b76b88da72c522eac9276a74f60c9592 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Mon, 20 Feb 2017 02:26:45 +0100 Subject: Several minor fixes --- conf/cf-lex.l | 39 +++++++++++++++------- conf/confbase.Y | 11 ++++--- doc/bird.sgml | 10 +++--- filter/filter.h | 6 ++-- lib/alloca.h | 2 ++ lib/net.c | 19 ++++++----- lib/net.h | 16 ++++++---- nest/route.h | 8 ++--- nest/rt-attr.c | 42 ++++++++++-------------- nest/rt-dev.c | 4 +-- nest/rt-table.c | 16 +++++----- proto/bgp/attrs.c | 3 +- proto/bgp/packets.c | 12 +++---- proto/ospf/rt.c | 10 ++---- proto/pipe/pipe.c | 2 -- proto/rip/rip.c | 21 +++++------- proto/rpki/rpki.c | 2 +- proto/static/config.Y | 87 ++++++++++++++++++++++++++++---------------------- proto/static/static.c | 53 +++++++++++++----------------- sysdep/bsd/krt-sock.c | 86 ++++++++++++++++++++++++------------------------- sysdep/linux/netlink.c | 52 +++++++++++++++++------------- sysdep/unix/krt.c | 13 +------- 22 files changed, 253 insertions(+), 261 deletions(-) (limited to 'sysdep') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 8e1f60a6..fb3d59e4 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -124,39 +124,56 @@ include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*; } [02]:{DIGIT}+:{DIGIT}+ { + unsigned long int l, len1, len2; char *e; - unsigned long int l; if (yytext[0] == '0') + { cf_lval.i64 = 0; + len1 = 16; + len2 = 32; + } else - cf_lval.i64 = 0x2000000000000ULL; + { + cf_lval.i64 = 2ULL << 48; + len1 = 32; + len2 = 16; + } errno = 0; l = strtoul(yytext+2, &e, 10); - if (e && (*e != ':') || errno == ERANGE || (yytext[0] == '0') && (l >= (1<<16))) + if (e && (*e != ':') || (errno == ERANGE) || (l >> len1)) cf_error("ASN out of range"); - cf_lval.i64 |= (((u64) l) << 32); + cf_lval.i64 |= ((u64) l) << len2; + errno = 0; l = strtoul(e+1, &e, 10); - if (e && *e || errno == ERANGE || (yytext[0] == '2') && (l >= (1<<16))) - cf_error("Assigned number out of range"); + if (e && *e || (errno == ERANGE) || (l >> len2)) + cf_error("Number out of range"); cf_lval.i64 |= l; + return VPN_RD; } 1:{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ { unsigned long int l; - char *e = strchr(yytext+2, ':'); - *e++ = '\0'; ip4_addr ip4; + char *e; + + cf_lval.i64 = 1ULL << 48; + + e = strchr(yytext+2, ':'); + *e++ = '\0'; if (!ip4_pton(yytext+2, &ip4)) cf_error("Invalid IPv4 address %s in Route Distinguisher", yytext+2); + cf_lval.i64 |= ((u64) ip4_to_u32(ip4)) << 16; + errno = 0; l = strtoul(e, &e, 10); - if (e && *e || errno == ERANGE || (l >= (1<<16))) - cf_error("Assigned number out of range"); - cf_lval.i64 = (1ULL<<48) | (((u64)ip4_to_u32(ip4)) << 16) | ((u64)l); + if (e && *e || (errno == ERANGE) || (l >> 16)) + cf_error("Number out of range"); + cf_lval.i64 |= l; + return VPN_RD; } diff --git a/conf/confbase.Y b/conf/confbase.Y index a5b8b692..291dc6a0 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -203,13 +203,13 @@ net_ip6_: IP6 '/' NUM net_vpn4_: VPN_RD net_ip4_ { $$ = cfg_alloc(sizeof(net_addr_vpn4)); - net_fill_vpn4($$, ((net_addr_ip4 *)&$2)->prefix, $2.pxlen, $1); + net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1); } net_vpn6_: VPN_RD net_ip6_ { $$ = cfg_alloc(sizeof(net_addr_vpn6)); - net_fill_vpn6($$, ((net_addr_ip6 *)&$2)->prefix, $2.pxlen, $1); + net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1); } net_roa4_: net_ip4_ MAX NUM AS NUM @@ -229,8 +229,8 @@ net_roa6_: net_ip6_ MAX NUM AS NUM }; net_ip_: net_ip4_ | net_ip6_ ; -net_roa_: net_roa4_ | net_roa6_ ; net_vpn_: net_vpn4_ | net_vpn6_ ; +net_roa_: net_roa4_ | net_roa6_ ; net_: net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); } @@ -297,8 +297,9 @@ label_stack: label_stack_start | label_stack '/' NUM { if ($1[0] >= MPLS_MAX_LABEL_STACK) - cf_error("Too many labels in stack."); - $1[++$1[0]] = $3; + cf_error("Too many labels in stack"); + $1[0]++; + $1[*$1] = $3; $$ = $1; } ; diff --git a/doc/bird.sgml b/doc/bird.sgml index 23026eae..c49e7e8e 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -4140,12 +4140,12 @@ return packets as undeliverable if they are in your IP block, you don't have any specific destination for them and you don't want to send them out through the default route to prevent routing loops). -

There are five types of static routes: `classical' routes telling to forward +

There are four types of static routes: `classical' routes telling to forward packets to a neighboring router (single path or multipath, possibly weighted), -device routes specifying forwarding to hosts on a -directly connected network, recursive routes computing their nexthops by doing -route table lookups for a given IP, and special routes (sink, blackhole etc.) -which specify a special action to be done instead of forwarding the packet. +device routes specifying forwarding to hosts on a directly connected network, +recursive routes computing their nexthops by doing route table lookups for a +given IP, and special routes (sink, blackhole etc.) which specify a special +action to be done instead of forwarding the packet.

When the particular destination is not available (the interface is down or the next hop of the route is not a neighbor at the moment), Static just diff --git a/filter/filter.h b/filter/filter.h index 0482b83b..855219ec 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -174,9 +174,9 @@ void val_format(struct f_val v, buffer *buf); #define SA_PROTO 4 #define SA_SOURCE 5 #define SA_SCOPE 6 -#define SA_DEST 8 -#define SA_IFNAME 9 -#define SA_IFINDEX 10 +#define SA_DEST 7 +#define SA_IFNAME 8 +#define SA_IFINDEX 9 struct f_tree { diff --git a/lib/alloca.h b/lib/alloca.h index f0d61bb4..e5557cdb 100644 --- a/lib/alloca.h +++ b/lib/alloca.h @@ -15,4 +15,6 @@ #include #endif +#define allocz(len) ({ void *_x = alloca(len); memset(_x, 0, len); _x; }) + #endif diff --git a/lib/net.c b/lib/net.c index e46be8b2..74cea277 100644 --- a/lib/net.c +++ b/lib/net.c @@ -69,21 +69,20 @@ net_format(const net_addr *N, char *buf, int buflen) case NET_VPN4: switch (n->vpn4.rd >> 48) { - case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); - case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); - case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); + case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); + case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); + case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen); + default: return bsnprintf(buf, buflen, "X:%08x:%08x %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen); } - return bsnprintf(buf, buflen, "X: %016x %I4/%d", (n->vpn4.rd), n->vpn4.prefix, n->vpn4.pxlen); - - /* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4. */ case NET_VPN6: + /* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4 */ switch (n->vpn6.rd >> 48) { - case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); - case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); - case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); + case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); + case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); + case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen); + default: return bsnprintf(buf, buflen, "X:%08x:%08x %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen); } - return bsnprintf(buf, buflen, "X: %016x %I6/%d", (n->vpn6.rd), n->vpn6.prefix, n->vpn6.pxlen); case NET_ROA4: return bsnprintf(buf, buflen, "%I4/%u-%u AS%u", n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn); case NET_ROA6: diff --git a/lib/net.h b/lib/net.h index 7c124fc0..7144bcb9 100644 --- a/lib/net.h +++ b/lib/net.h @@ -306,6 +306,9 @@ static inline int net_equal_flow4(const net_addr_flow4 *a, const net_addr_flow4 static inline int net_equal_flow6(const net_addr_flow6 *a, const net_addr_flow6 *b) { return net_equal((const net_addr *) a, (const net_addr *) b); } +static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b) +{ return !memcmp(a, b, sizeof(net_addr_mpls)); } + static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_roa4 *b) { return ip4_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); } @@ -313,8 +316,6 @@ static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_r static inline int net_equal_prefix_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b) { return ip6_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); } -static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b) -{ return !memcmp(a, b, sizeof(net_addr_mpls)); } static inline int net_zero_ip4(const net_addr_ip4 *a) { return !a->pxlen && ip4_zero(a->prefix); } @@ -404,16 +405,17 @@ static inline void net_copy_flow6(net_addr_flow6 *dst, const net_addr_flow6 *src static inline void net_copy_mpls(net_addr_mpls *dst, const net_addr_mpls *src) { memcpy(dst, src, sizeof(net_addr_mpls)); } + +/* XXXX */ +static inline u32 u64_hash(u64 a) +{ return u32_hash(a); } + static inline u32 net_hash_ip4(const net_addr_ip4 *n) { return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); } static inline u32 net_hash_ip6(const net_addr_ip6 *n) { return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); } -/* XXXX */ -static inline u32 u64_hash(u64 a) -{ return u32_hash(a); } - static inline u32 net_hash_vpn4(const net_addr_vpn4 *n) { return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } @@ -452,7 +454,7 @@ static inline int net_validate_ip6(const net_addr_ip6 *n) static inline int net_validate_mpls(const net_addr_mpls *n) { - return n->label < (1<<20); + return n->label < (1 << 20); } int net_validate(const net_addr *N); diff --git a/nest/route.h b/nest/route.h index eb98b609..1e0a14bc 100644 --- a/nest/route.h +++ b/nest/route.h @@ -390,11 +390,11 @@ typedef struct rta { #define RTC_MULTICAST 2 #define RTC_ANYCAST 3 /* IPv6 Anycast */ -#define RTD_UNICAST 0 /* Next hop is neighbor router */ +#define RTD_NONE 0 /* Undefined next hop */ +#define RTD_UNICAST 1 /* Next hop is neighbor router */ #define RTD_BLACKHOLE 2 /* Silently drop packets */ #define RTD_UNREACHABLE 3 /* Reject as unreachable */ #define RTD_PROHIBIT 4 /* Administratively prohibited */ -#define RTD_NONE 6 /* Invalid RTD */ /* Flags for net->n.flags, used by kernel syncer */ #define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */ @@ -408,7 +408,7 @@ typedef struct rta { /* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */ static inline int rte_is_reachable(rte *r) -{ uint d = r->attrs->dest; return (d == RTD_UNICAST); } +{ return r->attrs->dest == RTD_UNICAST; } /* @@ -523,7 +523,7 @@ static inline int nexthop_same(struct nexthop *x, struct nexthop *y) struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp); 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); +void nexthop_insert(struct nexthop **n, struct nexthop *y); int nexthop_is_sorted(struct nexthop *x); void rta_init(void); diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 120a8e24..afc97e22 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -150,7 +150,8 @@ nexthop_hash(struct nexthop *x) for (; x; x = x->next) { h ^= ipa_hash(x->gw) ^ (h << 5) ^ (h >> 9); - for (int i=0; ilabels; i++) + + for (int i = 0; i < x->labels; i++) h ^= x->label[i] ^ (h << 6) ^ (h >> 7); } @@ -164,12 +165,13 @@ nexthop__same(struct nexthop *x, struct nexthop *y) { if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight) || (x->labels != y->labels)) return 0; - for (int i=0; ilabels; i++) + + for (int i = 0; i < x->labels; i++) if (x->label[i] != y->label[i]) return 0; } - return 1; + return x == y; } static int @@ -195,7 +197,7 @@ nexthop_compare_node(struct nexthop *x, struct nexthop *y) if (r) return r; - for (int i=0; ilabels; i++) + for (int i = 0; i < y->labels; i++) { r = ((int) y->label[i]) - ((int) x->label[i]); if (r) @@ -271,34 +273,22 @@ nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, lin } void -nexthop_insert(struct nexthop *n, struct nexthop *x) +nexthop_insert(struct nexthop **n, struct nexthop *x) { - struct nexthop tmp; - memcpy(&tmp, n, sizeof(struct nexthop)); - if (nexthop_compare_node(n, x) > 0) /* Insert to the included nexthop */ - { - memcpy(n, x, sizeof(struct nexthop)); - memcpy(x, &tmp, sizeof(struct nexthop)); - n->next = x; - return; - } - - for (struct nexthop **nn = &(n->next); *nn; nn = &((*nn)->next)) + for (; *n; n = &((*n)->next)) { - int cmp = nexthop_compare_node(*nn, x); + int cmp = nexthop_compare_node(*n, x); if (cmp < 0) continue; - - if (cmp > 0) - { - x->next = *nn; - *nn = x; - } - - return; + else if (cmp > 0) + break; + else + return; } + x->next = *n; + *n = x; } int @@ -314,7 +304,7 @@ nexthop_is_sorted(struct nexthop *x) static inline slab * nexthop_slab(struct nexthop *nh) { - return nexthop_slab_[nh->labels > 2 ? 3 : nh->labels]; + return nexthop_slab_[MIN(nh->labels, 3)]; } static struct nexthop * diff --git a/nest/rt-dev.c b/nest/rt-dev.c index 5edd1c5d..9993da24 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -79,9 +79,7 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad) .source = RTS_DEVICE, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, - .nh = { - .iface = ad->iface - } + .nh.iface = ad->iface, }; a = rta_lookup(&a0); diff --git a/nest/rt-table.c b/nest/rt-table.c index ef402f28..a33b7909 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -1768,7 +1768,6 @@ static inline void rta_apply_hostentry(rta *a, struct hostentry *he) { a->hostentry = he; - a->dest = he->dest; a->igp_metric = he->igp_metric; @@ -1810,14 +1809,14 @@ rta_apply_hostentry(rta *a, struct hostentry *he) static inline rte * rt_next_hop_update_rte(rtable *tab UNUSED, rte *old) { - rta *ap = alloca(RTA_MAX_SIZE); - memcpy(ap, old->attrs, rta_size(old->attrs)); - rta_apply_hostentry(ap, old->attrs->hostentry); - ap->aflags = 0; + rta *a = alloca(RTA_MAX_SIZE); + memcpy(a, old->attrs, rta_size(old->attrs)); + rta_apply_hostentry(a, old->attrs->hostentry); + a->aflags = 0; rte *e = sl_alloc(rte_slab); memcpy(e, old, sizeof(rte)); - e->attrs = rta_lookup(ap); + e->attrs = rta_lookup(a); return e; } @@ -2373,7 +2372,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) } if ((a->dest == RTD_UNICAST) && ipa_zero(a->nh.gw) && !a->next) - { /* We have singlepath device route */ + { + /* We have singlepath device route */ if (if_local_addr(he->addr, a->nh.iface)) { /* The host address is a local address, this is not valid */ @@ -2389,7 +2389,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) else { /* The host is reachable through some route entry */ - he->nh = (&a->nh); + he->nh = &(a->nh); he->dest = a->dest; } diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 11666f30..1b124a17 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1461,8 +1461,7 @@ bgp_get_neighbor(rte *r) static inline int rte_resolvable(rte *rt) { - int rd = rt->attrs->dest; - return (rd == RTD_UNICAST); + return rt->attrs->dest == RTD_UNICAST; } int diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 9c59e6d8..9380f999 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -700,9 +700,7 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll) WITHDRAW(BAD_NEXT_HOP); a->dest = RTD_UNICAST; - a->nh.gw = nbr->addr; - a->nh.iface = nbr->iface; - a->nh.next = NULL; + a->nh = (struct nexthop){ .gw = nbr->addr, .iface = nbr->iface }; a->hostentry = NULL; a->igp_metric = 0; } @@ -749,8 +747,8 @@ bgp_use_gateway(struct bgp_export_state *s) if (s->channel->cf->next_hop_self) return 0; - /* We need valid global gateway */ - if ((ra->dest != RTD_UNICAST) || (ra->nh.next) || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw)) + /* We need one valid global gateway */ + if ((ra->dest != RTD_UNICAST) || ra->nh.next || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw)) return 0; /* Use it when exported to internal peers */ @@ -1434,12 +1432,10 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis if (ea) { - a = alloca(sizeof(struct rta)); - memset(a, 0, sizeof(struct rta)); + a = allocz(sizeof(struct rta)); a->source = RTS_BGP; a->scope = SCOPE_UNIVERSE; - a->dest = RTD_UNREACHABLE; a->from = s->proto->cf->remote_ip; a->eattrs = ea; diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 74f47810..1b0ac5e9 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -36,11 +36,9 @@ unresolved_vlink(ort *ort) static inline struct nexthop * new_nexthop(struct ospf_proto *p, ip_addr gw, struct iface *iface, byte weight) { - struct nexthop *nh = lp_alloc(p->nhpool, sizeof(struct nexthop)); - nh->labels = 0; + struct nexthop *nh = lp_allocz(p->nhpool, sizeof(struct nexthop)); nh->gw = gw; nh->iface = iface; - nh->next = NULL; nh->weight = weight; return nh; } @@ -1907,7 +1905,6 @@ ort_changed(ort *nf, rta *nr) (nf->n.metric1 != nf->old_metric1) || (nf->n.metric2 != nf->old_metric2) || (nf->n.tag != nf->old_tag) || (nf->n.rid != nf->old_rid) || (nr->source != or->source) || (nr->dest != or->dest) || - (nr->nh.iface != or->nh.iface) || !ipa_equal(nr->nh.gw, or->nh.gw) || !nexthop_same(&(nr->nh), &(or->nh)); } @@ -1952,11 +1949,10 @@ again1: .src = p->p.main_source, .source = nf->n.type, .scope = SCOPE_UNIVERSE, + .dest = RTD_UNICAST, + .nh = *(nf->n.nhs), }; - nexthop_link(&a0, nf->n.nhs); - a0.dest = RTD_UNICAST; - if (reload || ort_changed(nf, &a0)) { rta *a = rta_lookup(&a0); diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index a4d371fe..310f3c01 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -43,8 +43,6 @@ #include "pipe.h" -#include - static void pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old, ea_list *attrs) { diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 9bed9249..157093aa 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -147,20 +147,16 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) .src = p->p.main_source, .source = RTS_RIP, .scope = SCOPE_UNIVERSE, + .dest = RTD_UNICAST, }; u8 rt_metric = rt->metric; u16 rt_tag = rt->tag; - struct rip_rte *rt2 = rt->next; - /* Find second valid rte */ - while (rt2 && !rip_valid_rte(rt2)) - rt2 = rt2->next; - - a0.dest = RTD_UNICAST; - if (p->ecmp && rt2) + if (p->ecmp) { /* ECMP route */ + struct nexthop *nhs = NULL; int num = 0; for (rt = en->routes; rt && (num < p->ecmp); rt = rt->next) @@ -168,28 +164,27 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) if (!rip_valid_rte(rt)) continue; - struct nexthop *nh = (a0.nh.next ? &(a0.nh) : alloca(sizeof(struct nexthop))); + struct nexthop *nh = allocz(sizeof(struct nexthop)); nh->gw = rt->next_hop; nh->iface = rt->from->nbr->iface; nh->weight = rt->from->ifa->cf->ecmp_weight; - if (a0.nh.next) - nexthop_insert(&(a0.nh), nh); - + nexthop_insert(&nhs, nh); num++; if (rt->tag != rt_tag) rt_tag = 0; } + + a0.nh = *nhs; } else { /* Unipath route */ - a0.nh.next = NULL; + a0.from = rt->from->nbr->addr; a0.nh.gw = rt->next_hop; a0.nh.iface = rt->from->nbr->iface; - a0.from = rt->from->nbr->addr; } rta *a = rta_lookup(&a0); diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c index 81268e83..497edd3c 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -124,7 +124,7 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_ .src = p->p.main_source, .source = RTS_RPKI, .scope = SCOPE_UNIVERSE, - .dest = RTD_BLACKHOLE, + .dest = RTD_NONE, }; rta *a = rta_lookup(&a0); diff --git a/proto/static/config.Y b/proto/static/config.Y index 2fb54448..16c276ce 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -13,9 +13,33 @@ CF_HDR CF_DEFINES #define STATIC_CFG ((struct static_config *) this_proto) -static struct static_route *this_srt, *last_srt; +static struct static_route *this_srt, *this_snh; static struct f_inst **this_srt_last_cmd; +static struct static_route * +static_nexthop_new(void) +{ + struct static_route *nh; + + if (!this_snh) + { + /* First next hop */ + nh = this_srt; + rem_node(&this_srt->n); + } + else + { + /* Additional next hop */ + nh = cfg_allocz(sizeof(struct static_route)); + nh->net = this_srt->net; + this_snh->mp_next = nh; + } + + nh->dest = RTD_UNICAST; + nh->mp_head = this_srt; + return nh; +}; + static void static_route_finish(void) { } @@ -45,48 +69,35 @@ static_proto: | static_proto stat_route stat_route_opt_list ';' { static_route_finish(); } ; -stat_nexthop_via: VIA -{ - if (last_srt) - { - last_srt = (last_srt->mp_next = cfg_allocz(sizeof(struct static_route))); - last_srt->net = this_srt->net; - } - else - { - last_srt = this_srt; - rem_node(&this_srt->n); - } - - last_srt->mp_head = this_srt; - last_srt->dest = RTD_UNICAST; -}; - -stat_nexthop_ident: - stat_nexthop_via ipa ipa_scope { - last_srt->via = $2; - last_srt->iface = $3; - add_tail(&STATIC_CFG->neigh_routes, &last_srt->n); +stat_nexthop: + VIA ipa ipa_scope { + this_snh = static_nexthop_new(); + this_snh->via = $2; + this_snh->iface = $3; + add_tail(&STATIC_CFG->neigh_routes, &this_snh->n); } - | stat_nexthop_via TEXT { - last_srt->via = IPA_NONE; - last_srt->if_name = $2; - add_tail(&STATIC_CFG->iface_routes, &last_srt->n); + | VIA TEXT { + this_snh = static_nexthop_new(); + this_snh->via = IPA_NONE; + this_snh->if_name = $2; + add_tail(&STATIC_CFG->iface_routes, &this_snh->n); } - | stat_nexthop_ident MPLS label_stack { - last_srt->label_count = $3[0]; - last_srt->label_stack = &($3[1]); + | stat_nexthop MPLS label_stack { + this_snh->label_count = $3[0]; + this_snh->label_stack = &($3[1]); } - | stat_nexthop_ident WEIGHT expr { - last_srt->weight = $3 - 1; + | stat_nexthop WEIGHT expr { + this_snh->weight = $3 - 1; if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256"); } - | stat_nexthop_ident BFD bool { last_srt->use_bfd = $3; cf_check_bfd($3); } + | stat_nexthop BFD bool { + this_snh->use_bfd = $3; cf_check_bfd($3); + } ; -stat_nexthop: - stat_nexthop_ident - | stat_nexthop stat_nexthop_ident +stat_nexthops: + stat_nexthop + | stat_nexthops stat_nexthop ; stat_route0: ROUTE net_any { @@ -95,12 +106,12 @@ stat_route0: ROUTE net_any { this_srt->net = $2; this_srt_last_cmd = &(this_srt->cmds); this_srt->mp_next = NULL; - last_srt = NULL; + this_snh = NULL; } ; stat_route: - stat_route0 stat_nexthop + stat_route0 stat_nexthops | stat_route0 RECURSIVE ipa { this_srt->dest = RTDX_RECURSIVE; this_srt->via = $3; diff --git a/proto/static/static.c b/proto/static/static.c index 3e03708c..e5251bf6 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -60,54 +60,44 @@ p_igp_table(struct proto *p) static void static_install(struct proto *p, struct static_route *r) { - rta *ap = alloca(RTA_MAX_SIZE); + rta *ap = allocz(RTA_MAX_SIZE); rte *e; if (!(r->state & STS_WANT) && (r->state & (STS_INSTALLED | STS_FORCE)) && r->dest != RTD_UNICAST) goto drop; DBG("Installing static route %N, rtd=%d\n", r->net, r->dest); - bzero(ap, RTA_MAX_SIZE); ap->src = p->main_source; - ap->source = ((r->dest == RTD_UNICAST) && ipa_zero(r->via)) ? RTS_STATIC_DEVICE : RTS_STATIC; + ap->source = RTS_STATIC; ap->scope = SCOPE_UNIVERSE; ap->dest = r->dest; if (r->dest == RTD_UNICAST) { + struct nexthop *nhs = NULL; struct static_route *r2; - int num = 0, update = 0; + int update = 0; + r = r->mp_head; for (r2 = r; r2; r2 = r2->mp_next) { - if ((r2->state & STS_FORCE) || (!!(r2->state & STS_INSTALLED) != !!(r2->state & STS_WANT))) update++; if (r2->state & STS_WANT) - { - struct nexthop *nh = (ap->nh.next) ? alloca(NEXTHOP_MAX_SIZE) : &(ap->nh); - if (ipa_zero(r2->via)) // Device nexthop - { - nh->gw = IPA_NONE; - nh->iface = r2->iface; - } - else // Router nexthop - { - nh->gw = r2->via; - nh->iface = r2->neigh->iface; - } - nh->weight = r2->weight; - nh->labels = r2->label_count; - for (int i=0; ilabels; i++) - nh->label[i] = r2->label_stack[i]; - - if (ap->nh.next) - nexthop_insert(&(ap->nh), nh); - r2->state |= STS_INSTALLED; - num++; - } + { + struct nexthop *nh = allocz(NEXTHOP_MAX_SIZE); + + nh->gw = r2->via; + nh->iface = r2->neigh ? r2->neigh->iface : r2->iface; + nh->weight = r2->weight; + nh->labels = r2->label_count; + memcpy(nh->label, r2->label_stack, r2->label_count * sizeof(u32)); + + r2->state |= STS_INSTALLED; + nexthop_insert(&nhs, nh); + } else r2->state = 0; } @@ -115,18 +105,19 @@ static_install(struct proto *p, struct static_route *r) if (!update) // Nothing changed return; - r = r->mp_head; - - if (!num) // No nexthop to install + if (!nhs) // No nexthop to install { drop: rte_update(p, r->net, NULL); return; } + + ap->dest = RTD_UNICAST; + nexthop_link(ap, nhs); } else r->state |= STS_INSTALLED; - + if (r->dest == RTDX_RECURSIVE) { ap->nh.labels_append = ap->nh.labels = r->label_count; diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 2e0f194b..c65cba65 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -193,7 +193,6 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) struct ks_msg msg; char *body = (char *)msg.buf; sockaddr gate, mask, dst; - ip_addr gw; DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw); @@ -223,14 +222,12 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) msg.rtm.rtm_flags |= RTF_BLACKHOLE; #endif - /* This is really very nasty, but I'm not able - * to add "(reject|blackhole)" route without - * gateway set + /* + * This is really very nasty, but I'm not able to add reject/blackhole route + * without gateway address. */ - if(!i) + if (!i) { - i = HEAD(iface_list); - WALK_LIST(j, iface_list) { if (j->flags & IF_LOOPBACK) @@ -239,13 +236,13 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) break; } } - } - gw = a->nh.gw; - - /* Embed interface ID to link-local address */ - if (ipa_is_link_local(gw)) - _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff); + if (!i) + { + log(L_ERR "KRT: Cannot find loopback iface"); + return -1; + } + } int af = AF_UNSPEC; @@ -261,45 +258,51 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) return -1; } - sockaddr_fill(&dst, af, net_prefix(net->n.addr), NULL, 0); sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0); - sockaddr_fill(&gate, af, gw, NULL, 0); switch (a->dest) { - case RTD_UNICAST: - if (ipa_zero(gw)) - { - if(i) - { -#ifdef RTF_CLONING - if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */ - msg.rtm.rtm_flags |= RTF_CLONING; -#endif + case RTD_UNICAST: + if (ipa_nonzero(a->nh.gw)) + { + ip_addr gw = a->nh.gw; - if(!i->addr) { - log(L_ERR "KRT: interface %s has no IP addess", i->name); - return -1; - } - - sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0); - msg.rtm.rtm_addrs |= RTA_GATEWAY; - } - } else { - msg.rtm.rtm_flags |= RTF_GATEWAY; - msg.rtm.rtm_addrs |= RTA_GATEWAY; - } + /* Embed interface ID to link-local address */ + if (ipa_is_link_local(gw)) + _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff); + + sockaddr_fill(&gate, af, gw, NULL, 0); + msg.rtm.rtm_flags |= RTF_GATEWAY; + msg.rtm.rtm_addrs |= RTA_GATEWAY; break; + } #ifdef RTF_REJECT - case RTD_UNREACHABLE: + case RTD_UNREACHABLE: #endif #ifdef RTF_BLACKHOLE - case RTD_BLACKHOLE: + case RTD_BLACKHOLE: #endif - default: - bug("krt-sock: unknown flags, but not filtered"); + { + /* Fallback for all other valid cases */ + if (!i->addr) + { + log(L_ERR "KRT: interface %s has no IP addess", i->name); + return -1; + } + +#ifdef RTF_CLONING + if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */ + msg.rtm.rtm_flags |= RTF_CLONING; +#endif + + sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0); + msg.rtm.rtm_addrs |= RTA_GATEWAY; + } + + default: + bug("krt-sock: unknown flags, but not filtered"); } msg.rtm.rtm_index = i->index; @@ -497,7 +500,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) } a.dest = RTD_UNICAST; - a.nh.next = NULL; if (flags & RTF_GATEWAY) { neighbor *ng; @@ -520,8 +522,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) return; } } - else - a.nh.gw = IPA_NONE; done: e = rte_get_temp(&a); diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 23431172..80439c47 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -320,6 +320,7 @@ static struct nl_want_attrs ifa_attr_want4[BIRD_IFA_MAX] = { [IFA_ADDRESS] = { 1, 1, sizeof(ip4_addr) }, [IFA_LOCAL] = { 1, 1, sizeof(ip4_addr) }, [IFA_BROADCAST] = { 1, 1, sizeof(ip4_addr) }, + [IFA_FLAGS] = { 1, 1, sizeof(u32) }, }; static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = { @@ -543,18 +544,17 @@ nl_add_attr_via(struct nlmsghdr *h, uint bufsize, ip_addr ipa) h->nlmsg_len += sizeof(*via); - if (ipa_is_ip4(ipa)) { - ip4_addr ip4 = ipa_to_ip4(ipa); - ip4 = ip4_hton(ip4); + if (ipa_is_ip4(ipa)) + { via->rtvia_family = AF_INET; - memcpy(via->rtvia_addr, &ip4, sizeof(ip4)); - h->nlmsg_len += sizeof(ip4); - } else { - ip6_addr ip6 = ipa_to_ip6(ipa); - ip6 = ip6_hton(ip6); + put_ip4(via->rtvia_addr, ipa_to_ip4(ipa)); + h->nlmsg_len += sizeof(ip4_addr); + } + else + { via->rtvia_family = AF_INET6; - memcpy(via->rtvia_addr, &ip6, sizeof(ip6)); - h->nlmsg_len += sizeof(ip6); + put_ip6(via->rtvia_addr, ipa_to_ip6(ipa)); + h->nlmsg_len += sizeof(ip6_addr); } nl_close_attr(h, nest); @@ -669,6 +669,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra) } else rv->gw = IPA_NONE; + if (a[RTA_ENCAP_TYPE]) { if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) { @@ -1092,20 +1093,16 @@ krt_capable(rte *e) rta *a = e->attrs; switch (a->dest) - { + { case RTD_UNICAST: - for (struct nexthop *nh = &(a->nh); nh; nh = nh->next) - if (nh->iface) - return 1; - return 0; case RTD_BLACKHOLE: case RTD_UNREACHABLE: case RTD_PROHIBIT: - break; + return 1; + default: return 0; - } - return 1; + } } static inline int @@ -1210,7 +1207,6 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d dest: - /* a->iface != NULL checked in krt_capable() for router and device routes */ switch (dest) { case RTD_UNICAST: @@ -1502,6 +1498,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) switch (i->rtm_type) { case RTN_UNICAST: + ra->dest = RTD_UNICAST; if (a[RTA_MULTIPATH] && (i->rtm_family == AF_INET)) { @@ -1512,7 +1509,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; } - nexthop_link(ra, nh); + ra->nh = *nh; break; } @@ -1698,9 +1695,20 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) else { /* Merge next hops with the stored route */ - rta *a = s->attrs; + rta *oa = s->attrs; - nexthop_insert(&a->nh, &ra->nh); + struct nexthop *nhs = &oa->nh; + nexthop_insert(&nhs, &ra->nh); + + /* Perhaps new nexthop is inserted at the first position */ + if (nhs == &ra->nh) + { + /* Swap rtas */ + s->attrs = ra; + + /* Keep old eattrs */ + ra->eattrs = oa->eattrs; + } } } diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index c273cb10..c6ff6275 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -984,7 +984,7 @@ krt_store_tmp_attrs(rte *rt, struct ea_list *attrs) static int krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) { - struct krt_proto *p = (struct krt_proto *) P; + // struct krt_proto *p = (struct krt_proto *) P; rte *e = *new; if (e->attrs->src->proto == P) @@ -1005,17 +1005,6 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li return -1; } - if (!KRT_CF->devroutes && (e->attrs->source != RTS_STATIC_DEVICE)) - { - struct nexthop *nh = &(e->attrs->nh); - for (; nh; nh = nh->next) - if (ipa_nonzero(nh->gw)) - break; - - if (!nh) /* Gone through all the nexthops and no explicit GW found */ - return -1; - } - if (!krt_capable(e)) return -1; -- cgit v1.2.3