summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-09-01 14:21:56 +0200
committerMaria Matejka <mq@ucw.cz>2022-09-01 17:44:46 +0200
commit397fec4741b40f61d06a467b4110aad7e996485c (patch)
tree4bd33355175e42df9e3b7dee5517c19d4d6e337d
parent34912b029b161cbbed44057dfa913669ccb087eb (diff)
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.
-rw-r--r--conf/conf.h2
-rw-r--r--nest/config.Y7
-rw-r--r--nest/proto.c2
-rw-r--r--nest/rt-show.c4
-rw-r--r--nest/rt-table.c50
-rw-r--r--nest/rt.h2
-rw-r--r--proto/bgp/bgp.c4
-rw-r--r--proto/static/static.c4
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; i<NET_MAX; i++)
- if (config->def_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))