diff options
Diffstat (limited to 'lib')
57 files changed, 766 insertions, 531 deletions
diff --git a/lib/agentx.c b/lib/agentx.c index 6d4e68d651..5f865ca2b8 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -63,6 +63,8 @@ static int agentx_read(struct thread *t) int flags, new_flags = 0; int nonblock = false; struct listnode *ln = THREAD_ARG(t); + struct thread **thr = listgetdata(ln); + XFREE(MTYPE_TMP, thr); list_delete_node(events, ln); /* fix for non blocking socket */ @@ -109,7 +111,7 @@ static void agentx_events_update(void) struct timeval timeout = {.tv_sec = 0, .tv_usec = 0}; fd_set fds; struct listnode *ln; - struct thread *thr; + struct thread **thr; int fd, thr_fd; thread_cancel(&timeout_thr); @@ -125,7 +127,7 @@ static void agentx_events_update(void) ln = listhead(events); thr = ln ? listgetdata(ln) : NULL; - thr_fd = thr ? THREAD_FD(thr) : -1; + thr_fd = thr ? THREAD_FD(*thr) : -1; /* "two-pointer" / two-list simultaneous iteration * ln/thr/thr_fd point to the next existing event listener to hit while @@ -135,20 +137,21 @@ static void agentx_events_update(void) if (thr_fd == fd) { struct listnode *nextln = listnextnode(ln); if (!FD_ISSET(fd, &fds)) { - thread_cancel(&thr); + thread_cancel(thr); + XFREE(MTYPE_TMP, thr); list_delete_node(events, ln); } ln = nextln; thr = ln ? listgetdata(ln) : NULL; - thr_fd = thr ? THREAD_FD(thr) : -1; + thr_fd = thr ? THREAD_FD(*thr) : -1; } /* need listener, but haven't hit one where it would be */ else if (FD_ISSET(fd, &fds)) { struct listnode *newln; - thr = NULL; - thread_add_read(agentx_tm, agentx_read, NULL, fd, &thr); + thr = XCALLOC(MTYPE_TMP, sizeof(struct thread *)); + thread_add_read(agentx_tm, agentx_read, NULL, fd, thr); newln = listnode_add_before(events, ln, thr); - thr->arg = newln; + (*thr)->arg = newln; } } @@ -157,7 +160,8 @@ static void agentx_events_update(void) while (ln) { struct listnode *nextln = listnextnode(ln); thr = listgetdata(ln); - thread_cancel(&thr); + thread_cancel(thr); + XFREE(MTYPE_TMP, thr); list_delete_node(events, ln); ln = nextln; } diff --git a/lib/atomlist.c b/lib/atomlist.c index 8169ba9eb4..3668b083d0 100644 --- a/lib/atomlist.c +++ b/lib/atomlist.c @@ -121,7 +121,7 @@ static void atomlist_del_core(struct atomlist_head *h, memory_order_consume); /* track the beginning of a chain of deleted items - * this is neccessary to make this lock-free; we can + * this is necessary to make this lock-free; we can * complete deletions started by other threads. */ if (!atomptr_l(prevval)) { diff --git a/lib/atomlist.h b/lib/atomlist.h index c795128a34..b0c4da4baa 100644 --- a/lib/atomlist.h +++ b/lib/atomlist.h @@ -100,7 +100,7 @@ static inline bool atomptr_u(atomptr_t val) /* single-linked list, unsorted/arbitrary. * can be used as queue with add_tail / pop * - * all operations are lock-free, but not neccessarily wait-free. this means + * all operations are lock-free, but not necessarily wait-free. this means * that there is no state where the system as a whole stops making process, * but it *is* possible that a *particular* thread is delayed by some time. * @@ -203,7 +203,7 @@ static void bfd_last_update(time_t last_update, char *buf, size_t len) struct tm tm; struct timeval tv; - /* If no BFD satatus update has ever been received, print `never'. */ + /* If no BFD status update has ever been received, print `never'. */ if (last_update == 0) { snprintf(buf, len, "never"); return; diff --git a/lib/buffer.c b/lib/buffer.c index 41b1adc9fc..e976fecc1f 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -59,7 +59,7 @@ struct buffer_data { /* It should always be true that: 0 <= sp <= cp <= size */ /* Default buffer size (used if none specified). It is rounded up to the - next page boundery. */ + next page boundary. */ #define BUFFER_SIZE_DEFAULT 4096 #define BUFFER_DATA_FREE(D) XFREE(MTYPE_BUFFER_DATA, (D)) diff --git a/lib/command.c b/lib/command.c index 53aa064705..ea66a17bb0 100644 --- a/lib/command.c +++ b/lib/command.c @@ -86,6 +86,9 @@ vector cmdvec = NULL; /* Host information structure. */ struct host host; +/* for vtysh, put together CLI trees only when switching into node */ +static bool defer_cli_tree; + /* * Returns host.name if any, otherwise * it returns the system hostname. @@ -285,6 +288,11 @@ const char *cmd_prompt(enum node_type node) return cnode->prompt; } +void cmd_defer_tree(bool val) +{ + defer_cli_tree = val; +} + /* Install a command into a node. */ void _install_element(enum node_type ntype, const struct cmd_element *cmd) { @@ -319,20 +327,50 @@ void _install_element(enum node_type ntype, const struct cmd_element *cmd) assert(hash_get(cnode->cmd_hash, (void *)cmd, hash_alloc_intern)); + if (cnode->graph_built || !defer_cli_tree) { + struct graph *graph = graph_new(); + struct cmd_token *token = + cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, + (void (*)(void *)) & cmd_token_del); + + cmd_graph_parse(graph, cmd); + cmd_graph_names(graph); + cmd_graph_merge(cnode->cmdgraph, graph, +1); + graph_delete_graph(graph); + + cnode->graph_built = true; + } + + vector_set(cnode->cmd_vector, (void *)cmd); + + if (ntype == VIEW_NODE) + _install_element(ENABLE_NODE, cmd); +} + +static void cmd_finalize_iter(struct hash_bucket *hb, void *arg) +{ + struct cmd_node *cnode = arg; + const struct cmd_element *cmd = hb->data; struct graph *graph = graph_new(); struct cmd_token *token = cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del); cmd_graph_parse(graph, cmd); cmd_graph_names(graph); cmd_graph_merge(cnode->cmdgraph, graph, +1); graph_delete_graph(graph); +} - vector_set(cnode->cmd_vector, (void *)cmd); +void cmd_finalize_node(struct cmd_node *cnode) +{ + if (cnode->graph_built) + return; - if (ntype == VIEW_NODE) - _install_element(ENABLE_NODE, cmd); + hash_iterate(cnode->cmd_hash, cmd_finalize_iter, cnode); + cnode->graph_built = true; } void uninstall_element(enum node_type ntype, const struct cmd_element *cmd) @@ -368,15 +406,18 @@ void uninstall_element(enum node_type ntype, const struct cmd_element *cmd) vector_unset_value(cnode->cmd_vector, (void *)cmd); - struct graph *graph = graph_new(); - struct cmd_token *token = - cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del); + if (cnode->graph_built) { + struct graph *graph = graph_new(); + struct cmd_token *token = + cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, + (void (*)(void *)) & cmd_token_del); - cmd_graph_parse(graph, cmd); - cmd_graph_names(graph); - cmd_graph_merge(cnode->cmdgraph, graph, -1); - graph_delete_graph(graph); + cmd_graph_parse(graph, cmd); + cmd_graph_names(graph); + cmd_graph_merge(cnode->cmdgraph, graph, -1); + graph_delete_graph(graph); + } if (ntype == VIEW_NODE) uninstall_element(ENABLE_NODE, cmd); @@ -503,6 +544,8 @@ static int config_write_host(struct vty *vty) static struct graph *cmd_node_graph(vector v, enum node_type ntype) { struct cmd_node *cnode = vector_slot(v, ntype); + + cmd_finalize_node(cnode); return cnode->cmdgraph; } @@ -1506,9 +1549,10 @@ int cmd_list_cmds(struct vty *vty, int do_permute) { struct cmd_node *node = vector_slot(cmdvec, vty->node); - if (do_permute) + if (do_permute) { + cmd_finalize_node(node); permute(vector_slot(node->cmdgraph->nodes, 0), vty); - else { + } else { /* loop over all commands at this node */ const struct cmd_element *element = NULL; for (unsigned int i = 0; i < vector_active(node->cmd_vector); @@ -1551,7 +1595,10 @@ DEFUN_HIDDEN(show_cli_graph, "Dump current command space as DOT graph\n") { struct cmd_node *cn = vector_slot(cmdvec, vty->node); - char *dot = cmd_graph_dump_dot(cn->cmdgraph); + char *dot; + + cmd_finalize_node(cn); + dot = cmd_graph_dump_dot(cn->cmdgraph); vty_out(vty, "%s\n", dot); XFREE(MTYPE_TMP, dot); diff --git a/lib/command.h b/lib/command.h index 8a7c9a2048..e2086701ad 100644 --- a/lib/command.h +++ b/lib/command.h @@ -210,6 +210,9 @@ struct cmd_node { /* Hashed index of command node list, for de-dupping primarily */ struct hash *cmd_hash; + + /* set as soon as any command is in cmdgraph */ + bool graph_built; }; /* Return value of the commands. */ @@ -234,7 +237,7 @@ struct cmd_node { /* Argc max counts. */ #define CMD_ARGC_MAX 256 -/* Turn off these macros when uisng cpp with extract.pl */ +/* Turn off these macros when using cpp with extract.pl */ #ifndef VTYSH_EXTRACT_PL /* helper defines for end-user DEFUN* macros */ @@ -526,6 +529,12 @@ extern void _install_element(enum node_type, const struct cmd_element *); * deprecated/hidden) are not reversed. */ extern void uninstall_element(enum node_type, const struct cmd_element *); +/* construct CLI tree only when entering nodes */ +extern void cmd_defer_tree(bool val); + +/* finish CLI tree for node when above is true (noop otherwise) */ +extern void cmd_finalize_node(struct cmd_node *node); + /* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated string with a space between each element (allocated using XMALLOC(MTYPE_TMP)). Returns NULL if shift >= argc. */ diff --git a/lib/command_graph.c b/lib/command_graph.c index 15c8302e63..09d802e796 100644 --- a/lib/command_graph.c +++ b/lib/command_graph.c @@ -77,16 +77,17 @@ struct cmd_token *cmd_token_dup(struct cmd_token *token) return copy; } -void cmd_token_varname_set(struct cmd_token *token, const char *varname) +static void cmd_token_varname_do(struct cmd_token *token, const char *varname, + uint8_t varname_src) { - XFREE(MTYPE_CMD_VAR, token->varname); - if (!varname) { - token->varname = NULL; + if (token->varname_src >= varname_src) return; - } + + XFREE(MTYPE_CMD_VAR, token->varname); size_t len = strlen(varname), i; token->varname = XMALLOC(MTYPE_CMD_VAR, len + 1); + token->varname_src = varname_src; for (i = 0; i < len; i++) switch (varname[i]) { @@ -102,6 +103,80 @@ void cmd_token_varname_set(struct cmd_token *token, const char *varname) token->varname[len] = '\0'; } +void cmd_token_varname_set(struct cmd_token *token, const char *varname) +{ + if (varname) { + cmd_token_varname_do(token, varname, VARNAME_EXPLICIT); + return; + } + if (token->type == VARIABLE_TKN) { + if (strcmp(token->text, "WORD") && strcmp(token->text, "NAME")) + cmd_token_varname_do(token, token->text, VARNAME_TEXT); + } +} + +static void cmd_token_varname_fork(struct graph_node *node, + struct cmd_token *prevtoken) +{ + for (size_t i = 0; i < vector_active(node->to); i++) { + struct graph_node *next = vector_slot(node->to, i); + struct cmd_token *nexttoken = next->data; + + if (nexttoken->type == FORK_TKN) { + cmd_token_varname_fork(next, prevtoken); + continue; + } + if (nexttoken->varname) + continue; + if (!IS_VARYING_TOKEN(nexttoken->type)) + continue; + + cmd_token_varname_do(nexttoken, prevtoken->text, VARNAME_TEXT); + } +} + +void cmd_token_varname_join(struct graph_node *join, const char *varname) +{ + if (!varname) + return; + + for (size_t i = 0; i < vector_active(join->from); i++) { + struct graph_node *prev = vector_slot(join->from, i); + struct cmd_token *token = prev->data; + + if (token->type == JOIN_TKN) + cmd_token_varname_join(prev, varname); + else if (token->type < SPECIAL_TKN) + cmd_token_varname_do(token, varname, VARNAME_EXPLICIT); + } +} + +void cmd_token_varname_seqappend(struct graph_node *node) +{ + struct graph_node *prevnode = node; + struct cmd_token *token = node->data; + struct cmd_token *prevtoken; + + if (token->type == WORD_TKN) + return; + + do { + if (vector_active(prevnode->from) != 1) + return; + + prevnode = vector_slot(prevnode->from, 0); + prevtoken = prevnode->data; + } while (prevtoken->type == FORK_TKN); + + if (prevtoken->type != WORD_TKN) + return; + + if (token->type == FORK_TKN) + cmd_token_varname_fork(node, prevtoken); + else + cmd_token_varname_do(token, prevtoken->text, VARNAME_TEXT); +} + static bool cmd_nodes_link(struct graph_node *from, struct graph_node *to) { for (size_t i = 0; i < vector_active(from->to); i++) @@ -357,72 +432,6 @@ void cmd_graph_merge(struct graph *old, struct graph *new, int direction) vector_slot(new->nodes, 0), direction); } -static void cmd_node_names(struct graph_node *gn, struct graph_node *join, - const char *prevname) -{ - size_t i; - struct cmd_token *tok = gn->data, *jointok; - struct graph_node *stop = cmd_loopstop(gn); - - switch (tok->type) { - case WORD_TKN: - prevname = tok->text; - break; - - case VARIABLE_TKN: - if (!tok->varname && strcmp(tok->text, "WORD") - && strcmp(tok->text, "NAME")) - cmd_token_varname_set(tok, tok->text); - /* fallthrough */ - case RANGE_TKN: - case IPV4_TKN: - case IPV4_PREFIX_TKN: - case IPV6_TKN: - case IPV6_PREFIX_TKN: - case MAC_TKN: - case MAC_PREFIX_TKN: - if (!tok->varname && prevname) - cmd_token_varname_set(tok, prevname); - prevname = NULL; - break; - - case START_TKN: - case JOIN_TKN: - case NEG_ONLY_TKN: - /* "<foo|bar> WORD" -> word is not "bar" or "foo" */ - prevname = NULL; - break; - - case FORK_TKN: - /* apply "<A.B.C.D|X:X::X:X>$name" */ - jointok = tok->forkjoin->data; - if (!jointok->varname) - break; - for (i = 0; i < vector_active(tok->forkjoin->from); i++) { - struct graph_node *tail = - vector_slot(tok->forkjoin->from, i); - struct cmd_token *tailtok = tail->data; - if (tail == gn || tailtok->varname) - continue; - cmd_token_varname_set(tailtok, jointok->varname); - } - break; - - case END_TKN: - return; - } - - for (i = 0; i < vector_active(gn->to); i++) { - struct graph_node *next = vector_slot(gn->to, i); - if (next == stop || next == join) - continue; - cmd_node_names(next, join, prevname); - } - - if (tok->type == FORK_TKN && tok->forkjoin != join) - cmd_node_names(tok->forkjoin, join, NULL); -} - void cmd_graph_names(struct graph *graph) { struct graph_node *start; @@ -451,12 +460,10 @@ void cmd_graph_names(struct graph *graph) struct cmd_token *tok1 = next1->data; /* the other one needs to be "no" (only one will match here) */ if ((tok0->type == WORD_TKN && !strcmp(tok0->text, "no"))) - cmd_token_varname_set(tok0, "no"); + cmd_token_varname_do(tok0, "no", VARNAME_AUTO); if ((tok1->type == WORD_TKN && !strcmp(tok1->text, "no"))) - cmd_token_varname_set(tok1, "no"); + cmd_token_varname_do(tok1, "no", VARNAME_AUTO); } while (0); - - cmd_node_names(start, NULL, NULL); } #ifndef BUILDING_CLIPPY diff --git a/lib/command_graph.h b/lib/command_graph.h index c20c9874c2..ed4da6aa4c 100644 --- a/lib/command_graph.h +++ b/lib/command_graph.h @@ -79,11 +79,20 @@ enum { CMD_ATTR_NORMAL, CMD_ATTR_YANG, }; -/* Comamand token struct. */ +enum varname_src { + VARNAME_NONE = 0, + VARNAME_AUTO, + VARNAME_VAR, + VARNAME_TEXT, + VARNAME_EXPLICIT, +}; + +/* Command token struct. */ struct cmd_token { enum cmd_token_type type; // token type uint8_t attr; // token attributes - bool allowrepeat; // matcher allowed to match token repetively? + bool allowrepeat; // matcher allowed to match token repetitively? + uint8_t varname_src; uint32_t refcnt; char *text; // token text @@ -119,6 +128,8 @@ extern struct cmd_token *cmd_token_new(enum cmd_token_type, uint8_t attr, extern struct cmd_token *cmd_token_dup(struct cmd_token *); extern void cmd_token_del(struct cmd_token *); extern void cmd_token_varname_set(struct cmd_token *token, const char *varname); +extern void cmd_token_varname_seqappend(struct graph_node *n); +extern void cmd_token_varname_join(struct graph_node *n, const char *varname); extern void cmd_graph_parse(struct graph *graph, const struct cmd_element *cmd); extern void cmd_graph_names(struct graph *graph); diff --git a/lib/command_match.h b/lib/command_match.h index fcb333120f..0488cc1a1f 100644 --- a/lib/command_match.h +++ b/lib/command_match.h @@ -68,7 +68,7 @@ enum match_type { * @param[in] vline vectorized input string * @param[out] argv pointer to argument list if successful match, NULL * otherwise. The elements of this list are pointers to struct cmd_token - * and represent the sequence of tokens matched by the inpu. The ->arg + * and represent the sequence of tokens matched by the input. The ->arg * field of each token points to a copy of the input matched on it. These * may be safely deleted or modified. * @param[out] element pointer to matched cmd_element if successful match, diff --git a/lib/command_parse.y b/lib/command_parse.y index 3e2cdc79af..35c119691b 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -217,10 +217,12 @@ cmd_token: { if ((ctx->currnode = graph_add_edge (ctx->currnode, $1)) != $1) graph_delete_node (ctx->graph, $1); + cmd_token_varname_seqappend($1); } | selector { graph_add_edge (ctx->currnode, $1.start); + cmd_token_varname_seqappend($1.start); ctx->currnode = $1.end; } ; @@ -295,9 +297,8 @@ placeholder_token_real: placeholder_token: placeholder_token_real varname_token { - struct cmd_token *token = $$->data; $$ = $1; - cmd_token_varname_set (token, $2); + cmd_token_varname_set ($$->data, $2); XFREE (MTYPE_LEX, $2); }; @@ -306,7 +307,7 @@ placeholder_token: selector: '<' selector_seq_seq '>' varname_token { $$ = $2; - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); }; @@ -338,11 +339,11 @@ selector: '{' selector_seq_seq '}' varname_token * 1) this allows "at least 1 of" semantics, which are otherwise impossible * 2) this would add a start->end->start loop in the graph that the current * loop-avoidal fails to handle - * just use [{a|b}] if neccessary, that will work perfectly fine, and reason + * just use [{a|b}] if necessary, that will work perfectly fine, and reason * #1 is good enough to keep it this way. */ loopcheck(ctx, &$$); - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); }; @@ -359,6 +360,7 @@ selector_token_seq: selector_token_seq selector_token { graph_add_edge ($1.end, $2.start); + cmd_token_varname_seqappend($2.start); $$.start = $1.start; $$.end = $2.end; } @@ -370,7 +372,7 @@ selector: '[' selector_seq_seq ']' varname_token { $$ = $2; graph_add_edge ($$.start, $$.end); - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); } ; @@ -383,7 +385,7 @@ selector: EXCL_BRACKET selector_seq_seq ']' varname_token $$ = $2; graph_add_edge ($$.start, neg_only); graph_add_edge (neg_only, $$.end); - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); } ; @@ -60,7 +60,7 @@ int db_init(const char *path_fmt, ...) (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE), NULL) != SQLITE_OK) { if (dbp == NULL) { - zlog_warn("%s: failed to open dabatase '%s'", __func__, + zlog_warn("%s: failed to open database '%s'", __func__, path); return -1; } diff --git a/lib/distribute.h b/lib/distribute.h index 83682dea6a..6b3226e8b4 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -29,7 +29,7 @@ extern "C" { #endif -/* Disctirubte list types. */ +/* Distribute list types. */ enum distribute_type { DISTRIBUTE_V4_IN, DISTRIBUTE_V6_IN, diff --git a/lib/ferr.h b/lib/ferr.h index 4e95431cea..c27601f66c 100644 --- a/lib/ferr.h +++ b/lib/ferr.h @@ -34,7 +34,7 @@ extern "C" { /* return type when this error indication stuff is used. * * guaranteed to have boolean evaluation to "false" when OK, "true" when error - * (i.e. can be changed to pointer in the future if neccessary) + * (i.e. can be changed to pointer in the future if necessary) * * For checking, always use "if (value)", nothing else. * Do _NOT_ use any integer constant (!= 0), or sign check (< 0). diff --git a/lib/filter.c b/lib/filter.c index 744ea9c480..3a86fbce93 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -192,7 +192,7 @@ void access_list_delete(struct access_list *access) access_list_free(access); } -/* Insert new access list to list of access_list. Each acceess_list +/* Insert new access list to list of access_list. Each access_list is sorted by the name. */ static struct access_list *access_list_insert(afi_t afi, const char *name) { @@ -387,7 +387,7 @@ void access_list_filter_add(struct access_list *access, struct filter *replace; struct filter *point; - /* Automatic asignment of seq no. */ + /* Automatic assignment of seq no. */ if (filter->seq == -1) filter->seq = filter_new_seq_get(access); @@ -635,15 +635,11 @@ DEFUN (show_ip_access_list, DEFUN (show_ip_access_list_name, show_ip_access_list_name_cmd, - "show ip access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)|WORD> [json]", + "show ip access-list WORD [json]", SHOW_STR IP_STR "List IP access lists\n" - "IP standard access list\n" - "IP extended access list\n" - "IP standard access list (expanded range)\n" - "IP extended access list (expanded range)\n" - "IP zebra access-list\n" + "IP access-list name\n" JSON_STR) { bool uj = use_json(argc, argv); @@ -669,7 +665,7 @@ DEFUN (show_ipv6_access_list_name, SHOW_STR IPV6_STR "List IPv6 access lists\n" - "IPv6 zebra access-list\n" + "IPv6 access-list name\n" JSON_STR) { bool uj = use_json(argc, argv); diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 45c7544a3b..e424fcf878 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -36,10 +36,7 @@ #endif /* VTYSH_EXTRACT_PL */ #define ACCESS_LIST_STR "Access list entry\n" -#define ACCESS_LIST_LEG_STR "IP standard access list\n" -#define ACCESS_LIST_ELEG_STR "IP extended access list\n" -#define ACCESS_LIST_ELEG_EXT_STR "IP extended access list (expanded range)\n" -#define ACCESS_LIST_ZEBRA_STR "Access list entry\n" +#define ACCESS_LIST_ZEBRA_STR "Access list name\n" #define ACCESS_LIST_SEQ_STR \ "Sequence number of an entry\n" \ "Sequence number\n" @@ -137,7 +134,7 @@ DEFPY_YANG( access_list_std, access_list_std_cmd, "access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>", ACCESS_LIST_STR - ACCESS_LIST_LEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "A single host address\n" @@ -214,7 +211,7 @@ DEFPY_YANG( "no access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>", NO_STR ACCESS_LIST_STR - ACCESS_LIST_LEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "A single host address\n" @@ -258,7 +255,7 @@ DEFPY_YANG( access_list_ext, access_list_ext_cmd, "access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>", ACCESS_LIST_STR - ACCESS_LIST_ELEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "IPv4 address\n" @@ -377,7 +374,7 @@ DEFPY_YANG( "no access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action ip <A.B.C.D$src A.B.C.D$src_mask|host A.B.C.D$src|any> <A.B.C.D$dst A.B.C.D$dst_mask|host A.B.C.D$dst|any>", NO_STR ACCESS_LIST_STR - ACCESS_LIST_ELEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "Any Internet Protocol\n" diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c index ea9c828f7c..e572558de1 100644 --- a/lib/frr_zmq.c +++ b/lib/frr_zmq.c @@ -19,7 +19,7 @@ /* * IF YOU MODIFY THIS FILE PLEASE RUN `make check` and ensure that - * the test_zmq.c unit test is still working. There are dependancies + * the test_zmq.c unit test is still working. There are dependencies * between the two that are extremely fragile. My understanding * is that there is specialized ownership of the cb pointer based * upon what is happening. Those assumptions are supposed to be @@ -84,7 +84,10 @@ static int frrzmq_read_msg(struct thread *t) break; if (cb->read.cb_msg) { + cb->in_cb = true; cb->read.cb_msg(cb->read.arg, cb->zmqsock); + cb->in_cb = false; + read = 1; if (cb->read.cancelled) { @@ -92,7 +95,8 @@ static int frrzmq_read_msg(struct thread *t) ZMQ_POLLOUT); cb->read.thread = NULL; if (cb->write.cancelled && !cb->write.thread) - XFREE(MTYPE_ZEROMQ_CB, cb); + XFREE(MTYPE_ZEROMQ_CB, *cbp); + return 0; } continue; @@ -112,15 +116,19 @@ static int frrzmq_read_msg(struct thread *t) } read = 1; + cb->in_cb = true; cb->read.cb_part(cb->read.arg, cb->zmqsock, &msg, partno); + cb->in_cb = false; + if (cb->read.cancelled) { zmq_msg_close(&msg); frrzmq_check_events(cbp, &cb->write, ZMQ_POLLOUT); cb->read.thread = NULL; if (cb->write.cancelled && !cb->write.thread) - XFREE(MTYPE_ZEROMQ_CB, cb); + XFREE(MTYPE_ZEROMQ_CB, *cbp); + return 0; } @@ -183,7 +191,6 @@ int _frrzmq_thread_add_read(const struct xref_threadsched *xref, cb = *cbp; else { cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb)); - cb->write.cancelled = true; *cbp = cb; } @@ -195,6 +202,7 @@ int _frrzmq_thread_add_read(const struct xref_threadsched *xref, cb->read.cb_part = partfunc; cb->read.cb_error = errfunc; cb->read.cancelled = false; + cb->in_cb = false; if (events & ZMQ_POLLIN) { thread_cancel(&cb->read.thread); @@ -232,14 +240,18 @@ static int frrzmq_write_msg(struct thread *t) break; if (cb->write.cb_msg) { + cb->in_cb = true; cb->write.cb_msg(cb->write.arg, cb->zmqsock); + cb->in_cb = false; + written = 1; if (cb->write.cancelled) { frrzmq_check_events(cbp, &cb->read, ZMQ_POLLIN); cb->write.thread = NULL; if (cb->read.cancelled && !cb->read.thread) - XFREE(MTYPE_ZEROMQ_CB, cb); + XFREE(MTYPE_ZEROMQ_CB, *cbp); + return 0; } continue; @@ -286,7 +298,6 @@ int _frrzmq_thread_add_write(const struct xref_threadsched *xref, cb = *cbp; else { cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb)); - cb->read.cancelled = true; *cbp = cb; } @@ -298,6 +309,7 @@ int _frrzmq_thread_add_write(const struct xref_threadsched *xref, cb->write.cb_part = NULL; cb->write.cb_error = errfunc; cb->write.cancelled = false; + cb->in_cb = false; if (events & ZMQ_POLLOUT) { thread_cancel(&cb->write.thread); @@ -317,22 +329,15 @@ void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core) core->cancelled = true; thread_cancel(&core->thread); - /* - * Looking at this code one would assume that FRR - * would want a `!(*cb)->write.thread. This was - * attempted in e08165def1c62beee0e87385 but this - * change caused `make check` to stop working - * which was not noticed because our CI system - * does not build with zeromq. Put this back - * to the code as written in 2017. e08165de.. - * was introduced in 2021. So someone was ok - * with frrzmq_thread_cancel for 4 years. This will - * allow those people doing `make check` to continue - * working. In the meantime if the people using - * this code see an issue they can fix it + /* If cancelled from within a callback, don't try to free memory + * in this path. */ + if ((*cb)->in_cb) + return; + + /* Ok to free the callback context if no more ... context. */ if ((*cb)->read.cancelled && !(*cb)->read.thread - && (*cb)->write.cancelled && (*cb)->write.thread) + && (*cb)->write.cancelled && ((*cb)->write.thread == NULL)) XFREE(MTYPE_ZEROMQ_CB, *cb); } diff --git a/lib/frr_zmq.h b/lib/frr_zmq.h index d30cf8a841..b3be78cbea 100644 --- a/lib/frr_zmq.h +++ b/lib/frr_zmq.h @@ -49,10 +49,13 @@ struct cb_core { unsigned partnum); void (*cb_error)(void *arg, void *zmqsock); }; + struct frrzmq_cb { void *zmqsock; int fd; + bool in_cb; /* This context is in a read or write callback. */ + struct cb_core read; struct cb_core write; }; diff --git a/lib/frrscript.c b/lib/frrscript.c index 0e0d3c030c..b935b30cc2 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -226,7 +226,7 @@ void *frrscript_get_result(struct frrscript *fs, const char *function_name, p = lua_to(lfs->L, 2); /* At the end, the Lua state should be same as it was at the start - * i.e. containing soley the returned table. + * i.e. containing solely the returned table. */ assert(lua_gettop(lfs->L) == 1); assert(lua_istable(lfs->L, -1) == 1); diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 209765bd6f..f9778c5d4c 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -395,6 +395,7 @@ DEFUN (grammar_findambig, vector_slot(cmdvec, scannode++); if (!cnode) continue; + cmd_finalize_node(cnode); nodegraph = cnode->cmdgraph; if (!nodegraph) continue; @@ -466,6 +467,7 @@ DEFUN (grammar_access, } vty_out(vty, "node %d\n", (int)cnode->node); + cmd_finalize_node(cnode); nodegraph = cnode->cmdgraph; return CMD_SUCCESS; } diff --git a/lib/graph.c b/lib/graph.c index 1cbe1b90f9..ba7314fb25 100644 --- a/lib/graph.c +++ b/lib/graph.c @@ -69,7 +69,7 @@ static void graph_vector_remove(vector v, unsigned int ix) * and v->active is > ix. */ v->active--; /* if ix == v->active--, we set the item to itself, then to NULL... - * still correct, no check neccessary. */ + * still correct, no check necessary. */ v->index[ix] = v->index[v->active]; v->index[v->active] = NULL; } diff --git a/lib/hash.h b/lib/hash.h index 47d951a34b..f3b24f051b 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -161,7 +161,7 @@ hash_create_size(unsigned int size, unsigned int (*hash_key)(const void *), * an element from its key, you must provide the data item itself, with the * portions used in the hash function set to the same values as the data item * to retrieve. To insert a data element, either provide the key as just - * described and provide alloc_func as descrbied below to allocate the full + * described and provide alloc_func as described below to allocate the full * data element, or provide the full data element and pass 'hash_alloc_intern' * to alloc_func. * diff --git a/lib/hook.h b/lib/hook.h index 3a0db6009b..d75e623edc 100644 --- a/lib/hook.h +++ b/lib/hook.h @@ -193,7 +193,7 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, * usage: DECLARE_HOOK(my_hook, (int arg1, struct foo *arg2), (arg1, arg2)); * as above, "passlist" must use the same order and same names as "arglist" * - * theoretically passlist is not neccessary, but let's keep things simple and + * theoretically passlist is not necessary, but let's keep things simple and * use exact same args on DECLARE and DEFINE. */ #define DECLARE_HOOK(hookname, arglist, passlist) \ @@ -45,6 +45,7 @@ DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected"); DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label"); DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters"); +static void if_set_name(struct interface *ifp, const char *name); static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); static int if_cmp_func(const struct interface *, const struct interface *); @@ -153,16 +154,19 @@ static void ifp_connected_free(void *arg) } /* Create new interface structure. */ -static struct interface *if_new(vrf_id_t vrf_id) +static struct interface *if_new(struct vrf *vrf) { struct interface *ifp; + assert(vrf); + ifp = XCALLOC(MTYPE_IF, sizeof(struct interface)); ifp->ifindex = IFINDEX_INTERNAL; ifp->name[0] = '\0'; - ifp->vrf_id = vrf_id; + ifp->vrf = vrf; + ifp->vrf_id = vrf->vrf_id; ifp->connected = list_new(); ifp->connected->del = ifp_connected_free; @@ -207,11 +211,11 @@ void if_down_via_zapi(struct interface *ifp) (*ifp_master.down_hook)(ifp); } -struct interface *if_create_name(const char *name, vrf_id_t vrf_id) +static struct interface *if_create_name(const char *name, struct vrf *vrf) { struct interface *ifp; - ifp = if_new(vrf_id); + ifp = if_new(vrf); if_set_name(ifp, name); @@ -219,35 +223,23 @@ struct interface *if_create_name(const char *name, vrf_id_t vrf_id) return ifp; } -struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id) -{ - struct interface *ifp; - - ifp = if_new(vrf_id); - - if_set_index(ifp, ifindex); - - hook_call(if_add, ifp); - return ifp; -} - /* Create new interface structure. */ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) { struct vrf *old_vrf, *vrf; /* remove interface from old master vrf list */ - old_vrf = vrf_lookup_by_id(ifp->vrf_id); - if (old_vrf) { - if (ifp->name[0] != '\0') - IFNAME_RB_REMOVE(old_vrf, ifp); + old_vrf = ifp->vrf; - if (ifp->ifindex != IFINDEX_INTERNAL) - IFINDEX_RB_REMOVE(old_vrf, ifp); - } + if (ifp->name[0] != '\0') + IFNAME_RB_REMOVE(old_vrf, ifp); + + if (ifp->ifindex != IFINDEX_INTERNAL) + IFINDEX_RB_REMOVE(old_vrf, ifp); ifp->vrf_id = vrf_id; vrf = vrf_get(ifp->vrf_id, NULL); + ifp->vrf = vrf; if (ifp->name[0] != '\0') IFNAME_RB_INSERT(vrf, ifp); @@ -261,7 +253,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) * the interface and readding it in the new VRF, which would have * several implications. */ - if (yang_module_find("frr-interface")) { + if (!vrf_is_backend_netns() && yang_module_find("frr-interface")) { struct lyd_node *if_dnode; char oldpath[XPATH_MAXLEN]; char newpath[XPATH_MAXLEN]; @@ -304,15 +296,15 @@ void if_delete_retain(struct interface *ifp) void if_delete(struct interface **ifp) { struct interface *ptr = *ifp; - struct vrf *vrf; - - vrf = vrf_lookup_by_id(ptr->vrf_id); - assert(vrf); + struct vrf *vrf = ptr->vrf; IFNAME_RB_REMOVE(vrf, ptr); if (ptr->ifindex != IFINDEX_INTERNAL) IFINDEX_RB_REMOVE(vrf, ptr); + if (!vrf_is_enabled(vrf)) + vrf_delete(vrf); + if_delete_retain(ptr); list_delete(&ptr->connected); @@ -341,7 +333,7 @@ static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, return RB_FIND(if_index_head, &vrf->ifaces_by_index, &if_tmp); } -/* Interface existance check by index. */ +/* Interface existence check by index. */ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) { switch (vrf_get_backend()) { @@ -354,7 +346,7 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) return NULL; } -/* Interface existance check by index. */ +/* Interface existence check by index. */ struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex, vrf_id_t vrf_id) { @@ -406,7 +398,7 @@ ifindex_t ifname2ifindex(const char *name, vrf_id_t vrf_id) : IFINDEX_INTERNAL; } -/* Interface existance check by interface name. */ +/* Interface existence check by interface name. */ struct interface *if_lookup_by_name(const char *name, vrf_id_t vrf_id) { struct vrf *vrf = vrf_lookup_by_id(vrf_id); @@ -439,8 +431,8 @@ struct interface *if_lookup_by_name_all_vrf(const char *name) if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ) return NULL; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - ifp = if_lookup_by_name(name, vrf->vrf_id); + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + ifp = if_lookup_by_name_vrf(name, vrf); if (ifp) return ifp; } @@ -582,72 +574,58 @@ size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz, /* Get interface by name if given name interface doesn't exist create one. */ -struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id) +struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, + const char *vrf_name) { - struct interface *ifp; + struct interface *ifp = NULL; + struct vrf *vrf; switch (vrf_get_backend()) { case VRF_BACKEND_UNKNOWN: case VRF_BACKEND_NETNS: - ifp = if_lookup_by_name(name, vrf_id); - if (ifp) - return ifp; - return if_create_name(name, vrf_id); - case VRF_BACKEND_VRF_LITE: - ifp = if_lookup_by_name_all_vrf(name); + vrf = vrf_get(vrf_id, vrf_name); + assert(vrf); + + ifp = if_lookup_by_name_vrf(name, vrf); if (ifp) { - if (ifp->vrf_id == vrf_id) - return ifp; /* If it came from the kernel or by way of zclient, * believe it and update the ifp accordingly. */ - if_update_to_new_vrf(ifp, vrf_id); + if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN) + if_update_to_new_vrf(ifp, vrf_id); + return ifp; } - return if_create_name(name, vrf_id); - } - - return NULL; -} -struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id) -{ - struct interface *ifp; - - switch (vrf_get_backend()) { - case VRF_BACKEND_UNKNOWN: - case VRF_BACKEND_NETNS: - ifp = if_lookup_by_ifindex(ifindex, vrf_id); - if (ifp) - return ifp; - return if_create_ifindex(ifindex, vrf_id); + break; case VRF_BACKEND_VRF_LITE: - ifp = if_lookup_by_index_all_vrf(ifindex); + ifp = if_lookup_by_name_all_vrf(name); if (ifp) { - if (ifp->vrf_id == vrf_id) - return ifp; /* If it came from the kernel or by way of zclient, * believe it and update the ifp accordingly. */ - if_update_to_new_vrf(ifp, vrf_id); + if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN) + if_update_to_new_vrf(ifp, vrf_id); + return ifp; } - return if_create_ifindex(ifindex, vrf_id); + + vrf = vrf_get(vrf_id, vrf_name); + assert(vrf); + + break; + default: + return NULL; } - return NULL; + return if_create_name(name, vrf); } int if_set_index(struct interface *ifp, ifindex_t ifindex) { - struct vrf *vrf; - if (ifp->ifindex == ifindex) return 0; - vrf = vrf_get(ifp->vrf_id, NULL); - assert(vrf); - /* * If there is already an interface with this ifindex, we will collide * on insertion, so don't even try. @@ -656,7 +634,7 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex) return -1; if (ifp->ifindex != IFINDEX_INTERNAL) - IFINDEX_RB_REMOVE(vrf, ifp); + IFINDEX_RB_REMOVE(ifp->vrf, ifp); ifp->ifindex = ifindex; @@ -666,30 +644,25 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex) * already an interface with the desired ifindex at the top of * the function. Nevertheless. */ - if (IFINDEX_RB_INSERT(vrf, ifp)) + if (IFINDEX_RB_INSERT(ifp->vrf, ifp)) return -1; } return 0; } -void if_set_name(struct interface *ifp, const char *name) +static void if_set_name(struct interface *ifp, const char *name) { - struct vrf *vrf; - - vrf = vrf_get(ifp->vrf_id, NULL); - assert(vrf); - if (if_cmp_name_func(ifp->name, name) == 0) return; if (ifp->name[0] != '\0') - IFNAME_RB_REMOVE(vrf, ifp); + IFNAME_RB_REMOVE(ifp->vrf, ifp); strlcpy(ifp->name, name, sizeof(ifp->name)); if (ifp->name[0] != '\0') - IFNAME_RB_INSERT(vrf, ifp); + IFNAME_RB_INSERT(ifp->vrf, ifp); } /* Does interface up ? */ @@ -817,15 +790,12 @@ static void if_dump(const struct interface *ifp) struct listnode *node; struct connected *c __attribute__((unused)); - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) { - struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); - + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) zlog_info( "Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s", - ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex, + ifp->name, ifp->vrf->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu, ifp->mtu6, if_flag_dump(ifp->flags)); - } } /* Interface printing for all interface. */ @@ -894,16 +864,14 @@ connected_log(struct connected *connected, char *str) { struct prefix *p; struct interface *ifp; - struct vrf *vrf; char logbuf[BUFSIZ]; char buf[BUFSIZ]; ifp = connected->ifp; p = connected->address; - vrf = vrf_lookup_by_id(ifp->vrf_id); snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ", - str, ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, + str, ifp->name, ifp->vrf->name, ifp->vrf_id, prefix_family_str(p), p); p = connected->destination; @@ -1059,30 +1027,15 @@ struct connected *connected_get_linklocal(struct interface *ifp) void if_terminate(struct vrf *vrf) { struct interface *ifp; - bool delete; - - /* - * If the default VRF is being terminated or has - * already been terminated it means that - * the program is shutting down and we need to - * delete all the interfaces. Otherwise, we only - * need to move VRF's interfaces to the default VRF. - */ - delete = vrf_is_backend_netns() || vrf->vrf_id == VRF_DEFAULT - || !vrf_lookup_by_id(VRF_DEFAULT); while (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) { ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name); - if (delete) { - if (ifp->node) { - ifp->node->info = NULL; - route_unlock_node(ifp->node); - } - if_delete(&ifp); - } else { - if_update_to_new_vrf(ifp, VRF_DEFAULT); + if (ifp->node) { + ifp->node->info = NULL; + route_unlock_node(ifp->node); } + if_delete(&ifp); } } @@ -1108,6 +1061,8 @@ const char *if_link_type_str(enum zebra_link_type llt) llts(ZEBRA_LLT_CSLIP, "Compressed SLIP"); llts(ZEBRA_LLT_SLIP6, "SLIPv6"); llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6"); + llts(ZEBRA_LLT_RSRVD, "Reserved"); + llts(ZEBRA_LLT_ADAPT, "Adapt"); llts(ZEBRA_LLT_ROSE, "ROSE packet radio"); llts(ZEBRA_LLT_X25, "CCITT X.25"); llts(ZEBRA_LLT_PPP, "PPP"); @@ -1124,8 +1079,10 @@ const char *if_link_type_str(enum zebra_link_type llt) llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT"); llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel"); llts(ZEBRA_LLT_IPGRE, "GRE over IP"); + llts(ZEBRA_LLT_IP6GRE, "GRE over IPv6"); llts(ZEBRA_LLT_PIMREG, "PIMSM registration"); llts(ZEBRA_LLT_HIPPI, "HiPPI"); + llts(ZEBRA_LLT_ECONET, "Acorn Econet"); llts(ZEBRA_LLT_IRDA, "IrDA"); llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP"); llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop"); @@ -1136,9 +1093,6 @@ const char *if_link_type_str(enum zebra_link_type llt) llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap"); llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4"); llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy"); - default: - flog_err(EC_LIB_DEVELOPMENT, "Unknown value %d", llt); - return "Unknown type!"; #undef llts } return NULL; @@ -1185,6 +1139,25 @@ void if_link_params_free(struct interface *ifp) /* ----------- CLI commands ----------- */ +/* Guess the VRF of an interface. */ +static int vrfname_by_ifname(const char *ifname, const char **vrfname) +{ + struct vrf *vrf; + struct interface *ifp; + int count = 0; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + FOR_ALL_INTERFACES (vrf, ifp) { + if (strmatch(ifp->name, ifname)) { + *vrfname = vrf->name; + count++; + } + } + } + + return count; +} + /* * XPath: /frr-interface:lib/interface */ @@ -1196,12 +1169,9 @@ DEFPY_YANG_NOSH (interface, VRF_CMD_HELP_STR) { char xpath_list[XPATH_MAXLEN]; - vrf_id_t vrf_id; struct interface *ifp; - int ret; - - if (!vrf_name) - vrf_name = VRF_DEFAULT_NAME; + struct vrf *vrf; + int ret, count; /* * This command requires special handling to maintain backward @@ -1210,30 +1180,30 @@ DEFPY_YANG_NOSH (interface, * interface is found, then a new one should be created on the default * VRF. */ - VRF_GET_ID(vrf_id, vrf_name, false); - ifp = if_lookup_by_name_all_vrf(ifname); - if (ifp && ifp->vrf_id != vrf_id) { - struct vrf *vrf; - + if (vrf_is_backend_netns()) { /* - * Special case 1: a VRF name was specified, but the found - * interface is associated to different VRF. Reject the command. + * For backward compatibility, if the VRF name is not specified + * and there is exactly one interface with this name in the + * system, use its VRF. Otherwise fallback to the default VRF. */ - if (vrf_id != VRF_DEFAULT) { - vty_out(vty, "%% interface %s not in %s vrf\n", ifname, - vrf_name); - return CMD_WARNING_CONFIG_FAILED; + if (!vrf_name) { + count = vrfname_by_ifname(ifname, &vrf_name); + if (count != 1) + vrf_name = VRF_DEFAULT_NAME; } - + } else { /* - * Special case 2: a VRF name was *not* specified, and the found - * interface is associated to a VRF other than the default one. - * Update vrf_id and vrf_name to account for that. + * If the interface already exists, use its VRF regardless of + * what user specified. We can't have same interface name in + * different VRFs with VRF-lite backend. */ - vrf = vrf_lookup_by_id(ifp->vrf_id); - assert(vrf); - vrf_id = ifp->vrf_id; - vrf_name = vrf->name; + ifp = if_lookup_by_name_all_vrf(ifname); + if (ifp) { + vrf_name = ifp->vrf->name; + } else { + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + } } snprintf(xpath_list, sizeof(xpath_list), @@ -1251,7 +1221,15 @@ DEFPY_YANG_NOSH (interface, * all interface-level commands are converted to the new * northbound model. */ - ifp = if_lookup_by_name(ifname, vrf_id); + if (vrf_is_backend_netns()) { + vrf = vrf_lookup_by_name(vrf_name); + if (vrf) + ifp = if_lookup_by_name_vrf(ifname, vrf); + else + ifp = NULL; + } else { + ifp = if_lookup_by_name_all_vrf(ifname); + } if (ifp) VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp); } @@ -1396,7 +1374,6 @@ static int lib_interface_create(struct nb_cb_create_args *args) { const char *ifname; const char *vrfname; - struct vrf *vrf; struct interface *ifp; ifname = yang_dnode_get_string(args->dnode, "./name"); @@ -1404,39 +1381,11 @@ static int lib_interface_create(struct nb_cb_create_args *args) switch (args->event) { case NB_EV_VALIDATE: - vrf = vrf_lookup_by_name(vrfname); - if (!vrf) { - zlog_warn("%s: VRF %s doesn't exist", __func__, - vrfname); - return NB_ERR_VALIDATION; - } - if (vrf->vrf_id == VRF_UNKNOWN) { - zlog_warn("%s: VRF %s is not active", __func__, - vrf->name); - return NB_ERR_VALIDATION; - } - - /* if VRF is netns or not yet known - init for instance - * then assumption is that passed config is exact - * then the user intent was not to use an other iface - */ - if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) { - ifp = if_lookup_by_name_all_vrf(ifname); - if (ifp && ifp->vrf_id != vrf->vrf_id) { - zlog_warn( - "%s: interface %s already exists in another VRF", - __func__, ifp->name); - return NB_ERR_VALIDATION; - } - } - break; case NB_EV_PREPARE: case NB_EV_ABORT: break; case NB_EV_APPLY: - vrf = vrf_lookup_by_name(vrfname); - assert(vrf); - ifp = if_get_by_name(ifname, vrf->vrf_id); + ifp = if_get_by_name(ifname, VRF_UNKNOWN, vrfname); ifp->configured = true; nb_running_set_entry(args->dnode, ifp); @@ -1487,7 +1436,7 @@ static const void *lib_interface_get_next(struct nb_cb_get_next_args *args) assert(vrf); pif = RB_MIN(if_name_head, &vrf->ifaces_by_name); } else { - vrf = vrf_lookup_by_id(pif->vrf_id); + vrf = pif->vrf; pif = RB_NEXT(if_name_head, pif); /* if no more interfaces, switch to next vrf */ while (pif == NULL) { @@ -1505,13 +1454,9 @@ static int lib_interface_get_keys(struct nb_cb_get_keys_args *args) { const struct interface *ifp = args->list_entry; - struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); - - assert(vrf); - args->keys->num = 2; strlcpy(args->keys->key[0], ifp->name, sizeof(args->keys->key[0])); - strlcpy(args->keys->key[1], vrf->name, sizeof(args->keys->key[1])); + strlcpy(args->keys->key[1], ifp->vrf->name, sizeof(args->keys->key[1])); return NB_OK; } @@ -251,8 +251,8 @@ struct interface { /* Interface MTU. */ unsigned int mtu; /* IPv4 MTU */ unsigned int - mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu - */ + mtu6; /* IPv6 MTU - probably, but not necessarily same as mtu + */ /* Link-layer information and hardware address */ enum zebra_link_type ll_type; @@ -293,6 +293,8 @@ struct interface { #endif /* HAVE_NET_RT_IFLIST */ struct route_node *node; + + struct vrf *vrf; vrf_id_t vrf_id; /* @@ -510,11 +512,6 @@ extern int if_cmp_name_func(const char *p1, const char *p2); */ extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id); -/* Create new interface, adds to name list only */ -extern struct interface *if_create_name(const char *name, vrf_id_t vrf_id); - -/* Create new interface, adds to index list only */ -extern struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id); extern struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex, vrf_id_t vrf_id); @@ -532,13 +529,11 @@ struct vrf; extern struct interface *if_lookup_by_name_all_vrf(const char *ifname); extern struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf); extern struct interface *if_lookup_by_name(const char *ifname, vrf_id_t vrf_id); -extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id); -extern struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); +extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id, + const char *vrf_name); /* Sets the index and adds to index list */ extern int if_set_index(struct interface *ifp, ifindex_t ifindex); -/* Sets the name and adds to name list */ -extern void if_set_name(struct interface *ifp, const char *name); /* Delete the interface, but do not free the structure, and leave it in the interface list. It is often advisable to leave the pseudo interface diff --git a/lib/lib_errors.c b/lib/lib_errors.c index 17695e6607..a139b9a14c 100644 --- a/lib/lib_errors.c +++ b/lib/lib_errors.c @@ -41,19 +41,19 @@ static struct log_ref ferr_lib_warn[] = { { .code = EC_LIB_LINUX_NS, .title = "The Linux namespace subsystem has encountered a parsing error", - .description = "During system startup an invalid parameter for the namesapce was give to FRR", + .description = "During system startup an invalid parameter for the namespace was give to FRR", .suggestion = "Gather log data and open an Issue. restart FRR", }, { .code = EC_LIB_SLOW_THREAD_CPU, .title = "The Event subsystem has detected a slow cpu time process", - .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug, or some combination therof. In this case total CPU time was over 5 seconds. Which indicates that FRR is very busy doing some work and should be addressed", + .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug, or some combination thereof. In this case total CPU time was over 5 seconds. Which indicates that FRR is very busy doing some work and should be addressed", .suggestion = "Gather log data and open an Issue", }, { .code = EC_LIB_SLOW_THREAD_WALL, .title = "The Event subsystem has detected a slow wall time process", - .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug or some combination therof. In this case total WALL time was over 5 seconds. Which indicates that FRR might be having trouble being scheduled or some system call is delaying", + .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug or some combination thereof. In this case total WALL time was over 5 seconds. Which indicates that FRR might be having trouble being scheduled or some system call is delaying", .suggestion = "Gather log data and open an Issue", }, { @@ -286,7 +286,7 @@ static struct log_ref ferr_lib_err[] = { }, { .code = EC_LIB_NB_CB_INVALID_PRIO, - .title = "Norhtbound callback has an invalid priority", + .title = "Northbound callback has an invalid priority", .description = "The northbound subsystem, during initialization, has detected a callback whose priority is invalid", .suggestion = "This is a bug; please report it" }, diff --git a/lib/libospf.h b/lib/libospf.h index d2bb29d80e..c8ada9d3c5 100644 --- a/lib/libospf.h +++ b/lib/libospf.h @@ -36,7 +36,7 @@ extern "C" { #define IPPROTO_OSPFIGP 89 #endif /* IPPROTO_OSPFIGP */ -/* Architectual Constants */ +/* Architectural Constants */ #ifdef DEBUG #define OSPF_LS_REFRESH_TIME 120 #else @@ -355,9 +355,6 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_ADD), DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE), DESC_ENTRY(ZEBRA_INTERFACE_BFD_DEST_UPDATE), - DESC_ENTRY(ZEBRA_IMPORT_ROUTE_REGISTER), - DESC_ENTRY(ZEBRA_IMPORT_ROUTE_UNREGISTER), - DESC_ENTRY(ZEBRA_IMPORT_CHECK_UPDATE), DESC_ENTRY(ZEBRA_BFD_DEST_REGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE), diff --git a/lib/netns_linux.c b/lib/netns_linux.c index cde842b88c..43c0d8c359 100644 --- a/lib/netns_linux.c +++ b/lib/netns_linux.c @@ -279,7 +279,7 @@ static void ns_disable_internal(struct ns *ns) } } -/* VRF list existance check by name. */ +/* VRF list existence check by name. */ static struct ns_map_nsid *ns_map_nsid_lookup_by_nsid(ns_id_t ns_id) { struct ns_map_nsid ns_map; diff --git a/lib/network.h b/lib/network.h index 4a9666984f..10ed917572 100644 --- a/lib/network.h +++ b/lib/network.h @@ -22,6 +22,13 @@ #ifndef _ZEBRA_NETWORK_H #define _ZEBRA_NETWORK_H +#ifdef HAVE_SYS_ENDIAN_H +#include <sys/endian.h> +#endif +#ifdef HAVE_ENDIAN_H +#include <endian.h> +#endif + #ifdef __cplusplus extern "C" { #endif @@ -45,6 +52,35 @@ extern int set_cloexec(int fd); extern float htonf(float); extern float ntohf(float); +/* force type for be64toh/htobe64 to be uint64_t, *without* a direct cast + * + * this is a workaround for false-positive printfrr warnings from FRR's + * frr-format GCC plugin that would be triggered from + * { printfrr("%"PRIu64, (uint64_t)be64toh(...)); } + * + * the key element here is that "(uint64_t)expr" causes the warning, while + * "({ uint64_t x = expr; x; })" does not. (The cast is the trigger, a + * variable of the same type works correctly.) + */ + +/* zap system definitions... */ +#ifdef be64toh +#undef be64toh +#endif +#ifdef htobe64 +#undef htobe64 +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +#define be64toh(x) ({ uint64_t r = __builtin_bswap64(x); r; }) +#define htobe64(x) ({ uint64_t r = __builtin_bswap64(x); r; }) +#elif BYTE_ORDER == BIG_ENDIAN +#define be64toh(x) ({ uint64_t r = (x); r; }) +#define htobe64(x) ({ uint64_t r = (x); r; }) +#else +#error nobody expects the endianish inquisition. check OS endian.h headers. +#endif + /** * Helper function that returns a random long value. The main purpose of * this function is to hide a `random()` call that gets flagged by coverity diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c index 76af494e30..e62a83cee2 100644 --- a/lib/northbound_confd.c +++ b/lib/northbound_confd.c @@ -425,8 +425,7 @@ static int frr_confd_cdb_read_cb(struct thread *thread) int *subp = NULL; int reslen = 0; - thread = NULL; - thread_add_read(master, frr_confd_cdb_read_cb, NULL, fd, &thread); + thread_add_read(master, frr_confd_cdb_read_cb, NULL, fd, &t_cdb_sub); if (cdb_read_subscription_socket2(fd, &cdb_ev, &flags, &subp, &reslen) != CONFD_OK) { @@ -1164,15 +1163,10 @@ exit: } -static int frr_confd_dp_read(struct thread *thread) +static int frr_confd_dp_read(struct confd_daemon_ctx *dctx, int fd) { - struct confd_daemon_ctx *dctx = THREAD_ARG(thread); - int fd = THREAD_FD(thread); int ret; - thread = NULL; - thread_add_read(master, frr_confd_dp_read, dctx, fd, &thread); - ret = confd_fd_ready(dctx, fd); if (ret == CONFD_EOF) { flog_err_confd("confd_fd_ready"); @@ -1187,6 +1181,26 @@ static int frr_confd_dp_read(struct thread *thread) return 0; } +static int frr_confd_dp_ctl_read(struct thread *thread) +{ + struct confd_daemon_ctx *dctx = THREAD_ARG(thread); + int fd = THREAD_FD(thread); + + thread_add_read(master, frr_confd_dp_ctl_read, dctx, fd, &t_dp_ctl); + + frr_confd_dp_read(dctx, fd); +} + +static int frr_confd_dp_worker_read(struct thread *thread) +{ + struct confd_daemon_ctx *dctx = THREAD_ARG(thread); + int fd = THREAD_FD(thread); + + thread_add_read(master, frr_confd_dp_worker_read, dctx, fd, &t_dp_worker); + + frr_confd_dp_read(dctx, fd); +} + static int frr_confd_subscribe_state(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node = snode->priv; @@ -1314,9 +1328,9 @@ static int frr_confd_init_dp(const char *program_name) goto error; } - thread_add_read(master, frr_confd_dp_read, dctx, dp_ctl_sock, + thread_add_read(master, frr_confd_dp_ctl_read, dctx, dp_ctl_sock, &t_dp_ctl); - thread_add_read(master, frr_confd_dp_read, dctx, dp_worker_sock, + thread_add_read(master, frr_confd_dp_worker_read, dctx, dp_worker_sock, &t_dp_worker); return 0; diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp index 71f07dfe86..e227d0385c 100644 --- a/lib/northbound_grpc.cpp +++ b/lib/northbound_grpc.cpp @@ -344,6 +344,10 @@ static struct lyd_node *get_dnode_config(const std::string &path) { struct lyd_node *dnode; + if (!yang_dnode_exists(running_config->dnode, + path.empty() ? NULL : path.c_str())) + return NULL; + dnode = yang_dnode_get(running_config->dnode, path.empty() ? NULL : path.c_str()); if (dnode) diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c index 7c463dd61f..86a159e507 100644 --- a/lib/northbound_sysrepo.c +++ b/lib/northbound_sysrepo.c @@ -528,19 +528,18 @@ static int frr_sr_notification_send(const char *xpath, struct list *arguments) static int frr_sr_read_cb(struct thread *thread) { - sr_subscription_ctx_t *sr_subscription = THREAD_ARG(thread); + struct yang_module *module = THREAD_ARG(thread); int fd = THREAD_FD(thread); int ret; - ret = sr_process_events(sr_subscription, session, NULL); + ret = sr_process_events(module->sr_subscription, session, NULL); if (ret != SR_ERR_OK) { flog_err(EC_LIB_LIBSYSREPO, "%s: sr_fd_event_process(): %s", __func__, sr_strerror(ret)); return -1; } - thread = NULL; - thread_add_read(master, frr_sr_read_cb, sr_subscription, fd, &thread); + thread_add_read(master, frr_sr_read_cb, module, fd, &module->sr_thread); return 0; } @@ -703,7 +702,7 @@ static int frr_sr_init(void) sr_strerror(ret)); goto cleanup; } - thread_add_read(master, frr_sr_read_cb, module->sr_subscription, + thread_add_read(master, frr_sr_read_cb, module, event_pipe, &module->sr_thread); } diff --git a/lib/prefix.c b/lib/prefix.c index ef7d2e59da..df753fe10b 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -113,7 +113,7 @@ const char *family2str(int family) return "?"; } -/* Address Famiy Identifier to Address Family converter. */ +/* Address Family Identifier to Address Family converter. */ int afi2family(afi_t afi) { if (afi == AFI_IP) diff --git a/lib/resolver.c b/lib/resolver.c index c2153e0a5e..4aba909f25 100644 --- a/lib/resolver.c +++ b/lib/resolver.c @@ -53,14 +53,14 @@ static int resolver_cb_socket_readable(struct thread *t) { struct resolver_state *r = THREAD_ARG(t); int fd = THREAD_FD(t); + struct thread **t_ptr; vector_set_index(r->read_threads, fd, THREAD_RUNNING); ares_process_fd(r->channel, fd, ARES_SOCKET_BAD); if (vector_lookup(r->read_threads, fd) == THREAD_RUNNING) { - t = NULL; + t_ptr = (struct thread **)vector_get_index(r->read_threads, fd); thread_add_read(r->master, resolver_cb_socket_readable, r, fd, - &t); - vector_set_index(r->read_threads, fd, t); + t_ptr); } resolver_update_timeouts(r); @@ -71,14 +71,14 @@ static int resolver_cb_socket_writable(struct thread *t) { struct resolver_state *r = THREAD_ARG(t); int fd = THREAD_FD(t); + struct thread **t_ptr; vector_set_index(r->write_threads, fd, THREAD_RUNNING); ares_process_fd(r->channel, ARES_SOCKET_BAD, fd); if (vector_lookup(r->write_threads, fd) == THREAD_RUNNING) { - t = NULL; + t_ptr = (struct thread **)vector_get_index(r->write_threads, fd); thread_add_write(r->master, resolver_cb_socket_writable, r, fd, - &t); - vector_set_index(r->write_threads, fd, t); + t_ptr); } resolver_update_timeouts(r); @@ -105,14 +105,15 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable, int writable) { struct resolver_state *r = (struct resolver_state *)data; - struct thread *t; + struct thread *t, **t_ptr; if (readable) { - t = vector_lookup_ensure(r->read_threads, fd); + t = vector_lookup(r->read_threads, fd); if (!t) { + t_ptr = (struct thread **)vector_get_index( + r->read_threads, fd); thread_add_read(r->master, resolver_cb_socket_readable, - r, fd, &t); - vector_set_index(r->read_threads, fd, t); + r, fd, t_ptr); } } else { t = vector_lookup(r->read_threads, fd); @@ -125,11 +126,12 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable, } if (writable) { - t = vector_lookup_ensure(r->write_threads, fd); + t = vector_lookup(r->write_threads, fd); if (!t) { + t_ptr = (struct thread **)vector_get_index( + r->write_threads, fd); thread_add_read(r->master, resolver_cb_socket_writable, - r, fd, &t); - vector_set_index(r->write_threads, fd, t); + r, fd, t_ptr); } } else { t = vector_lookup(r->write_threads, fd); diff --git a/lib/routemap.c b/lib/routemap.c index 5c60b7d1c6..6227ebf158 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -2480,7 +2480,7 @@ void route_map_notify_pentry_dependencies(const char *affected_name, do whatever the exit policy (EXIT, NEXT or GOTO) tells. on-match next - If this clause is matched, then the set statements are executed and then we drop through to the next clause - on-match goto n - If this clause is matched, then the set statments + on-match goto n - If this clause is matched, then the set statements are executed and then we goto the nth clause, or the first clause greater than this. In order to ensure route-maps *always* exit, you cannot jump backwards. diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index cadad15fa7..e2db511fc0 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -165,12 +165,10 @@ DEFPY_YANG( DEFPY_YANG( match_ip_address, match_ip_address_cmd, - "match ip address <(1-199)|(1300-2699)|WORD>$name", + "match ip address WORD$name", MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = @@ -187,13 +185,11 @@ DEFPY_YANG( DEFPY_YANG( no_match_ip_address, no_match_ip_address_cmd, - "no match ip address [<(1-199)|(1300-2699)|WORD>]", + "no match ip address [WORD]", NO_STR MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = @@ -246,12 +242,10 @@ DEFPY_YANG( DEFPY_YANG( match_ip_next_hop, match_ip_next_hop_cmd, - "match ip next-hop <(1-199)|(1300-2699)|WORD>$name", + "match ip next-hop WORD$name", MATCH_STR IP_STR "Match next-hop address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = @@ -268,13 +262,11 @@ DEFPY_YANG( DEFPY_YANG( no_match_ip_next_hop, no_match_ip_next_hop_cmd, - "no match ip next-hop [<(1-199)|(1300-2699)|WORD>]", + "no match ip next-hop [WORD]", NO_STR MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = diff --git a/lib/sbuf.h b/lib/sbuf.h index 9f0311006d..aaa2db0edb 100644 --- a/lib/sbuf.h +++ b/lib/sbuf.h @@ -35,7 +35,7 @@ extern "C" { * without any information about the previous parsing steps, is usually not very * helpful. * Using sbuf, the parser can log the whole parsing process into a buffer using - * a printf like API. When an error ocurrs, all the information about previous + * a printf like API. When an error occurs, all the information about previous * parsing steps is there in the log, without any need for backtracking, and can * be used to give a detailed and useful error description. * When parsing completes successfully without any error, the log can just be diff --git a/lib/sigevent.c b/lib/sigevent.c index be7297f264..6710527ae9 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -96,7 +96,7 @@ int quagga_sigevent_process(void) struct quagga_signal_t *sig; int i; #ifdef SIGEVENT_BLOCK_SIGNALS - /* shouldnt need to block signals, but potentially may be needed */ + /* shouldn't need to block signals, but potentially may be needed */ sigset_t newmask, oldmask; /* @@ -142,7 +142,7 @@ int quagga_sigevent_process(void) } #ifdef SIGEVENT_SCHEDULE_THREAD -/* timer thread to check signals. Shouldnt be needed */ +/* timer thread to check signals. shouldn't be needed */ int quagga_signal_timer(struct thread *t) { struct quagga_sigevent_master_t *sigm; diff --git a/lib/skiplist.c b/lib/skiplist.c index c5219f7381..81407826f2 100644 --- a/lib/skiplist.c +++ b/lib/skiplist.c @@ -21,7 +21,7 @@ */ /* - * Skip List impementation based on code from William Pugh. + * Skip List implementation based on code from William Pugh. * ftp://ftp.cs.umd.edu/pub/skipLists/ * * Skip Lists are a probabilistic alternative to balanced trees, as diff --git a/lib/skiplist.h b/lib/skiplist.h index 00950e13bb..165607820a 100644 --- a/lib/skiplist.h +++ b/lib/skiplist.h @@ -21,7 +21,7 @@ */ /* - * Skip List impementation based on code from William Pugh. + * Skip List implementation based on code from William Pugh. * ftp://ftp.cs.umd.edu/pub/skipLists/ */ diff --git a/lib/sockopt.c b/lib/sockopt.c index 150736e00c..45f3c23330 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -122,7 +122,7 @@ int setsockopt_ipv6_pktinfo(int sock, int val) if (ret < 0) flog_err(EC_LIB_SOCKET, "can't setsockopt IPV6_PKTINFO : %s", safe_strerror(errno)); -#endif /* INIA_IPV6 */ +#endif /* IANA_IPV6 */ return ret; } @@ -595,7 +595,7 @@ int sockopt_tcp_signature_ext(int sock, union sockunion *su, uint16_t prefixlen, /* If this does not work, then all users of this sockopt will * need to - * differentiate between IPv4 and IPv6, and keep seperate + * differentiate between IPv4 and IPv6, and keep separate * sockets for * each. * diff --git a/lib/table.c b/lib/table.c index e6030ca4ca..523183bef2 100644 --- a/lib/table.c +++ b/lib/table.c @@ -393,7 +393,7 @@ void route_node_delete(struct route_node *node) route_node_delete(parent); } -/* Get fist node and lock it. This function is useful when one want +/* Get first node and lock it. This function is useful when one wants to lookup all the node exist in the routing table. */ struct route_node *route_top(struct route_table *table) { diff --git a/lib/thread.c b/lib/thread.c index 835aa38115..5dbba6363d 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -922,10 +922,10 @@ done: } /* Add new read thread. */ -struct thread *_thread_add_read_write(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, int fd, struct thread **t_ptr) +void _thread_add_read_write(const struct xref_threadsched *xref, + struct thread_master *m, + int (*func)(struct thread *), void *arg, int fd, + struct thread **t_ptr) { int dir = xref->thread_type; struct thread *thread = NULL; @@ -1000,15 +1000,13 @@ struct thread *_thread_add_read_write(const struct xref_threadsched *xref, AWAKEN(m); } - - return thread; } -static struct thread * -_thread_add_timer_timeval(const struct xref_threadsched *xref, - struct thread_master *m, int (*func)(struct thread *), - void *arg, struct timeval *time_relative, - struct thread **t_ptr) +static void _thread_add_timer_timeval(const struct xref_threadsched *xref, + struct thread_master *m, + int (*func)(struct thread *), void *arg, + struct timeval *time_relative, + struct thread **t_ptr) { struct thread *thread; struct timeval t; @@ -1028,7 +1026,7 @@ _thread_add_timer_timeval(const struct xref_threadsched *xref, frr_with_mutex(&m->mtx) { if (t_ptr && *t_ptr) /* thread is already scheduled; don't reschedule */ - return NULL; + return; thread = thread_get(m, THREAD_TIMER, func, arg, xref); @@ -1048,16 +1046,13 @@ _thread_add_timer_timeval(const struct xref_threadsched *xref, if (thread_timer_list_first(&m->timer) == thread) AWAKEN(m); } - - return thread; } /* Add timer event thread. */ -struct thread *_thread_add_timer(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, long timer, struct thread **t_ptr) +void _thread_add_timer(const struct xref_threadsched *xref, + struct thread_master *m, int (*func)(struct thread *), + void *arg, long timer, struct thread **t_ptr) { struct timeval trel; @@ -1066,15 +1061,14 @@ struct thread *_thread_add_timer(const struct xref_threadsched *xref, trel.tv_sec = timer; trel.tv_usec = 0; - return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); + _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); } /* Add timer event thread with "millisecond" resolution */ -struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, long timer, - struct thread **t_ptr) +void _thread_add_timer_msec(const struct xref_threadsched *xref, + struct thread_master *m, + int (*func)(struct thread *), void *arg, long timer, + struct thread **t_ptr) { struct timeval trel; @@ -1083,24 +1077,21 @@ struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref, trel.tv_sec = timer / 1000; trel.tv_usec = 1000 * (timer % 1000); - return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); + _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); } /* Add timer event thread with "timeval" resolution */ -struct thread *_thread_add_timer_tv(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, struct timeval *tv, - struct thread **t_ptr) +void _thread_add_timer_tv(const struct xref_threadsched *xref, + struct thread_master *m, int (*func)(struct thread *), + void *arg, struct timeval *tv, struct thread **t_ptr) { - return _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr); + _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr); } /* Add simple event thread. */ -struct thread *_thread_add_event(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, int val, struct thread **t_ptr) +void _thread_add_event(const struct xref_threadsched *xref, + struct thread_master *m, int (*func)(struct thread *), + void *arg, int val, struct thread **t_ptr) { struct thread *thread = NULL; @@ -1128,8 +1119,6 @@ struct thread *_thread_add_event(const struct xref_threadsched *xref, AWAKEN(m); } - - return thread; } /* Thread cancellation ------------------------------------------------------ */ @@ -2059,3 +2048,11 @@ void debug_signals(const sigset_t *sigs) zlog_debug("%s: %s", __func__, buf); } + +bool thread_is_scheduled(struct thread *thread) +{ + if (thread == NULL) + return false; + + return true; +} diff --git a/lib/thread.h b/lib/thread.h index abd94ff4f0..39f21da11d 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -219,26 +219,30 @@ void thread_master_set_name(struct thread_master *master, const char *name); extern void thread_master_free(struct thread_master *); extern void thread_master_free_unused(struct thread_master *); -extern struct thread *_thread_add_read_write( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, int fd, struct thread **tref); - -extern struct thread *_thread_add_timer( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, long t, struct thread **tref); - -extern struct thread *_thread_add_timer_msec( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, long t, struct thread **tref); - -extern struct thread *_thread_add_timer_tv( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, struct timeval *tv, - struct thread **tref); - -extern struct thread *_thread_add_event( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, int val, struct thread **tref); +extern void _thread_add_read_write(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, + int fd, struct thread **tref); + +extern void _thread_add_timer(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, long t, + struct thread **tref); + +extern void _thread_add_timer_msec(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, + long t, struct thread **tref); + +extern void _thread_add_timer_tv(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, + struct timeval *tv, struct thread **tref); + +extern void _thread_add_event(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, int val, + struct thread **tref); extern void _thread_execute(const struct xref_threadsched *xref, struct thread_master *master, @@ -273,6 +277,7 @@ extern pthread_key_t thread_current; extern char *thread_timer_to_hhmmss(char *buf, int buf_size, struct thread *t_timer); +extern bool thread_is_scheduled(struct thread *thread); /* Debug signal mask */ void debug_signals(const sigset_t *sigs); diff --git a/lib/typerb.c b/lib/typerb.c index 092faa4cc9..e1346df191 100644 --- a/lib/typerb.c +++ b/lib/typerb.c @@ -45,6 +45,7 @@ #include "config.h" #endif +#include <string.h> #include "typerb.h" #define RB_BLACK 0 @@ -330,6 +331,7 @@ color: rbe_remove_color(rbt, parent, child); rbt->count--; + memset(old, 0, sizeof(*old)); return (old); } @@ -478,3 +480,11 @@ struct rb_entry *typed_rb_min(const struct rbt_tree *rbt) return parent; } + +bool typed_rb_member(const struct typed_rb_root *rbt, + const struct typed_rb_entry *rbe) +{ + while (rbe->rbt_parent) + rbe = rbe->rbt_parent; + return rbe == rbt->rbt_root; +} diff --git a/lib/typerb.h b/lib/typerb.h index cbed8d4893..d22d864aae 100644 --- a/lib/typerb.h +++ b/lib/typerb.h @@ -62,6 +62,8 @@ const struct typed_rb_entry *typed_rb_find_lt(const struct typed_rb_root *rbt, const struct typed_rb_entry *b)); struct typed_rb_entry *typed_rb_min(const struct typed_rb_root *rbt); struct typed_rb_entry *typed_rb_next(const struct typed_rb_entry *rbe); +bool typed_rb_member(const struct typed_rb_root *rbt, + const struct typed_rb_entry *rbe); #define _PREDECL_RBTREE(prefix) \ struct prefix ## _head { struct typed_rb_root rr; }; \ @@ -142,6 +144,11 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->rr.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + return typed_rb_member(&h->rr, &item->field.re); \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ #define PREDECL_RBTREE_UNIQ(prefix) \ diff --git a/lib/typesafe.c b/lib/typesafe.c index 76705fad0d..f90b59daf0 100644 --- a/lib/typesafe.c +++ b/lib/typesafe.c @@ -29,6 +29,46 @@ DEFINE_MTYPE_STATIC(LIB, TYPEDHASH_BUCKET, "Typed-hash bucket"); DEFINE_MTYPE_STATIC(LIB, SKIPLIST_OFLOW, "Skiplist overflow"); DEFINE_MTYPE_STATIC(LIB, HEAP_ARRAY, "Typed-heap array"); +struct slist_item typesafe_slist_sentinel = { NULL }; + +bool typesafe_list_member(const struct slist_head *head, + const struct slist_item *item) +{ + struct slist_item *fromhead = head->first; + struct slist_item **fromnext = (struct slist_item **)&item->next; + + while (fromhead != _SLIST_LAST) { + if (fromhead == item || fromnext == head->last_next) + return true; + + fromhead = fromhead->next; + if (!*fromnext || *fromnext == _SLIST_LAST) + break; + fromnext = &(*fromnext)->next; + } + + return false; +} + +bool typesafe_dlist_member(const struct dlist_head *head, + const struct dlist_item *item) +{ + const struct dlist_item *fromhead = head->hitem.next; + const struct dlist_item *fromitem = item->next; + + if (!item->prev || !item->next) + return false; + + while (fromhead != &head->hitem && fromitem != item) { + if (fromitem == &head->hitem || fromhead == item) + return true; + fromhead = fromhead->next; + fromitem = fromitem->next; + } + + return false; +} + #if 0 static void hash_consistency_check(struct thash_head *head) { diff --git a/lib/typesafe.h b/lib/typesafe.h index ecac1a4381..44c42ffbca 100644 --- a/lib/typesafe.h +++ b/lib/typesafe.h @@ -78,8 +78,34 @@ macro_inline type *prefix ## _find_gteq(struct prefix##_head *h, \ } \ /* ... */ +/* *_member via find - when there is no better membership check than find() */ +#define TYPESAFE_MEMBER_VIA_FIND(prefix, type) \ +macro_inline bool prefix ## _member(struct prefix##_head *h, \ + const type *item) \ +{ \ + return item == prefix ## _const_find(h, item); \ +} \ +/* ... */ + +/* *_member via find_gteq - same for non-unique containers */ +#define TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \ +macro_inline bool prefix ## _member(struct prefix##_head *h, \ + const type *item) \ +{ \ + const type *iter; \ + for (iter = prefix ## _const_find_gteq(h, item); iter; \ + iter = prefix ## _const_next(h, iter)) { \ + if (iter == item) \ + return true; \ + if (cmpfn(iter, item) > 0) \ + break; \ + } \ + return false; \ +} \ +/* ... */ + /* SWAP_ALL_SIMPLE = for containers where the items don't point back to the - * head *AND* the head doesn'T points to itself (= everything except LIST, + * head *AND* the head doesn't point to itself (= everything except LIST, * DLIST and SKIPLIST), just switch out the entire head */ #define TYPESAFE_SWAP_ALL_SIMPLE(prefix) \ @@ -106,6 +132,10 @@ struct slist_head { size_t count; }; +/* this replaces NULL as the value for ->next on the last item. */ +extern struct slist_item typesafe_slist_sentinel; +#define _SLIST_LAST &typesafe_slist_sentinel + static inline void typesafe_list_add(struct slist_head *head, struct slist_item **pos, struct slist_item *item) { @@ -116,6 +146,9 @@ static inline void typesafe_list_add(struct slist_head *head, head->count++; } +extern bool typesafe_list_member(const struct slist_head *head, + const struct slist_item *item); + /* use as: * * PREDECL_LIST(namelist); @@ -136,6 +169,7 @@ MACRO_REQUIRE_SEMICOLON() /* end */ macro_inline void prefix ## _init(struct prefix##_head *h) \ { \ memset(h, 0, sizeof(*h)); \ + h->sh.first = _SLIST_LAST; \ h->sh.last_next = &h->sh.first; \ } \ macro_inline void prefix ## _fini(struct prefix##_head *h) \ @@ -161,25 +195,27 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ struct slist_item **iter = &h->sh.first; \ - while (*iter && *iter != &item->field.si) \ + while (*iter != _SLIST_LAST && *iter != &item->field.si) \ iter = &(*iter)->next; \ - if (!*iter) \ + if (*iter == _SLIST_LAST) \ return NULL; \ h->sh.count--; \ *iter = item->field.si.next; \ - if (!item->field.si.next) \ + if (item->field.si.next == _SLIST_LAST) \ h->sh.last_next = iter; \ + item->field.si.next = NULL; \ return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { \ struct slist_item *sitem = h->sh.first; \ - if (!sitem) \ + if (sitem == _SLIST_LAST) \ return NULL; \ h->sh.count--; \ h->sh.first = sitem->next; \ - if (h->sh.first == NULL) \ + if (h->sh.first == _SLIST_LAST) \ h->sh.last_next = &h->sh.first; \ + sitem->next = NULL; \ return container_of(sitem, type, field.si); \ } \ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ @@ -195,13 +231,17 @@ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ } \ macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \ { \ - return container_of_null(h->sh.first, type, field.si); \ + if (h->sh.first != _SLIST_LAST) \ + return container_of(h->sh.first, type, field.si); \ + return NULL; \ } \ macro_pure const type *prefix ## _const_next(const struct prefix##_head *h, \ const type *item) \ { \ const struct slist_item *sitem = &item->field.si; \ - return container_of_null(sitem->next, type, field.si); \ + if (sitem->next != _SLIST_LAST) \ + return container_of(sitem->next, type, field.si); \ + return NULL; \ } \ TYPESAFE_FIRST_NEXT(prefix, type) \ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ @@ -210,12 +250,23 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ if (!item) \ return NULL; \ sitem = &item->field.si; \ - return container_of_null(sitem->next, type, field.si); \ + if (sitem->next != _SLIST_LAST) \ + return container_of(sitem->next, type, field.si); \ + return NULL; \ } \ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->sh.count; \ } \ +macro_pure bool prefix ## _anywhere(const type *item) \ +{ \ + return item->field.si.next != NULL; \ +} \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + return typesafe_list_member(&h->sh, &item->field.si); \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ /* don't use these structs directly */ @@ -267,6 +318,9 @@ static inline void typesafe_dlist_swap_all(struct dlist_head *a, } } +extern bool typesafe_dlist_member(const struct dlist_head *head, + const struct dlist_item *item); + /* double-linked list, for fast item deletion */ #define PREDECL_DLIST(prefix) \ @@ -321,6 +375,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ ditem->prev->next = ditem->next; \ ditem->next->prev = ditem->prev; \ h->dh.count--; \ + ditem->prev = ditem->next = NULL; \ return container_of(ditem, type, field.di); \ } \ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ @@ -354,6 +409,16 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->dh.count; \ } \ +macro_pure bool prefix ## _anywhere(const type *item) \ +{ \ + const struct dlist_item *ditem = &item->field.di; \ + return ditem->next && ditem->prev; \ +} \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + return typesafe_dlist_member(&h->dh, &item->field.di); \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ /* note: heap currently caps out at 4G items */ @@ -463,6 +528,14 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->hh.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + uint32_t idx = item->field.hi.index; \ + if (idx >= h->hh.count) \ + return false; \ + return h->hh.array[idx] == &item->field.hi; \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ extern void typesafe_heap_resize(struct heap_head *head, bool grow); @@ -565,6 +638,7 @@ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ return NULL; \ h->sh.count--; \ *iter = item->field.si.next; \ + item->field.si.next = NULL; \ return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ @@ -618,6 +692,7 @@ macro_inline const type *prefix ## _const_find(const struct prefix##_head *h, \ return container_of(sitem, type, field.si); \ } \ TYPESAFE_FIND(prefix, type) \ +TYPESAFE_MEMBER_VIA_FIND(prefix, type) \ MACRO_REQUIRE_SEMICOLON() /* end */ #define DECLARE_SORTLIST_NONUNIQ(prefix, type, field, cmpfn) \ @@ -633,6 +708,7 @@ macro_inline int _ ## prefix ## _cmp(const type *a, const type *b) \ return 0; \ } \ _DECLARE_SORTLIST(prefix, type, field, cmpfn, _ ## prefix ## _cmp); \ +TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \ MACRO_REQUIRE_SEMICOLON() /* end */ @@ -799,6 +875,19 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->hh.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + uint32_t hval = item->field.hi.hashval, hbits = HASH_KEY(h->hh, hval); \ + const struct thash_item *hitem = h->hh.entries[hbits]; \ + while (hitem && hitem->hashval < hval) \ + hitem = hitem->next; \ + for (hitem = h->hh.entries[hbits]; hitem && hitem->hashval <= hval; \ + hitem = hitem->next) \ + if (hitem == &item->field.hi) \ + return true; \ + return false; \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ /* skiplist, sorted. @@ -937,6 +1026,7 @@ macro_inline const type *prefix ## _const_find(const struct prefix##_head *h, \ return container_of_null(sitem, type, field.si); \ } \ TYPESAFE_FIND(prefix, type) \ +TYPESAFE_MEMBER_VIA_FIND(prefix, type) \ \ _DECLARE_SKIPLIST(prefix, type, field, \ prefix ## __cmp, prefix ## __cmp); \ @@ -968,6 +1058,7 @@ macro_inline int prefix ## __cmp_uq(const struct sskip_item *a, \ \ _DECLARE_SKIPLIST(prefix, type, field, \ prefix ## __cmp, prefix ## __cmp_uq); \ +TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \ MACRO_REQUIRE_SEMICOLON() /* end */ diff --git a/lib/vector.c b/lib/vector.c index 565c49fd59..38f9b1b85f 100644 --- a/lib/vector.c +++ b/lib/vector.c @@ -37,6 +37,7 @@ vector vector_init(unsigned int size) v->alloced = size; v->active = 0; + v->count = 0; v->index = XCALLOC(MTYPE_VECTOR_INDEX, sizeof(void *) * size); return v; } @@ -54,6 +55,7 @@ vector vector_copy(vector v) new->active = v->active; new->alloced = v->alloced; + new->count = v->count; size = sizeof(void *) * (v->alloced); new->index = XCALLOC(MTYPE_VECTOR_INDEX, size); @@ -84,6 +86,9 @@ int vector_empty_slot(vector v) { unsigned int i; + if (v->active == v->count) + return v->active; + if (v->active == 0) return 0; @@ -102,6 +107,10 @@ int vector_set(vector v, void *val) i = vector_empty_slot(v); vector_ensure(v, i); + if (v->index[i]) + v->count--; + if (val) + v->count++; v->index[i] = val; if (v->active <= i) @@ -115,6 +124,10 @@ int vector_set_index(vector v, unsigned int i, void *val) { vector_ensure(v, i); + if (v->index[i]) + v->count--; + if (val) + v->count++; v->index[i] = val; if (v->active <= i) @@ -123,6 +136,17 @@ int vector_set_index(vector v, unsigned int i, void *val) return i; } +/* Make a specified index slot active and return its address. */ +void **vector_get_index(vector v, unsigned int i) +{ + vector_ensure(v, i); + + if (v->active <= i) + v->active = i + 1; + + return &v->index[i]; +} + /* Look up vector. */ void *vector_lookup(vector v, unsigned int i) { @@ -144,6 +168,9 @@ void vector_unset(vector v, unsigned int i) if (i >= v->alloced) return; + if (v->index[i]) + v->count--; + v->index[i] = NULL; if (i + 1 == v->active) { @@ -158,6 +185,9 @@ void vector_remove(vector v, unsigned int ix) if (ix >= v->active) return; + if (v->index[ix]) + v->count--; + int n = (--v->active) - ix; memmove(&v->index[ix], &v->index[ix + 1], n * sizeof(void *)); @@ -181,6 +211,7 @@ void vector_unset_value(vector v, void *val) for (i = 0; i < v->active; i++) if (v->index[i] == val) { v->index[i] = NULL; + v->count--; break; } @@ -190,19 +221,6 @@ void vector_unset_value(vector v, void *val) while (i && v->index[--i] == NULL); } -/* Count the number of not emplty slot. */ -unsigned int vector_count(vector v) -{ - unsigned int i; - unsigned count = 0; - - for (i = 0; i < v->active; i++) - if (v->index[i] != NULL) - count++; - - return count; -} - void vector_to_array(vector v, void ***dest, int *argc) { *dest = XCALLOC(MTYPE_TMP, sizeof(void *) * v->active); diff --git a/lib/vector.h b/lib/vector.h index d5857eb599..6208be1cc7 100644 --- a/lib/vector.h +++ b/lib/vector.h @@ -32,6 +32,7 @@ extern "C" { struct _vector { unsigned int active; /* number of active slots */ unsigned int alloced; /* number of allocated slot */ + unsigned int count; void **index; /* index to data */ }; typedef struct _vector *vector; @@ -54,12 +55,17 @@ extern void vector_ensure(vector v, unsigned int num); extern int vector_empty_slot(vector v); extern int vector_set(vector v, void *val); extern int vector_set_index(vector v, unsigned int i, void *val); +extern void **vector_get_index(vector v, unsigned int i); extern void vector_unset(vector v, unsigned int i); extern void vector_unset_value(vector v, void *val); extern void vector_remove(vector v, unsigned int ix); extern void vector_compact(vector v); -extern unsigned int vector_count(vector v); +static inline unsigned int vector_count(vector v) +{ + return v->count; +} + extern void vector_free(vector v); extern vector vector_copy(vector v); @@ -272,32 +272,29 @@ void vrf_delete(struct vrf *vrf) if (vrf_is_enabled(vrf)) vrf_disable(vrf); + if (vrf->vrf_id != VRF_UNKNOWN) { + RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); + vrf->vrf_id = VRF_UNKNOWN; + } + /* If the VRF is user configured, it'll stick around, just remove * the ID mapping. Interfaces assigned to this VRF should've been * removed already as part of the VRF going down. */ if (vrf_is_user_cfged(vrf)) { - if (vrf->vrf_id != VRF_UNKNOWN) { - /* Delete any VRF interfaces - should be only - * the VRF itself, other interfaces should've - * been moved out of the VRF. - */ - if_terminate(vrf); - RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); - vrf->vrf_id = VRF_UNKNOWN; - } vrf->ns_ctxt = NULL; return; } + /* Do not delete the VRF if it has interfaces configured in it. */ + if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) + return; + if (vrf_master.vrf_delete_hook) (*vrf_master.vrf_delete_hook)(vrf); QOBJ_UNREG(vrf); - if_terminate(vrf); - if (vrf->vrf_id != VRF_UNKNOWN) - RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); if (vrf->name[0] != '\0') RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf); @@ -571,6 +568,7 @@ static void vrf_terminate_single(struct vrf *vrf) { /* Clear configured flag and invoke delete. */ UNSET_FLAG(vrf->status, VRF_CONFIGURED); + if_terminate(vrf); vrf_delete(vrf); } @@ -776,7 +776,7 @@ static void vty_end_config(struct vty *vty) vty->cp = 0; } -/* Delete a charcter at the current point. */ +/* Delete a character at the current point. */ static void vty_delete_char(struct vty *vty) { int i; @@ -2282,7 +2282,7 @@ static void vty_read_file(struct nb_config *config, FILE *confp) vty = vty_new(); /* vty_close won't close stderr; if some config command prints - * something it'll end up there. (not ideal; it'd be beter if output + * something it'll end up there. (not ideal; it'd be better if output * from a file-load went to logging instead. Also note that if this * function is called after daemonizing, stderr will be /dev/null.) * @@ -2697,19 +2697,21 @@ static struct thread_master *vty_master; static void vty_event_serv(enum event event, int sock) { - struct thread *vty_serv_thread = NULL; + struct thread **vty_serv_thread_ptr = NULL; switch (event) { case VTY_SERV: - vty_serv_thread = thread_add_read(vty_master, vty_accept, - NULL, sock, NULL); - vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); + vty_serv_thread_ptr = (struct thread **)vector_get_index( + Vvty_serv_thread, sock); + thread_add_read(vty_master, vty_accept, NULL, sock, + vty_serv_thread_ptr); break; #ifdef VTYSH case VTYSH_SERV: - vty_serv_thread = thread_add_read(vty_master, vtysh_accept, - NULL, sock, NULL); - vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); + vty_serv_thread_ptr = (struct thread **)vector_get_index( + Vvty_serv_thread, sock); + thread_add_read(vty_master, vtysh_accept, NULL, sock, + vty_serv_thread_ptr); break; #endif /* VTYSH */ default: @@ -3165,7 +3167,7 @@ void vty_init(struct thread_master *master_thread, bool do_command_logging) atexit(vty_stdio_atexit); - /* Initilize server thread vector. */ + /* Initialize server thread vector. */ Vvty_serv_thread = vector_init(VECTOR_MIN_SIZE); /* Install bgp top node. */ diff --git a/lib/vxlan.h b/lib/vxlan.h index 62963a6097..220fd8d232 100644 --- a/lib/vxlan.h +++ b/lib/vxlan.h @@ -26,7 +26,7 @@ extern "C" { #endif -/* EVPN MH DF election alogorithm */ +/* EVPN MH DF election algorithm */ #define EVPN_MH_DF_ALG_SERVICE_CARVING 0 #define EVPN_MH_DF_ALG_HRW 1 #define EVPN_MH_DF_ALG_PREF 2 diff --git a/lib/yang.h b/lib/yang.h index d4517f969a..d625b24f6a 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -183,7 +183,7 @@ extern int yang_snodes_iterate_subtree(const struct lysc_node *snode, void *arg); /* - * Iterate over all libyang schema nodes from all loeaded modules of from the + * Iterate over all libyang schema nodes from all loaded modules of the * given YANG module. * * module diff --git a/lib/zclient.c b/lib/zclient.c index dde60a6c90..90439d5e17 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -765,15 +765,17 @@ static int zclient_connect(struct thread *t) enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p, - bool exact_match, vrf_id_t vrf_id) + bool connected, + bool resolve_via_def, vrf_id_t vrf_id) { struct stream *s; s = zclient->obuf; stream_reset(s); zclient_create_header(s, command, vrf_id); - stream_putc(s, (exact_match) ? 1 : 0); - + stream_putc(s, (connected) ? 1 : 0); + stream_putc(s, (resolve_via_def) ? 1 : 0); + stream_putw(s, SAFI_UNICAST); stream_putw(s, PREFIX_FAMILY(p)); stream_putc(s, p->prefixlen); switch (PREFIX_FAMILY(p)) { @@ -1925,6 +1927,7 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr) memset(nhr, 0, sizeof(*nhr)); STREAM_GETL(s, nhr->message); + STREAM_GETW(s, nhr->safi); STREAM_GETW(s, nhr->prefix.family); STREAM_GETC(s, nhr->prefix.prefixlen); switch (nhr->prefix.family) { @@ -2096,7 +2099,7 @@ stream_failure: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Harware Address Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Hardware Address if HW lenght different from 0 | + * | Hardware Address if HW length different from 0 | * | ... max INTERFACE_HWADDR_MAX | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Link_params? | Whether a link-params follows: 1 or 0. @@ -2161,19 +2164,21 @@ static int zclient_interface_add(struct zclient *zclient, vrf_id_t vrf_id) struct interface *ifp; char ifname_tmp[INTERFACE_NAMSIZ + 1] = {}; struct stream *s = zclient->ibuf; + struct vrf *vrf; /* Read interface name. */ STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ); /* Lookup/create interface by name. */ - if (!vrf_get(vrf_id, NULL)) { + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) { zlog_debug( "Rx'd interface add from Zebra, but VRF %u does not exist", vrf_id); return -1; } - ifp = if_get_by_name(ifname_tmp, vrf_id); + ifp = if_get_by_name(ifname_tmp, vrf_id, vrf->name); zebra_interface_if_set_value(s, ifp); @@ -2435,7 +2440,7 @@ size_t zebra_interface_link_params_write(struct stream *s, } /* - * format of message for address additon is: + * format of message for address addition is: * 0 * 0 1 2 3 4 5 6 7 * +-+-+-+-+-+-+-+-+ @@ -2700,9 +2705,9 @@ static int zclient_read_sync_response(struct zclient *zclient, return 0; } /** - * Connect to label manager in a syncronous way + * Connect to label manager in a synchronous way * - * It first writes the request to zcient output buffer and then + * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. * * @param zclient Zclient used to connect to label manager (zebra) @@ -2795,7 +2800,7 @@ stream_failure: } /** - * Function to request a srv6-locator chunk in an Asyncronous way + * Function to request a srv6-locator chunk in an asynchronous way * * @param zclient Zclient used to connect to table manager (zebra) * @param locator_name Name of SRv6-locator @@ -2905,9 +2910,9 @@ enum zclient_send_status zclient_send_get_label_chunk(struct zclient *zclient, } /** - * Function to request a label chunk in a syncronous way + * Function to request a label chunk in a synchronous way * - * It first writes the request to zlcient output buffer and then + * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. * * @param zclient Zclient used to connect to label manager (zebra) @@ -3082,9 +3087,9 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start, } /** - * Connect to table manager in a syncronous way + * Connect to table manager in a synchronous way * - * It first writes the request to zcient output buffer and then + * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. * * @param zclient Zclient used to connect to table manager (zebra) @@ -3141,7 +3146,7 @@ stream_failure: } /** - * Function to request a table chunk in a syncronous way + * Function to request a table chunk in a synchronous way * * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. @@ -4016,13 +4021,6 @@ static int zclient_read(struct thread *thread) (*zclient->nexthop_update)(command, zclient, length, vrf_id); break; - case ZEBRA_IMPORT_CHECK_UPDATE: - if (zclient_debug) - zlog_debug("zclient rcvd import check update"); - if (zclient->import_check_update) - (*zclient->import_check_update)(command, zclient, - length, vrf_id); - break; case ZEBRA_BFD_DEST_REPLAY: if (zclient->bfd_dest_replay) (*zclient->bfd_dest_replay)(command, zclient, length, diff --git a/lib/zclient.h b/lib/zclient.h index f9438d5db7..3cad9bd4fa 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -126,9 +126,6 @@ typedef enum { ZEBRA_INTERFACE_NBR_ADDRESS_ADD, ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, ZEBRA_INTERFACE_BFD_DEST_UPDATE, - ZEBRA_IMPORT_ROUTE_REGISTER, - ZEBRA_IMPORT_ROUTE_UNREGISTER, - ZEBRA_IMPORT_CHECK_UPDATE, ZEBRA_BFD_DEST_REGISTER, ZEBRA_BFD_DEST_DEREGISTER, ZEBRA_BFD_DEST_UPDATE, @@ -292,7 +289,7 @@ struct zclient { /* The thread master we schedule ourselves on */ struct thread_master *master; - /* Priviledges to change socket values */ + /* Privileges to change socket values */ struct zebra_privs_t *privs; /* Do we care about failure events for route install? */ @@ -332,7 +329,7 @@ struct zclient { struct redist_proto mi_redist[AFI_MAX][ZEBRA_ROUTE_MAX]; vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; - /* Redistribute defauilt. */ + /* Redistribute default. */ vrf_bitmap_t default_information[AFI_MAX]; #define ZAPI_CALLBACK_ARGS \ @@ -362,7 +359,6 @@ struct zclient { int (*interface_nbr_address_delete)(ZAPI_CALLBACK_ARGS); int (*interface_vrf_update)(ZAPI_CALLBACK_ARGS); int (*nexthop_update)(ZAPI_CALLBACK_ARGS); - int (*import_check_update)(ZAPI_CALLBACK_ARGS); int (*bfd_dest_replay)(ZAPI_CALLBACK_ARGS); int (*redistribute_route_add)(ZAPI_CALLBACK_ARGS); int (*redistribute_route_del)(ZAPI_CALLBACK_ARGS); @@ -1107,7 +1103,7 @@ extern enum zclient_send_status zclient_route_send(uint8_t, struct zclient *, struct zapi_route *); extern enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p, - bool exact_match, vrf_id_t vrf_id); + bool connected, bool resolve_via_default, vrf_id_t vrf_id); int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, uint32_t api_flags, uint32_t api_message); extern int zapi_route_encode(uint8_t, struct stream *, struct zapi_route *); |
