From 6e75d0d27fe85f12a22928e5729465823704281e Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Mon, 19 Sep 2016 12:29:56 +0200 Subject: KRT: Add krt_scope attribute Add a new route attribute, krt_scope, to expose the Linux kernel route scope. Constants from /etc/iproute2/rt_scopes (prefixed by "ips_") are expected to be used with the attribute. Both import and export are supported. Also, the patch fixes device route export to the kernel, by setting link scope automatically. --- sysdep/linux/netlink.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'sysdep/linux/netlink.c') diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 9bdcc0d2..1490213e 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -899,7 +899,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d r.r.rtm_family = BIRD_AF; r.r.rtm_dst_len = net->n.pxlen; r.r.rtm_protocol = RTPROT_BIRD; - r.r.rtm_scope = RT_SCOPE_UNIVERSE; + r.r.rtm_scope = RT_SCOPE_NOWHERE; nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix); /* @@ -928,6 +928,12 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d if (op == NL_OP_DELETE) goto dest; + /* Default scope is LINK for device routes, UNIVERSE otherwise */ + 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; + if (ea = ea_find(eattrs, EA_KRT_PREFSRC)) nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data); @@ -1135,6 +1141,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) u32 oif = ~0; u32 table; u32 priority = 0; + u32 def_scope = RT_SCOPE_UNIVERSE; int src; if (!(i = nl_checkin(h, sizeof(*i)))) @@ -1157,7 +1164,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; } - if (a[RTA_DST]) { memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst)); @@ -1195,11 +1201,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK)) SKIP("strange class/scope\n"); - // ignore rtm_scope, it is not a real scope - // if (i->rtm_scope != RT_SCOPE_UNIVERSE) - // SKIP("scope %u\n", i->rtm_scope); - - switch (i->rtm_protocol) { case RTPROT_UNSPEC: @@ -1286,6 +1287,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) else { ra->dest = RTD_DEVICE; + def_scope = RT_SCOPE_LINK; } break; @@ -1304,6 +1306,19 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; } + if (i->rtm_scope != def_scope) + { + ea_list *ea = lp_alloc(s->pool, sizeof(ea_list) + sizeof(eattr)); + ea->next = ra->eattrs; + ra->eattrs = ea; + ea->flags = EALF_SORTED; + ea->count = 1; + ea->attrs[0].id = EA_KRT_SCOPE; + ea->attrs[0].flags = 0; + ea->attrs[0].type = EAF_TYPE_INT; + ea->attrs[0].u.data = i->rtm_scope; + } + if (a[RTA_PREFSRC]) { ip_addr ps; @@ -1633,6 +1648,10 @@ krt_sys_get_attr(eattr *a, byte *buf, int buflen UNUSED) bsprintf(buf, "realm"); return GA_NAME; + case EA_KRT_SCOPE: + bsprintf(buf, "scope"); + return GA_NAME; + case EA_KRT_LOCK: buf += bsprintf(buf, "lock:"); ea_format_bitfield(a, buf, buflen, krt_metrics_names, 2, KRT_METRICS_MAX); -- cgit v1.2.3