diff options
Diffstat (limited to 'sysdep')
-rw-r--r-- | sysdep/unix/krt.c | 253 | ||||
-rw-r--r-- | sysdep/unix/krt.h | 4 |
2 files changed, 19 insertions, 238 deletions
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 4539feee..93d19614 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -302,241 +302,29 @@ krt_uptodate(rte *a, rte *b) return (a->attrs == b->attrs); } -static void -krt_learn_announce_update(struct krt_proto *p, rte *e) -{ - rte e0 = { - .attrs = ea_clone(e->attrs), - .src = p->p.main_source, - }; - - rte_update(p->p.main_channel, e->net, &e0, p->p.main_source); -} - -static void -krt_learn_announce_delete(struct krt_proto *p, net_addr *n) -{ - rte_update(p->p.main_channel, n, NULL, p->p.main_source); -} - -static struct rte_storage * -krt_store_async(struct krt_proto *p, net *n, rte *e) -{ - ea_set_attr_u32(&e->attrs, &ea_gen_preference, 0, p->p.main_channel->preference); - e->src = p->p.main_source; - return rte_store(e, n, p->krt_table); -} - /* Called when alien route is discovered during scan */ static void krt_learn_scan(struct krt_proto *p, rte *e) { - net *n = net_get(p->krt_table, e->net); - struct rte_storage *m, **mm; - struct rte_storage *ee = krt_store_async(p, n, e); - - for(mm = &n->routes; m = *mm; mm = &m->next) - if (krt_same_key(&m->rte, e)) - break; - if (m) - { - if (krt_uptodate(&m->rte, e)) - { - krt_trace_in_rl(&rl_alien, p, e, "[alien] seen"); - rte_free(ee); - m->rte.pflags |= KRT_REF_SEEN; - } - else - { - krt_trace_in(p, e, "[alien] updated"); - *mm = m->next; - rte_free(m); - m = NULL; - } - } - else - krt_trace_in(p, e, "[alien] created"); - - if (!m) - { - ee->next = n->routes; - n->routes = ee; - ee->rte.pflags |= KRT_REF_SEEN; - } -} - -static void -krt_learn_prune(struct krt_proto *p) -{ - struct fib *fib = &p->krt_table->fib; - struct fib_iterator fit; - - KRT_TRACE(p, D_EVENTS, "Pruning inherited routes"); - - FIB_ITERATE_INIT(&fit, fib); -again: - FIB_ITERATE_START(fib, &fit, net, n) - { - struct rte_storage *e, **ee, *best, **pbest, *old_best; - - /* - * Note that old_best may be NULL even if there was an old best route in - * the previous step, because it might be replaced in krt_learn_scan(). - * But in that case there is a new valid best route. - */ - - old_best = NULL; - best = NULL; - pbest = NULL; - ee = &n->routes; - while (e = *ee) - { - if (e->rte.pflags & KRT_REF_BEST) - old_best = e; - - if (!(e->rte.pflags & KRT_REF_SEEN)) - { - *ee = e->next; - rte_free(e); - continue; - } - - if (!best || krt_metric(&best->rte) > krt_metric(&e->rte)) - { - best = e; - pbest = ee; - } - - e->rte.pflags &= ~(KRT_REF_SEEN | KRT_REF_BEST); - ee = &e->next; - } - if (!n->routes) - { - DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen); - if (old_best) - krt_learn_announce_delete(p, n->n.addr); - - FIB_ITERATE_PUT(&fit); - fib_delete(fib, n); - goto again; - } - - best->rte.pflags |= KRT_REF_BEST; - *pbest = best->next; - best->next = n->routes; - n->routes = best; + rte e0 = { + .attrs = e->attrs, + .src = rt_get_source(&p->p, krt_metric(e)), + }; - if ((best != old_best) || p->reload) - { - DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(&best->rte)); - krt_learn_announce_update(p, &best->rte); - } - else - DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(&best->rte)); - } - FIB_ITERATE_END; + ea_set_attr_u32(&e0.attrs, &ea_gen_preference, 0, p->p.main_channel->preference); - p->reload = 0; + rte_update(p->p.main_channel, e->net, &e0, e0.src); } static void krt_learn_async(struct krt_proto *p, rte *e, int new) { - net *n = net_get(p->krt_table, e->net); - struct rte_storage *g, **gg, *best, **bestp, *old_best; - struct rte_storage *ee = krt_store_async(p, n, e); - - old_best = n->routes; - for(gg=&n->routes; g = *gg; gg = &g->next) - if (krt_same_key(&g->rte, e)) - break; if (new) - { - if (g) - { - if (krt_uptodate(&g->rte, e)) - { - krt_trace_in(p, e, "[alien async] same"); - rte_free(ee); - return; - } - krt_trace_in(p, e, "[alien async] updated"); - *gg = g->next; - rte_free(g); - } - else - krt_trace_in(p, e, "[alien async] created"); - - ee->next = n->routes; - n->routes = ee; - } - else if (!g) - { - krt_trace_in(p, e, "[alien async] delete failed"); - rte_free(ee); - return; - } - else - { - krt_trace_in(p, e, "[alien async] removed"); - *gg = g->next; - rte_free(ee); - rte_free(g); - } - best = n->routes; - bestp = &n->routes; - for(gg=&n->routes; g=*gg; gg=&g->next) - { - if (krt_metric(&best->rte) > krt_metric(&g->rte)) - { - best = g; - bestp = gg; - } - - g->rte.pflags &= ~KRT_REF_BEST; - } - - if (best) - { - best->rte.pflags |= KRT_REF_BEST; - *bestp = best->next; - best->next = n->routes; - n->routes = best; - } - - if (best != old_best) - { - DBG("krt_learn_async: distributing change\n"); - if (best) - krt_learn_announce_update(p, &best->rte); - else - krt_learn_announce_delete(p, n->n.addr); - } -} - -static void -krt_learn_init(struct krt_proto *p) -{ - if (KRT_CF->learn) - { - struct rtable_config *cf = mb_allocz(p->p.pool, sizeof(struct rtable_config)); - cf->name = "Inherited"; - cf->addr_type = p->p.net_type; - cf->internal = 1; + return krt_learn_scan(p, e); - p->krt_table = rt_setup(p->p.pool, cf); - } -} - -static void -krt_dump(struct proto *P) -{ - struct krt_proto *p = (struct krt_proto *) P; - - if (!KRT_CF->learn) - return; - debug("KRT: Table of inheritable routes\n"); - rt_dump(p->krt_table); + struct rte_src *src = rt_find_source(&p->p, krt_metric(e)); + if (src) + rte_update(p->p.main_channel, e->net, NULL, src); } #endif @@ -743,11 +531,6 @@ krt_prune(struct krt_proto *p) } FIB_WALK_END; -#ifdef KRT_ALLOW_LEARN - if (KRT_CF->learn) - krt_learn_prune(p); -#endif - if (p->ready) p->initialized = 1; } @@ -974,6 +757,14 @@ krt_feed_end(struct channel *C) krt_scan_timer_kick(p); } +static int +krt_rte_better(rte *new, rte *old) +{ + u32 n = ea_get_int(new->attrs, &ea_krt_metric, IGP_METRIC_UNKNOWN); + u32 o = ea_get_int(old->attrs, &ea_krt_metric, IGP_METRIC_UNKNOWN); + + return (n < o); +} /* * Protocol glue @@ -1033,6 +824,7 @@ krt_init(struct proto_config *CF) p->p.if_notify = krt_if_notify; p->p.reload_routes = krt_reload_routes; p->p.feed_end = krt_feed_end; + p->p.rte_better = krt_rte_better; krt_sys_init(p); return &p->p; @@ -1058,10 +850,6 @@ krt_start(struct proto *P) bmap_init(&p->seen_map, p->p.pool, 1024); add_tail(&krt_proto_list, &p->krt_node); -#ifdef KRT_ALLOW_LEARN - krt_learn_init(p); -#endif - if (!krt_sys_start(p)) { rem_node(&p->krt_node); @@ -1177,9 +965,6 @@ struct protocol proto_unix_kernel = { .shutdown = krt_shutdown, .reconfigure = krt_reconfigure, .copy_config = krt_copy_config, -#ifdef KRT_ALLOW_LEARN - .dump = krt_dump, -#endif }; void diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 69fc9aa1..e0d60cbd 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -55,10 +55,6 @@ struct krt_proto { struct proto p; struct krt_state sys; /* Sysdep state */ -#ifdef KRT_ALLOW_LEARN - struct rtable *krt_table; /* Internal table of inherited routes */ -#endif - #ifndef CONFIG_ALL_TABLES_AT_ONCE timer *scan_timer; #endif |