diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2010-02-26 10:55:58 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2010-02-26 10:55:58 +0100 |
commit | ff2857b03db854f99902766ad842aaa5fa29ec3c (patch) | |
tree | 8484bfcabaa9805fab2ae188a6855314192d92e1 /nest | |
parent | e81b440f6878605edd19ed62441648ac71260881 (diff) | |
download | bird-ff2857b03db854f99902766ad842aaa5fa29ec3c.tar bird-ff2857b03db854f99902766ad842aaa5fa29ec3c.zip |
Many changes in (mainly) kernel syncers.
- BSD kernel syncer is now self-conscious and can learn alien routes
- important bugfix in BSD kernel syncer (crash after protocol restart)
- many minor changes and bugfixes in kernel syncers and neighbor cache
- direct protocol does not generate host and link local routes
- min_scope check is removed, all routes have SCOPE_UNIVERSE by default
- also fixes some remaining compiler warnings
Diffstat (limited to 'nest')
-rw-r--r-- | nest/iface.h | 1 | ||||
-rw-r--r-- | nest/neighbor.c | 23 | ||||
-rw-r--r-- | nest/proto.c | 1 | ||||
-rw-r--r-- | nest/protocol.h | 1 | ||||
-rw-r--r-- | nest/rt-dev.c | 7 | ||||
-rw-r--r-- | nest/rt-table.c | 52 |
6 files changed, 35 insertions, 50 deletions
diff --git a/nest/iface.h b/nest/iface.h index a982c17..02129ac 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -97,6 +97,7 @@ typedef struct neighbor { } neighbor; #define NEF_STICKY 1 +#define NEF_ONLINK 2 neighbor *neigh_find(struct proto *, ip_addr *, unsigned flags); neighbor *neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags); diff --git a/nest/neighbor.c b/nest/neighbor.c index a44667f..25b98db 100644 --- a/nest/neighbor.c +++ b/nest/neighbor.c @@ -112,12 +112,12 @@ neighbor * neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags) { neighbor *n; - int class, scope = SCOPE_HOST; + int class, scope = -1; ; unsigned int h = neigh_hash(p, a); struct iface *i; WALK_LIST(n, neigh_hash_table[h]) /* Search the cache */ - if (n->proto == p && ipa_equal(*a, n->addr)) + if (n->proto == p && ipa_equal(*a, n->addr) && (!ifa || (ifa == n->iface))) return n; class = ipa_classify(*a); @@ -129,7 +129,12 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags) return NULL; /* Bad scope or a somecast */ if (ifa) - scope = if_connected(a, ifa); + { + scope = if_connected(a, ifa); + + if ((scope < 0) && (flags & NEF_ONLINK)) + scope = class & IADDR_SCOPE_MASK; + } else WALK_LIST(i, iface_list) if ((scope = if_connected(a, i)) >= 0) @@ -138,22 +143,28 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags) break; } - if (!ifa && !(flags & NEF_STICKY)) + /* scope < 0 means i don't know neighbor */ + /* scope >= 0 implies ifa != NULL */ + + if ((scope < 0) && !(flags & NEF_STICKY)) return NULL; n = sl_alloc(neigh_slab); n->addr = *a; - n->iface = ifa; - if (ifa) + if (scope >= 0) { add_tail(&neigh_hash_table[h], &n->n); add_tail(&ifa->neighbors, &n->if_n); } 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 = 0; } + n->iface = ifa; n->proto = p; n->data = NULL; n->aux = 0; diff --git a/nest/proto.c b/nest/proto.c index 4883705..db6bf9b 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -113,7 +113,6 @@ proto_new(struct proto_config *c, unsigned size) p->table = c->table->table; p->in_filter = c->in_filter; p->out_filter = c->out_filter; - p->min_scope = SCOPE_SITE; p->hash_key = random_u32(); c->proto = p; return p; diff --git a/nest/protocol.h b/nest/protocol.h index 99356a3..d94873e 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -130,7 +130,6 @@ struct proto { u32 debug; /* Debugging flags */ u32 mrtdump; /* MRTDump flags */ unsigned preference; /* Default route preference */ - int min_scope; /* Minimal route scope accepted */ unsigned accept_ra_types; /* Which types of route announcements are accepted (RA_OPTIMAL or RA_ANY) */ unsigned disabled; /* Manually disabled */ unsigned proto_state; /* Protocol state machine (see below) */ diff --git a/nest/rt-dev.c b/nest/rt-dev.c index b86015d..bb8eb8e 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -33,6 +33,10 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad) !iface_patt_find(&P->iface_list, ad->iface)) /* Empty list is automagically treated as "*" */ return; + + if (ad->scope <= SCOPE_LINK) + return; + if (c & IF_CHANGE_DOWN) { net *n; @@ -56,7 +60,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad) bzero(&A, sizeof(A)); A.proto = p; A.source = RTS_DEVICE; - A.scope = ad->scope; + A.scope = SCOPE_UNIVERSE; A.cast = RTC_UNICAST; A.dest = RTD_DEVICE; A.iface = ad->iface; @@ -76,7 +80,6 @@ dev_init(struct proto_config *c) struct proto *p = proto_new(c, sizeof(struct proto)); p->ifa_notify = dev_ifa_notify; - p->min_scope = SCOPE_HOST; return p; } diff --git a/nest/rt-table.c b/nest/rt-table.c index 41ecf64..1860b1a 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -158,7 +158,7 @@ rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg) } static inline void -do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int class, int refeed) +do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int refeed) { struct proto *p = a->proto; struct filter *filter = p->out_filter; @@ -183,13 +183,7 @@ do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rt stats->exp_updates_received++; char *drop_reason = NULL; - if ((class & IADDR_SCOPE_MASK) < p->min_scope) - { - stats->exp_updates_rejected++; - drop_reason = "out of scope"; - fast_exit_hack = 1; - } - else if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0) + if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0) { stats->exp_updates_rejected++; drop_reason = "rejected by protocol"; @@ -332,7 +326,6 @@ static void rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, ea_list *tmpa) { struct announce_hook *a; - int class = ipa_classify(net->n.prefix); if (type == RA_OPTIMAL) { @@ -346,7 +339,7 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, ea_list * { ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING); if (a->proto->accept_ra_types == type) - do_rte_announce(a, type, net, new, old, tmpa, class, 0); + do_rte_announce(a, type, net, new, old, tmpa, 0); } } @@ -362,33 +355,15 @@ rte_validate(rte *e) n->n.prefix, n->n.pxlen, e->sender->name); return 0; } - if (n->n.pxlen) + + c = ipa_classify_net(n->n.prefix); + if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK)) { - c = ipa_classify(n->n.prefix); - if (c < 0 || !(c & IADDR_HOST)) - { - if (!ipa_nonzero(n->n.prefix)) - { - /* Various default routes */ -#ifdef IPV6 - if (n->n.pxlen == 96) -#else - if (n->n.pxlen <= 1) -#endif - return 1; - } - log(L_WARN "Ignoring bogus route %I/%d received via %s", - n->n.prefix, n->n.pxlen, e->sender->name); - return 0; - } - if ((c & IADDR_SCOPE_MASK) < e->sender->min_scope) - { - log(L_WARN "Ignoring %s scope route %I/%d received from %I via %s", - ip_scope_text(c & IADDR_SCOPE_MASK), - n->n.prefix, n->n.pxlen, e->attrs->from, e->sender->name); - return 0; - } + log(L_WARN "Ignoring bogus route %I/%d received via %s", + n->n.prefix, n->n.pxlen, e->sender->name); + return 0; } + return 1; } @@ -1018,7 +993,7 @@ do_feed_baby(struct proto *p, int type, struct announce_hook *h, net *n, rte *e) rte_update_lock(); tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL; - do_rte_announce(h, type, n, e, p->refeeding ? e : NULL, tmpa, ipa_classify(n->n.prefix), p->refeeding); + do_rte_announce(h, type, n, e, p->refeeding ? e : NULL, tmpa, p->refeeding); rte_update_unlock(); } @@ -1190,11 +1165,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) if (p2 && p2 != p0) ok = 0; if (ok && d->export_mode) { - int class = ipa_classify(n->n.prefix); int ic; - if ((class & IADDR_SCOPE_MASK) < p1->min_scope) - ok = 0; - else if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0) + if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0) ok = 0; else if (!ic && d->export_mode > 1) { |