mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 02:01:55 +00:00
Interface subsystem locking
This commit is contained in:
parent
a26d307eab
commit
b8a230e478
295
nest/iface.c
295
nest/iface.c
@ -31,19 +31,51 @@
|
|||||||
#include "nest/cli.h"
|
#include "nest/cli.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
#include "lib/locking.h"
|
||||||
#include "conf/conf.h"
|
#include "conf/conf.h"
|
||||||
#include "sysdep/unix/krt.h"
|
#include "sysdep/unix/krt.h"
|
||||||
|
|
||||||
|
DOMAIN(attrs) iface_domain;
|
||||||
|
|
||||||
|
#define IFACE_LOCK LOCK_DOMAIN(attrs, iface_domain)
|
||||||
|
#define IFACE_UNLOCK UNLOCK_DOMAIN(attrs, iface_domain)
|
||||||
|
#define IFACE_ASSERT_LOCKED ASSERT_DIE(DOMAIN_IS_LOCKED(attrs, iface_domain))
|
||||||
|
|
||||||
static TLIST_LIST(ifsub) iface_sub_list;
|
static TLIST_LIST(ifsub) iface_sub_list;
|
||||||
static slab *iface_sub_slab;
|
static slab *iface_sub_slab;
|
||||||
static pool *if_pool;
|
static pool *if_pool;
|
||||||
|
|
||||||
list iface_list;
|
list global_iface_list;
|
||||||
struct iface default_vrf;
|
struct iface default_vrf;
|
||||||
|
|
||||||
static void if_recalc_preferred(struct iface *i);
|
static void if_recalc_preferred(struct iface *i);
|
||||||
|
|
||||||
|
static void ifa_dump_locked(struct ifa *);
|
||||||
|
static void if_dump_locked(struct iface *);
|
||||||
|
|
||||||
|
struct iface *
|
||||||
|
if_walk_first(void)
|
||||||
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
struct iface *i = HEAD(global_iface_list);
|
||||||
|
return NODE_VALID(i) ? i : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iface *
|
||||||
|
if_walk_next(struct iface *i)
|
||||||
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
|
i = NODE_NEXT(i);
|
||||||
|
return NODE_VALID(i) ? i : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
if_walk_done(void)
|
||||||
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
|
IFACE_UNLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ifa_dump - dump interface address
|
* ifa_dump - dump interface address
|
||||||
* @a: interface address descriptor
|
* @a: interface address descriptor
|
||||||
@ -52,6 +84,14 @@ static void if_recalc_preferred(struct iface *i);
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ifa_dump(struct ifa *a)
|
ifa_dump(struct ifa *a)
|
||||||
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
ifa_dump_locked(a);
|
||||||
|
IFACE_UNLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ifa_dump_locked(struct ifa *a)
|
||||||
{
|
{
|
||||||
debug("\t%I, net %N bc %I -> %I%s%s%s%s\n", a->ip, &a->prefix, a->brd, a->opposite,
|
debug("\t%I, net %N bc %I -> %I%s%s%s%s\n", a->ip, &a->prefix, a->brd, a->opposite,
|
||||||
(a->flags & IA_PRIMARY) ? " PRIMARY" : "",
|
(a->flags & IA_PRIMARY) ? " PRIMARY" : "",
|
||||||
@ -69,6 +109,14 @@ ifa_dump(struct ifa *a)
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
if_dump(struct iface *i)
|
if_dump(struct iface *i)
|
||||||
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
if_dump_locked(i);
|
||||||
|
IFACE_UNLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
if_dump_locked(struct iface *i)
|
||||||
{
|
{
|
||||||
struct ifa *a;
|
struct ifa *a;
|
||||||
|
|
||||||
@ -96,7 +144,7 @@ if_dump(struct iface *i)
|
|||||||
debug(" MTU=%d\n", i->mtu);
|
debug(" MTU=%d\n", i->mtu);
|
||||||
WALK_LIST(a, i->addrs)
|
WALK_LIST(a, i->addrs)
|
||||||
{
|
{
|
||||||
ifa_dump(a);
|
ifa_dump_locked(a);
|
||||||
ASSERT(!!(a->flags & IA_PRIMARY) ==
|
ASSERT(!!(a->flags & IA_PRIMARY) ==
|
||||||
((a == i->addr4) || (a == i->addr6) || (a == i->llv6)));
|
((a == i->addr4) || (a == i->addr6) || (a == i->llv6)));
|
||||||
}
|
}
|
||||||
@ -111,14 +159,60 @@ if_dump(struct iface *i)
|
|||||||
void
|
void
|
||||||
if_dump_all(void)
|
if_dump_all(void)
|
||||||
{
|
{
|
||||||
struct iface *i;
|
|
||||||
|
|
||||||
debug("Known network interfaces:\n");
|
debug("Known network interfaces:\n");
|
||||||
WALK_LIST(i, iface_list)
|
IFACE_WALK(i)
|
||||||
if_dump(i);
|
if_dump(i);
|
||||||
debug("Router ID: %08x\n", config->router_id);
|
debug("Router ID: %08x\n", config->router_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
if_link(struct iface *i)
|
||||||
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
|
|
||||||
|
if (i)
|
||||||
|
i->uc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
if_unlink(struct iface *i)
|
||||||
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
|
|
||||||
|
if (i)
|
||||||
|
i->uc--;
|
||||||
|
/* TODO: Do some interface object cleanup */
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifa_link(struct ifa *a)
|
||||||
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
|
|
||||||
|
if (a)
|
||||||
|
{
|
||||||
|
debug("ifa_link: %p %d\n", a, a->uc);
|
||||||
|
a->uc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifa_unlink(struct ifa *a)
|
||||||
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
|
|
||||||
|
if (!a)
|
||||||
|
return;
|
||||||
|
|
||||||
|
debug("ifa_unlink: %p %d\n", a, a->uc);
|
||||||
|
if (--a->uc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if_unlink(a->iface);
|
||||||
|
#if DEBUGGING
|
||||||
|
memset(a, 0x5b, sizeof(struct ifa));
|
||||||
|
#endif
|
||||||
|
mb_free(a);
|
||||||
|
}
|
||||||
|
|
||||||
static inline unsigned
|
static inline unsigned
|
||||||
if_what_changed(struct iface *i, struct iface *j)
|
if_what_changed(struct iface *i, struct iface *j)
|
||||||
{
|
{
|
||||||
@ -151,6 +245,8 @@ if_copy(struct iface *to, struct iface *from)
|
|||||||
void
|
void
|
||||||
if_enqueue_notify_to(struct iface_notification x, struct iface_subscription *s)
|
if_enqueue_notify_to(struct iface_notification x, struct iface_subscription *s)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
|
|
||||||
switch (x.type) {
|
switch (x.type) {
|
||||||
case IFNOT_ADDRESS:
|
case IFNOT_ADDRESS:
|
||||||
if (!s->ifa_notify) return;
|
if (!s->ifa_notify) return;
|
||||||
@ -174,12 +270,14 @@ if_enqueue_notify_to(struct iface_notification x, struct iface_subscription *s)
|
|||||||
debug("Enqueue notify %d/%p (%p) to %p\n", x.type, x.a, in, s);
|
debug("Enqueue notify %d/%p (%p) to %p\n", x.type, x.a, in, s);
|
||||||
|
|
||||||
ifnot_add_tail(&s->queue, in);
|
ifnot_add_tail(&s->queue, in);
|
||||||
ev_schedule(&s->event);
|
ev_send(s->target, &s->event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
if_enqueue_notify(struct iface_notification x)
|
if_enqueue_notify(struct iface_notification x)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
|
|
||||||
WALK_TLIST(ifsub, s, &iface_sub_list)
|
WALK_TLIST(ifsub, s, &iface_sub_list)
|
||||||
if_enqueue_notify_to(x, s);
|
if_enqueue_notify_to(x, s);
|
||||||
}
|
}
|
||||||
@ -261,7 +359,7 @@ if_notify_change(unsigned c, struct iface *i)
|
|||||||
|
|
||||||
DBG("Interface change notification (%x) for %s\n", c, i->name);
|
DBG("Interface change notification (%x) for %s\n", c, i->name);
|
||||||
#ifdef LOCAL_DEBUG
|
#ifdef LOCAL_DEBUG
|
||||||
if_dump(i);
|
if_dump_locked(i);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (c & IF_CHANGE_DOWN)
|
if (c & IF_CHANGE_DOWN)
|
||||||
@ -323,10 +421,12 @@ if_change_flags(struct iface *i, uint flags)
|
|||||||
void
|
void
|
||||||
if_delete(struct iface *old)
|
if_delete(struct iface *old)
|
||||||
{
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
struct iface f = {};
|
struct iface f = {};
|
||||||
strncpy(f.name, old->name, sizeof(f.name)-1);
|
strncpy(f.name, old->name, sizeof(f.name)-1);
|
||||||
f.flags = IF_SHUTDOWN;
|
f.flags = IF_SHUTDOWN;
|
||||||
if_update(&f);
|
if_update_locked(&f);
|
||||||
|
IFACE_UNLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -347,6 +447,15 @@ if_delete(struct iface *old)
|
|||||||
*/
|
*/
|
||||||
struct iface *
|
struct iface *
|
||||||
if_update(struct iface *new)
|
if_update(struct iface *new)
|
||||||
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
struct iface *i = if_update_locked(new);
|
||||||
|
IFACE_UNLOCK;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iface *
|
||||||
|
if_update_locked(struct iface *new)
|
||||||
{
|
{
|
||||||
struct iface *i;
|
struct iface *i;
|
||||||
unsigned c;
|
unsigned c;
|
||||||
@ -354,7 +463,7 @@ if_update(struct iface *new)
|
|||||||
if (!new->master)
|
if (!new->master)
|
||||||
new->master = &default_vrf;
|
new->master = &default_vrf;
|
||||||
|
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, global_iface_list)
|
||||||
if (!strcmp(new->name, i->name))
|
if (!strcmp(new->name, i->name))
|
||||||
{
|
{
|
||||||
new->flags = if_recalc_flags(new, new->flags);
|
new->flags = if_recalc_flags(new, new->flags);
|
||||||
@ -389,17 +498,16 @@ if_update(struct iface *new)
|
|||||||
init_list(&i->neighbors);
|
init_list(&i->neighbors);
|
||||||
newif:
|
newif:
|
||||||
i->flags |= IF_UPDATED | IF_TMP_DOWN; /* Tmp down as we don't have addresses yet */
|
i->flags |= IF_UPDATED | IF_TMP_DOWN; /* Tmp down as we don't have addresses yet */
|
||||||
add_tail(&iface_list, &i->n);
|
add_tail(&global_iface_list, &i->n);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
if_start_update(void)
|
if_start_update(void)
|
||||||
{
|
{
|
||||||
struct iface *i;
|
|
||||||
struct ifa *a;
|
struct ifa *a;
|
||||||
|
|
||||||
WALK_LIST(i, iface_list)
|
IFACE_WALK(i)
|
||||||
{
|
{
|
||||||
i->flags &= ~IF_UPDATED;
|
i->flags &= ~IF_UPDATED;
|
||||||
WALK_LIST(a, i->addrs)
|
WALK_LIST(a, i->addrs)
|
||||||
@ -407,8 +515,8 @@ if_start_update(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
if_end_partial_update(struct iface *i)
|
if_end_partial_update_locked(struct iface *i)
|
||||||
{
|
{
|
||||||
if (i->flags & IF_NEEDS_RECALC)
|
if (i->flags & IF_NEEDS_RECALC)
|
||||||
if_recalc_preferred(i);
|
if_recalc_preferred(i);
|
||||||
@ -417,13 +525,20 @@ if_end_partial_update(struct iface *i)
|
|||||||
if_change_flags(i, i->flags & ~IF_TMP_DOWN);
|
if_change_flags(i, i->flags & ~IF_TMP_DOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
if_end_partial_update(struct iface *i)
|
||||||
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
if_end_partial_update_locked(i);
|
||||||
|
IFACE_UNLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
if_end_update(void)
|
if_end_update(void)
|
||||||
{
|
{
|
||||||
struct iface *i;
|
|
||||||
struct ifa *a, *b;
|
struct ifa *a, *b;
|
||||||
|
|
||||||
WALK_LIST(i, iface_list)
|
IFACE_WALK(i)
|
||||||
{
|
{
|
||||||
if (!(i->flags & IF_UPDATED))
|
if (!(i->flags & IF_UPDATED))
|
||||||
if_change_flags(i, (i->flags & ~IF_ADMIN_UP) | IF_SHUTDOWN);
|
if_change_flags(i, (i->flags & ~IF_ADMIN_UP) | IF_SHUTDOWN);
|
||||||
@ -432,55 +547,53 @@ if_end_update(void)
|
|||||||
WALK_LIST_DELSAFE(a, b, i->addrs)
|
WALK_LIST_DELSAFE(a, b, i->addrs)
|
||||||
if (!(a->flags & IA_UPDATED))
|
if (!(a->flags & IA_UPDATED))
|
||||||
ifa_delete(a);
|
ifa_delete(a);
|
||||||
if_end_partial_update(i);
|
if_end_partial_update_locked(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
if_link(struct iface *i)
|
|
||||||
{
|
|
||||||
if (i)
|
|
||||||
i->uc++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
if_unlink(struct iface *i)
|
|
||||||
{
|
|
||||||
if (i)
|
|
||||||
i->uc--;
|
|
||||||
/* TODO: Do some interface object cleanup */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
iface_notify_hook(void *_s)
|
iface_notify_hook(void *_s)
|
||||||
{
|
{
|
||||||
struct iface_subscription *s = _s;
|
struct iface_subscription *s = _s;
|
||||||
|
|
||||||
|
IFACE_LOCK;
|
||||||
|
|
||||||
while (!EMPTY_TLIST(ifnot, &s->queue))
|
while (!EMPTY_TLIST(ifnot, &s->queue))
|
||||||
{
|
{
|
||||||
struct iface_notification *n = THEAD(ifnot, &s->queue);
|
struct iface_notification *n = THEAD(ifnot, &s->queue);
|
||||||
debug("Process notify %d/%p (%p) to %p\n", n->type, n->a, n, s);
|
debug("Process notify %d/%p (%p) to %p\n", n->type, n->a, n, s);
|
||||||
|
IFACE_UNLOCK;
|
||||||
|
|
||||||
switch (n->type) {
|
switch (n->type) {
|
||||||
case IFNOT_ADDRESS:
|
case IFNOT_ADDRESS:
|
||||||
ifa_send_notify(s, n->flags, n->a);
|
ifa_send_notify(s, n->flags, n->a);
|
||||||
|
IFACE_LOCK;
|
||||||
ifa_unlink(n->a);
|
ifa_unlink(n->a);
|
||||||
|
IFACE_UNLOCK;
|
||||||
break;
|
break;
|
||||||
case IFNOT_INTERFACE:
|
case IFNOT_INTERFACE:
|
||||||
if_send_notify(s, n->flags, n->i);
|
if_send_notify(s, n->flags, n->i);
|
||||||
|
IFACE_LOCK;
|
||||||
if_unlink(n->i);
|
if_unlink(n->i);
|
||||||
|
IFACE_UNLOCK;
|
||||||
break;
|
break;
|
||||||
case IFNOT_NEIGHBOR:
|
case IFNOT_NEIGHBOR:
|
||||||
s->neigh_notify(n->n);
|
s->neigh_notify(n->n);
|
||||||
|
IFACE_LOCK;
|
||||||
neigh_unlink(n->n);
|
neigh_unlink(n->n);
|
||||||
|
IFACE_UNLOCK;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bug("Bad interface notification type: %d", n->type);
|
bug("Bad interface notification type: %d", n->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IFACE_LOCK;
|
||||||
ifnot_rem_node(&s->queue, n);
|
ifnot_rem_node(&s->queue, n);
|
||||||
sl_free(n);
|
sl_free(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IFACE_UNLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -494,6 +607,7 @@ iface_notify_hook(void *_s)
|
|||||||
void
|
void
|
||||||
iface_subscribe(struct iface_subscription *s)
|
iface_subscribe(struct iface_subscription *s)
|
||||||
{
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
ifsub_add_tail(&iface_sub_list, s);
|
ifsub_add_tail(&iface_sub_list, s);
|
||||||
s->event = (event) {
|
s->event = (event) {
|
||||||
.hook = iface_notify_hook,
|
.hook = iface_notify_hook,
|
||||||
@ -501,19 +615,34 @@ iface_subscribe(struct iface_subscription *s)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!s->if_notify && !s->ifa_notify) /* shortcut */
|
if (!s->if_notify && !s->ifa_notify) /* shortcut */
|
||||||
|
{
|
||||||
|
IFACE_UNLOCK;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct iface *i;
|
struct iface *i;
|
||||||
DBG("Announcing interfaces to new protocol %s\n", p->name);
|
DBG("Announcing interfaces to new protocol %s\n", p->name);
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, global_iface_list)
|
||||||
{
|
{
|
||||||
if_send_notify(s, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i);
|
if_enqueue_notify_to(
|
||||||
|
(struct iface_notification) {
|
||||||
|
.type = IFNOT_INTERFACE,
|
||||||
|
.i = i,
|
||||||
|
.flags = IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0),
|
||||||
|
}, s);
|
||||||
|
|
||||||
struct ifa *a;
|
struct ifa *a;
|
||||||
if (i->flags & IF_UP)
|
if (i->flags & IF_UP)
|
||||||
WALK_LIST(a, i->addrs)
|
WALK_LIST(a, i->addrs)
|
||||||
ifa_send_notify(s, IF_CHANGE_CREATE | IF_CHANGE_UP, a);
|
if_enqueue_notify_to(
|
||||||
|
(struct iface_notification) {
|
||||||
|
.type = IFNOT_ADDRESS,
|
||||||
|
.a = a,
|
||||||
|
.flags = IF_CHANGE_CREATE | IF_CHANGE_UP,
|
||||||
|
}, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IFACE_UNLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -523,6 +652,12 @@ iface_subscribe(struct iface_subscription *s)
|
|||||||
void
|
void
|
||||||
iface_unsubscribe(struct iface_subscription *s)
|
iface_unsubscribe(struct iface_subscription *s)
|
||||||
{
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
|
||||||
|
struct proto *p = SKIP_BACK(struct proto, iface_sub, s);
|
||||||
|
WALK_TLIST_DELSAFE(proto_neigh, n, &p->neighbors)
|
||||||
|
neigh_unlink(n);
|
||||||
|
|
||||||
ifsub_rem_node(&iface_sub_list, s);
|
ifsub_rem_node(&iface_sub_list, s);
|
||||||
ev_postpone(&s->event);
|
ev_postpone(&s->event);
|
||||||
|
|
||||||
@ -547,6 +682,10 @@ iface_unsubscribe(struct iface_subscription *s)
|
|||||||
ifnot_rem_node(&s->queue, n);
|
ifnot_rem_node(&s->queue, n);
|
||||||
sl_free(n);
|
sl_free(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASSERT_DIE(EMPTY_TLIST(proto_neigh, &p->neighbors));
|
||||||
|
|
||||||
|
IFACE_UNLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -558,16 +697,26 @@ iface_unsubscribe(struct iface_subscription *s)
|
|||||||
* if no such structure exists.
|
* if no such structure exists.
|
||||||
*/
|
*/
|
||||||
struct iface *
|
struct iface *
|
||||||
if_find_by_index(unsigned idx)
|
if_find_by_index_locked(unsigned idx)
|
||||||
{
|
{
|
||||||
struct iface *i;
|
struct iface *i;
|
||||||
|
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, global_iface_list)
|
||||||
if (i->index == idx && !(i->flags & IF_SHUTDOWN))
|
if (i->index == idx && !(i->flags & IF_SHUTDOWN))
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct iface *
|
||||||
|
if_find_by_index(unsigned idx)
|
||||||
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
struct iface *i = if_find_by_index_locked(idx);
|
||||||
|
IFACE_UNLOCK;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* if_find_by_name - find interface by name
|
* if_find_by_name - find interface by name
|
||||||
* @name: interface name
|
* @name: interface name
|
||||||
@ -581,9 +730,15 @@ if_find_by_name(const char *name)
|
|||||||
{
|
{
|
||||||
struct iface *i;
|
struct iface *i;
|
||||||
|
|
||||||
WALK_LIST(i, iface_list)
|
IFACE_LOCK;
|
||||||
|
WALK_LIST(i, global_iface_list)
|
||||||
if (!strcmp(i->name, name) && !(i->flags & IF_SHUTDOWN))
|
if (!strcmp(i->name, name) && !(i->flags & IF_SHUTDOWN))
|
||||||
|
{
|
||||||
|
IFACE_UNLOCK;
|
||||||
return i;
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFACE_UNLOCK;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,9 +747,13 @@ if_get_by_name(const char *name)
|
|||||||
{
|
{
|
||||||
struct iface *i;
|
struct iface *i;
|
||||||
|
|
||||||
WALK_LIST(i, iface_list)
|
IFACE_LOCK;
|
||||||
|
WALK_LIST(i, global_iface_list)
|
||||||
if (!strcmp(i->name, name))
|
if (!strcmp(i->name, name))
|
||||||
|
{
|
||||||
|
IFACE_UNLOCK;
|
||||||
return i;
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
/* No active iface, create a dummy */
|
/* No active iface, create a dummy */
|
||||||
i = mb_allocz(if_pool, sizeof(struct iface));
|
i = mb_allocz(if_pool, sizeof(struct iface));
|
||||||
@ -602,7 +761,9 @@ if_get_by_name(const char *name)
|
|||||||
i->flags = IF_SHUTDOWN;
|
i->flags = IF_SHUTDOWN;
|
||||||
init_list(&i->addrs);
|
init_list(&i->addrs);
|
||||||
init_list(&i->neighbors);
|
init_list(&i->neighbors);
|
||||||
add_tail(&iface_list, &i->n);
|
add_tail(&global_iface_list, &i->n);
|
||||||
|
|
||||||
|
IFACE_UNLOCK;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,9 +847,7 @@ if_recalc_preferred(struct iface *i)
|
|||||||
void
|
void
|
||||||
if_recalc_all_preferred_addresses(void)
|
if_recalc_all_preferred_addresses(void)
|
||||||
{
|
{
|
||||||
struct iface *i;
|
IFACE_WALK(i)
|
||||||
|
|
||||||
WALK_LIST(i, iface_list)
|
|
||||||
{
|
{
|
||||||
if_recalc_preferred(i);
|
if_recalc_preferred(i);
|
||||||
|
|
||||||
@ -715,6 +874,8 @@ ifa_same(struct ifa *a, struct ifa *b)
|
|||||||
struct ifa *
|
struct ifa *
|
||||||
ifa_update(struct ifa *a)
|
ifa_update(struct ifa *a)
|
||||||
{
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
|
||||||
struct iface *i = a->iface;
|
struct iface *i = a->iface;
|
||||||
struct ifa *b;
|
struct ifa *b;
|
||||||
|
|
||||||
@ -727,6 +888,8 @@ ifa_update(struct ifa *a)
|
|||||||
!((b->flags ^ a->flags) & (IA_SECONDARY | IA_PEER | IA_HOST)))
|
!((b->flags ^ a->flags) & (IA_SECONDARY | IA_PEER | IA_HOST)))
|
||||||
{
|
{
|
||||||
b->flags |= IA_UPDATED;
|
b->flags |= IA_UPDATED;
|
||||||
|
|
||||||
|
IFACE_UNLOCK;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
ifa_delete(b);
|
ifa_delete(b);
|
||||||
@ -746,6 +909,8 @@ ifa_update(struct ifa *a)
|
|||||||
i->flags |= IF_NEEDS_RECALC;
|
i->flags |= IF_NEEDS_RECALC;
|
||||||
if (i->flags & IF_UP)
|
if (i->flags & IF_UP)
|
||||||
ifa_notify_change(IF_CHANGE_CREATE | IF_CHANGE_UP, b);
|
ifa_notify_change(IF_CHANGE_CREATE | IF_CHANGE_UP, b);
|
||||||
|
|
||||||
|
IFACE_UNLOCK;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,6 +928,8 @@ ifa_delete(struct ifa *a)
|
|||||||
struct iface *i = a->iface;
|
struct iface *i = a->iface;
|
||||||
struct ifa *b;
|
struct ifa *b;
|
||||||
|
|
||||||
|
IFACE_LOCK;
|
||||||
|
|
||||||
WALK_LIST(b, i->addrs)
|
WALK_LIST(b, i->addrs)
|
||||||
if (ifa_same(b, a))
|
if (ifa_same(b, a))
|
||||||
{
|
{
|
||||||
@ -787,43 +954,23 @@ ifa_delete(struct ifa *a)
|
|||||||
ifa_notify_change(IF_CHANGE_DOWN, b);
|
ifa_notify_change(IF_CHANGE_DOWN, b);
|
||||||
|
|
||||||
ifa_unlink(b);
|
ifa_unlink(b);
|
||||||
|
IFACE_UNLOCK;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void ifa_link(struct ifa *a)
|
IFACE_UNLOCK;
|
||||||
{
|
|
||||||
if (a)
|
|
||||||
{
|
|
||||||
debug("ifa_link: %p %d\n", a, a->uc);
|
|
||||||
a->uc++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ifa_unlink(struct ifa *a)
|
|
||||||
{
|
|
||||||
if (!a)
|
|
||||||
return;
|
|
||||||
|
|
||||||
debug("ifa_unlink: %p %d\n", a, a->uc);
|
|
||||||
if (--a->uc)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if_unlink(a->iface);
|
|
||||||
#if DEBUGGING
|
|
||||||
memset(a, 0x5b, sizeof(struct ifa));
|
|
||||||
#endif
|
|
||||||
mb_free(a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32
|
u32
|
||||||
if_choose_router_id(struct iface_patt *mask, u32 old_id)
|
if_choose_router_id(struct iface_patt *mask, u32 old_id)
|
||||||
{
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
|
||||||
struct iface *i;
|
struct iface *i;
|
||||||
struct ifa *a, *b;
|
struct ifa *a, *b;
|
||||||
|
|
||||||
b = NULL;
|
b = NULL;
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, global_iface_list)
|
||||||
{
|
{
|
||||||
if (!(i->flags & IF_ADMIN_UP) ||
|
if (!(i->flags & IF_ADMIN_UP) ||
|
||||||
(i->flags & IF_SHUTDOWN))
|
(i->flags & IF_SHUTDOWN))
|
||||||
@ -850,6 +997,8 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IFACE_UNLOCK;
|
||||||
|
|
||||||
if (!b)
|
if (!b)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -870,10 +1019,11 @@ void
|
|||||||
if_init(void)
|
if_init(void)
|
||||||
{
|
{
|
||||||
if_pool = rp_new(&root_pool, "Interfaces");
|
if_pool = rp_new(&root_pool, "Interfaces");
|
||||||
init_list(&iface_list);
|
init_list(&global_iface_list);
|
||||||
iface_sub_slab = sl_new(if_pool, sizeof(struct iface_notification));
|
iface_sub_slab = sl_new(if_pool, sizeof(struct iface_notification));
|
||||||
strcpy(default_vrf.name, "default");
|
strcpy(default_vrf.name, "default");
|
||||||
neigh_init(if_pool);
|
neigh_init(if_pool);
|
||||||
|
iface_domain = DOMAIN_NEW(attrs, "Interfaces");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -995,11 +1145,10 @@ if_show_addr(struct ifa *a)
|
|||||||
void
|
void
|
||||||
if_show(void)
|
if_show(void)
|
||||||
{
|
{
|
||||||
struct iface *i;
|
|
||||||
struct ifa *a;
|
struct ifa *a;
|
||||||
char *type;
|
char *type;
|
||||||
|
|
||||||
WALK_LIST(i, iface_list)
|
IFACE_WALK(i)
|
||||||
{
|
{
|
||||||
if (i->flags & IF_SHUTDOWN)
|
if (i->flags & IF_SHUTDOWN)
|
||||||
continue;
|
continue;
|
||||||
@ -1039,10 +1188,8 @@ if_show(void)
|
|||||||
void
|
void
|
||||||
if_show_summary(void)
|
if_show_summary(void)
|
||||||
{
|
{
|
||||||
struct iface *i;
|
|
||||||
|
|
||||||
cli_msg(-2005, "%-10s %-6s %-18s %s", "Interface", "State", "IPv4 address", "IPv6 address");
|
cli_msg(-2005, "%-10s %-6s %-18s %s", "Interface", "State", "IPv4 address", "IPv6 address");
|
||||||
WALK_LIST(i, iface_list)
|
IFACE_WALK(i)
|
||||||
{
|
{
|
||||||
byte a4[IPA_MAX_TEXT_LENGTH + 17];
|
byte a4[IPA_MAX_TEXT_LENGTH + 17];
|
||||||
byte a6[IPA_MAX_TEXT_LENGTH + 17];
|
byte a6[IPA_MAX_TEXT_LENGTH + 17];
|
||||||
|
17
nest/iface.h
17
nest/iface.h
@ -9,13 +9,12 @@
|
|||||||
#ifndef _BIRD_IFACE_H_
|
#ifndef _BIRD_IFACE_H_
|
||||||
#define _BIRD_IFACE_H_
|
#define _BIRD_IFACE_H_
|
||||||
|
|
||||||
|
#include "lib/locking.h"
|
||||||
#include "lib/event.h"
|
#include "lib/event.h"
|
||||||
#include "lib/lists.h"
|
#include "lib/lists.h"
|
||||||
#include "lib/tlists.h"
|
#include "lib/tlists.h"
|
||||||
#include "lib/ip.h"
|
#include "lib/ip.h"
|
||||||
|
|
||||||
extern list iface_list;
|
|
||||||
|
|
||||||
struct proto;
|
struct proto;
|
||||||
struct pool;
|
struct pool;
|
||||||
|
|
||||||
@ -112,6 +111,7 @@ void ifa_dump(struct ifa *);
|
|||||||
void if_show(void);
|
void if_show(void);
|
||||||
void if_show_summary(void);
|
void if_show_summary(void);
|
||||||
struct iface *if_update(struct iface *);
|
struct iface *if_update(struct iface *);
|
||||||
|
struct iface *if_update_locked(struct iface *);
|
||||||
void if_delete(struct iface *old);
|
void if_delete(struct iface *old);
|
||||||
struct ifa *ifa_update(struct ifa *);
|
struct ifa *ifa_update(struct ifa *);
|
||||||
void ifa_delete(struct ifa *);
|
void ifa_delete(struct ifa *);
|
||||||
@ -119,14 +119,16 @@ void if_start_update(void);
|
|||||||
void if_end_partial_update(struct iface *);
|
void if_end_partial_update(struct iface *);
|
||||||
void if_end_update(void);
|
void if_end_update(void);
|
||||||
struct iface *if_find_by_index(unsigned);
|
struct iface *if_find_by_index(unsigned);
|
||||||
|
struct iface *if_find_by_index_locked(unsigned);
|
||||||
struct iface *if_find_by_name(const char *);
|
struct iface *if_find_by_name(const char *);
|
||||||
struct iface *if_get_by_name(const char *);
|
struct iface *if_get_by_name(const char *);
|
||||||
void if_recalc_all_preferred_addresses(void);
|
void if_recalc_all_preferred_addresses(void);
|
||||||
|
|
||||||
void if_link(struct iface *);
|
struct iface *if_walk_first(void);
|
||||||
void if_unlink(struct iface *);
|
struct iface *if_walk_next(struct iface *);
|
||||||
void ifa_link(struct ifa *);
|
void if_walk_done(void);
|
||||||
void ifa_unlink(struct ifa *);
|
|
||||||
|
#define IFACE_WALK(_i) for (struct iface *_i = if_walk_first(); _i || (if_walk_done(), 0); _i = if_walk_next(_i))
|
||||||
|
|
||||||
/* The Neighbor Cache */
|
/* The Neighbor Cache */
|
||||||
|
|
||||||
@ -161,9 +163,7 @@ typedef struct neighbor {
|
|||||||
|
|
||||||
neighbor *neigh_find(struct proto *p, ip_addr a, struct iface *ifa, uint flags);
|
neighbor *neigh_find(struct proto *p, ip_addr a, struct iface *ifa, uint flags);
|
||||||
|
|
||||||
void neigh_dump(neighbor *);
|
|
||||||
void neigh_dump_all(void);
|
void neigh_dump_all(void);
|
||||||
void neigh_prune(struct proto *);
|
|
||||||
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_if_link(struct iface *);
|
||||||
@ -212,6 +212,7 @@ struct iface_subscription {
|
|||||||
TLIST_DEFAULT_NODE;
|
TLIST_DEFAULT_NODE;
|
||||||
|
|
||||||
event event;
|
event event;
|
||||||
|
event_list *target;
|
||||||
TLIST_LIST(ifnot) queue;
|
TLIST_LIST(ifnot) queue;
|
||||||
|
|
||||||
void (*if_notify)(struct proto *, unsigned flags, struct iface *i);
|
void (*if_notify)(struct proto *, unsigned flags, struct iface *i);
|
||||||
|
@ -60,6 +60,19 @@
|
|||||||
static slab *neigh_slab;
|
static slab *neigh_slab;
|
||||||
static list neigh_hash_table[NEIGH_HASH_SIZE], sticky_neigh_list;
|
static list neigh_hash_table[NEIGH_HASH_SIZE], sticky_neigh_list;
|
||||||
|
|
||||||
|
void if_link(struct iface *);
|
||||||
|
void if_unlink(struct iface *);
|
||||||
|
void ifa_link(struct ifa *);
|
||||||
|
void ifa_unlink(struct ifa *);
|
||||||
|
|
||||||
|
extern list global_iface_list;
|
||||||
|
|
||||||
|
extern DOMAIN(attrs) iface_domain;
|
||||||
|
|
||||||
|
#define IFACE_LOCK LOCK_DOMAIN(attrs, iface_domain)
|
||||||
|
#define IFACE_UNLOCK UNLOCK_DOMAIN(attrs, iface_domain)
|
||||||
|
#define IFACE_ASSERT_LOCKED ASSERT_DIE(DOMAIN_IS_LOCKED(attrs, iface_domain))
|
||||||
|
|
||||||
static inline uint
|
static inline uint
|
||||||
neigh_hash(struct proto *p, ip_addr a, struct iface *i)
|
neigh_hash(struct proto *p, ip_addr a, struct iface *i)
|
||||||
{
|
{
|
||||||
@ -152,7 +165,7 @@ if_connected_any(ip_addr a, struct iface *vrf, struct iface **iface, struct ifa
|
|||||||
*addr = NULL;
|
*addr = NULL;
|
||||||
|
|
||||||
/* Prefer SCOPE_HOST or longer prefix */
|
/* Prefer SCOPE_HOST or longer prefix */
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, global_iface_list)
|
||||||
if ((!vrf || vrf == i->master) && ((s = if_connected(a, i, &b, flags)) >= 0))
|
if ((!vrf || vrf == i->master) && ((s = if_connected(a, i, &b, flags)) >= 0))
|
||||||
if (scope_better(s, scope) || (scope_remote(s, scope) && ifa_better(b, *addr)))
|
if (scope_better(s, scope) || (scope_remote(s, scope) && ifa_better(b, *addr)))
|
||||||
{
|
{
|
||||||
@ -210,6 +223,8 @@ if_intersect(struct iface *ia, struct iface *ib)
|
|||||||
neighbor *
|
neighbor *
|
||||||
neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
|
neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
|
||||||
{
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
|
||||||
neighbor *n;
|
neighbor *n;
|
||||||
int class, scope = -1;
|
int class, scope = -1;
|
||||||
uint h = neigh_hash(p, a, iface);
|
uint h = neigh_hash(p, a, iface);
|
||||||
@ -218,26 +233,29 @@ neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
|
|||||||
|
|
||||||
WALK_LIST(n, neigh_hash_table[h]) /* Search the cache */
|
WALK_LIST(n, neigh_hash_table[h]) /* Search the cache */
|
||||||
if ((n->proto == p) && ipa_equal(n->addr, a) && (n->ifreq == iface))
|
if ((n->proto == p) && ipa_equal(n->addr, a) && (n->ifreq == iface))
|
||||||
|
{
|
||||||
|
IFACE_UNLOCK;
|
||||||
return n;
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & NEF_IFACE)
|
if (flags & NEF_IFACE)
|
||||||
{
|
{
|
||||||
if (ipa_nonzero(a) || !iface)
|
if (ipa_nonzero(a) || !iface)
|
||||||
return NULL;
|
goto bad;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
class = ipa_classify(a);
|
class = ipa_classify(a);
|
||||||
if (class < 0) /* Invalid address */
|
if (class < 0) /* Invalid address */
|
||||||
return NULL;
|
goto bad;
|
||||||
if (((class & IADDR_SCOPE_MASK) == SCOPE_HOST) ||
|
if (((class & IADDR_SCOPE_MASK) == SCOPE_HOST) ||
|
||||||
(((class & IADDR_SCOPE_MASK) == SCOPE_LINK) && !iface) ||
|
(((class & IADDR_SCOPE_MASK) == SCOPE_LINK) && !iface) ||
|
||||||
!(class & IADDR_HOST))
|
!(class & IADDR_HOST))
|
||||||
return NULL; /* Bad scope or a somecast */
|
goto bad; /* Bad scope or a somecast */
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & NEF_ONLINK) && !iface)
|
if ((flags & NEF_ONLINK) && !iface)
|
||||||
return NULL;
|
goto bad;
|
||||||
|
|
||||||
if (iface)
|
if (iface)
|
||||||
{
|
{
|
||||||
@ -251,7 +269,7 @@ neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
|
|||||||
/* scope >= 0 <=> iface != NULL */
|
/* scope >= 0 <=> iface != NULL */
|
||||||
|
|
||||||
if ((scope < 0) && !(flags & NEF_STICKY))
|
if ((scope < 0) && !(flags & NEF_STICKY))
|
||||||
return NULL;
|
goto bad;
|
||||||
|
|
||||||
n = sl_allocz(neigh_slab);
|
n = sl_allocz(neigh_slab);
|
||||||
add_tail(&neigh_hash_table[h], &n->n);
|
add_tail(&neigh_hash_table[h], &n->n);
|
||||||
@ -267,7 +285,12 @@ neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
|
|||||||
|
|
||||||
neigh_link(n);
|
neigh_link(n);
|
||||||
|
|
||||||
|
IFACE_UNLOCK;
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
IFACE_UNLOCK;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -276,7 +299,7 @@ neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
|
|||||||
*
|
*
|
||||||
* This functions dumps the contents of a given neighbor entry to debug output.
|
* This functions dumps the contents of a given neighbor entry to debug output.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
neigh_dump(neighbor *n)
|
neigh_dump(neighbor *n)
|
||||||
{
|
{
|
||||||
debug("%p %I %s %s ", n, n->addr,
|
debug("%p %I %s %s ", n, n->addr,
|
||||||
@ -298,6 +321,8 @@ neigh_dump(neighbor *n)
|
|||||||
void
|
void
|
||||||
neigh_dump_all(void)
|
neigh_dump_all(void)
|
||||||
{
|
{
|
||||||
|
IFACE_LOCK;
|
||||||
|
|
||||||
neighbor *n;
|
neighbor *n;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -306,11 +331,14 @@ neigh_dump_all(void)
|
|||||||
WALK_LIST(n, neigh_hash_table[i])
|
WALK_LIST(n, neigh_hash_table[i])
|
||||||
neigh_dump(n);
|
neigh_dump(n);
|
||||||
debug("\n");
|
debug("\n");
|
||||||
|
|
||||||
|
IFACE_UNLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
neigh_notify(neighbor *n)
|
neigh_notify(neighbor *n)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
if_enqueue_notify_to((struct iface_notification) { .type = IFNOT_NEIGHBOR, .n = n, }, &n->proto->iface_sub);
|
if_enqueue_notify_to((struct iface_notification) { .type = IFNOT_NEIGHBOR, .n = n, }, &n->proto->iface_sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,12 +380,14 @@ neigh_down(neighbor *n)
|
|||||||
void
|
void
|
||||||
neigh_link(neighbor *n)
|
neigh_link(neighbor *n)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
n->uc++;
|
n->uc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
neigh_unlink(neighbor *n)
|
neigh_unlink(neighbor *n)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
if (--n->uc)
|
if (--n->uc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -365,7 +395,7 @@ neigh_unlink(neighbor *n)
|
|||||||
proto_neigh_rem_node(&p->neighbors, n);
|
proto_neigh_rem_node(&p->neighbors, n);
|
||||||
|
|
||||||
if ((p->proto_state == PS_DOWN) && EMPTY_TLIST(proto_neigh, &p->neighbors))
|
if ((p->proto_state == PS_DOWN) && EMPTY_TLIST(proto_neigh, &p->neighbors))
|
||||||
ev_schedule(p->event);
|
proto_send_event(p, p->event);
|
||||||
|
|
||||||
n->proto = NULL;
|
n->proto = NULL;
|
||||||
|
|
||||||
@ -391,6 +421,8 @@ neigh_unlink(neighbor *n)
|
|||||||
void
|
void
|
||||||
neigh_update(neighbor *n, struct iface *iface)
|
neigh_update(neighbor *n, struct iface *iface)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
|
|
||||||
struct proto *p = n->proto;
|
struct proto *p = n->proto;
|
||||||
struct ifa *ifa = NULL;
|
struct ifa *ifa = NULL;
|
||||||
int scope = -1;
|
int scope = -1;
|
||||||
@ -461,12 +493,13 @@ neigh_update(neighbor *n, struct iface *iface)
|
|||||||
void
|
void
|
||||||
neigh_if_up(struct iface *i)
|
neigh_if_up(struct iface *i)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
struct iface *ii;
|
struct iface *ii;
|
||||||
neighbor *n;
|
neighbor *n;
|
||||||
node *x, *y;
|
node *x, *y;
|
||||||
|
|
||||||
/* Update neighbors that might be better off with the new iface */
|
/* Update neighbors that might be better off with the new iface */
|
||||||
WALK_LIST(ii, iface_list)
|
WALK_LIST(ii, global_iface_list)
|
||||||
if (!EMPTY_LIST(ii->neighbors) && (ii != i) && if_intersect(i, ii))
|
if (!EMPTY_LIST(ii->neighbors) && (ii != i) && if_intersect(i, ii))
|
||||||
WALK_LIST2_DELSAFE(n, x, y, ii->neighbors, if_n)
|
WALK_LIST2_DELSAFE(n, x, y, ii->neighbors, if_n)
|
||||||
neigh_update(n, i);
|
neigh_update(n, i);
|
||||||
@ -486,6 +519,7 @@ neigh_if_up(struct iface *i)
|
|||||||
void
|
void
|
||||||
neigh_if_down(struct iface *i)
|
neigh_if_down(struct iface *i)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
neighbor *n;
|
neighbor *n;
|
||||||
node *x, *y;
|
node *x, *y;
|
||||||
|
|
||||||
@ -503,6 +537,7 @@ neigh_if_down(struct iface *i)
|
|||||||
void
|
void
|
||||||
neigh_if_link(struct iface *i)
|
neigh_if_link(struct iface *i)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
neighbor *n;
|
neighbor *n;
|
||||||
node *x, *y;
|
node *x, *y;
|
||||||
|
|
||||||
@ -523,12 +558,13 @@ neigh_if_link(struct iface *i)
|
|||||||
void
|
void
|
||||||
neigh_ifa_up(struct ifa *a)
|
neigh_ifa_up(struct ifa *a)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
struct iface *i = a->iface, *ii;
|
struct iface *i = a->iface, *ii;
|
||||||
neighbor *n;
|
neighbor *n;
|
||||||
node *x, *y;
|
node *x, *y;
|
||||||
|
|
||||||
/* Update neighbors that might be better off with the new ifa */
|
/* Update neighbors that might be better off with the new ifa */
|
||||||
WALK_LIST(ii, iface_list)
|
WALK_LIST(ii, global_iface_list)
|
||||||
if (!EMPTY_LIST(ii->neighbors) && ifa_intersect(a, ii))
|
if (!EMPTY_LIST(ii->neighbors) && ifa_intersect(a, ii))
|
||||||
WALK_LIST2_DELSAFE(n, x, y, ii->neighbors, if_n)
|
WALK_LIST2_DELSAFE(n, x, y, ii->neighbors, if_n)
|
||||||
neigh_update(n, i);
|
neigh_update(n, i);
|
||||||
@ -541,6 +577,7 @@ neigh_ifa_up(struct ifa *a)
|
|||||||
void
|
void
|
||||||
neigh_ifa_down(struct ifa *a)
|
neigh_ifa_down(struct ifa *a)
|
||||||
{
|
{
|
||||||
|
IFACE_ASSERT_LOCKED;
|
||||||
struct iface *i = a->iface;
|
struct iface *i = a->iface;
|
||||||
neighbor *n;
|
neighbor *n;
|
||||||
node *x, *y;
|
node *x, *y;
|
||||||
@ -551,22 +588,6 @@ neigh_ifa_down(struct ifa *a)
|
|||||||
neigh_update(n, i);
|
neigh_update(n, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* neigh_prune - prune neighbor cache
|
|
||||||
*
|
|
||||||
* neigh_prune() examines all neighbor entries cached and removes those
|
|
||||||
* corresponding to inactive protocols. It's called whenever a protocol
|
|
||||||
* is shut down to get rid of all its heritage.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
neigh_prune(struct proto *p)
|
|
||||||
{
|
|
||||||
WALK_TLIST_DELSAFE(proto_neigh, n, &p->neighbors)
|
|
||||||
neigh_unlink(n);
|
|
||||||
|
|
||||||
ASSERT_DIE(EMPTY_TLIST(proto_neigh, &p->neighbors));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* neigh_init - initialize the neighbor cache.
|
* neigh_init - initialize the neighbor cache.
|
||||||
* @if_pool: resource pool to be used for neighbor entries.
|
* @if_pool: resource pool to be used for neighbor entries.
|
||||||
|
@ -1142,7 +1142,6 @@ proto_event(void *ptr)
|
|||||||
if (p->do_stop)
|
if (p->do_stop)
|
||||||
{
|
{
|
||||||
iface_unsubscribe(&p->iface_sub);
|
iface_unsubscribe(&p->iface_sub);
|
||||||
neigh_prune(p);
|
|
||||||
|
|
||||||
p->do_stop = 0;
|
p->do_stop = 0;
|
||||||
}
|
}
|
||||||
@ -1219,6 +1218,8 @@ proto_start(struct proto *p)
|
|||||||
if (p->cf->loop_order != DOMAIN_ORDER(the_bird))
|
if (p->cf->loop_order != DOMAIN_ORDER(the_bird))
|
||||||
p->loop = birdloop_new(p->pool, p->cf->loop_order, p->pool->name);
|
p->loop = birdloop_new(p->pool, p->cf->loop_order, p->pool->name);
|
||||||
|
|
||||||
|
p->iface_sub.target = proto_event_list(p);
|
||||||
|
|
||||||
PROTO_LOCKED_FROM_MAIN(p)
|
PROTO_LOCKED_FROM_MAIN(p)
|
||||||
proto_notify_state(p, (p->proto->start ? p->proto->start(p) : PS_UP));
|
proto_notify_state(p, (p->proto->start ? p->proto->start(p) : PS_UP));
|
||||||
}
|
}
|
||||||
|
@ -1944,9 +1944,7 @@ babel_reconfigure_iface(struct babel_proto *p, struct babel_iface *ifa, struct b
|
|||||||
static void
|
static void
|
||||||
babel_reconfigure_ifaces(struct babel_proto *p, struct babel_config *cf)
|
babel_reconfigure_ifaces(struct babel_proto *p, struct babel_config *cf)
|
||||||
{
|
{
|
||||||
struct iface *iface;
|
IFACE_WALK(iface)
|
||||||
|
|
||||||
WALK_LIST(iface, iface_list)
|
|
||||||
{
|
{
|
||||||
if (p->p.vrf && p->p.vrf != iface->master)
|
if (p->p.vrf && p->p.vrf != iface->master)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1225,10 +1225,9 @@ ospf_ifa_notify3(struct proto *P, uint flags, struct ifa *a)
|
|||||||
static void
|
static void
|
||||||
ospf_reconfigure_ifaces2(struct ospf_proto *p)
|
ospf_reconfigure_ifaces2(struct ospf_proto *p)
|
||||||
{
|
{
|
||||||
struct iface *iface;
|
|
||||||
struct ifa *a;
|
struct ifa *a;
|
||||||
|
|
||||||
WALK_LIST(iface, iface_list)
|
IFACE_WALK(iface)
|
||||||
{
|
{
|
||||||
if (p->p.vrf && p->p.vrf != iface->master)
|
if (p->p.vrf && p->p.vrf != iface->master)
|
||||||
continue;
|
continue;
|
||||||
@ -1274,10 +1273,9 @@ ospf_reconfigure_ifaces2(struct ospf_proto *p)
|
|||||||
static void
|
static void
|
||||||
ospf_reconfigure_ifaces3(struct ospf_proto *p)
|
ospf_reconfigure_ifaces3(struct ospf_proto *p)
|
||||||
{
|
{
|
||||||
struct iface *iface;
|
|
||||||
struct ifa *a;
|
struct ifa *a;
|
||||||
|
|
||||||
WALK_LIST(iface, iface_list)
|
IFACE_WALK(iface)
|
||||||
{
|
{
|
||||||
if (p->p.vrf && p->p.vrf != iface->master)
|
if (p->p.vrf && p->p.vrf != iface->master)
|
||||||
continue;
|
continue;
|
||||||
|
@ -666,8 +666,7 @@ radv_reconfigure(struct proto *P, struct proto_config *CF)
|
|||||||
if (!old->propagate_routes && new->propagate_routes)
|
if (!old->propagate_routes && new->propagate_routes)
|
||||||
channel_request_feeding(p->p.main_channel);
|
channel_request_feeding(p->p.main_channel);
|
||||||
|
|
||||||
struct iface *iface;
|
IFACE_WALK(iface)
|
||||||
WALK_LIST(iface, iface_list)
|
|
||||||
{
|
{
|
||||||
if (p->p.vrf && p->p.vrf != iface->master)
|
if (p->p.vrf && p->p.vrf != iface->master)
|
||||||
continue;
|
continue;
|
||||||
|
@ -807,9 +807,7 @@ rip_reconfigure_iface(struct rip_proto *p, struct rip_iface *ifa, struct rip_ifa
|
|||||||
static void
|
static void
|
||||||
rip_reconfigure_ifaces(struct rip_proto *p, struct rip_config *cf)
|
rip_reconfigure_ifaces(struct rip_proto *p, struct rip_config *cf)
|
||||||
{
|
{
|
||||||
struct iface *iface;
|
IFACE_WALK(iface)
|
||||||
|
|
||||||
WALK_LIST(iface, iface_list)
|
|
||||||
{
|
{
|
||||||
if (p->p.vrf && p->p.vrf != iface->master)
|
if (p->p.vrf && p->p.vrf != iface->master)
|
||||||
continue;
|
continue;
|
||||||
|
@ -277,14 +277,17 @@ krt_send_route(struct krt_proto *p, int cmd, const rte *e)
|
|||||||
*/
|
*/
|
||||||
if (!i)
|
if (!i)
|
||||||
{
|
{
|
||||||
WALK_LIST(j, iface_list)
|
j = if_walk_first();
|
||||||
|
while (j)
|
||||||
{
|
{
|
||||||
if (j->flags & IF_LOOPBACK)
|
if (j->flags & IF_LOOPBACK)
|
||||||
{
|
{
|
||||||
i = j;
|
i = j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
j = if_walk_next(j);
|
||||||
}
|
}
|
||||||
|
if_walk_done();
|
||||||
|
|
||||||
if (!i)
|
if (!i)
|
||||||
{
|
{
|
||||||
|
@ -1283,8 +1283,7 @@ kif_do_scan(struct kif_proto *p UNUSED)
|
|||||||
log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
|
log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
|
||||||
|
|
||||||
/* Re-resolve master interface for slaves */
|
/* Re-resolve master interface for slaves */
|
||||||
struct iface *i;
|
IFACE_WALK(i)
|
||||||
WALK_LIST(i, iface_list)
|
|
||||||
if (i->master_index)
|
if (i->master_index)
|
||||||
{
|
{
|
||||||
struct iface f = {
|
struct iface f = {
|
||||||
@ -1292,13 +1291,13 @@ kif_do_scan(struct kif_proto *p UNUSED)
|
|||||||
.mtu = i->mtu,
|
.mtu = i->mtu,
|
||||||
.index = i->index,
|
.index = i->index,
|
||||||
.master_index = i->master_index,
|
.master_index = i->master_index,
|
||||||
.master = if_find_by_index(i->master_index)
|
.master = if_find_by_index_locked(i->master_index)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (f.master != i->master)
|
if (f.master != i->master)
|
||||||
{
|
{
|
||||||
memcpy(f.name, i->name, sizeof(f.name));
|
memcpy(f.name, i->name, sizeof(f.name));
|
||||||
if_update(&f);
|
if_update_locked(&f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user