mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-17 16:48:43 +00:00
Adds support for iface link check to static protocol.
This commit is contained in:
parent
f25cb0ef9f
commit
fe181e7c63
@ -117,7 +117,7 @@ if_what_changed(struct iface *i, struct iface *j)
|
|||||||
{
|
{
|
||||||
unsigned c;
|
unsigned c;
|
||||||
|
|
||||||
if (((i->flags ^ j->flags) & ~(IF_UP | IF_SHUTDOWN | IF_UPDATED | IF_ADMIN_UP | IF_TMP_DOWN | IF_JUST_CREATED))
|
if (((i->flags ^ j->flags) & ~(IF_UP | IF_SHUTDOWN | IF_UPDATED | IF_ADMIN_UP | IF_LINK_UP | IF_TMP_DOWN | IF_JUST_CREATED))
|
||||||
|| i->index != j->index)
|
|| i->index != j->index)
|
||||||
return IF_CHANGE_TOO_MUCH;
|
return IF_CHANGE_TOO_MUCH;
|
||||||
c = 0;
|
c = 0;
|
||||||
@ -213,6 +213,10 @@ if_notify_change(unsigned c, struct iface *i)
|
|||||||
a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
|
a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
|
||||||
ifa_notify_change(IF_CHANGE_UP, a);
|
ifa_notify_change(IF_CHANGE_UP, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((c & (IF_CHANGE_UP | IF_CHANGE_DOWN | IF_CHANGE_LINK)) == IF_CHANGE_LINK)
|
||||||
|
neigh_if_link(i);
|
||||||
|
|
||||||
if (c & IF_CHANGE_DOWN)
|
if (c & IF_CHANGE_DOWN)
|
||||||
neigh_if_down(i);
|
neigh_if_down(i);
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,7 @@ void neigh_dump_all(void);
|
|||||||
void neigh_prune(void);
|
void neigh_prune(void);
|
||||||
void neigh_if_up(struct iface *);
|
void neigh_if_up(struct iface *);
|
||||||
void neigh_if_down(struct iface *);
|
void neigh_if_down(struct iface *);
|
||||||
|
void neigh_if_link(struct iface *);
|
||||||
void neigh_init(struct pool *);
|
void neigh_init(struct pool *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -278,6 +278,28 @@ neigh_if_down(struct iface *i)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* neigh_if_link - notify neighbor cache about interface link change
|
||||||
|
* @i: the interface in question
|
||||||
|
*
|
||||||
|
* Notify the neighbor cache that an interface changed link state.
|
||||||
|
* All owners of neighbor entries connected to this interface are
|
||||||
|
* notified.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
neigh_if_link(struct iface *i)
|
||||||
|
{
|
||||||
|
node *x, *y;
|
||||||
|
|
||||||
|
WALK_LIST_DELSAFE(x, y, i->neighbors)
|
||||||
|
{
|
||||||
|
neighbor *n = SKIP_BACK(neighbor, if_n, x);
|
||||||
|
if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING)
|
||||||
|
n->proto->neigh_notify(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
neigh_prune_one(neighbor *n)
|
neigh_prune_one(neighbor *n)
|
||||||
{
|
{
|
||||||
|
@ -12,11 +12,12 @@ CF_HDR
|
|||||||
|
|
||||||
CF_DEFINES
|
CF_DEFINES
|
||||||
|
|
||||||
|
#define STATIC_CFG ((struct static_config *) this_proto)
|
||||||
static struct static_route *this_srt;
|
static struct static_route *this_srt;
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(STATIC, ROUTE, VIA, DROP, REJECT, PROHIBIT, PREFERENCE)
|
CF_KEYWORDS(STATIC, ROUTE, VIA, DROP, REJECT, PROHIBIT, PREFERENCE, CHECK, LINK)
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
@ -31,12 +32,13 @@ static_proto_start: proto_start STATIC {
|
|||||||
static_proto:
|
static_proto:
|
||||||
static_proto_start proto_name '{'
|
static_proto_start proto_name '{'
|
||||||
| static_proto proto_item ';'
|
| static_proto proto_item ';'
|
||||||
|
| static_proto CHECK LINK ';' { STATIC_CFG->check = STATIC_CHECK_LINK; }
|
||||||
| static_proto stat_route ';'
|
| static_proto stat_route ';'
|
||||||
;
|
;
|
||||||
|
|
||||||
stat_route0: ROUTE prefix {
|
stat_route0: ROUTE prefix {
|
||||||
this_srt = cfg_allocz(sizeof(struct static_route));
|
this_srt = cfg_allocz(sizeof(struct static_route));
|
||||||
add_tail(&((struct static_config *) this_proto)->other_routes, &this_srt->n);
|
add_tail(&STATIC_CFG->other_routes, &this_srt->n);
|
||||||
this_srt->net = $2.addr;
|
this_srt->net = $2.addr;
|
||||||
this_srt->masklen = $2.len;
|
this_srt->masklen = $2.len;
|
||||||
}
|
}
|
||||||
@ -51,7 +53,7 @@ stat_route:
|
|||||||
this_srt->dest = RTD_DEVICE;
|
this_srt->dest = RTD_DEVICE;
|
||||||
this_srt->if_name = $3;
|
this_srt->if_name = $3;
|
||||||
rem_node(&this_srt->n);
|
rem_node(&this_srt->n);
|
||||||
add_tail(&((struct static_config *) this_proto)->iface_routes, &this_srt->n);
|
add_tail(&STATIC_CFG->iface_routes, &this_srt->n);
|
||||||
}
|
}
|
||||||
| stat_route0 DROP { this_srt->dest = RTD_BLACKHOLE; }
|
| stat_route0 DROP { this_srt->dest = RTD_BLACKHOLE; }
|
||||||
| stat_route0 REJECT { this_srt->dest = RTD_UNREACHABLE; }
|
| stat_route0 REJECT { this_srt->dest = RTD_UNREACHABLE; }
|
||||||
|
@ -64,6 +64,20 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
|
|||||||
r->installed = 1;
|
r->installed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
static_decide(struct static_config *cf, struct static_route *r)
|
||||||
|
{
|
||||||
|
struct iface *ifa = r->neigh->iface;
|
||||||
|
|
||||||
|
if (!ifa)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((cf->check == STATIC_CHECK_LINK) && !(ifa->flags & IF_LINK_UP))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
static_remove(struct proto *p, struct static_route *r)
|
static_remove(struct proto *p, struct static_route *r)
|
||||||
{
|
{
|
||||||
@ -80,7 +94,7 @@ static_remove(struct proto *p, struct static_route *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
static_add(struct proto *p, struct static_route *r)
|
static_add(struct proto *p, struct static_config *cf, struct static_route *r)
|
||||||
{
|
{
|
||||||
DBG("static_add(%I/%d,%d)\n", r->net, r->masklen, r->dest);
|
DBG("static_add(%I/%d,%d)\n", r->net, r->masklen, r->dest);
|
||||||
switch (r->dest)
|
switch (r->dest)
|
||||||
@ -93,8 +107,10 @@ static_add(struct proto *p, struct static_route *r)
|
|||||||
r->chain = n->data;
|
r->chain = n->data;
|
||||||
n->data = r;
|
n->data = r;
|
||||||
r->neigh = n;
|
r->neigh = n;
|
||||||
if (n->iface)
|
if (static_decide(cf, r))
|
||||||
static_install(p, r, n->iface);
|
static_install(p, r, n->iface);
|
||||||
|
else
|
||||||
|
static_remove(p, r);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
log(L_ERR "Static route destination %I is invalid. Ignoring.", r->via);
|
log(L_ERR "Static route destination %I is invalid. Ignoring.", r->via);
|
||||||
@ -115,7 +131,7 @@ static_start(struct proto *p)
|
|||||||
|
|
||||||
DBG("Static: take off!\n");
|
DBG("Static: take off!\n");
|
||||||
WALK_LIST(r, c->other_routes)
|
WALK_LIST(r, c->other_routes)
|
||||||
static_add(p, r);
|
static_add(p, c, r);
|
||||||
return PS_UP;
|
return PS_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +158,7 @@ static_neigh_notify(struct neighbor *n)
|
|||||||
|
|
||||||
DBG("Static: neighbor notify for %I: iface %p\n", n->addr, n->iface);
|
DBG("Static: neighbor notify for %I: iface %p\n", n->addr, n->iface);
|
||||||
for(r=n->data; r; r=r->chain)
|
for(r=n->data; r; r=r->chain)
|
||||||
if (n->iface)
|
if (static_decide((struct static_config *) p->cf, r))
|
||||||
static_install(p, r, n->iface);
|
static_install(p, r, n->iface);
|
||||||
else
|
else
|
||||||
static_remove(p, r);
|
static_remove(p, r);
|
||||||
@ -249,13 +265,13 @@ static_match(struct proto *p, struct static_route *r, struct static_config *n)
|
|||||||
WALK_LIST(t, n->iface_routes)
|
WALK_LIST(t, n->iface_routes)
|
||||||
if (static_same_net(r, t))
|
if (static_same_net(r, t))
|
||||||
{
|
{
|
||||||
t->installed = static_same_dest(r, t);
|
t->installed = r->installed && static_same_dest(r, t);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WALK_LIST(t, n->other_routes)
|
WALK_LIST(t, n->other_routes)
|
||||||
if (static_same_net(r, t))
|
if (static_same_net(r, t))
|
||||||
{
|
{
|
||||||
t->installed = static_same_dest(r, t);
|
t->installed = r->installed && static_same_dest(r, t);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
static_remove(p, r);
|
static_remove(p, r);
|
||||||
@ -282,7 +298,7 @@ static_reconfigure(struct proto *p, struct proto_config *new)
|
|||||||
static_install(p, r, ifa);
|
static_install(p, r, ifa);
|
||||||
}
|
}
|
||||||
WALK_LIST(r, n->other_routes)
|
WALK_LIST(r, n->other_routes)
|
||||||
static_add(p, r);
|
static_add(p, n, r);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,12 @@ struct static_config {
|
|||||||
struct proto_config c;
|
struct proto_config c;
|
||||||
list iface_routes; /* Routes to search on interface events */
|
list iface_routes; /* Routes to search on interface events */
|
||||||
list other_routes; /* Routes hooked to neighbor cache and reject routes */
|
list other_routes; /* Routes hooked to neighbor cache and reject routes */
|
||||||
|
int check; /* Condition for route install */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define STATIC_CHECK_NONE 0
|
||||||
|
#define STATIC_CHECK_LINK 1
|
||||||
|
|
||||||
void static_init_config(struct static_config *);
|
void static_init_config(struct static_config *);
|
||||||
|
|
||||||
struct static_route {
|
struct static_route {
|
||||||
|
Loading…
Reference in New Issue
Block a user