]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
KRT: Add krt_scope attribute
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Mon, 19 Sep 2016 10:29:56 +0000 (12:29 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Mon, 19 Sep 2016 10:29:56 +0000 (12:29 +0200)
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.

doc/bird.sgml
sysdep/linux/krt-sys.h
sysdep/linux/netlink.Y
sysdep/linux/netlink.c

index 9bd7df86d309af396667d3954333f5792a4a01cc..af5b798028387c8399204525571a073e1c19a027 100644 (file)
@@ -2443,6 +2443,15 @@ these attributes:
 
        <tag>int <cf/krt_realm/</tag> (Linux)
        The realm of the route. Can be used for traffic classification.
+
+       <tag>int <cf/krt_scope/</tag> (Linux IPv4)
+       The scope of the route. Valid values are 0-254, although Linux kernel
+       may reject some values depending on route type and nexthop. It is
+       supposed to represent `indirectness' of the route, where nexthops of
+       routes are resolved through routes with a higher scope, but in current
+       kernels anything below <it/link/ (253) is treated as <it/global/ (0).
+       When not present, global scope is implied for all routes except device
+       routes, where link scope is used by default.
 </descrip>
 
 <p>In Linux, there is also a plenty of obscure route attributes mostly focused
index 96688e34c86089d7215d72131b83cfea72c672c9..6d6586d10f0295843b9cbcca970e99eaa6f96ef5 100644 (file)
@@ -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 */
index a1c22f3ece17b66103b1a33ce5f4967bc923ce3e..f577244de183f20b0315e694a12e983547ae7ad9 100644 (file)
@@ -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); })
index 9bdcc0d2ff19a5dad3d159e4b60536cfa5fe2f94..1490213e04efb9b9431c729bb4dd8273f00cc131 100644 (file)
@@ -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);