Hi all, Some weird idea. I'm not sure it needs to be in the mainstream version, but somebody might find it helpful.
For example I may want to refactor the naming scheme for protocols/tables in my bird config. But when I apply the new config with the new names, such renamed protocols will be recreated or restarted, which may be undesired. So if I could rename protocols/tables in advance and then load the new config, I can hope than no changes would be found and the there would be no interruptions. The attached patch solves the problem, by introducing such changes: To rename some symbol one can use cli command: rename <old_symbol> "<new_name>" The new name is in the form of the string, because symbol form requires symbol to be created. I tried to use CF_SYM_UNDEFINED for the second parameter. It works somehow, but leaves duplicate symbols in the table. If there is some way to clean them after it, it could be more visually pleasing option. The other problem is that a symbol has the fixed buffer for the name bound by its length. And one would not be able to rename it to a new name that is longer. But to overcome that, I add a field to a symbol to remember the length of the allocated buffer and allow the buffer to be bigger. This can be controlled by config option: symbols min <len> Which sets minum length that will fit the buffer. But as symbols are allocated while reading the config, you need to place this configuration option to the top of your config, i.e. before all the symbols you want to rename. So you can load the old config with the old names and this option added, it will allocate bigger buffers for the symbols. Then you can rename your symbols to the new ones. And finally load the new config with the new names. Of course you need the bird version with this patch applied in advace to do the trick. :)
diff --git a/conf/cf-lex.l b/conf/cf-lex.l index ceedee8a..92d81989 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -584,11 +584,13 @@ cf_new_symbol(const byte *c) uint l = strlen(c); if (l > SYM_MAX_LEN) cf_error("Symbol too long"); + if (l < new_config->symbols_min) + l = new_config->symbols_min; cf_swap_soft_scope(); s = cfg_allocz(sizeof(struct symbol) + l + 1); - *s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, }; + *s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, .len = l, }; strcpy(s->name, c); if (!new_config->sym_hash.data) @@ -667,6 +669,23 @@ cf_localize_symbol(struct symbol *sym) return cf_new_symbol(sym->name); } +int +cf_rename_symbol(struct symbol *sym, const char *name) +{ + if (sym->len < strlen(name)) + return 1; + + if (cf_find_symbol(config, name)) + return 1; + + strcpy(sym->name, name); + + HASH_REMOVE2(config->sym_hash, SYM, config->pool, sym); + HASH_INSERT2(config->sym_hash, SYM, config->pool, sym); + + return 0; +} + struct symbol * cf_default_name(char *template, int *counter) { diff --git a/conf/conf.h b/conf/conf.h index b409750e..581ced71 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -26,6 +26,8 @@ struct config { list tests; /* Configured unit tests (f_bt_test_suite) */ list symbols; /* Configured symbols in config order */ + int symbols_min; /* Mimimal name length to fit symbol buffer */ + 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 */ @@ -116,6 +118,7 @@ struct symbol { struct sym_scope *scope; int class; /* SYM_* */ uint flags; /* SYM_FLAG_* */ + int len; /* Name buffer length */ union { struct proto_config *proto; /* For SYM_PROTO and SYM_TEMPLATE */ @@ -192,6 +195,7 @@ struct symbol *cf_find_symbol(const struct config *cfg, const byte *c); struct symbol *cf_get_symbol(const byte *c); struct symbol *cf_default_name(char *template, int *counter); struct symbol *cf_localize_symbol(struct symbol *sym); +int cf_rename_symbol(struct symbol *sym, const char *name); static inline int cf_symbol_is_local(struct symbol *sym) { return (sym->scope == conf_this_scope) && !conf_this_scope->soft_scopes; } diff --git a/nest/cmds.c b/nest/cmds.c index bcc8d6c2..4dea7ebe 100644 --- a/nest/cmds.c +++ b/nest/cmds.c @@ -142,3 +142,24 @@ cmd_eval(const struct f_line *expr) cli_msg(23, "%s", buf.start); } + +void +cmd_rename(struct symbol *sym, const char *name) +{ + if (!sym->class) + { + cli_msg(8010, "symbol is void"); + return; + } + + if (cf_find_symbol(config, name)) + { + cli_msg(8010, "symbol name is taken"); + return; + } + + if (cf_rename_symbol(sym, name)) + cli_msg(8010, "runtime error"); + else + cli_msg(10, "ok"); +} diff --git a/nest/cmds.h b/nest/cmds.h index 194a9d7f..f4440a16 100644 --- a/nest/cmds.h +++ b/nest/cmds.h @@ -19,3 +19,5 @@ void cmd_show_memory(void); struct f_line; void cmd_eval(const struct f_line *expr); + +void cmd_rename(struct symbol *sym, const char *name); diff --git a/nest/config.Y b/nest/config.Y index b2aa0906..832cd5c9 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -122,7 +122,7 @@ CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, IN, COMMANDS, PREEXPORT, NOEXPORT, E CF_KEYWORDS(BGP, PASSWORDS, DESCRIPTION) CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP) CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US) -CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS) +CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS, RENAME) CF_KEYWORDS(MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE) CF_KEYWORDS(CHECK, LINK) CF_KEYWORDS(SORTED, TRIE, MIN, MAX, SETTLE, TIME, GC, THRESHOLD, PERIOD) @@ -154,6 +154,15 @@ CF_ENUM_PX(T_ENUM_AF, AF_, AFI_, IPV4, IPV6) CF_GRAMMAR +conf: symbols_min ; + +symbols_min: SYMBOLS MIN expr ';' +{ + if (($3 < 0) || ($3 > SYM_MAX_LEN)) + cf_error("Invalid symbols min length"); + new_config->symbols_min = $3; +}; + /* Setting of router ID */ conf: rtrid ; @@ -925,6 +934,9 @@ proto_patt2: dynamic_attr: IGP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_GEN_IGP_METRIC); } ; +CF_CLI(RENAME, CF_SYM_KNOWN TEXT, <sym> <name>, [[Rename symbol]]) +{ cmd_rename($2, $3); } ; + CF_CODE