Direct: Implement check link for direct protocol
When enabled, direct protocol generates routes only if the underlying link state is up.
This commit is contained in:
parent
f2ae2badff
commit
e90dd656cc
4 changed files with 36 additions and 2 deletions
|
@ -2155,7 +2155,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
|
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.
|
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>
|
<p><descrip>
|
||||||
<tag>interface <m/pattern [, ...]/</tag>
|
<tag>interface <m/pattern [, ...]/</tag>
|
||||||
|
@ -2166,6 +2166,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">
|
interfaces), just use this clause. See <ref id="dsc-iface" name="interface">
|
||||||
common option for detailed description. The Direct protocol uses
|
common option for detailed description. The Direct protocol uses
|
||||||
extended interface clauses.
|
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>
|
</descrip>
|
||||||
|
|
||||||
<p>Direct device routes don't contain any specific attributes.
|
<p>Direct device routes don't contain any specific attributes.
|
||||||
|
|
|
@ -335,6 +335,7 @@ dev_proto:
|
||||||
dev_proto_start proto_name '{'
|
dev_proto_start proto_name '{'
|
||||||
| dev_proto proto_item ';'
|
| dev_proto proto_item ';'
|
||||||
| dev_proto dev_iface_patt ';'
|
| dev_proto dev_iface_patt ';'
|
||||||
|
| dev_proto CHECK LINK bool ';' { DIRECT_CFG->check_link = $4; }
|
||||||
;
|
;
|
||||||
|
|
||||||
dev_iface_init:
|
dev_iface_init:
|
||||||
|
|
|
@ -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);
|
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 */
|
/* Use iface ID as local source ID */
|
||||||
struct rte_src *src = rt_get_source(p, ad->iface->index);
|
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 *
|
static struct proto *
|
||||||
dev_init(struct proto_config *c)
|
dev_init(struct proto_config *c)
|
||||||
{
|
{
|
||||||
struct proto *p = proto_new(c, sizeof(struct proto));
|
struct proto *p = proto_new(c, sizeof(struct proto));
|
||||||
|
|
||||||
|
p->if_notify = dev_if_notify;
|
||||||
p->ifa_notify = dev_ifa_notify;
|
p->ifa_notify = dev_ifa_notify;
|
||||||
return p;
|
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 *o = (struct rt_dev_config *) p->cf;
|
||||||
struct rt_dev_config *n = (struct rt_dev_config *) new;
|
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
|
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).
|
* old nodes cannot be modified (although they contain internal lists).
|
||||||
*/
|
*/
|
||||||
cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt));
|
cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt));
|
||||||
|
|
||||||
|
d->check_link = s->check_link;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct protocol proto_device = {
|
struct protocol proto_device = {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
struct rt_dev_config {
|
struct rt_dev_config {
|
||||||
struct proto_config c;
|
struct proto_config c;
|
||||||
list iface_list; /* list of struct iface_patt */
|
list iface_list; /* list of struct iface_patt */
|
||||||
|
int check_link;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue