]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
KRT: Add kernel metric protocol option
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Thu, 15 Sep 2016 12:59:06 +0000 (14:59 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Thu, 15 Sep 2016 12:59:06 +0000 (14:59 +0200)
Kernel routes with different metrics do not clash with each other,
therefore using dedicated metric value is a reliable way to avoid
overwriting routes from other sources (e.g. kernel device routes).

Although kernel route metric could already be set as a route attribute by
filters, that is not consistent with the way how Linux kernel handles
route metric - not just a route attribute, but a part of a route key.

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

index 1af7f2c1fa53867ea1c3aea0542f4393420b3948..9bd7df86d309af396667d3954333f5792a4a01cc 100644 (file)
@@ -2388,6 +2388,17 @@ limitations can be overcome using another routing table and the pipe protocol.
        protocol work with. Available only on systems supporting multiple
        routing tables.
 
+       <tag>metric <m/number/</tag> (Linux)
+       Use specified value as a kernel metric (priority) for all routes sent to
+       the kernel. When multiple routes for the same network are in the kernel
+       routing table, the Linux kernel chooses one with lower metric. Also,
+       routes with different metrics do not clash with each other, therefore
+       using dedicated metric value is a reliable way to avoid overwriting
+       routes from other sources (e.g. kernel device routes). Metric 0 has a
+       special meaning of undefined metric, in which either OS default is used,
+       or per-route metric can be set using <cf/krt_metric/ attribute. Default:
+       0 (undefined).
+
        <tag>graceful restart <m/switch/</tag>
        Participate in graceful restart recovery. If this option is enabled and
        a graceful restart recovery is active, the Kernel protocol will defer
@@ -2420,9 +2431,11 @@ these attributes:
        route. See /etc/iproute2/rt_protos for common values. On BSD, it is
        based on STATIC and PROTOx flags. The attribute is read-only.
 
-       <tag>int <cf/krt_metric/</tag>
+       <tag>int <cf/krt_metric/</tag> (Linux)
        The kernel metric of the route. When multiple same routes are in a
        kernel routing table, the Linux kernel chooses one with lower metric.
+       Note that preferred way to set kernel metric is to use protocol option
+       <cf/metric/, unless per-route metric values are needed.
 
        <tag>ip <cf/krt_prefsrc/</tag> (Linux)
        The preferred source address. Used in source address selection for
index 076870f5cfa7a6ea0feb60f6f49d17fbb5f13909..96688e34c86089d7215d72131b83cfea72c672c9 100644 (file)
@@ -88,6 +88,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; }
 
 struct krt_params {
   u32 table_id;                                /* Kernel table ID we sync with */
+  u32 metric;                          /* Kernel metric used for all routes */
 };
 
 struct krt_state {
index e9c225a202335f06aa75f81b14730b031604400c..a1c22f3ece17b66103b1a33ce5f4967bc923ce3e 100644 (file)
@@ -10,8 +10,8 @@ CF_HDR
 
 CF_DECLS
 
-CF_KEYWORDS(KERNEL, TABLE, KRT_PREFSRC, KRT_REALM, KRT_MTU, KRT_WINDOW, KRT_RTT,
-           KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
+CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, 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,
            KRT_LOCK_SSTRESH, KRT_LOCK_CWND, KRT_LOCK_ADVMSS, KRT_LOCK_REORDERING,
@@ -22,9 +22,8 @@ CF_GRAMMAR
 CF_ADDTO(kern_proto, kern_proto kern_sys_item ';')
 
 kern_sys_item:
-   KERNEL TABLE expr {
-       THIS_KRT->sys.table_id = $3;
-   }
+   KERNEL TABLE expr { THIS_KRT->sys.table_id = $3; }
+ | METRIC expr { THIS_KRT->sys.metric = $2; }
  ;
 
 CF_ADDTO(dynamic_attr, KRT_PREFSRC     { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_KRT_PREFSRC); })
index 1ab1cda19614399259c47afb9c9e69a0edf06b70..9bdcc0d2ff19a5dad3d159e4b60536cfa5fe2f94 100644 (file)
@@ -880,6 +880,8 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
   eattr *ea;
   net *net = e->net;
   rta *a = e->attrs;
+  u32 priority = 0;
+
   struct {
     struct nlmsghdr h;
     struct rtmsg r;
@@ -912,13 +914,20 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
   else
     nl_add_attr_u32(&r.h, sizeof(r), RTA_TABLE, krt_table_id(p));
 
+  if (a->source == RTS_DUMMY)
+    priority = e->u.krt.metric;
+  else if (KRT_CF->sys.metric)
+    priority = KRT_CF->sys.metric;
+  else if ((op != NL_OP_DELETE) && (ea = ea_find(eattrs, EA_KRT_METRIC)))
+    priority = ea->u.data;
+
+  if (priority)
+    nl_add_attr_u32(&r.h, sizeof(r), RTA_PRIORITY, priority);
+
   /* For route delete, we do not specify remaining route attributes */
   if (op == NL_OP_DELETE)
     goto dest;
 
-  if (ea = ea_find(eattrs, EA_KRT_METRIC))
-    nl_add_attr_u32(&r.h, sizeof(r), RTA_PRIORITY, ea->u.data);
-
   if (ea = ea_find(eattrs, EA_KRT_PREFSRC))
     nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
 
@@ -1585,19 +1594,21 @@ krt_sys_shutdown(struct krt_proto *p)
 int
 krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o)
 {
-  return n->sys.table_id == o->sys.table_id;
+  return (n->sys.table_id == o->sys.table_id) && (n->sys.metric == o->sys.metric);
 }
 
 void
 krt_sys_init_config(struct krt_config *cf)
 {
   cf->sys.table_id = RT_TABLE_MAIN;
+  cf->sys.metric = 0;
 }
 
 void
 krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
 {
   d->sys.table_id = s->sys.table_id;
+  d->sys.metric = s->sys.metric;
 }
 
 static const char *krt_metrics_names[KRT_METRICS_MAX] = {