[PATCH] Netlink: add krt_scope attribute

Vincent Bernat vincent at bernat.im
Thu Sep 15 18:05:27 CEST 2016


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.

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.

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.

Signed-off-by: Vincent Bernat <vincent at bernat.im>
---
 sysdep/linux/krt-sys.h |  1 +
 sysdep/linux/netlink.Y |  3 ++-
 sysdep/linux/netlink.c | 40 ++++++++++++++++++++++++++++++++++------
 3 files changed, 37 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..c1c9503c33ec 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_ENUM_SCOPE, 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..9f73e0feeeaf 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -900,6 +900,15 @@ 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))
+    switch (ea->u.data)
+      {
+      case SCOPE_HOST: r.r.rtm_scope = RT_SCOPE_HOST; break;
+      case SCOPE_LINK: r.r.rtm_scope = RT_SCOPE_LINK; break;
+      case SCOPE_SITE: r.r.rtm_scope = RT_SCOPE_SITE; break;
+      case SCOPE_UNIVERSE: r.r.rtm_scope = RT_SCOPE_UNIVERSE; break;
+      }
+
   nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
 
   /*
@@ -1157,7 +1166,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 +1203,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 +1307,27 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
       return;
     }
 
+  int krt_scope = -1;
+  switch (i->rtm_scope)
+    {
+    case RT_SCOPE_HOST: krt_scope = SCOPE_HOST; break;
+    case RT_SCOPE_LINK: krt_scope = SCOPE_LINK; break;
+    case RT_SCOPE_SITE: krt_scope = SCOPE_SITE; break;
+    case RT_SCOPE_UNIVERSE: krt_scope = SCOPE_UNIVERSE; break;
+    }
+  if (krt_scope != -1)
+    {
+      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 = krt_scope;
+    }
+
   if (a[RTA_PREFSRC])
     {
       ip_addr ps;
@@ -1633,6 +1657,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);
-- 
2.9.3



More information about the Bird-users mailing list