diff options
author | Martin Mares <mj@ucw.cz> | 1999-03-02 19:36:09 +0100 |
---|---|---|
committer | Martin Mares <mj@ucw.cz> | 1999-03-02 19:36:09 +0100 |
commit | e35ef181a41384446aca614522a7cbb10606dd5b (patch) | |
tree | ac8f7b78a3782ea8f09c7c649fefd3ab40bd1f78 | |
parent | bcbd8cc3be670a96e1405b896cff4be0912ba379 (diff) | |
download | bird-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.c | 37 | ||||
-rw-r--r-- | nest/iface.h | 2 | ||||
-rw-r--r-- | sysdep/unix/sync-if.c | 1 |
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)); |