Hi, I did some more experimenting with making aliases from cli. As I understand, cli has its own "config" structure and memory pool, where its symbols are allocated. So I need to copy it to the current config, but I did not find suitable functions for doing that. And I make a copy for cf_new_symbol. Not sure though, that I did everything right. It would be great if someone looked at it and gave me some advice.
I split the modifications into two parts: creating aliases in the config and then creating it in the cli. I think this idea with aliases is not that ugly. The solution is quite minimal and does not affect anybody who do not touch aliases. So if somebody wants to be able to do renaming in their setup - feel free to use/test the patches. And maybe in such form it would be meaningful to include it into the upstream version, as it is not that ugly anymore (at least from my point of view). :) I also not sure wether I need to copy the "scope" field from the reference symbol or keep it from aliased. I originally kept if from alias symbol and it worked too, at least with "config"-aliases. Now I'm copying it from the reference symbol and it also works. On Tue, Jan 24, 2023 at 9:42 AM Alexander Zubkov <gr...@qrator.net> wrote: > > > On Tue, Jan 24, 2023 at 8:12 AM Alexander Zubkov <gr...@qrator.net> wrote: > >> >> >> On Tue, Jan 24, 2023 at 7:59 AM Ondrej Zajicek <santi...@crfreenet.org> >> wrote: >> >>> On Tue, Jan 24, 2023 at 07:44:47AM +0100, Maria Matejka wrote: >>> > >Hello >>> > > >>> > >I thing that the most elegant way how to handle renaming of objects >>> > >during reconfiguration is to allow multiple names / aliases. There >>> could >>> > >be be more symbols pointing to given object (but the object points >>> back >>> > >to its primary name). >>> > > >>> > >Reconfiguration to rename objects could be done in two steps - in the >>> > >first step, the user would add alias for the new name. In the second >>> step, >>> > >the old name would be removed. >>> > >>> > I think this keeps the problem with protocol restart when the renaming >>> > of "base name" is done. >>> >>> The primary problem of renaming is matching existing objects with >>> definitions from the new config. If that can be done (by finding >>> existing objects through aliases), it is just a reconfiguration of >>> object property, like any other. I.e. implementation problem instead >>> of conceptual problem. >>> >>> >> Adding aliases is an interesting option. But for example now in >> protos_commit() it uses WALK_LIST(oc, old->protos), so it walks around old >> protos first and then searches for a new ones. So it is not enough to add >> another name pointing to the protocol, you need to search for protocol name >> and also its aliases in the new protocols, or "invert" walking the lists in >> all such places. >> Probably might work if it is done in several steps: >> 1) name1 >> 2) name1 + alias name2 >> 3) name2 + alias name1 >> 4) name2 >> > > I've checked such modifications (in attached patch), and it seems to work > too. The transition with those several steps goes without protocol > interruption for changing the names of protocols and tables. The patch adds > the config statement: > link <alias> to <symbol> > It makes "alias" to reference the same entity as "symbol". > > In this case the transition process is longer, but less intervention in > the code is required and it may be less ugly. As a plus, the transition can > be done without additional CLI commands, only with a series of configs. On > the other hand you can not do aliases CLI-only for the transition, you need > them to be present in the new config while it is loading. You can do it in > CLI for step 1->2, but for 2->3 it will not work. Renaming, though, needed > intervention in the config too, to extend the symbol buffers. > > I also tried to also do a CLI command for aliasing. But it does not work > in this variant, the new symbol does not appear in the table. Probably it > is cleaned up after the command finishes. It is strange, because when I > tried the same for "rename" version like that: > CF_CLI(RENAME, CF_SYM_KNOWN CF_SYM_UNDEFINED, <sym> <new>, [[Rename > symbol]]) > Then I just copied the name from the undefined symbol to the known symbol. > And after that I saw multiple occurence of the name in "show symbols". So I > thought the undefined one was left in the table. But now when I run "link" > in the cli, I do not see the new symbol in the table afterwards. >
commit 8fe58867e3444bfb3aa8fafb3a0b5669cd8c49f9 Author: Alexander Zubkov <gr...@qrator.net> Date: Wed Jan 25 19:28:50 2023 +0100 Configure: introduce alias symbols Allow to create symbols that act as aliases to other symbols. Alias symbol allows to reference the same object and to find it also by another name. Such symbols can be used for seamless renaming of protocols without interruption by loading a series of configs: 1) original config with original name "A" only 2) config with original name "A" and new name "B" as alias 3) config with new name "B" and original name "A" as alias 4) final config with new name "B" only New syntax was added to the config to add aliases: link <alias> to <symbol>; diff --git a/conf/cf-lex.l b/conf/cf-lex.l index ceedee8a..ec5eceec 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -667,6 +667,25 @@ cf_localize_symbol(struct symbol *sym) return cf_new_symbol(sym->name); } +/** + * cf_alias_symbol - make an "alias" symbol + * @sym: the reference symbol + * @alias: the symbol to be linked to the reference + * + * This function defines the meaning of the symbol from the reference symbol. + * The protocol/table/... keeps its original name, but can be also accessed + * accessed with the new alias symbol + */ +void +cf_alias_symbol(struct symbol *sym, struct symbol *alias) +{ + struct symbol tmp = *sym; + tmp.n = alias->n; + tmp.next = alias->next; + //tmp.scope = alias->scope; + *alias = tmp; +} + struct symbol * cf_default_name(char *template, int *counter) { diff --git a/conf/conf.h b/conf/conf.h index b409750e..d7796c5c 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -192,6 +192,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); +void cf_alias_symbol(struct symbol *sym, struct symbol *alias); 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/config.Y b/nest/config.Y index b2aa0906..10cb15cb 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -154,6 +154,15 @@ CF_ENUM_PX(T_ENUM_AF, AF_, AFI_, IPV4, IPV6) CF_GRAMMAR +/* Makeing alias of a symbol */ + +conf: link_to ; + +link_to: LINK CF_SYM_UNDEFINED TO CF_SYM_KNOWN ';' +{ + cf_alias_symbol($4, $2); +} + /* Setting of router ID */ conf: rtrid ;
commit 09002a15b090908284cc142939ea58573a8a2b76 Author: Alexander Zubkov <gr...@qrator.net> Date: Wed Jan 25 19:57:38 2023 +0100 CLI: create alias symbols from CLI Make it possible to create alias symbols from CLI too using the same syntax as in the config. diff --git a/conf/cf-lex.l b/conf/cf-lex.l index ec5eceec..8cb6b5ea 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -601,6 +601,34 @@ cf_new_symbol(const byte *c) return s; } +/** + * cf_new_runtime_symbol - create a new symbol during runtime + * + * This function is used to create a new symbol after configuration is commited. + */ +struct symbol * +cf_new_runtime_symbol(const byte *c) +{ + struct symbol *s; + + uint l = strlen(c); + if (l > SYM_MAX_LEN) + cf_error("Symbol too long"); + + s = lp_allocz(config->mem, sizeof(struct symbol) + l + 1); + *s = (struct symbol) { .scope = config->root_scope, .class = SYM_VOID, }; + strcpy(s->name, c); + + if (!config->sym_hash.data) + HASH_INIT(config->sym_hash, config->pool, SYM_ORDER); + + HASH_INSERT2(config->sym_hash, SYM, config->pool, s); + + add_tail(&(config->symbols), &(s->n)); + + return s; +} + /** * cf_find_symbol - find a symbol by name * @cfg: specificed config diff --git a/conf/conf.h b/conf/conf.h index d7796c5c..3a54e1eb 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -193,6 +193,7 @@ 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); void cf_alias_symbol(struct symbol *sym, struct symbol *alias); +struct symbol *cf_new_runtime_symbol(const byte *c); 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..6fa02797 100644 --- a/nest/cmds.c +++ b/nest/cmds.c @@ -142,3 +142,12 @@ cmd_eval(const struct f_line *expr) cli_msg(23, "%s", buf.start); } + +void +cmd_alias_symbol(struct symbol *sym, struct symbol *alias) +{ + /* uniqueness is implicit by CF_SYM_UNDEFINED in CLI syntax */ + struct symbol *newalias = cf_new_runtime_symbol(alias->name); + cf_alias_symbol(sym, newalias); + cli_msg(10, "ok"); +} diff --git a/nest/cmds.h b/nest/cmds.h index 194a9d7f..426501a1 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_alias_symbol(struct symbol *sym, struct symbol *alias); diff --git a/nest/config.Y b/nest/config.Y index 10cb15cb..30fdbc22 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -934,6 +934,9 @@ proto_patt2: dynamic_attr: IGP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_GEN_IGP_METRIC); } ; +CF_CLI_HELP(LINK, ..., [[Add alias symbol]]) +CF_CLI(LINK, CF_SYM_UNDEFINED TO CF_SYM_KNOWN, <alias> to <symbol>, [[Add alias symbol]]) +{ cmd_alias_symbol($4, $2); }; CF_CODE