summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/agentx.c20
-rw-r--r--lib/atomlist.c2
-rw-r--r--lib/atomlist.h2
-rw-r--r--lib/bfd.c2
-rw-r--r--lib/buffer.c2
-rw-r--r--lib/command.c75
-rw-r--r--lib/command.h11
-rw-r--r--lib/command_graph.c157
-rw-r--r--lib/command_graph.h15
-rw-r--r--lib/command_match.h2
-rw-r--r--lib/command_parse.y16
-rw-r--r--lib/db.c2
-rw-r--r--lib/distribute.h2
-rw-r--r--lib/ferr.h2
-rw-r--r--lib/filter.c14
-rw-r--r--lib/filter_cli.c13
-rw-r--r--lib/frr_zmq.c45
-rw-r--r--lib/frr_zmq.h3
-rw-r--r--lib/frrscript.c2
-rw-r--r--lib/grammar_sandbox.c2
-rw-r--r--lib/graph.c2
-rw-r--r--lib/hash.h2
-rw-r--r--lib/hook.h2
-rw-r--r--lib/if.c289
-rw-r--r--lib/if.h17
-rw-r--r--lib/lib_errors.c8
-rw-r--r--lib/libospf.h2
-rw-r--r--lib/log.c3
-rw-r--r--lib/netns_linux.c2
-rw-r--r--lib/network.h36
-rw-r--r--lib/northbound_confd.c34
-rw-r--r--lib/northbound_grpc.cpp4
-rw-r--r--lib/northbound_sysrepo.c9
-rw-r--r--lib/prefix.c2
-rw-r--r--lib/resolver.c28
-rw-r--r--lib/routemap.c2
-rw-r--r--lib/routemap_cli.c16
-rw-r--r--lib/sbuf.h2
-rw-r--r--lib/sigevent.c4
-rw-r--r--lib/skiplist.c2
-rw-r--r--lib/skiplist.h2
-rw-r--r--lib/sockopt.c4
-rw-r--r--lib/table.c2
-rw-r--r--lib/thread.c71
-rw-r--r--lib/thread.h45
-rw-r--r--lib/typerb.c10
-rw-r--r--lib/typerb.h7
-rw-r--r--lib/typesafe.c40
-rw-r--r--lib/typesafe.h109
-rw-r--r--lib/vector.c44
-rw-r--r--lib/vector.h8
-rw-r--r--lib/vrf.c22
-rw-r--r--lib/vty.c22
-rw-r--r--lib/vxlan.h2
-rw-r--r--lib/yang.h2
-rw-r--r--lib/zclient.c42
-rw-r--r--lib/zclient.h10
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.
*
diff --git a/lib/bfd.c b/lib/bfd.c
index ea363b7ca4..5a8a46b67b 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -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);
}
;
diff --git a/lib/db.c b/lib/db.c
index 32ba83b656..b4286b8d2c 100644
--- a/lib/db.c
+++ b/lib/db.c
@@ -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) \
diff --git a/lib/if.c b/lib/if.c
index 424880ff42..cb6270f5ec 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -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;
}
diff --git a/lib/if.h b/lib/if.h
index 43e2d3cffa..1125acd204 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -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
diff --git a/lib/log.c b/lib/log.c
index 936422104f..8be171613e 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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);
diff --git a/lib/vrf.c b/lib/vrf.c
index 198d5253c8..6bc10b8cfd 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -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);
}
diff --git a/lib/vty.c b/lib/vty.c
index fef16f1ee7..5a03514be4 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -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 *);