Allows sticky link-local neighbors.
Allows using NEF_STICKY neighbors with link-local addresses. This is used for static route nexthops, they can be specified like fe80::1%eth0 .
This commit is contained in:
parent
c32c3f88f0
commit
69a8259c5e
8 changed files with 48 additions and 18 deletions
|
@ -50,6 +50,7 @@ CF_DECLS
|
|||
struct f_path_mask *h;
|
||||
struct password_item *p;
|
||||
struct rt_show_data *ra;
|
||||
struct iface *iface;
|
||||
void *g;
|
||||
bird_clock_t time;
|
||||
struct prefix px;
|
||||
|
@ -65,6 +66,7 @@ CF_DECLS
|
|||
%token <a> IPA
|
||||
%token <s> SYM
|
||||
%token <t> TEXT
|
||||
%type <iface> ipa_scope
|
||||
|
||||
%type <i> expr bool pxlen
|
||||
%type <time> datetime
|
||||
|
@ -140,6 +142,11 @@ ipa:
|
|||
}
|
||||
;
|
||||
|
||||
ipa_scope:
|
||||
/* empty */ { $$ = NULL; }
|
||||
| '%' SYM { $$ = if_get_by_name($2->name); }
|
||||
;
|
||||
|
||||
prefix:
|
||||
ipa pxlen {
|
||||
if (!ip_is_prefix($1, $2)) cf_error("Invalid prefix");
|
||||
|
|
18
nest/iface.c
18
nest/iface.c
|
@ -424,6 +424,24 @@ if_find_by_name(char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct iface *
|
||||
if_get_by_name(char *name)
|
||||
{
|
||||
struct iface *i;
|
||||
|
||||
if (i = if_find_by_name(name))
|
||||
return i;
|
||||
|
||||
/* No active iface, create a dummy */
|
||||
i = mb_allocz(if_pool, sizeof(struct iface));
|
||||
strncpy(i->name, name, sizeof(i->name)-1);
|
||||
i->flags = IF_SHUTDOWN;
|
||||
init_list(&i->addrs);
|
||||
init_list(&i->neighbors);
|
||||
add_tail(&iface_list, &i->n);
|
||||
return i;
|
||||
}
|
||||
|
||||
struct ifa *kif_choose_primary(struct iface *i);
|
||||
|
||||
static int
|
||||
|
|
|
@ -97,6 +97,7 @@ void if_flush_ifaces(struct proto *p);
|
|||
void if_feed_baby(struct proto *);
|
||||
struct iface *if_find_by_index(unsigned);
|
||||
struct iface *if_find_by_name(char *);
|
||||
struct iface *if_get_by_name(char *);
|
||||
void ifa_recalc_all_primary_addresses(void);
|
||||
|
||||
/* The Neighbor Cache */
|
||||
|
@ -110,11 +111,13 @@ typedef struct neighbor {
|
|||
void *data; /* Protocol-specific data */
|
||||
unsigned aux; /* Protocol-specific data */
|
||||
unsigned flags;
|
||||
unsigned scope; /* Address scope, SCOPE_HOST when it's our own address */
|
||||
int scope; /* Address scope, -1 for unreachable sticky neighbors,
|
||||
SCOPE_HOST when it's our own address */
|
||||
} neighbor;
|
||||
|
||||
#define NEF_STICKY 1
|
||||
#define NEF_ONLINK 2
|
||||
#define NEF_BIND 4 /* Used internally for neighbors bound to an iface */
|
||||
|
||||
neighbor *neigh_find(struct proto *, ip_addr *, unsigned flags);
|
||||
neighbor *neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags);
|
||||
|
|
|
@ -133,6 +133,7 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
|
|||
if (ifa)
|
||||
{
|
||||
scope = if_connected(a, ifa);
|
||||
flags |= NEF_BIND;
|
||||
|
||||
if ((scope < 0) && (flags & NEF_ONLINK))
|
||||
scope = class & IADDR_SCOPE_MASK;
|
||||
|
@ -160,10 +161,7 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* sticky flag does not work for link-local neighbors;
|
||||
fortunately, we don't use this combination */
|
||||
add_tail(&sticky_neigh_list, &n->n);
|
||||
ifa = NULL;
|
||||
scope = -1;
|
||||
}
|
||||
n->iface = ifa;
|
||||
|
@ -235,7 +233,9 @@ neigh_down(neighbor *n)
|
|||
{
|
||||
DBG("Flushing neighbor %I on %s\n", n->addr, i->name);
|
||||
rem_node(&n->if_n);
|
||||
n->iface = NULL;
|
||||
if (! (n->flags & NEF_BIND))
|
||||
n->iface = NULL;
|
||||
n->scope = -1;
|
||||
if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING)
|
||||
n->proto->neigh_notify(n);
|
||||
rem_node(&n->n);
|
||||
|
@ -262,7 +262,8 @@ neigh_if_up(struct iface *i)
|
|||
int scope;
|
||||
|
||||
WALK_LIST_DELSAFE(n, next, sticky_neigh_list)
|
||||
if ((scope = if_connected(&n->addr, i)) >= 0)
|
||||
if ((!n->iface || n->iface == i) &&
|
||||
((scope = if_connected(&n->addr, i)) >= 0))
|
||||
neigh_up(n, i, scope);
|
||||
}
|
||||
|
||||
|
@ -339,7 +340,7 @@ neigh_prune_one(neighbor *n)
|
|||
if (n->proto->proto_state != PS_DOWN)
|
||||
return;
|
||||
rem_node(&n->n);
|
||||
if (n->iface)
|
||||
if (n->scope >= 0)
|
||||
rem_node(&n->if_n);
|
||||
sl_free(neigh_slab, n);
|
||||
}
|
||||
|
|
|
@ -804,7 +804,7 @@ bgp_start_locked(struct object_lock *lock)
|
|||
return;
|
||||
}
|
||||
|
||||
if (p->neigh->iface)
|
||||
if (p->neigh->scope > 0)
|
||||
bgp_start_neighbor(p);
|
||||
else
|
||||
BGP_TRACE(D_EVENTS, "Waiting for %I to become my neighbor", cf->remote_ip);
|
||||
|
|
|
@ -48,11 +48,12 @@ stat_route0: ROUTE prefix {
|
|||
;
|
||||
|
||||
stat_multipath1:
|
||||
VIA ipa {
|
||||
VIA ipa ipa_scope {
|
||||
last_srt_nh = this_srt_nh;
|
||||
this_srt_nh = cfg_allocz(sizeof(struct static_route));
|
||||
this_srt_nh->dest = RTD_NONE;
|
||||
this_srt_nh->via = $2;
|
||||
this_srt_nh->via_if = $3;
|
||||
this_srt_nh->if_name = (void *) this_srt; /* really */
|
||||
}
|
||||
| stat_multipath1 WEIGHT expr {
|
||||
|
@ -67,9 +68,10 @@ stat_multipath:
|
|||
;
|
||||
|
||||
stat_route:
|
||||
stat_route0 VIA ipa {
|
||||
stat_route0 VIA ipa ipa_scope {
|
||||
this_srt->dest = RTD_ROUTER;
|
||||
this_srt->via = $3;
|
||||
this_srt->via_if = $4;
|
||||
}
|
||||
| stat_route0 VIA TEXT {
|
||||
this_srt->dest = RTD_DEVICE;
|
||||
|
|
|
@ -138,12 +138,10 @@ static_decide(struct static_config *cf, struct static_route *r)
|
|||
/* r->dest != RTD_MULTIPATH, but may be RTD_NONE (part of multipath route)
|
||||
the route also have to be valid (r->neigh != NULL) */
|
||||
|
||||
struct iface *ifa = r->neigh->iface;
|
||||
|
||||
if (!ifa)
|
||||
if (r->neigh->scope < 0)
|
||||
return 0;
|
||||
|
||||
if (cf->check_link && !(ifa->flags & IF_LINK_UP))
|
||||
if (cf->check_link && !(r->neigh->iface->flags & IF_LINK_UP))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
@ -158,7 +156,7 @@ static_add(struct proto *p, struct static_config *cf, struct static_route *r)
|
|||
{
|
||||
case RTD_ROUTER:
|
||||
{
|
||||
struct neighbor *n = neigh_find(p, &r->via, NEF_STICKY);
|
||||
struct neighbor *n = neigh_find2(p, &r->via, r->via_if, NEF_STICKY);
|
||||
if (n)
|
||||
{
|
||||
r->chain = n->data;
|
||||
|
@ -187,7 +185,7 @@ static_add(struct proto *p, struct static_config *cf, struct static_route *r)
|
|||
|
||||
for (r2 = r->mp_next; r2; r2 = r2->mp_next)
|
||||
{
|
||||
struct neighbor *n = neigh_find(p, &r2->via, NEF_STICKY);
|
||||
struct neighbor *n = neigh_find2(p, &r2->via, r2->via_if, NEF_STICKY);
|
||||
if (n)
|
||||
{
|
||||
r2->chain = n->data;
|
||||
|
@ -385,7 +383,7 @@ static_same_dest(struct static_route *x, struct static_route *y)
|
|||
switch (x->dest)
|
||||
{
|
||||
case RTD_ROUTER:
|
||||
return ipa_equal(x->via, y->via);
|
||||
return ipa_equal(x->via, y->via) && (x->via_if == y->via_if);
|
||||
|
||||
case RTD_DEVICE:
|
||||
return !strcmp(x->if_name, y->if_name);
|
||||
|
@ -394,7 +392,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))
|
||||
if (!ipa_equal(x->via, y->via) || (x->via_if != y->via_if))
|
||||
return 0;
|
||||
return !x && !y;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ struct static_route {
|
|||
int masklen; /* Mask length */
|
||||
int dest; /* Destination type (RTD_*) */
|
||||
ip_addr via; /* Destination router */
|
||||
struct iface *via_if; /* Destination iface, for link-local vias */
|
||||
struct neighbor *neigh;
|
||||
byte *if_name; /* Name for RTD_DEVICE routes */
|
||||
struct static_route *mp_next; /* Nexthops for RTD_MULTIPATH routes */
|
||||
|
|
Loading…
Reference in a new issue