]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Default tables are not created unless actually used.
authorMaria Matejka <mq@ucw.cz>
Thu, 1 Sep 2022 12:21:56 +0000 (14:21 +0200)
committerMaria Matejka <mq@ucw.cz>
Thu, 1 Sep 2022 15:44:46 +0000 (17:44 +0200)
This allows for setting default table values at the beginning of config
file before "master4" and "master6" tables are initialized.

conf/conf.h
nest/config.Y
nest/proto.c
nest/rt-show.c
nest/rt-table.c
nest/rt.h
proto/bgp/bgp.c
proto/static/static.c

index 50e01bf594c8e2336439594d218b6b46e56ea9eb..ffefa519f3e22545ea141898cbbcf755b200c874 100644 (file)
@@ -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 */
index 91147a29dbcbe3329624e609d64c5f09d46e6034..4bf0fefebfde944a523774005cd25a977c9a55a3 100644 (file)
@@ -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;
index 853b1cf9f1b2ca090f4c0455b8f1cbe78aa1c030..ef3e3f4db4dc00fa6cd92d96e53b8b07414372a6 100644 (file)
@@ -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)
index 174000292b4c98764f79a2296bef90328e00de59..5d7723cf4ec2a46d75870854a500ca18c9cdb5cf 100644 (file)
@@ -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
index 8e1e03fb59146fa7dafcfe112f84e23c5cf1a171..f0552965227f9326934b325feddab59dec51cbf0 100644 (file)
@@ -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;
 }
index 1a6b7a9377b6525b58ae56f248b107be6f27ab51..f5cf9457f4f6f47d35691377c9bf138a5260f53b 100644 (file)
--- 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); }
index 68c788eaaab7c2c2bcbb53f3e6dfb6b372ba0026..97b18fcf2ac1378d7f61881f14e4989b5b853d56 100644 (file)
@@ -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;
 
index 65f3eccc81ac7f3d81c63497323e56bfd4784638..cb764a1c833d9cc0e6293c6a4352b5156c259ef4 100644 (file)
@@ -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))