1
0
mirror of https://gitlab.labs.nic.cz/labs/bird.git synced 2024-05-11 16:54:54 +00:00

Static: Support for BFD controlled static routes

This commit is contained in:
Ondrej Zajicek
2015-07-24 18:02:07 +02:00
parent 1321e12ac4
commit 538264cf1a
4 changed files with 141 additions and 37 deletions

View File

@@ -141,6 +141,29 @@ static_remove(struct proto *p, struct static_route *r)
r->installed = 0;
}
static void
static_bfd_notify(struct bfd_request *req);
static void
static_update_bfd(struct proto *p, struct static_route *r)
{
struct neighbor *nb = r->neigh;
int bfd_up = (nb->scope > 0) && r->use_bfd;
if (bfd_up && !r->bfd_req)
{
// ip_addr local = ipa_nonzero(r->local) ? r->local : nb->ifa->ip;
r->bfd_req = bfd_request_session(p->pool, r->via, nb->ifa->ip, nb->iface,
static_bfd_notify, r);
}
if (!bfd_up && r->bfd_req)
{
rfree(r->bfd_req);
r->bfd_req = NULL;
}
}
static int
static_decide(struct static_config *cf, struct static_route *r)
{
@@ -153,6 +176,9 @@ static_decide(struct static_config *cf, struct static_route *r)
if (cf->check_link && !(r->neigh->iface->flags & IF_LINK_UP))
return 0;
if (r->bfd_req && r->bfd_req->state != BFD_STATE_UP)
return 0;
return 1;
}
@@ -171,6 +197,8 @@ static_add(struct proto *p, struct static_config *cf, struct static_route *r)
r->chain = n->data;
n->data = r;
r->neigh = n;
static_update_bfd(p, r);
if (static_decide(cf, r))
static_install(p, r, n->iface);
else
@@ -200,6 +228,8 @@ static_add(struct proto *p, struct static_config *cf, struct static_route *r)
r2->chain = n->data;
n->data = r2;
r2->neigh = n;
static_update_bfd(p, r2);
r2->installed = static_decide(cf, r2);
count += r2->installed;
}
@@ -222,6 +252,26 @@ static_add(struct proto *p, struct static_config *cf, struct static_route *r)
}
}
static void
static_rte_cleanup(struct proto *p, struct static_route *r)
{
struct static_route *r2;
if (r->bfd_req)
{
rfree(r->bfd_req);
r->bfd_req = NULL;
}
if (r->dest == RTD_MULTIPATH)
for (r2 = r->mp_next; r2; r2 = r2->mp_next)
if (r2->bfd_req)
{
rfree(r2->bfd_req);
r2->bfd_req = NULL;
}
}
static int
static_start(struct proto *p)
{
@@ -254,7 +304,10 @@ static_shutdown(struct proto *p)
WALK_LIST(r, cf->iface_routes)
r->installed = 0;
WALK_LIST(r, cf->other_routes)
{
static_rte_cleanup(p, r);
r->installed = 0;
}
return PS_DOWN;
}
@@ -268,6 +321,44 @@ static_cleanup(struct proto *p)
rt_unlock_table(cf->igp_table->table);
}
static void
static_update_rte(struct proto *p, struct static_route *r)
{
switch (r->dest)
{
case RTD_ROUTER:
if (static_decide((struct static_config *) p->cf, r))
static_install(p, r, r->neigh->iface);
else
static_remove(p, r);
break;
case RTD_NONE: /* a part of multipath route */
{
int decision = static_decide((struct static_config *) p->cf, r);
if (decision == r->installed)
break; /* no change */
r->installed = decision;
struct static_route *r1, *r2;
int count = 0;
r1 = (void *) r->if_name; /* really */
for (r2 = r1->mp_next; r2; r2 = r2->mp_next)
count += r2->installed;
if (count)
{
/* Set of nexthops changed - force reinstall */
r1->installed = 0;
static_install(p, r1, NULL);
}
else
static_remove(p, r1);
break;
}
}
}
static void
static_neigh_notify(struct neighbor *n)
@@ -277,40 +368,21 @@ static_neigh_notify(struct neighbor *n)
DBG("Static: neighbor notify for %I: iface %p\n", n->addr, n->iface);
for(r=n->data; r; r=r->chain)
switch (r->dest)
{
case RTD_ROUTER:
if (static_decide((struct static_config *) p->cf, r))
static_install(p, r, n->iface);
else
static_remove(p, r);
break;
{
static_update_bfd(p, r);
static_update_rte(p, r);
}
}
case RTD_NONE: /* a part of multipath route */
{
int decision = static_decide((struct static_config *) p->cf, r);
if (decision == r->installed)
break; /* no change */
r->installed = decision;
static void
static_bfd_notify(struct bfd_request *req)
{
struct static_route *r = req->data;
struct proto *p = r->neigh->proto;
struct static_route *r1, *r2;
int count = 0;
r1 = (void *) r->if_name; /* really */
for (r2 = r1->mp_next; r2; r2 = r2->mp_next)
count += r2->installed;
// if (req->down) TRACE(D_EVENTS, "BFD session down for nbr %I on %s", XXXX);
if (count)
{
/* Set of nexthops changed - force reinstall */
r1->installed = 0;
static_install(p, r1, NULL);
}
else
static_remove(p, r1);
break;
}
}
static_update_rte(p, r);
}
static void
@@ -414,7 +486,7 @@ static_same_dest(struct static_route *x, struct static_route *y)
for (x = x->mp_next, y = y->mp_next;
x && y;
x = x->mp_next, y = y->mp_next)
if (!ipa_equal(x->via, y->via) || (x->via_if != y->via_if))
if (!ipa_equal(x->via, y->via) || (x->via_if != y->via_if) || (x->use_bfd != y->use_bfd))
return 0;
return !x && !y;
@@ -499,6 +571,9 @@ static_reconfigure(struct proto *p, struct proto_config *new)
WALK_LIST(r, n->other_routes)
static_add(p, n, r);
WALK_LIST(r, o->other_routes)
static_rte_cleanup(p, r);
return 1;
}
@@ -584,13 +659,14 @@ static_show_rt(struct static_route *r)
case RTDX_RECURSIVE: bsprintf(via, "recursive %I", r->via); break;
default: bsprintf(via, "???");
}
cli_msg(-1009, "%I/%d %s%s", r->net, r->masklen, via, r->installed ? "" : " (dormant)");
cli_msg(-1009, "%I/%d %s%s%s", r->net, r->masklen, via,
r->bfd_req ? " (bfd)" : "", r->installed ? "" : " (dormant)");
struct static_route *r2;
if (r->dest == RTD_MULTIPATH)
for (r2 = r->mp_next; r2; r2 = r2->mp_next)
cli_msg(-1009, "\tvia %I%J weight %d%s", r2->via, r2->via_if, r2->masklen + 1, /* really */
r2->installed ? "" : " (dormant)");
cli_msg(-1009, "\tvia %I%J weight %d%s%s", r2->via, r2->via_if, r2->masklen + 1, /* really */
r2->bfd_req ? " (bfd)" : "", r2->installed ? "" : " (dormant)");
}
void