o The if_change_too_big_p change was too high-spirited. Fixed.
o Introduced if_find_by_index() o Recognizing two types of interface updates: full update (starting with if_start_update(), ending with if_end_update(), guaranteed to see all existing interfaces) and a partial update (only if_update(), usually due to asynchronous interface notifications).
This commit is contained in:
parent
bcbd8cc3be
commit
e35ef181a4
3 changed files with 31 additions and 9 deletions
37
nest/iface.c
37
nest/iface.c
|
@ -231,8 +231,6 @@ if_dump_all(void)
|
||||||
static inline int
|
static inline int
|
||||||
if_change_too_big_p(struct iface *i, struct iface *j)
|
if_change_too_big_p(struct iface *i, struct iface *j)
|
||||||
{
|
{
|
||||||
if ((i->flags ^ j->flags) & IF_UP) /* Going up/down is always OK */
|
|
||||||
return 0;
|
|
||||||
if (!ipa_equal(i->ip, j->ip) || /* Address change isn't */
|
if (!ipa_equal(i->ip, j->ip) || /* Address change isn't */
|
||||||
!ipa_equal(i->prefix, j->prefix) ||
|
!ipa_equal(i->prefix, j->prefix) ||
|
||||||
i->pxlen != j->pxlen ||
|
i->pxlen != j->pxlen ||
|
||||||
|
@ -310,16 +308,19 @@ if_update(struct iface *new)
|
||||||
if (if_change_too_big_p(i, new)) /* Changed a lot, convert it to down/up */
|
if (if_change_too_big_p(i, new)) /* Changed a lot, convert it to down/up */
|
||||||
{
|
{
|
||||||
DBG("Interface %s changed too much -- forcing down/up transition\n", i->name);
|
DBG("Interface %s changed too much -- forcing down/up transition\n", i->name);
|
||||||
i->flags &= ~IF_UP;
|
if (i->flags & IF_UP)
|
||||||
if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, i, NULL);
|
{
|
||||||
|
i->flags &= ~IF_UP;
|
||||||
|
if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, i, NULL);
|
||||||
|
}
|
||||||
rem_node(&i->n);
|
rem_node(&i->n);
|
||||||
goto newif;
|
goto newif;
|
||||||
}
|
}
|
||||||
c = if_changed(i, new);
|
c = if_changed(i, new);
|
||||||
if_copy(i, new); /* Even if c==0 as we might need to update i->index et al. */
|
|
||||||
i->flags |= IF_UPDATED;
|
|
||||||
if (c)
|
if (c)
|
||||||
if_notify_change(c, i, new);
|
if_notify_change(c, i, new);
|
||||||
|
if_copy(i, new); /* Even if c==0 as we might need to update i->index et al. */
|
||||||
|
i->flags |= IF_UPDATED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,6 +333,15 @@ newif:
|
||||||
| IF_CHANGE_FLAGS | IF_CHANGE_MTU, NULL, i);
|
| IF_CHANGE_FLAGS | IF_CHANGE_MTU, NULL, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
if_start_update(void)
|
||||||
|
{
|
||||||
|
struct iface *i;
|
||||||
|
|
||||||
|
WALK_LIST(i, iface_list)
|
||||||
|
i->flags &= ~IF_UPDATED;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
if_end_update(void)
|
if_end_update(void)
|
||||||
{
|
{
|
||||||
|
@ -341,9 +351,7 @@ if_end_update(void)
|
||||||
auto_router_id();
|
auto_router_id();
|
||||||
|
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, iface_list)
|
||||||
if (i->flags & IF_UPDATED)
|
if (!(i->flags & IF_UPDATED))
|
||||||
i->flags &= ~IF_UPDATED;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
memcpy(&j, i, sizeof(struct iface));
|
memcpy(&j, i, sizeof(struct iface));
|
||||||
i->flags = (i->flags & ~(IF_LINK_UP | IF_UP)) | IF_ADMIN_DOWN;
|
i->flags = (i->flags & ~(IF_LINK_UP | IF_UP)) | IF_ADMIN_DOWN;
|
||||||
|
@ -364,6 +372,17 @@ if_feed_baby(struct proto *p)
|
||||||
p->if_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i, NULL);
|
p->if_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct iface *
|
||||||
|
if_find_by_index(unsigned idx)
|
||||||
|
{
|
||||||
|
struct iface *i;
|
||||||
|
|
||||||
|
WALK_LIST(i, iface_list)
|
||||||
|
if (i->index == idx)
|
||||||
|
return i;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
auto_router_id(void) /* FIXME: What if we run IPv6??? */
|
auto_router_id(void) /* FIXME: What if we run IPv6??? */
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,8 +53,10 @@ void if_init(void);
|
||||||
void if_dump(struct iface *);
|
void if_dump(struct iface *);
|
||||||
void if_dump_all(void);
|
void if_dump_all(void);
|
||||||
void if_update(struct iface *);
|
void if_update(struct iface *);
|
||||||
|
void if_start_update(void);
|
||||||
void if_end_update(void);
|
void if_end_update(void);
|
||||||
void if_feed_baby(struct proto *);
|
void if_feed_baby(struct proto *);
|
||||||
|
struct iface *if_find_by_index(unsigned);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Neighbor Cache. We hold (direct neighbor, protocol) pairs we've seen
|
* Neighbor Cache. We hold (direct neighbor, protocol) pairs we've seen
|
||||||
|
|
|
@ -37,6 +37,7 @@ scan_ifs(struct ifreq *r, int cnt)
|
||||||
ip_addr netmask;
|
ip_addr netmask;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
|
if_start_update();
|
||||||
for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
|
for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
|
||||||
{
|
{
|
||||||
bzero(&i, sizeof(i));
|
bzero(&i, sizeof(i));
|
||||||
|
|
Loading…
Reference in a new issue