Commit 5bcbcaeb authored by Ondrej Zajicek (work)'s avatar Ondrej Zajicek (work) Committed by Pavel Tvrdik
Browse files

Direct: Implement check link for direct protocol

When enabled, direct protocol generates routes only if the underlying
link state is up.
parent 26d5565d
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -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.
+1 −0
Original line number Diff line number Diff line
@@ -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:
+27 −1
Original line number Diff line number Diff line
@@ -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 = {
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
struct rt_dev_config {
  struct proto_config c;
  list iface_list;		/* list of struct iface_patt */
  int check_link;
};

#endif