summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>1999-03-02 19:36:09 +0100
committerMartin Mares <mj@ucw.cz>1999-03-02 19:36:09 +0100
commite35ef181a41384446aca614522a7cbb10606dd5b (patch)
treeac8f7b78a3782ea8f09c7c649fefd3ab40bd1f78
parentbcbd8cc3be670a96e1405b896cff4be0912ba379 (diff)
downloadbird-e35ef181a41384446aca614522a7cbb10606dd5b.tar
bird-e35ef181a41384446aca614522a7cbb10606dd5b.zip
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).
-rw-r--r--nest/iface.c37
-rw-r--r--nest/iface.h2
-rw-r--r--sysdep/unix/sync-if.c1
3 files changed, 31 insertions, 9 deletions
diff --git a/nest/iface.c b/nest/iface.c
index 4d1b685..9a02a3f 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -231,8 +231,6 @@ if_dump_all(void)
static inline int
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 */
!ipa_equal(i->prefix, j->prefix) ||
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 */
{
DBG("Interface %s changed too much -- forcing down/up transition\n", i->name);
- i->flags &= ~IF_UP;
- if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, i, NULL);
+ if (i->flags & IF_UP)
+ {
+ i->flags &= ~IF_UP;
+ if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, i, NULL);
+ }
rem_node(&i->n);
goto newif;
}
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_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;
}
@@ -333,6 +334,15 @@ newif:
}
void
+if_start_update(void)
+{
+ struct iface *i;
+
+ WALK_LIST(i, iface_list)
+ i->flags &= ~IF_UPDATED;
+}
+
+void
if_end_update(void)
{
struct iface *i, j;
@@ -341,9 +351,7 @@ if_end_update(void)
auto_router_id();
WALK_LIST(i, iface_list)
- if (i->flags & IF_UPDATED)
- i->flags &= ~IF_UPDATED;
- else
+ if (!(i->flags & IF_UPDATED))
{
memcpy(&j, i, sizeof(struct iface));
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);
}
+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
auto_router_id(void) /* FIXME: What if we run IPv6??? */
{
diff --git a/nest/iface.h b/nest/iface.h
index fcad718..8677be0 100644
--- a/nest/iface.h
+++ b/nest/iface.h
@@ -53,8 +53,10 @@ void if_init(void);
void if_dump(struct iface *);
void if_dump_all(void);
void if_update(struct iface *);
+void if_start_update(void);
void if_end_update(void);
void if_feed_baby(struct proto *);
+struct iface *if_find_by_index(unsigned);
/*
* Neighbor Cache. We hold (direct neighbor, protocol) pairs we've seen
diff --git a/sysdep/unix/sync-if.c b/sysdep/unix/sync-if.c
index ce54fc7..3dfa4f0 100644
--- a/sysdep/unix/sync-if.c
+++ b/sysdep/unix/sync-if.c
@@ -37,6 +37,7 @@ scan_ifs(struct ifreq *r, int cnt)
ip_addr netmask;
int l;
+ if_start_update();
for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
{
bzero(&i, sizeof(i));