Re: [PATCH] Netlink: add krt_scope attribute
❦ 16 septembre 2016 11:33 CEST, Ondrej Zajicek : >> > For device routes created by the kernel, scope is link, but if you >> > create them manually, you get a global scope. >> >> My point was that 'ip' tool does that automatically for users: >> >> # ip r a 10.1.1.0/24 dev eth0 >> # ip r l >> 10.1.1.0/24 dev eth0 scope link >> >> Perhaps we should do that too. The fact that we do not set link scope >> for device routes sent to kernel is probably an oversight, not by design. > > Here is an attached patch, which does that. Does it work for you? Yes, works just fine for me! -- April 1 This is the day upon which we are reminded of what we are on the other three hundred and sixty-four. -- Mark Twain, "Pudd'nhead Wilson's Calendar"
Re: [PATCH] Netlink: add krt_scope attribute
On Thu, Sep 15, 2016 at 10:36:11PM +0200, Ondrej Zajicek wrote: > On Thu, Sep 15, 2016 at 09:22:02PM +0200, Vincent Bernat wrote: > > > I though that kernel sets scope link automatically for device routes, > > > but in reality it is done by ip tool. Perhaps we should do that too. > > > > For device routes created by the kernel, scope is link, but if you > > create them manually, you get a global scope. > > My point was that 'ip' tool does that automatically for users: > > # ip r a 10.1.1.0/24 dev eth0 > # ip r l > 10.1.1.0/24 dev eth0 scope link > > Perhaps we should do that too. The fact that we do not set link scope > for device routes sent to kernel is probably an oversight, not by design. Here is an attached patch, which does that. Does it work for you? -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santi...@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so." diff --git a/sysdep/linux/krt-sys.h b/sysdep/linux/krt-sys.h index 96688e3..6d6586d 100644 --- a/sysdep/linux/krt-sys.h +++ b/sysdep/linux/krt-sys.h @@ -36,6 +36,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; } #define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 0x10) #define EA_KRT_REALM EA_CODE(EAP_KRT, 0x11) +#define EA_KRT_SCOPE EA_CODE(EAP_KRT, 0x12) #define KRT_METRICS_MAX 0x10 /* RTAX_QUICKACK+1 */ diff --git a/sysdep/linux/netlink.Y b/sysdep/linux/netlink.Y index a1c22f3..f577244 100644 --- a/sysdep/linux/netlink.Y +++ b/sysdep/linux/netlink.Y @@ -10,7 +10,7 @@ CF_HDR CF_DECLS -CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, KRT_MTU, KRT_WINDOW, +CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, KRT_SCOPE, KRT_MTU, KRT_WINDOW, KRT_RTT, KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING, KRT_HOPLIMIT, KRT_INITCWND, KRT_RTO_MIN, KRT_INITRWND, KRT_QUICKACK, KRT_LOCK_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR, @@ -28,6 +28,7 @@ kern_sys_item: CF_ADDTO(dynamic_attr, KRT_PREFSRC { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_KRT_PREFSRC); }) CF_ADDTO(dynamic_attr, KRT_REALM { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_REALM); }) +CF_ADDTO(dynamic_attr, KRT_SCOPE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SCOPE); }) CF_ADDTO(dynamic_attr, KRT_MTU { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_MTU); }) CF_ADDTO(dynamic_attr, KRT_WINDOW { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_WINDOW); }) diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 9bdcc0d..1490213 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_TYP
Re: [PATCH] Netlink: add krt_scope attribute
On Thu, Sep 15, 2016 at 09:22:02PM +0200, Vincent Bernat wrote: > > I though that kernel sets scope link automatically for device routes, > > but in reality it is done by ip tool. Perhaps we should do that too. > > For device routes created by the kernel, scope is link, but if you > create them manually, you get a global scope. My point was that 'ip' tool does that automatically for users: # ip r a 10.1.1.0/24 dev eth0 # ip r l 10.1.1.0/24 dev eth0 scope link Perhaps we should do that too. The fact that we do not set link scope for device routes sent to kernel is probably an oversight, not by design. I think reasonable behavior would be like: if route has krt_scope attribute -> use that else if it is device route -> use link else -> use universe And in other direction (kernel->bird): if route has expected scope (link for device, universe otherwise) -> do not set krt_scope else -> set krt_scope -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santi...@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so." signature.asc Description: Digital signature
Re: [PATCH] Netlink: add krt_scope attribute
❦ 15 septembre 2016 21:22 CEST, Vincent Bernat : >> Thans for the patch. I agree that we should handle the attribute >> if it has some usage. I have some questions/comments: >> >> Perhaps we should use the same approach like we use for krt_realm? >> i.e., handle krt_scope as an integer variable and import constants >> from /etc/iproute2/rt_scopes. So we could handle all values as the >> Linux kernel and we would be consistent with iproute2 tools. > > I didn't know that scope names could be defined in this file. So, yes, > we should. Everything was already in place to use this file. So, the patch is now simplified. While the scope is correctly imported for regular routes, it is not for device routes. I still have to do: protocol direct { table public; import filter { krt_scope = ips_link; accept "ok"; }; interface "eth0*", "eth1*"; } I don't see why, I will investigate more tomorrow. >From 29787207b33162046bfae06086e248f47d947bde Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Thu, 15 Sep 2016 18:04:19 +0200 Subject: [PATCH] Netlink: add krt_scope attribute The general-purpose scope attribute is detailed in the documentation as an attribute that BIRD won't set and won't use. Therefore, to expose the scope of a kernel route, this commit adds a new attribute, krt_scope. The possible values are read from /etc/iproute2/rt_scopes (prefixed by "ips_"). Both import and export are supported. Signed-off-by: Vincent Bernat --- sysdep/linux/krt-sys.h | 1 + sysdep/linux/netlink.Y | 3 ++- sysdep/linux/netlink.c | 23 +-- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/sysdep/linux/krt-sys.h b/sysdep/linux/krt-sys.h index 96688e34c860..6d6586d10f02 100644 --- a/sysdep/linux/krt-sys.h +++ b/sysdep/linux/krt-sys.h @@ -36,6 +36,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; } #define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 0x10) #define EA_KRT_REALM EA_CODE(EAP_KRT, 0x11) +#define EA_KRT_SCOPE EA_CODE(EAP_KRT, 0x12) #define KRT_METRICS_MAX 0x10 /* RTAX_QUICKACK+1 */ diff --git a/sysdep/linux/netlink.Y b/sysdep/linux/netlink.Y index a1c22f3ece17..f577244de183 100644 --- a/sysdep/linux/netlink.Y +++ b/sysdep/linux/netlink.Y @@ -10,7 +10,7 @@ CF_HDR CF_DECLS -CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, KRT_MTU, KRT_WINDOW, +CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, KRT_SCOPE, KRT_MTU, KRT_WINDOW, KRT_RTT, KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING, KRT_HOPLIMIT, KRT_INITCWND, KRT_RTO_MIN, KRT_INITRWND, KRT_QUICKACK, KRT_LOCK_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR, @@ -28,6 +28,7 @@ kern_sys_item: CF_ADDTO(dynamic_attr, KRT_PREFSRC { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_KRT_PREFSRC); }) CF_ADDTO(dynamic_attr, KRT_REALM { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_REALM); }) +CF_ADDTO(dynamic_attr, KRT_SCOPE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SCOPE); }) CF_ADDTO(dynamic_attr, KRT_MTU { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_MTU); }) CF_ADDTO(dynamic_attr, KRT_WINDOW { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_WINDOW); }) diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 9bdcc0d2ff19..2aeadbae4117 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -900,6 +900,9 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d r.r.rtm_dst_len = net->n.pxlen; r.r.rtm_protocol = RTPROT_BIRD; r.r.rtm_scope = RT_SCOPE_UNIVERSE; + if (ea = ea_find(eattrs, EA_KRT_SCOPE)) +r.r.rtm_scope = ea->u.data; + nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix); /* @@ -1157,7 +1160,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 +1197,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: @@ -1304,6 +1301,16 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; } + 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 +1640,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; + cas
Re: [PATCH] Netlink: add krt_scope attribute
❦ 15 septembre 2016 20:36 CEST, Ondrej Zajicek : > Thans for the patch. I agree that we should handle the attribute > if it has some usage. I have some questions/comments: > > Perhaps we should use the same approach like we use for krt_realm? > i.e., handle krt_scope as an integer variable and import constants > from /etc/iproute2/rt_scopes. So we could handle all values as the > Linux kernel and we would be consistent with iproute2 tools. I didn't know that scope names could be defined in this file. So, yes, we should. > I don't really understand how Linux handles scope argument. If i > remember correctly, the idea is that next hop of a route could be > resolvable through a route with higher scope value, but it seems > that it distinguish only host (internal), link and anything other. At least, Linux will refuse to install a route "scope global" when the next-hop is "scope global" too. >> A typical use case is to install "scope link" routes for directly >> connected destinations, as the kernel won't accept routes with a broader >> scope when issuing an internal lookup. > > You mean for regular routes (with next hop) or device routes? Device routes. > I though that kernel sets scope link automatically for device routes, > but in reality it is done by ip tool. Perhaps we should do that too. For device routes created by the kernel, scope is link, but if you create them manually, you get a global scope. > I could create regular routes with scope link directed to device routes > with scope link (which is a bit strange) and then create regular routes > with normal scope directed on them, but i cannot get more hierarchy. In fact, I need top copy device routes from main table to other tables (to workaround a limitation with Linux kernel before 3.15). Currently, they are copied with "scope global". I need them to copy them with "scope link", otherwise BIRD won't be able to install routes with a next-hop in the connected subnet. -- 10.0 times 0.1 is hardly ever 1.0. - The Elements of Programming Style (Kernighan & Plauger)
Re: [PATCH] Netlink: add krt_scope attribute
On Thu, Sep 15, 2016 at 06:05:27PM +0200, Vincent Bernat wrote: > The general-purpose scope attribute is detailed in the documentation as > an attribute that BIRD won't set and won't use. Therefore, to expose the > scope of a kernel route, this commit adds a new attribute, > krt_scope. Its possible values are the numeric values for SCOPE_* > variables (1 is SCOPE_LINK for example), not the values from the > kernel (253 is RT_SCOPE_LINK). Both import and export are supported. Hi Thans for the patch. I agree that we should handle the attribute if it has some usage. I have some questions/comments: Perhaps we should use the same approach like we use for krt_realm? i.e., handle krt_scope as an integer variable and import constants from /etc/iproute2/rt_scopes. So we could handle all values as the Linux kernel and we would be consistent with iproute2 tools. I don't really understand how Linux handles scope argument. If i remember correctly, the idea is that next hop of a route could be resolvable through a route with higher scope value, but it seems that it distinguish only host (internal), link and anything other. > A typical use case is to install "scope link" routes for directly > connected destinations, as the kernel won't accept routes with a broader > scope when issuing an internal lookup. You mean for regular routes (with next hop) or device routes? I though that kernel sets scope link automatically for device routes, but in reality it is done by ip tool. Perhaps we should do that too. I could create regular routes with scope link directed to device routes with scope link (which is a bit strange) and then create regular routes with normal scope directed on them, but i cannot get more hierarchy. -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santi...@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so." signature.asc Description: Digital signature
Re: [PATCH] Netlink: add krt_scope attribute
❦ 15 septembre 2016 18:05 CEST, Vincent Bernat : > It would have been neat to be able to use "SCOPE_LINK" in a filter > or to show "SCOPE_LINK" when displaying the route, but currently, only > the numerical value can be used. Any hint for this part would be welcome. The T_ENUM_SCOPE is ignored and SCOPE_LINK is considered as non-int for some reason. -- Take care to branch the right way on equality. - The Elements of Programming Style (Kernighan & Plauger)