From 432dfe3b9b97062be243609d69e0f49bdb0bcaf6 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Fri, 22 Jul 2022 15:48:20 +0200 Subject: Fixed a rarely used part of Babel: comparing two routes in table by their metric --- proto/babel/babel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 7ea1aba8..ecfd2763 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -2338,8 +2338,8 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net, static int babel_rte_better(struct rte *new, struct rte *old) { - uint new_metric = ea_find(new->attrs->eattrs, EA_BABEL_SEQNO)->u.data; - uint old_metric = ea_find(old->attrs->eattrs, EA_BABEL_SEQNO)->u.data; + uint new_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY); + uint old_metric = ea_get_int(old->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY); return new_metric < old_metric; } -- cgit v1.2.3 From 73abd91ac661f28d9341c7fbb80d2f7a71db186d Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Fri, 22 Jul 2022 16:09:37 +0200 Subject: rip_rte_better() uses the IGP_METRIC_UNKNOWN instead of protocol-specific infinity --- proto/rip/rip.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 6ca7a6b5..b0b5b8a1 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -1101,24 +1101,18 @@ rip_reload_routes(struct channel *C) rip_kick_timer(p); } -static int -rip_rte_better(struct rte *new, struct rte *old) -{ - ASSERT_DIE(new->src == old->src); - struct rip_proto *p = (struct rip_proto *) new->src->proto; - - u32 new_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, p->infinity); - u32 old_metric = ea_get_int(old->attrs->eattrs, EA_RIP_METRIC, p->infinity); - - return new_metric < old_metric; -} - static u32 rip_rte_igp_metric(struct rte *rt) { return ea_get_int(rt->attrs->eattrs, EA_RIP_METRIC, IGP_METRIC_UNKNOWN); } +static int +rip_rte_better(struct rte *new, struct rte *old) +{ + return rip_rte_igp_metric(new) < rip_rte_igp_metric(old); +} + static void rip_postconfig(struct proto_config *CF) { -- cgit v1.2.3 From 34912b029b161cbbed44057dfa913669ccb087eb Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Tue, 30 Aug 2022 18:05:00 +0200 Subject: Tables: Requesting prune only after export cleanup We can't free the network structures before the export has been cleaned up, therefore it makes more sense to request prune only after export cleanup. This change also reduces prune calls on table shutdown. --- nest/rt-table.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/nest/rt-table.c b/nest/rt-table.c index 3ade4237..8e1e03fb 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -1748,10 +1748,6 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr rte_announce(table, net, new_stored, old_stored, net->routes, old_best_stored); - if (!net->routes && - (table->gc_counter++ >= table->config->gc_threshold)) - rt_kick_prune_timer(table); - #if 0 /* Enable and reimplement these callbacks if anybody wants to use them */ if (old_ok && p->rte_remove) @@ -2852,6 +2848,7 @@ rt_export_cleanup(rtable *tab) u64 min_seq = ~((u64) 0); struct rt_pending_export *last_export_to_free = NULL; struct rt_pending_export *first = tab->exporter.first; + int want_prune = 0; struct rt_export_hook *eh; node *n; @@ -2928,6 +2925,8 @@ rt_export_cleanup(rtable *tab) /* First is now the next one */ net->first = atomic_load_explicit(&first->next, memory_order_relaxed); + want_prune += !net->routes && !net->first; + /* For now, the old route may be finally freed */ if (first->old) { @@ -3003,6 +3002,9 @@ done:; rt_unlock_table(tab); } + if ((tab->gc_counter += want_prune) >= tab->config->gc_threshold) + rt_kick_prune_timer(tab); + if (tab->export_used) ev_schedule(tab->rt_event); -- cgit v1.2.3 From 397fec4741b40f61d06a467b4110aad7e996485c Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Thu, 1 Sep 2022 14:21:56 +0200 Subject: Default tables are not created unless actually used. This allows for setting default table values at the beginning of config file before "master4" and "master6" tables are initialized. --- conf/conf.h | 2 +- nest/config.Y | 7 ++++++- nest/proto.c | 2 +- nest/rt-show.c | 4 ++-- nest/rt-table.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- nest/rt.h | 2 ++ proto/bgp/bgp.c | 4 ++-- proto/static/static.c | 4 ++-- 8 files changed, 56 insertions(+), 19 deletions(-) diff --git a/conf/conf.h b/conf/conf.h index 50e01bf5..ffefa519 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -27,7 +27,7 @@ struct config { int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */ const char *syslog_name; /* Name used for syslog (NULL -> no syslog) */ - struct rtable_config *def_tables[NET_MAX]; /* Default routing tables for each network */ + struct symbol *def_tables[NET_MAX]; /* Default routing tables for each network */ struct iface_patt *router_id_from; /* Configured list of router ID iface patterns */ u32 router_id; /* Our Router ID */ diff --git a/nest/config.Y b/nest/config.Y index 91147a29..4bf0fefe 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -361,7 +361,11 @@ channel_end: proto_channel: channel_start channel_opt_list channel_end; -rtable: CF_SYM_KNOWN { cf_assert_symbol($1, SYM_TABLE); $$ = $1->table; } ; +rtable: CF_SYM_KNOWN { + cf_assert_symbol($1, SYM_TABLE); + if (!$1->table) rt_new_default_table($1); + $$ = $1->table; +} ; imexport: FILTER filter { $$ = $2; } @@ -683,6 +687,7 @@ r_args: } | r_args TABLE symbol_known { cf_assert_symbol($3, SYM_TABLE); + if (!$3->table) cf_error("Table %s not configured", $3->name); $$ = $1; rt_show_add_table($$, $3->table->table); $$->tables_defined_by = RSD_TDB_DIRECT; diff --git a/nest/proto.c b/nest/proto.c index 853b1cf9..ef3e3f4d 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -864,7 +864,7 @@ channel_config_new(const struct channel_class *cc, const char *name, uint net_ty if (proto->net_type && (net_type != proto->net_type)) cf_error("Different channel type"); - tab = new_config->def_tables[net_type]; + tab = rt_get_default_table(new_config, net_type); } if (!cc) diff --git a/nest/rt-show.c b/nest/rt-show.c index 17400029..5d7723cf 100644 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@ -400,8 +400,8 @@ rt_show_get_default_tables(struct rt_show_data *d) } for (int i=1; idef_tables[i] && config->def_tables[i]->table) - rt_show_add_table(d, config->def_tables[i]->table); + if (config->def_tables[i] && config->def_tables[i]->table && config->def_tables[i]->table->table) + rt_show_add_table(d, config->def_tables[i]->table->table); } static inline void diff --git a/nest/rt-table.c b/nest/rt-table.c index 8e1e03fb..f0552965 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -3094,8 +3094,8 @@ rt_preconfig(struct config *c) { init_list(&c->tables); - rt_new_table(cf_get_symbol("master4"), NET_IP4); - rt_new_table(cf_get_symbol("master6"), NET_IP6); + c->def_tables[NET_IP4] = cf_define_symbol(cf_get_symbol("master4"), SYM_TABLE, table, NULL); + c->def_tables[NET_IP6] = cf_define_symbol(cf_get_symbol("master6"), SYM_TABLE, table, NULL); } void @@ -3110,6 +3110,13 @@ rt_postconfig(struct config *c) WALK_LIST(rc, c->tables) if (rc->gc_period == (uint) -1) rc->gc_period = (uint) def_gc_period; + + for (uint net_type = 0; net_type < NET_MAX; net_type++) + if (c->def_tables[net_type] && !c->def_tables[net_type]->table) + { + c->def_tables[net_type]->class = SYM_VOID; + c->def_tables[net_type] = NULL; + } } @@ -3584,19 +3591,42 @@ rt_next_hop_update(rtable *tab) ev_schedule(tab->rt_event); } +void +rt_new_default_table(struct symbol *s) +{ + for (uint addr_type = 0; addr_type < NET_MAX; addr_type++) + if (s == new_config->def_tables[addr_type]) + { + s->table = rt_new_table(s, addr_type); + return; + } + + bug("Requested an unknown new default table: %s", s->name); +} + +struct rtable_config * +rt_get_default_table(struct config *cf, uint addr_type) +{ + struct symbol *ts = cf->def_tables[addr_type]; + if (!ts) + return NULL; + + if (!ts->table) + rt_new_default_table(ts); + + return ts->table; +} struct rtable_config * rt_new_table(struct symbol *s, uint addr_type) { - /* Hack that allows to 'redefine' the master table */ - if ((s->class == SYM_TABLE) && - (s->table == new_config->def_tables[addr_type]) && - ((addr_type == NET_IP4) || (addr_type == NET_IP6))) - return s->table; - struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config)); - cf_define_symbol(s, SYM_TABLE, table, c); + if (s == new_config->def_tables[addr_type]) + s->table = c; + else + cf_define_symbol(s, SYM_TABLE, table, c); + c->name = s->name; c->addr_type = addr_type; c->gc_threshold = 1000; @@ -3610,7 +3640,7 @@ rt_new_table(struct symbol *s, uint addr_type) /* First table of each type is kept as default */ if (! new_config->def_tables[addr_type]) - new_config->def_tables[addr_type] = c; + new_config->def_tables[addr_type] = s; return c; } diff --git a/nest/rt.h b/nest/rt.h index 1a6b7a93..f5cf9457 100644 --- a/nest/rt.h +++ b/nest/rt.h @@ -481,6 +481,8 @@ void rt_reload_channel_abort(struct channel *c); void rt_refeed_channel(struct channel *c); void rt_prune_sync(rtable *t, int all); struct rtable_config *rt_new_table(struct symbol *s, uint addr_type); +void rt_new_default_table(struct symbol *s); +struct rtable_config *rt_get_default_table(struct config *cf, uint addr_type); static inline int rt_is_ip(rtable *tab) { return (tab->addr_type == NET_IP4) || (tab->addr_type == NET_IP6); } diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 68c788ea..97b18fcf 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -1934,7 +1934,7 @@ bgp_default_igp_table(struct bgp_config *cf, struct bgp_channel_config *cc, u32 return cc2->c.table; /* Last, try default table of given type */ - if (tab = cf->c.global->def_tables[type]) + if (tab = rt_get_default_table(cf->c.global, type)) return tab; cf_error("Undefined IGP table"); @@ -1953,7 +1953,7 @@ bgp_default_base_table(struct bgp_config *cf, struct bgp_channel_config *cc) return cc2->c.table; /* Last, try default table of given type */ - struct rtable_config *tab = cf->c.global->def_tables[type]; + struct rtable_config *tab = rt_get_default_table(cf->c.global, type); if (tab) return tab; diff --git a/proto/static/static.c b/proto/static/static.c index 65f3eccc..cb764a1c 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -436,11 +436,11 @@ static_postconfig(struct proto_config *CF) if (!cf->igp_table_ip4) cf->igp_table_ip4 = (cc->table->addr_type == NET_IP4) ? - cc->table : cf->c.global->def_tables[NET_IP4]; + cc->table : rt_get_default_table(cf->c.global, NET_IP4); if (!cf->igp_table_ip6) cf->igp_table_ip6 = (cc->table->addr_type == NET_IP6) ? - cc->table : cf->c.global->def_tables[NET_IP6]; + cc->table : rt_get_default_table(cf->c.global, NET_IP6); WALK_LIST(r, cf->routes) if (r->net && (r->net->type != CF->net_type)) -- cgit v1.2.3 From 83ceb91b50ae75ee5509faa74e2f6d4bdcf78505 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Tue, 30 Aug 2022 19:40:58 +0200 Subject: Table debug is now a per-table setting and has categories. --- doc/bird.sgml | 15 +++++++++++++++ nest/config.Y | 3 ++- nest/rt-table.c | 32 ++++++++++++++++---------------- nest/rt.h | 1 + 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/doc/bird.sgml b/doc/bird.sgml index c29353fc..b12ac544 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -505,6 +505,11 @@ include "tablename.conf";; See in the channel section. Default: off. +