]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Direct: Implement check link for direct protocol
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Fri, 8 Apr 2016 13:10:57 +0000 (15:10 +0200)
committerPavel Tvrdik <pawel.tvrdik@gmail.com>
Tue, 3 May 2016 07:25:37 +0000 (09:25 +0200)
When enabled, direct protocol generates routes only if the underlying
link state is up.

doc/bird.sgml
nest/config.Y
nest/rt-dev.c
nest/rt-dev.h

index bd04ac870ce143118b1b5d8530e4274e3bf444a0..4ace60be7c5c3746e283465ccf6602fa41f7bdd2 100644 (file)
@@ -2194,7 +2194,7 @@ conditions, because a lower priority IGP route for the same network is not
 exported to the kernel routing table. This is an issue on BSD systems only, as
 on Linux systems BIRD cannot change non-BIRD route in the kernel routing table.
 
-<p>The only configurable thing about direct is what interfaces it watches:
+<p>There are just few configuration options for the Direct protocol:
 
 <p><descrip>
        <tag>interface <m/pattern [, ...]/</tag>
@@ -2205,6 +2205,12 @@ on Linux systems BIRD cannot change non-BIRD route in the kernel routing table.
        interfaces), just use this clause. See <ref id="dsc-iface" name="interface">
        common option for detailed description. The Direct protocol uses
        extended interface clauses.
+
+       <tag>check link <m/switch/</tag>
+       If enabled, a hardware link state (reported by OS) is taken into
+       consideration. Routes for directly connected networks are generated only
+       if link up is reported and they are withdrawn when link disappears
+       (e.g., an ethernet cable is unplugged). Default value is no.
 </descrip>
 
 <p>Direct device routes don't contain any specific attributes.
index 435bc986be8fa391f675a5d2368e3aff5a32309a..cd888ab8f5355461119daba0868190a80e2df7fd 100644 (file)
@@ -337,6 +337,7 @@ dev_proto:
    dev_proto_start proto_name '{'
  | dev_proto proto_item ';'
  | dev_proto dev_iface_patt ';'
+ | dev_proto CHECK LINK bool ';' { DIRECT_CFG->check_link = $4; }
  ;
 
 dev_iface_init:
index f6bc1432b7da24dbf00adac5334860811d02bb5c..ed6c06afd70ee4ef53bc4356a4440bf7d059d95e 100644 (file)
@@ -64,6 +64,9 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
 
       DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);
 
+      if (P->check_link && !(ad->iface->flags & IF_LINK_UP))
+       return;
+
       /* Use iface ID as local source ID */
       struct rte_src *src = rt_get_source(p, ad->iface->index);
 
@@ -85,11 +88,31 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
     }
 }
 
+static void
+dev_if_notify(struct proto *p, uint c, struct iface *iface)
+{
+  struct rt_dev_config *cf = (void *) p->cf;
+
+  if (c & (IF_CHANGE_UP | IF_CHANGE_DOWN))
+    return;
+
+  if ((c & IF_CHANGE_LINK) && cf->check_link)
+  {
+    uint ac = (iface->flags & IF_LINK_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN;
+
+    struct ifa *a;
+    WALK_LIST(a, iface->addrs)
+      dev_ifa_notify(p, ac, a);
+  }
+}
+
+
 static struct proto *
 dev_init(struct proto_config *c)
 {
   struct proto *p = proto_new(c, sizeof(struct proto));
 
+  p->if_notify = dev_if_notify;
   p->ifa_notify = dev_ifa_notify;
   return p;
 }
@@ -100,7 +123,8 @@ dev_reconfigure(struct proto *p, struct proto_config *new)
   struct rt_dev_config *o = (struct rt_dev_config *) p->cf;
   struct rt_dev_config *n = (struct rt_dev_config *) new;
 
-  return iface_patts_equal(&o->iface_list, &n->iface_list, NULL);
+  return iface_patts_equal(&o->iface_list, &n->iface_list, NULL) &&
+    (o->check_link == n->check_link);
 }
 
 static void
@@ -115,6 +139,8 @@ dev_copy_config(struct proto_config *dest, struct proto_config *src)
    * old nodes cannot be modified (although they contain internal lists).
    */
   cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt));
+
+  d->check_link = s->check_link;
 }
 
 struct protocol proto_device = {
index c36d074238c99f0cf48fa55f4e2078923100ef3f..191b9a0209c8fd3c9012b037caa92b305579cd6e 100644 (file)
@@ -12,6 +12,7 @@
 struct rt_dev_config {
   struct proto_config c;
   list iface_list;             /* list of struct iface_patt */
+  int check_link;
 };
 
 #endif