X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=sysdep%2Funix%2Fkrt.c;h=42dd12f6e22f250835f4a9ac14b54ebde5ca0d58;hb=7d767c5a3d001a6a1a5c3e800553202fd492190c;hp=9f66d2f4c5fcd8681c3a0a46d34fa1d7205aeebc;hpb=4e276a8920ed0496836f002f144943ab42f120f6;p=thirdparty%2Fbird.git diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 9f66d2f4c..42dd12f6e 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -56,9 +56,9 @@ #include "nest/route.h" #include "nest/protocol.h" #include "filter/filter.h" -#include "sysdep/unix/timer.h" #include "conf/conf.h" #include "lib/string.h" +#include "lib/timer.h" #include "unix.h" #include "krt.h" @@ -75,7 +75,7 @@ void krt_io_init(void) { krt_pool = rp_new(&root_pool, "Kernel Syncer"); - krt_filter_lp = lp_new(krt_pool, 4080); + krt_filter_lp = lp_new_default(krt_pool); init_list(&krt_proto_list); krt_sys_io_init(); } @@ -87,7 +87,17 @@ krt_io_init(void) struct kif_proto *kif_proto; static struct kif_config *kif_cf; static timer *kif_scan_timer; -static bird_clock_t kif_last_shot; +static btime kif_last_shot; + +static struct kif_iface_config kif_default_iface = {}; + +struct kif_iface_config * +kif_get_iface_config(struct iface *iface) +{ + struct kif_config *cf = (void *) (kif_proto->p.cf); + struct kif_iface_config *ic = (void *) iface_patt_find(&cf->iface_list, iface, NULL); + return ic ?: &kif_default_iface; +} static void kif_scan(timer *t) @@ -95,14 +105,14 @@ kif_scan(timer *t) struct kif_proto *p = t->data; KRT_TRACE(p, D_EVENTS, "Scanning interfaces"); - kif_last_shot = now; + kif_last_shot = current_time(); kif_do_scan(p); } static void kif_force_scan(void) { - if (kif_proto && kif_last_shot + 2 < now) + if (kif_proto && ((kif_last_shot + 2 S) < current_time())) { kif_scan(kif_scan_timer); tm_start(kif_scan_timer, ((struct kif_config *) kif_proto->p.cf)->scan_time); @@ -112,61 +122,10 @@ kif_force_scan(void) void kif_request_scan(void) { - if (kif_proto && kif_scan_timer->expires > now) - tm_start(kif_scan_timer, 1); -} - -static inline int -prefer_addr(struct ifa *a, struct ifa *b) -{ - int sa = a->scope > SCOPE_LINK; - int sb = b->scope > SCOPE_LINK; - - if (sa < sb) - return 0; - else if (sa > sb) - return 1; - else - return ipa_compare(a->ip, b->ip) < 0; + if (kif_proto && (kif_scan_timer->expires > (current_time() + 1 S))) + tm_start(kif_scan_timer, 1 S); } -static inline struct ifa * -find_preferred_ifa(struct iface *i, const net_addr *n) -{ - struct ifa *a, *b = NULL; - - WALK_LIST(a, i->addrs) - { - if (!(a->flags & IA_SECONDARY) && - (!n || ipa_in_netX(a->ip, n)) && - (!b || prefer_addr(a, b))) - b = a; - } - - return b; -} - -struct ifa * -kif_choose_primary(struct iface *i) -{ - struct kif_config *cf = (struct kif_config *) (kif_proto->p.cf); - struct kif_primary_item *it; - struct ifa *a; - - WALK_LIST(it, cf->primary) - { - if (!it->pattern || patmatch(it->pattern, i->name)) - if (a = find_preferred_ifa(i, &it->addr)) - return a; - } - - if (a = kif_get_primary_ip(i)) - return a; - - return find_preferred_ifa(i, NULL); -} - - static struct proto * kif_init(struct proto_config *c) { @@ -185,10 +144,7 @@ kif_start(struct proto *P) kif_sys_start(p); /* Start periodic interface scanning */ - kif_scan_timer = tm_new(P->pool); - kif_scan_timer->hook = kif_scan; - kif_scan_timer->data = p; - kif_scan_timer->recurrent = KIF_CF->scan_time; + kif_scan_timer = tm_new_init(P->pool, kif_scan, p, KIF_CF->scan_time, 0); kif_scan(kif_scan_timer); tm_start(kif_scan_timer, KIF_CF->scan_time); @@ -224,15 +180,15 @@ kif_reconfigure(struct proto *p, struct proto_config *new) tm_start(kif_scan_timer, n->scan_time); } - if (!EMPTY_LIST(o->primary) || !EMPTY_LIST(n->primary)) + if (!EMPTY_LIST(o->iface_list) || !EMPTY_LIST(n->iface_list)) { /* This is hack, we have to update a configuration * to the new value just now, because it is used - * for recalculation of primary addresses. + * for recalculation of preferred addresses. */ p->cf = new; - ifa_recalc_all_primary_addresses(); + if_recalc_all_preferred_addresses(); } return 1; @@ -253,8 +209,8 @@ kif_init_config(int class) cf_error("Kernel device protocol already defined"); kif_cf = (struct kif_config *) proto_config_new(&proto_unix_iface, class); - kif_cf->scan_time = 60; - init_list(&kif_cf->primary); + kif_cf->scan_time = 60 S; + init_list(&kif_cf->iface_list); kif_sys_init_config(kif_cf); return (struct proto_config *) kif_cf; @@ -266,17 +222,17 @@ kif_copy_config(struct proto_config *dest, struct proto_config *src) struct kif_config *d = (struct kif_config *) dest; struct kif_config *s = (struct kif_config *) src; - /* Copy primary addr list */ - cfg_copy_list(&d->primary, &s->primary, sizeof(struct kif_primary_item)); + /* Copy interface config list */ + cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct kif_iface_config)); /* Fix sysdep parts */ kif_sys_copy_config(d, s); } - struct protocol proto_unix_iface = { .name = "Device", .template = "device%d", + .class = PROTOCOL_DEVICE, .proto_size = sizeof(struct kif_proto), .config_size = sizeof(struct kif_config), .preconfig = kif_preconfig, @@ -345,7 +301,7 @@ krt_learn_announce_update(struct krt_proto *p, rte *e) net *n = e->net; rta *aa = rta_clone(e->attrs); rte *ee = rte_get_temp(aa); - ee->pflags = 0; + ee->pflags = EA_ID_FLAG(EA_KRT_SOURCE) | EA_ID_FLAG(EA_KRT_METRIC); ee->u.krt = e->u.krt; rte_update(&p->p, n->n.addr, ee); } @@ -551,7 +507,13 @@ static void krt_learn_init(struct krt_proto *p) { if (KRT_CF->learn) - rt_setup(p->p.pool, &p->krt_table, "Inherited", NULL); + { + struct rtable_config *cf = mb_allocz(p->p.pool, sizeof(struct rtable_config)); + cf->name = "Inherited"; + cf->addr_type = p->p.net_type; + + rt_setup(p->p.pool, &p->krt_table, cf); + } } static void @@ -577,6 +539,12 @@ krt_dump_attrs(rte *e) * Routes */ +static inline int +krt_is_installed(struct krt_proto *p, net *n) +{ + return n->routes && bmap_test(&p->p.main_channel->export_map, n->routes->id); +} + static void krt_flush_routes(struct krt_proto *p) { @@ -585,26 +553,24 @@ krt_flush_routes(struct krt_proto *p) KRT_TRACE(p, D_EVENTS, "Flushing kernel routes"); FIB_WALK(&t->fib, net, n) { - rte *e = n->routes; - if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED)) + if (krt_is_installed(p, n)) { /* FIXME: this does not work if gw is changed in export filter */ - krt_replace_rte(p, e->net, NULL, e, NULL); - n->n.flags &= ~KRF_INSTALLED; + krt_replace_rte(p, n, NULL, n->routes); } } FIB_WALK_END; } static struct rte * -krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa) +krt_export_net(struct krt_proto *p, net *net, rte **rt_free) { struct channel *c = p->p.main_channel; - struct filter *filter = c->out_filter; + const struct filter *filter = c->out_filter; rte *rt; if (c->ra_mode == RA_MERGED) - return rt_export_merged(c, net, rt_free, tmpa, krt_filter_lp, 1); + return rt_export_merged(c, net, rt_free, krt_filter_lp, 1); rt = net->routes; *rt_free = NULL; @@ -615,15 +581,14 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa) if (filter == FILTER_REJECT) return NULL; - struct proto *src = rt->attrs->src->proto; - *tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(rt, krt_filter_lp) : NULL; + rte_make_tmp_attrs(&rt, krt_filter_lp, NULL); - /* We could run krt_import_control() here, but it is already handled by KRF_INSTALLED */ + /* We could run krt_preexport() here, but it is already handled by krt_is_installed() */ if (filter == FILTER_ACCEPT) goto accept; - if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR) > F_ACCEPT) + if (f_run(filter, &rt, krt_filter_lp, FF_SILENT) > F_ACCEPT) goto reject; @@ -660,19 +625,17 @@ krt_same_dest(rte *k, rte *e) void krt_got_route(struct krt_proto *p, rte *e) { - net *net = e->net; - int verdict; + rte *new = NULL, *rt_free = NULL; + net *n = e->net; #ifdef KRT_ALLOW_LEARN switch (e->u.krt.src) { case KRT_SRC_KERNEL: - verdict = KRF_IGNORE; - goto sentenced; + goto ignore; case KRT_SRC_REDIRECT: - verdict = KRF_DELETE; - goto sentenced; + goto delete; case KRT_SRC_ALIEN: if (KRT_CF->learn) @@ -687,59 +650,68 @@ krt_got_route(struct krt_proto *p, rte *e) #endif /* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */ - if (net->n.flags & KRF_VERDICT_MASK) - { - /* Route to this destination was already seen. Strange, but it happens... */ - krt_trace_in(p, e, "already seen"); - rte_free(e); - return; - } + /* We wait for the initial feed to have correct installed state */ if (!p->ready) - { - /* We wait for the initial feed to have correct KRF_INSTALLED flag */ - verdict = KRF_IGNORE; - goto sentenced; - } + goto ignore; - if (net->n.flags & KRF_INSTALLED) - { - rte *new, *rt_free; - ea_list *tmpa; + if (!krt_is_installed(p, n)) + goto delete; - new = krt_export_net(p, net, &rt_free, &tmpa); + new = krt_export_net(p, n, &rt_free); - /* TODO: There also may be changes in route eattrs, we ignore that for now. */ + /* Rejected by filters */ + if (!new) + goto delete; - if (!new) - verdict = KRF_DELETE; - else if ((net->n.flags & KRF_SYNC_ERROR) || !krt_same_dest(e, new)) - verdict = KRF_UPDATE; - else - verdict = KRF_SEEN; + /* Route to this destination was already seen. Strange, but it happens... */ + if (bmap_test(&p->seen_map, new->id)) + goto aseen; - if (rt_free) - rte_free(rt_free); + /* Mark route as seen */ + bmap_set(&p->seen_map, new->id); - lp_flush(krt_filter_lp); - } - else - verdict = KRF_DELETE; + /* TODO: There also may be changes in route eattrs, we ignore that for now. */ + if (!bmap_test(&p->sync_map, new->id) || !krt_same_dest(e, new)) + goto update; - sentenced: - krt_trace_in(p, e, ((char *[]) { "?", "seen", "will be updated", "will be removed", "ignored" }) [verdict]); - net->n.flags = (net->n.flags & ~KRF_VERDICT_MASK) | verdict; - if (verdict == KRF_UPDATE || verdict == KRF_DELETE) - { - /* Get a cached copy of attributes and temporarily link the route */ - rta *a = e->attrs; - a->source = RTS_DUMMY; - e->attrs = rta_lookup(a); - e->next = net->routes; - net->routes = e; - } - else - rte_free(e); + goto seen; + +seen: + krt_trace_in(p, e, "seen"); + goto done; + +aseen: + krt_trace_in(p, e, "already seen"); + goto done; + +ignore: + krt_trace_in(p, e, "ignored"); + goto done; + +update: + krt_trace_in(p, new, "updating"); + krt_replace_rte(p, n, new, e); + goto done; + +delete: + krt_trace_in(p, e, "deleting"); + krt_replace_rte(p, n, NULL, e); + goto done; + +done: + rte_free(e); + + if (rt_free) + rte_free(rt_free); + + lp_flush(krt_filter_lp); +} + +static void +krt_init_scan(struct krt_proto *p) +{ + bmap_reset(&p->seen_map, 1024); } static void @@ -749,65 +721,24 @@ krt_prune(struct krt_proto *p) KRT_TRACE(p, D_EVENTS, "Pruning table %s", t->name); FIB_WALK(&t->fib, net, n) + { + if (p->ready && krt_is_installed(p, n) && !bmap_test(&p->seen_map, n->routes->id)) { - int verdict = n->n.flags & KRF_VERDICT_MASK; - rte *new, *old, *rt_free = NULL; - ea_list *tmpa = NULL; - - if (verdict == KRF_UPDATE || verdict == KRF_DELETE) - { - /* Get a dummy route from krt_got_route() */ - old = n->routes; - n->routes = old->next; - } - else - old = NULL; - - if (verdict == KRF_CREATE || verdict == KRF_UPDATE) - { - /* We have to run export filter to get proper 'new' route */ - new = krt_export_net(p, n, &rt_free, &tmpa); - - if (!new) - verdict = (verdict == KRF_CREATE) ? KRF_IGNORE : KRF_DELETE; - else - tmpa = ea_append(tmpa, new->attrs->eattrs); - } - else - new = NULL; + rte *rt_free = NULL; + rte *new = krt_export_net(p, n, &rt_free); - switch (verdict) - { - case KRF_CREATE: - if (new && (n->n.flags & KRF_INSTALLED)) - { - krt_trace_in(p, new, "reinstalling"); - krt_replace_rte(p, n, new, NULL, tmpa); - } - break; - case KRF_SEEN: - case KRF_IGNORE: - /* Nothing happens */ - break; - case KRF_UPDATE: - krt_trace_in(p, new, "updating"); - krt_replace_rte(p, n, new, old, tmpa); - break; - case KRF_DELETE: - krt_trace_in(p, old, "deleting"); - krt_replace_rte(p, n, NULL, old, NULL); - break; - default: - bug("krt_prune: invalid route status"); - } + if (new) + { + krt_trace_in(p, new, "installing"); + krt_replace_rte(p, n, new, NULL); + } - if (old) - rte_free(old); if (rt_free) rte_free(rt_free); + lp_flush(krt_filter_lp); - n->n.flags &= ~KRF_VERDICT_MASK; } + } FIB_WALK_END; #ifdef KRT_ALLOW_LEARN @@ -827,13 +758,14 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new) switch (e->u.krt.src) { case KRT_SRC_BIRD: - ASSERT(0); /* Should be filtered by the back end */ + /* Should be filtered by the back end */ + bug("BIRD originated routes should not get here."); case KRT_SRC_REDIRECT: if (new) { krt_trace_in(p, e, "[redirect] deleting"); - krt_replace_rte(p, net, NULL, e, NULL); + krt_replace_rte(p, net, NULL, e); } /* If !new, it is probably echo of our deletion */ break; @@ -864,6 +796,7 @@ static void krt_scan(timer *t UNUSED) { struct krt_proto *p; + node *n; kif_force_scan(); @@ -871,25 +804,24 @@ krt_scan(timer *t UNUSED) p = SKIP_BACK(struct krt_proto, krt_node, HEAD(krt_proto_list)); KRT_TRACE(p, D_EVENTS, "Scanning routing table"); + WALK_LIST2(p, n, krt_proto_list, krt_node) + krt_init_scan(p); + krt_do_scan(NULL); - void *q; - WALK_LIST(q, krt_proto_list) - { - p = SKIP_BACK(struct krt_proto, krt_node, q); + WALK_LIST2(p, n, krt_proto_list, krt_node) krt_prune(p); - } } static void krt_scan_timer_start(struct krt_proto *p) { if (!krt_scan_count) - krt_scan_timer = tm_new_set(krt_pool, krt_scan, NULL, 0, KRT_CF->scan_time); + krt_scan_timer = tm_new_init(krt_pool, krt_scan, NULL, KRT_CF->scan_time, 0); krt_scan_count++; - tm_start(krt_scan_timer, 1); + tm_start(krt_scan_timer, 1 S); } static void @@ -920,6 +852,7 @@ krt_scan(timer *t) kif_force_scan(); KRT_TRACE(p, D_EVENTS, "Scanning routing table"); + krt_init_scan(p); krt_do_scan(p); krt_prune(p); } @@ -927,8 +860,8 @@ krt_scan(timer *t) static void krt_scan_timer_start(struct krt_proto *p) { - p->scan_timer = tm_new_set(p->p.pool, krt_scan, p, 0, KRT_CF->scan_time); - tm_start(p->scan_timer, 1); + p->scan_timer = tm_new_init(p->p.pool, krt_scan, p, KRT_CF->scan_time, 0); + tm_start(p->scan_timer, 1 S); } static void @@ -952,69 +885,30 @@ krt_scan_timer_kick(struct krt_proto *p) * Updates */ -static struct ea_list * -krt_make_tmp_attrs(rte *rt, struct linpool *pool) +static void +krt_make_tmp_attrs(struct rte *rt, struct linpool *pool) { - struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr)); - - l->next = NULL; - l->flags = EALF_SORTED; - l->count = 2; - - l->attrs[0].id = EA_KRT_SOURCE; - l->attrs[0].flags = 0; - l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP; - l->attrs[0].u.data = rt->u.krt.proto; - - l->attrs[1].id = EA_KRT_METRIC; - l->attrs[1].flags = 0; - l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP; - l->attrs[1].u.data = rt->u.krt.metric; - - return l; + rte_init_tmp_attrs(rt, pool, 2); + rte_make_tmp_attr(rt, EA_KRT_SOURCE, EAF_TYPE_INT, rt->u.krt.proto); + rte_make_tmp_attr(rt, EA_KRT_METRIC, EAF_TYPE_INT, rt->u.krt.metric); } static void -krt_store_tmp_attrs(rte *rt, struct ea_list *attrs) +krt_store_tmp_attrs(struct rte *rt, struct linpool *pool) { - /* EA_KRT_SOURCE is read-only */ - rt->u.krt.metric = ea_get_int(attrs, EA_KRT_METRIC, 0); + rte_init_tmp_attrs(rt, pool, 2); + rt->u.krt.proto = rte_store_tmp_attr(rt, EA_KRT_SOURCE); + rt->u.krt.metric = rte_store_tmp_attr(rt, EA_KRT_METRIC); } static int -krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) +krt_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED) { - struct krt_proto *p = (struct krt_proto *) P; + // struct krt_proto *p = (struct krt_proto *) P; rte *e = *new; if (e->attrs->src->proto == P) - { -#ifdef CONFIG_SINGLE_ROUTE - /* - * Implicit withdraw - when the imported kernel route becomes the best one, - * we know that the previous one exported to the kernel was already removed, - * but if we processed the update as usual, we would send withdraw to the - * kernel, which would remove the new imported route instead. - * - * We will remove KRT_INSTALLED flag, which stops such withdraw to be - * processed in krt_rt_notify() and krt_replace_rte(). - */ - if (e == e->net->routes) - e->net->n.flags &= ~KRF_INSTALLED; -#endif return -1; - } - - if (!KRT_CF->devroutes && (e->attrs->source != RTS_STATIC_DEVICE)) - { - struct nexthop *nh = &(e->attrs->nh); - for (; nh; nh = nh->next) - if (ipa_nonzero(nh->gw)) - break; - - if (!nh) /* Gone through all the nexthops and no explicit GW found */ - return -1; - } if (!krt_capable(e)) return -1; @@ -1024,20 +918,27 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li static void krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net, - rte *new, rte *old, struct ea_list *eattrs) + rte *new, rte *old) { struct krt_proto *p = (struct krt_proto *) P; if (config->shutdown) return; - if (!(net->n.flags & KRF_INSTALLED)) - old = NULL; - if (new) - net->n.flags |= KRF_INSTALLED; - else - net->n.flags &= ~KRF_INSTALLED; + +#ifdef CONFIG_SINGLE_ROUTE + /* + * Implicit withdraw - when the imported kernel route becomes the best one, + * we know that the previous one exported to the kernel was already removed, + * but if we processed the update as usual, we would send withdraw to the + * kernel, which would remove the new imported route instead. + */ + rte *best = net->routes; + if (!new && best && (best->attrs->src->proto == P)) + return; +#endif + if (p->initialized) /* Before first scan we don't touch the routes */ - krt_replace_rte(p, net, new, old, eattrs); + krt_replace_rte(p, net, new, old); } static void @@ -1115,11 +1016,18 @@ krt_postconfig(struct proto_config *CF) cf_error("All kernel syncers must use the same table scan interval"); #endif - struct rtable_config *tab = proto_cf_main_channel(CF)->table; + struct channel_config *cc = proto_cf_main_channel(CF); + struct rtable_config *tab = cc->table; if (tab->krt_attached) cf_error("Kernel syncer (%s) already attached to table %s", tab->krt_attached->name, tab->name); tab->krt_attached = CF; + if (cf->merge_paths) + { + cc->ra_mode = RA_MERGED; + cc->merge_limit = cf->merge_paths; + } + krt_sys_postconfig(cf); } @@ -1131,7 +1039,7 @@ krt_init(struct proto_config *CF) p->p.main_channel = proto_add_channel(&p->p, proto_cf_main_channel(CF)); - p->p.import_control = krt_import_control; + p->p.preexport = krt_preexport; p->p.rt_notify = krt_rt_notify; p->p.if_notify = krt_if_notify; p->p.reload_routes = krt_reload_routes; @@ -1151,11 +1059,17 @@ krt_start(struct proto *P) switch (p->p.net_type) { - case NET_IP4: p->af = AF_INET; break; - case NET_IP6: p->af = AF_INET6; break; - default: ASSERT(0); + case NET_IP4: p->af = AF_INET; break; + case NET_IP6: p->af = AF_INET6; break; + case NET_IP6_SADR: p->af = AF_INET6; break; +#ifdef AF_MPLS + case NET_MPLS: p->af = AF_MPLS; break; +#endif + default: log(L_ERR "KRT: Tried to start with strange net type: %d", p->p.net_type); return PS_START; break; } + bmap_init(&p->sync_map, p->p.pool, 1024); + bmap_init(&p->seen_map, p->p.pool, 1024); add_tail(&krt_proto_list, &p->krt_node); #ifdef KRT_ALLOW_LEARN @@ -1184,7 +1098,7 @@ krt_shutdown(struct proto *P) krt_scan_timer_stop(p); /* FIXME we should flush routes even when persist during reconfiguration */ - if (p->initialized && !KRT_CF->persist) + if (p->initialized && !KRT_CF->persist && (P->down_code != PDC_CMD_GR_DOWN)) krt_flush_routes(p); p->ready = 0; @@ -1195,6 +1109,7 @@ krt_shutdown(struct proto *P) krt_sys_shutdown(p); rem_node(&p->krt_node); + bmap_free(&p->sync_map); return PS_DOWN; } @@ -1212,7 +1127,7 @@ krt_reconfigure(struct proto *p, struct proto_config *CF) return 0; /* persist, graceful restart need not be the same */ - return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes; + return o->scan_time == n->scan_time && o->learn == n->learn; } struct proto_config * @@ -1224,7 +1139,7 @@ krt_init_config(int class) #endif krt_cf = (struct krt_config *) proto_config_new(&proto_unix_kernel, class); - krt_cf->scan_time = 60; + krt_cf->scan_time = 60 S; krt_sys_init_config(krt_cf); return (struct proto_config *) krt_cf; @@ -1259,12 +1174,24 @@ krt_get_attr(eattr *a, byte *buf, int buflen) } +#ifdef CONFIG_IP6_SADR_KERNEL +#define MAYBE_IP6_SADR NB_IP6_SADR +#else +#define MAYBE_IP6_SADR 0 +#endif + +#ifdef HAVE_MPLS_KERNEL +#define MAYBE_MPLS NB_MPLS +#else +#define MAYBE_MPLS 0 +#endif + struct protocol proto_unix_kernel = { .name = "Kernel", .template = "kernel%d", - .attr_class = EAP_KRT, + .class = PROTOCOL_KERNEL, .preference = DEF_PREF_INHERITED, - .channel_mask = NB_IP, + .channel_mask = NB_IP | MAYBE_IP6_SADR | MAYBE_MPLS, .proto_size = sizeof(struct krt_proto), .config_size = sizeof(struct krt_config), .preconfig = krt_preconfig,