summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.c26
-rw-r--r--lib/command.h93
-rw-r--r--lib/command_graph.c5
-rw-r--r--lib/command_graph.h9
-rw-r--r--lib/command_match.c3
-rw-r--r--lib/command_py.c10
-rw-r--r--lib/frrscript.c28
-rw-r--r--lib/frrscript.h5
-rw-r--r--lib/grammar_sandbox.c3
-rw-r--r--lib/if.c26
-rw-r--r--lib/if.h2
-rw-r--r--lib/libfrr.c4
-rw-r--r--lib/log_vty.c4
-rw-r--r--lib/orr_msg.h94
-rw-r--r--lib/prefix.c57
-rw-r--r--lib/prefix.h1
-rw-r--r--lib/routemap.c32
-rw-r--r--lib/routemap.h2
-rw-r--r--lib/sockopt.c49
-rw-r--r--lib/sockopt.h22
-rw-r--r--lib/srv6.c13
-rw-r--r--lib/srv6.h1
-rw-r--r--lib/subdir.am1
-rw-r--r--lib/typesafe.h9
-rw-r--r--lib/zclient.c69
-rw-r--r--lib/zclient.h6
26 files changed, 451 insertions, 123 deletions
diff --git a/lib/command.c b/lib/command.c
index a23afb1e43..1fae32a04a 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -48,6 +48,7 @@
#include "lib_errors.h"
#include "northbound_cli.h"
#include "network.h"
+#include "routemap.h"
#include "frrscript.h"
@@ -264,8 +265,7 @@ void install_node(struct cmd_node *node)
node->cmdgraph = graph_new();
node->cmd_vector = vector_init(VECTOR_MIN_SIZE);
// add start node
- struct cmd_token *token =
- cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
+ struct cmd_token *token = cmd_token_new(START_TKN, 0, NULL, NULL);
graph_new_node(node->cmdgraph, token,
(void (*)(void *)) & cmd_token_del);
@@ -325,7 +325,7 @@ void _install_element(enum node_type ntype, const struct cmd_element *cmd)
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);
+ cmd_token_new(START_TKN, 0, NULL, NULL);
graph_new_node(graph, token,
(void (*)(void *)) & cmd_token_del);
@@ -348,8 +348,7 @@ 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);
+ struct cmd_token *token = cmd_token_new(START_TKN, 0, NULL, NULL);
graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del);
@@ -404,7 +403,7 @@ void uninstall_element(enum node_type ntype, const struct cmd_element *cmd)
if (cnode->graph_built) {
struct graph *graph = graph_new();
struct cmd_token *token =
- cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
+ cmd_token_new(START_TKN, 0, NULL, NULL);
graph_new_node(graph, token,
(void (*)(void *)) & cmd_token_del);
@@ -990,7 +989,7 @@ static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
* Perform pending commit (if any) before executing
* non-YANG command.
*/
- if (matched_element->attr != CMD_ATTR_YANG)
+ if (!(matched_element->attr & CMD_ATTR_YANG))
(void)nb_cli_pending_commit_check(vty);
}
@@ -1471,8 +1470,7 @@ static void permute(struct graph_node *start, struct vty *vty)
for (unsigned int i = 0; i < vector_active(start->to); i++) {
struct graph_node *gn = vector_slot(start->to, i);
struct cmd_token *tok = gn->data;
- if (tok->attr == CMD_ATTR_HIDDEN
- || tok->attr == CMD_ATTR_DEPRECATED)
+ if (tok->attr & CMD_ATTR_HIDDEN)
continue;
else if (tok->type == END_TKN || gn == start) {
vty_out(vty, " ");
@@ -1561,9 +1559,8 @@ int cmd_list_cmds(struct vty *vty, int do_permute)
const struct cmd_element *element = NULL;
for (unsigned int i = 0; i < vector_active(node->cmd_vector);
i++)
- if ((element = vector_slot(node->cmd_vector, i))
- && element->attr != CMD_ATTR_DEPRECATED
- && element->attr != CMD_ATTR_HIDDEN) {
+ if ((element = vector_slot(node->cmd_vector, i)) &&
+ !(element->attr & CMD_ATTR_HIDDEN)) {
vty_out(vty, " ");
print_cmd(vty, element->string);
}
@@ -2446,6 +2443,11 @@ const char *host_config_get(void)
return host.config;
}
+void cmd_show_lib_debugs(struct vty *vty)
+{
+ route_map_show_debug(vty);
+}
+
void install_default(enum node_type node)
{
_install_element(node, &config_exit_cmd);
diff --git a/lib/command.h b/lib/command.h
index 70e52708a7..f4168dedd7 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -280,17 +280,18 @@ struct cmd_node {
int argc __attribute__((unused)), \
struct cmd_token *argv[] __attribute__((unused)))
-#define DEFPY(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
- funcdecl_##funcname
-
-#define DEFPY_NOSH(funcname, cmdname, cmdstr, helpstr) \
- DEFPY(funcname, cmdname, cmdstr, helpstr)
+/* DEFPY variants */
#define DEFPY_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) \
funcdecl_##funcname
+#define DEFPY(funcname, cmdname, cmdstr, helpstr) \
+ DEFPY_ATTR(funcname, cmdname, cmdstr, helpstr, 0)
+
+#define DEFPY_NOSH(funcname, cmdname, cmdstr, helpstr) \
+ DEFPY_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_NOSH)
+
#define DEFPY_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
DEFPY_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
@@ -298,18 +299,19 @@ struct cmd_node {
DEFPY_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_YANG)
#define DEFPY_YANG_NOSH(funcname, cmdname, cmdstr, helpstr) \
- DEFPY_YANG(funcname, cmdname, cmdstr, helpstr)
+ DEFPY_ATTR(funcname, cmdname, cmdstr, helpstr, \
+ CMD_ATTR_YANG | CMD_ATTR_NOSH)
-#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_FUNC_DECL(funcname) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
- DEFUN_CMD_FUNC_TEXT(funcname)
+/* DEFUN variants */
#define DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
DEFUN_CMD_FUNC_DECL(funcname) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) \
DEFUN_CMD_FUNC_TEXT(funcname)
+#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, 0)
+
#define DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
@@ -318,73 +320,55 @@ struct cmd_node {
/* DEFUN_NOSH for commands that vtysh should ignore */
#define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \
- DEFUN(funcname, cmdname, cmdstr, helpstr)
+ DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_NOSH)
#define DEFUN_YANG_NOSH(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_YANG(funcname, cmdname, cmdstr, helpstr)
+ DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, \
+ CMD_ATTR_YANG | CMD_ATTR_NOSH)
/* DEFSH for vtysh. */
+#define DEFSH_ATTR(daemon, cmdname, cmdstr, helpstr, attr) \
+ DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, attr, daemon)
+
#define DEFSH(daemon, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, 0, daemon)
+ DEFSH_ATTR(daemon, cmdname, cmdstr, helpstr, 0)
#define DEFSH_HIDDEN(daemon, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, \
- daemon)
-
-#define DEFSH_YANG(daemon, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, CMD_ATTR_YANG, daemon)
+ DEFSH_ATTR(daemon, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
/* DEFUN + DEFSH */
-#define DEFUNSH(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_FUNC_DECL(funcname) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) \
- DEFUN_CMD_FUNC_TEXT(funcname)
-
-/* DEFUN + DEFSH with attributes */
#define DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, attr) \
DEFUN_CMD_FUNC_DECL(funcname) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \
DEFUN_CMD_FUNC_TEXT(funcname)
+#define DEFUNSH(daemon, funcname, cmdname, cmdstr, helpstr) \
+ DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, 0)
+
#define DEFUNSH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, \
CMD_ATTR_HIDDEN)
-#define DEFUNSH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, \
- CMD_ATTR_DEPRECATED)
-
-#define DEFUNSH_YANG(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_YANG)
-
/* ALIAS macro which define existing command's alias. */
-#define ALIAS(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0)
-
#define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0)
+#define ALIAS(funcname, cmdname, cmdstr, helpstr) \
+ ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, 0)
+
#define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, \
- 0)
+ ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
+/* note: DEPRECATED implies HIDDEN, and other than that there is currently no
+ * difference. It's purely for expressing intent in the source code - a
+ * DEPRECATED command is supposed to go away, a HIDDEN one is likely to stay.
+ */
#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, \
- CMD_ATTR_DEPRECATED, 0)
+ ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, \
+ CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN)
#define ALIAS_YANG(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_YANG, 0)
-
-#define ALIAS_SH(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon)
-
-#define ALIAS_SH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, \
- daemon)
-
-#define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, \
- CMD_ATTR_DEPRECATED, daemon)
+ ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_YANG)
#endif /* VTYSH_EXTRACT_PL */
@@ -417,6 +401,7 @@ struct cmd_node {
#define BGP_SOFT_IN_STR "Send route-refresh unless using 'soft-reconfiguration inbound'\n"
#define BGP_SOFT_OUT_STR "Resend all outbound updates\n"
#define BGP_SOFT_RSCLIENT_RIB_STR "Soft reconfig for rsclient RIB\n"
+#define BGP_ORR_DEBUG "Enable Optimal Route Reflection Debugging logs\n"
#define OSPF_STR "OSPF information\n"
#define NEIGHBOR_STR "Specify neighbor router\n"
#define DEBUG_STR "Debugging functions\n"
@@ -649,6 +634,12 @@ extern char *cmd_variable_comp2str(vector comps, unsigned short cols);
extern void command_setup_early_logging(const char *dest, const char *level);
+/*
+ * Allow a mechanism for `debug XXX` commands that live
+ * under the lib directory to output their debug status
+ */
+extern void cmd_show_lib_debugs(struct vty *vty);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/command_graph.c b/lib/command_graph.c
index 09d802e796..e940685250 100644
--- a/lib/command_graph.c
+++ b/lib/command_graph.c
@@ -494,9 +494,10 @@ void cmd_graph_node_print_cb(struct graph_node *gn, struct buffer *buf)
snprintf(nbuf, sizeof(nbuf), "<b>%s</b>",
lookup_msg(tokennames, tok->type, NULL));
buffer_putstr(buf, nbuf);
- if (tok->attr == CMD_ATTR_DEPRECATED)
+ if (tok->attr & CMD_ATTR_DEPRECATED)
buffer_putstr(buf, " (d)");
- else if (tok->attr == CMD_ATTR_HIDDEN)
+ /* DEPRECATED implies HIDDEN, don't print both */
+ else if (tok->attr & CMD_ATTR_HIDDEN)
buffer_putstr(buf, " (h)");
if (tok->text) {
if (tok->type == WORD_TKN)
diff --git a/lib/command_graph.h b/lib/command_graph.h
index ed4da6aa4c..b8c7a9c72c 100644
--- a/lib/command_graph.h
+++ b/lib/command_graph.h
@@ -73,10 +73,11 @@ enum cmd_token_type {
#define IS_VARYING_TOKEN(x) ((x) >= VARIABLE_TKN && (x) < FORK_TKN)
/* Command attributes */
-enum { CMD_ATTR_NORMAL,
- CMD_ATTR_DEPRECATED,
- CMD_ATTR_HIDDEN,
- CMD_ATTR_YANG,
+enum {
+ CMD_ATTR_YANG = (1 << 0),
+ CMD_ATTR_HIDDEN = (1 << 1),
+ CMD_ATTR_DEPRECATED = (1 << 2),
+ CMD_ATTR_NOSH = (1 << 3),
};
enum varname_src {
diff --git a/lib/command_match.c b/lib/command_match.c
index f221e0a02c..ce2dbc9528 100644
--- a/lib/command_match.c
+++ b/lib/command_match.c
@@ -395,8 +395,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
for (ALL_LIST_ELEMENTS_RO(current, node, gstack)) {
struct cmd_token *token = gstack[0]->data;
- if (token->attr == CMD_ATTR_HIDDEN
- || token->attr == CMD_ATTR_DEPRECATED)
+ if (token->attr & CMD_ATTR_HIDDEN)
continue;
enum match_type minmatch = min_match_level(token->type);
diff --git a/lib/command_py.c b/lib/command_py.c
index 6301eec5e8..cce9542e30 100644
--- a/lib/command_py.c
+++ b/lib/command_py.c
@@ -226,8 +226,8 @@ static PyObject *graph_to_pyobj(struct wrap_graph *wgraph,
wrap->type = "???";
}
- wrap->deprecated = (tok->attr == CMD_ATTR_DEPRECATED);
- wrap->hidden = (tok->attr == CMD_ATTR_HIDDEN);
+ wrap->deprecated = !!(tok->attr & CMD_ATTR_DEPRECATED);
+ wrap->hidden = !!(tok->attr & CMD_ATTR_HIDDEN);
wrap->text = tok->text;
wrap->desc = tok->desc;
wrap->varname = tok->varname;
@@ -353,6 +353,12 @@ PyMODINIT_FUNC command_py_init(void)
if (!pymod)
initret(NULL);
+ if (PyModule_AddIntMacro(pymod, CMD_ATTR_YANG)
+ || PyModule_AddIntMacro(pymod, CMD_ATTR_HIDDEN)
+ || PyModule_AddIntMacro(pymod, CMD_ATTR_DEPRECATED)
+ || PyModule_AddIntMacro(pymod, CMD_ATTR_NOSH))
+ initret(NULL);
+
Py_INCREF(&typeobj_graph_node);
PyModule_AddObject(pymod, "GraphNode", (PyObject *)&typeobj_graph_node);
Py_INCREF(&typeobj_graph);
diff --git a/lib/frrscript.c b/lib/frrscript.c
index a19bd0c3db..2e56932613 100644
--- a/lib/frrscript.c
+++ b/lib/frrscript.c
@@ -184,13 +184,14 @@ static void *codec_alloc(void *arg)
return e;
}
-#if 0
-static void codec_free(struct codec *c)
+static void codec_free(void *data)
{
- XFREE(MTYPE_TMP, c->typename);
- XFREE(MTYPE_TMP, c);
+ struct frrscript_codec *c = data;
+ char *constworkaroundandihateit = (char *)c->typename;
+
+ XFREE(MTYPE_SCRIPT, constworkaroundandihateit);
+ XFREE(MTYPE_SCRIPT, c);
}
-#endif
/* Lua function hash utils */
@@ -212,17 +213,18 @@ bool lua_function_hash_cmp(const void *d1, const void *d2)
void *lua_function_alloc(void *arg)
{
struct lua_function_state *tmp = arg;
-
struct lua_function_state *lfs =
XCALLOC(MTYPE_SCRIPT, sizeof(struct lua_function_state));
+
lfs->name = tmp->name;
lfs->L = tmp->L;
return lfs;
}
-static void lua_function_free(struct hash_bucket *b, void *data)
+static void lua_function_free(void *data)
{
- struct lua_function_state *lfs = (struct lua_function_state *)b->data;
+ struct lua_function_state *lfs = data;
+
lua_close(lfs->L);
XFREE(MTYPE_SCRIPT, lfs);
}
@@ -409,7 +411,8 @@ fail:
void frrscript_delete(struct frrscript *fs)
{
- hash_iterate(fs->lua_function_hash, lua_function_free, NULL);
+ hash_clean(fs->lua_function_hash, lua_function_free);
+ hash_free(fs->lua_function_hash);
XFREE(MTYPE_SCRIPT, fs->name);
XFREE(MTYPE_SCRIPT, fs);
}
@@ -425,4 +428,11 @@ void frrscript_init(const char *sd)
frrscript_register_type_codecs(frrscript_codecs_lib);
}
+void frrscript_fini(void)
+{
+ hash_clean(codec_hash, codec_free);
+ hash_free(codec_hash);
+
+ frrscript_names_destroy();
+}
#endif /* HAVE_SCRIPTING */
diff --git a/lib/frrscript.h b/lib/frrscript.h
index 4db3e6f1b2..7fa01f70d1 100644
--- a/lib/frrscript.h
+++ b/lib/frrscript.h
@@ -162,6 +162,11 @@ void frrscript_register_type_codecs(struct frrscript_codec *codecs);
void frrscript_init(const char *scriptdir);
/*
+ * On shutdown clean up memory associated with the scripting subsystem
+ */
+void frrscript_fini(void);
+
+/*
* This macro is mapped to every (name, value) in frrscript_call,
* so this in turn maps them onto their encoders
*/
diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c
index f9778c5d4c..8fa47c053b 100644
--- a/lib/grammar_sandbox.c
+++ b/lib/grammar_sandbox.c
@@ -76,8 +76,7 @@ DEFUN (grammar_test,
// parse the command and install it into the command graph
struct graph *graph = graph_new();
- struct cmd_token *token =
- cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
+ struct cmd_token *token = cmd_token_new(START_TKN, 0, NULL, NULL);
graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del);
cmd_graph_parse(graph, cmd);
diff --git a/lib/if.c b/lib/if.c
index fa4fdb82d3..deb0690dcf 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1095,13 +1095,15 @@ const char *if_link_type_str(enum zebra_link_type llt)
struct if_link_params *if_link_params_get(struct interface *ifp)
{
- int i;
+ return ifp->link_params;
+}
- if (ifp->link_params != NULL)
- return ifp->link_params;
+struct if_link_params *if_link_params_enable(struct interface *ifp)
+{
+ struct if_link_params *iflp;
+ int i;
- struct if_link_params *iflp =
- XCALLOC(MTYPE_IF_LINK_PARAMS, sizeof(struct if_link_params));
+ iflp = if_link_params_init(ifp);
/* Compute default bandwidth based on interface */
iflp->default_bw =
@@ -1129,6 +1131,20 @@ struct if_link_params *if_link_params_get(struct interface *ifp)
return iflp;
}
+struct if_link_params *if_link_params_init(struct interface *ifp)
+{
+ struct if_link_params *iflp = if_link_params_get(ifp);
+
+ if (iflp)
+ return iflp;
+
+ iflp = XCALLOC(MTYPE_IF_LINK_PARAMS, sizeof(struct if_link_params));
+
+ ifp->link_params = iflp;
+
+ return iflp;
+}
+
void if_link_params_free(struct interface *ifp)
{
XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params);
diff --git a/lib/if.h b/lib/if.h
index 1c948b875a..478a90d63a 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -588,6 +588,8 @@ struct connected *connected_get_linklocal(struct interface *ifp);
/* link parameters */
struct if_link_params *if_link_params_get(struct interface *);
+struct if_link_params *if_link_params_enable(struct interface *ifp);
+struct if_link_params *if_link_params_init(struct interface *ifp);
void if_link_params_free(struct interface *);
/* Northbound. */
diff --git a/lib/libfrr.c b/lib/libfrr.c
index f5aecd9f75..aee6981854 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -1219,6 +1219,10 @@ void frr_fini(void)
db_close();
#endif
log_ref_fini();
+
+#ifdef HAVE_SCRIPTING
+ frrscript_fini();
+#endif
frr_pthread_finish();
zprivs_terminate(di->privs);
/* signal_init -> nothing needed */
diff --git a/lib/log_vty.c b/lib/log_vty.c
index 81280f302f..c9268734c4 100644
--- a/lib/log_vty.c
+++ b/lib/log_vty.c
@@ -761,8 +761,8 @@ DEFPY (log_immediate_mode,
log_immediate_mode_cmd,
"[no] log immediate-mode",
NO_STR
- "Logging control"
- "Output immediately, without buffering")
+ "Logging control\n"
+ "Output immediately, without buffering\n")
{
zlog_set_immediate(!no);
return CMD_SUCCESS;
diff --git a/lib/orr_msg.h b/lib/orr_msg.h
new file mode 100644
index 0000000000..b0c4c48df8
--- /dev/null
+++ b/lib/orr_msg.h
@@ -0,0 +1,94 @@
+/*
+ * Structures common to BGP, OSPF and ISIS for BGP Optimal Route Reflection
+ * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
+ * Madhurilatha Kuruganti
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _FRR_ORR_MSG_H
+#define _FRR_ORR_MSG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* REVISIT: Need to check if we can use zero length array */
+#define ORR_MAX_PREFIX 100
+#define ORR_GROUP_NAME_SIZE 32
+
+struct orr_prefix_metric {
+ struct prefix prefix;
+ uint32_t metric;
+};
+
+/* BGP-IGP Register for IGP metric */
+struct orr_igp_metric_reg {
+ bool reg;
+ uint8_t proto;
+ safi_t safi;
+ struct prefix prefix;
+ char group_name[ORR_GROUP_NAME_SIZE];
+};
+
+/* IGP-BGP message structures */
+struct orr_igp_metric_info {
+ /* IGP instance data. */
+ uint8_t proto;
+ uint32_t instId;
+
+ safi_t safi;
+
+ /* Add or delete routes */
+ bool add;
+
+ /* IGP metric from Active Root. */
+ struct prefix root;
+ uint32_t num_entries;
+ struct orr_prefix_metric nexthop[ORR_MAX_PREFIX];
+};
+
+/* BGP ORR Root node */
+struct orr_root {
+ afi_t afi;
+ safi_t safi;
+
+ char group_name[ORR_GROUP_NAME_SIZE];
+
+ /* MPLS_TE prefix and router ID */
+ struct prefix prefix;
+ struct in_addr router_id;
+
+ /* Advertising OSPF Router ID. */
+ struct in_addr adv_router;
+
+ /* BGP-ORR Received LSAs */
+ struct ospf_lsa *router_lsa_rcvd;
+
+ /* Routing tables from root node */
+ struct route_table *old_table; /* Old routing table. */
+ struct route_table *new_table; /* Current routing table. */
+
+ struct route_table *old_rtrs; /* Old ABR/ASBR RT. */
+ struct route_table *new_rtrs; /* New ABR/ASBR RT. */
+};
+
+/* Prototypes. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FRR_ORR_MSG_H */
diff --git a/lib/prefix.c b/lib/prefix.c
index e64b10bf24..4642f14d35 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1404,6 +1404,63 @@ bool ipv4_unicast_valid(const struct in_addr *addr)
return true;
}
+static int ipaddr2prefix(const struct ipaddr *ip, uint16_t prefixlen,
+ struct prefix *p)
+{
+ switch (ip->ipa_type) {
+ case (IPADDR_V4):
+ p->family = AF_INET;
+ p->u.prefix4 = ip->ipaddr_v4;
+ p->prefixlen = prefixlen;
+ break;
+ case (IPADDR_V6):
+ p->family = AF_INET6;
+ p->u.prefix6 = ip->ipaddr_v6;
+ p->prefixlen = prefixlen;
+ break;
+ case (IPADDR_NONE):
+ p->family = AF_UNSPEC;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Convert type-2 and type-5 evpn route prefixes into the more
+ * general ipv4/ipv6 prefix types so we can match prefix lists
+ * and such.
+ */
+int evpn_prefix2prefix(const struct prefix *evpn, struct prefix *to)
+{
+ const struct evpn_addr *addr;
+
+ if (evpn->family != AF_EVPN)
+ return -1;
+
+ addr = &evpn->u.prefix_evpn;
+
+ switch (addr->route_type) {
+ case BGP_EVPN_MAC_IP_ROUTE:
+ if (IS_IPADDR_V4(&addr->macip_addr.ip))
+ ipaddr2prefix(&addr->macip_addr.ip, 32, to);
+ else if (IS_IPADDR_V6(&addr->macip_addr.ip))
+ ipaddr2prefix(&addr->macip_addr.ip, 128, to);
+ else
+ return -1; /* mac only? */
+
+ break;
+ case BGP_EVPN_IP_PREFIX_ROUTE:
+ ipaddr2prefix(&addr->prefix_addr.ip,
+ addr->prefix_addr.ip_prefix_length, to);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
printfrr_ext_autoreg_p("EA", printfrr_ea);
static ssize_t printfrr_ea(struct fbuf *buf, struct printfrr_eargs *ea,
const void *ptr)
diff --git a/lib/prefix.h b/lib/prefix.h
index b904311539..c67656cfd1 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -510,6 +510,7 @@ extern char *esi_to_str(const esi_t *esi, char *buf, int size);
extern char *evpn_es_df_alg2str(uint8_t df_alg, char *buf, int buf_len);
extern void prefix_evpn_hexdump(const struct prefix_evpn *p);
extern bool ipv4_unicast_valid(const struct in_addr *addr);
+extern int evpn_prefix2prefix(const struct prefix *evpn, struct prefix *to);
static inline int ipv6_martian(const struct in6_addr *addr)
{
diff --git a/lib/routemap.c b/lib/routemap.c
index 3cc010c148..44d7185567 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -1815,7 +1815,24 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix,
struct route_map_index *index = NULL, *best_index = NULL;
struct route_map_index *head_index = NULL;
struct route_table *table = NULL;
- unsigned char family = prefix->family;
+ struct prefix conv;
+ unsigned char family;
+
+ /*
+ * Handling for matching evpn_routes in the prefix table.
+ *
+ * We convert type2/5 prefix to ipv4/6 prefix to do longest
+ * prefix matching on.
+ */
+ if (prefix->family == AF_EVPN) {
+ if (evpn_prefix2prefix(prefix, &conv) != 0)
+ return NULL;
+
+ prefix = &conv;
+ }
+
+
+ family = prefix->family;
if (family == AF_INET)
table = map->ipv4_prefix_table;
@@ -1890,12 +1907,7 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix,
static int route_map_candidate_list_cmp(struct route_map_index *idx1,
struct route_map_index *idx2)
{
- if (!idx1)
- return -1;
- if (!idx2)
- return 1;
-
- return (idx1->pref - idx2->pref);
+ return idx1->pref - idx2->pref;
}
/*
@@ -3174,6 +3186,12 @@ static struct cmd_node rmap_debug_node = {
.config_write = rmap_config_write_debug,
};
+void route_map_show_debug(struct vty *vty)
+{
+ if (rmap_debug)
+ vty_out(vty, "debug route-map\n");
+}
+
/* Configuration write function. */
static int rmap_config_write_debug(struct vty *vty)
{
diff --git a/lib/routemap.h b/lib/routemap.h
index a365925854..c2e9de6cfb 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -1015,6 +1015,8 @@ extern void route_map_optimization_disabled_show(struct vty *vty,
bool show_defaults);
extern void route_map_cli_init(void);
+extern void route_map_show_debug(struct vty *vty);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/sockopt.c b/lib/sockopt.c
index 7a2b8a1c83..de11a9eab3 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -693,3 +693,52 @@ int sockopt_tcp_mss_get(int sock)
return tcp_maxseg;
}
+
+int setsockopt_tcp_keepalive(int sock, uint16_t keepalive_idle,
+ uint16_t keepalive_intvl,
+ uint16_t keepalive_probes)
+{
+ int val = 1;
+
+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) < 0) {
+ flog_err_sys(EC_LIB_SYSTEM_CALL,
+ "%s failed: setsockopt SO_KEEPALIVE (%d): %s",
+ __func__, sock, safe_strerror(errno));
+ return -1;
+ }
+
+#if defined __OpenBSD__
+ return 0;
+#else
+ /* Send first probe after keepalive_idle seconds */
+ val = keepalive_idle;
+ if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) <
+ 0) {
+ flog_err_sys(EC_LIB_SYSTEM_CALL,
+ "%s failed: setsockopt TCP_KEEPIDLE (%d): %s",
+ __func__, sock, safe_strerror(errno));
+ return -1;
+ }
+
+ /* Set interval between two probes */
+ val = keepalive_intvl;
+ if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) <
+ 0) {
+ flog_err_sys(EC_LIB_SYSTEM_CALL,
+ "%s failed: setsockopt TCP_KEEPINTVL (%d): %s",
+ __func__, sock, safe_strerror(errno));
+ return -1;
+ }
+
+ /* Set maximum probes */
+ val = keepalive_probes;
+ if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {
+ flog_err_sys(EC_LIB_SYSTEM_CALL,
+ "%s failed: setsockopt TCP_KEEPCNT (%d): %s",
+ __func__, sock, safe_strerror(errno));
+ return -1;
+ }
+
+ return 0;
+#endif
+}
diff --git a/lib/sockopt.h b/lib/sockopt.h
index 6c80841e3c..694edf7638 100644
--- a/lib/sockopt.h
+++ b/lib/sockopt.h
@@ -153,6 +153,28 @@ extern int sockopt_tcp_mss_set(int sock, int tcp_maxseg);
* Socket to get max segement size.
*/
extern int sockopt_tcp_mss_get(int sock);
+
+/*
+ * Configure TCP keepalive for a given socket
+ *
+ * sock
+ * Socket to enable keepalive option on.
+ *
+ * keepalive_idle
+ * number of seconds a connection needs to be idle
+ * before sending out keep-alive proves
+ *
+ * keepalive_intvl
+ * number of seconds between TCP keep-alive probes
+ *
+ * keepalive_probes
+ * max number of probers to send before giving up
+ * and killing tcp connection
+ */
+extern int setsockopt_tcp_keepalive(int sock, uint16_t keepalive_idle,
+ uint16_t keepalive_intvl,
+ uint16_t keepalive_probes);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/srv6.c b/lib/srv6.c
index 6a658444c6..306d92ae30 100644
--- a/lib/srv6.c
+++ b/lib/srv6.c
@@ -57,6 +57,8 @@ const char *seg6local_action2str(uint32_t action)
return "End.AS";
case ZEBRA_SEG6_LOCAL_ACTION_END_AM:
return "End.AM";
+ case ZEBRA_SEG6_LOCAL_ACTION_END_DT46:
+ return "End.DT46";
case ZEBRA_SEG6_LOCAL_ACTION_UNSPEC:
return "unspec";
default:
@@ -105,6 +107,7 @@ const char *seg6local_context2str(char *str, size_t size,
case ZEBRA_SEG6_LOCAL_ACTION_END_T:
case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
case ZEBRA_SEG6_LOCAL_ACTION_END_DT4:
+ case ZEBRA_SEG6_LOCAL_ACTION_END_DT46:
snprintf(str, size, "table %u", ctx->table);
return str;
@@ -228,10 +231,20 @@ json_object *srv6_locator_json(const struct srv6_locator *loc)
/* set prefix */
json_object_string_addf(jo_root, "prefix", "%pFX", &loc->prefix);
+ /* set block_bits_length */
+ json_object_int_add(jo_root, "blockBitsLength", loc->block_bits_length);
+
+ /* set node_bits_length */
+ json_object_int_add(jo_root, "nodeBitsLength", loc->node_bits_length);
+
/* set function_bits_length */
json_object_int_add(jo_root, "functionBitsLength",
loc->function_bits_length);
+ /* set argument_bits_length */
+ json_object_int_add(jo_root, "argumentBitsLength",
+ loc->argument_bits_length);
+
/* set status_up */
json_object_boolean_add(jo_root, "statusUp",
loc->status_up);
diff --git a/lib/srv6.h b/lib/srv6.h
index e0db30cd13..6e0c3ce99d 100644
--- a/lib/srv6.h
+++ b/lib/srv6.h
@@ -60,6 +60,7 @@ enum seg6local_action_t {
ZEBRA_SEG6_LOCAL_ACTION_END_AS = 13,
ZEBRA_SEG6_LOCAL_ACTION_END_AM = 14,
ZEBRA_SEG6_LOCAL_ACTION_END_BPF = 15,
+ ZEBRA_SEG6_LOCAL_ACTION_END_DT46 = 16,
};
struct seg6_segs {
diff --git a/lib/subdir.am b/lib/subdir.am
index d6defd7149..e04e700eb6 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -245,6 +245,7 @@ pkginclude_HEADERS += \
lib/ns.h \
lib/openbsd-queue.h \
lib/openbsd-tree.h \
+ lib/orr_msg.h \
lib/plist.h \
lib/prefix.h \
lib/printfrr.h \
diff --git a/lib/typesafe.h b/lib/typesafe.h
index 50c410ad24..8aeabb34e6 100644
--- a/lib/typesafe.h
+++ b/lib/typesafe.h
@@ -850,9 +850,12 @@ macro_inline type *prefix ## _add(struct prefix##_head *h, type *item) \
struct thash_item **np = &h->hh.entries[hbits]; \
while (*np && (*np)->hashval < hval) \
np = &(*np)->next; \
- if (*np && cmpfn(container_of(*np, type, field.hi), item) == 0) { \
- h->hh.count--; \
- return container_of(*np, type, field.hi); \
+ while (*np && (*np)->hashval == hval) { \
+ if (cmpfn(container_of(*np, type, field.hi), item) == 0) { \
+ h->hh.count--; \
+ return container_of(*np, type, field.hi); \
+ } \
+ np = &(*np)->next; \
} \
item->field.hi.next = *np; \
*np = &item->field.hi; \
diff --git a/lib/zclient.c b/lib/zclient.c
index 8ec82ab7bb..f5d45b40ef 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -2299,13 +2299,22 @@ static int zclient_handle_error(ZAPI_CALLBACK_ARGS)
return 0;
}
-static int link_params_set_value(struct stream *s, struct if_link_params *iflp)
+static int link_params_set_value(struct stream *s, struct interface *ifp)
{
+ uint8_t link_params_enabled;
+ struct if_link_params *iflp;
+ uint32_t bwclassnum;
+
+ iflp = if_link_params_get(ifp);
if (iflp == NULL)
- return -1;
+ iflp = if_link_params_init(ifp);
- uint32_t bwclassnum;
+ STREAM_GETC(s, link_params_enabled);
+ if (!link_params_enabled) {
+ if_link_params_free(ifp);
+ return 0;
+ }
STREAM_GETL(s, iflp->lp_status);
STREAM_GETL(s, iflp->te_metric);
@@ -2346,9 +2355,9 @@ struct interface *zebra_interface_link_params_read(struct stream *s,
bool *changed)
{
struct if_link_params *iflp;
- struct if_link_params iflp_copy;
+ struct if_link_params iflp_prev;
ifindex_t ifindex;
- bool params_changed = false;
+ bool iflp_prev_set;
STREAM_GETL(s, ifindex);
@@ -2361,22 +2370,32 @@ struct interface *zebra_interface_link_params_read(struct stream *s,
return NULL;
}
- if (ifp->link_params == NULL)
- params_changed = true;
-
- if ((iflp = if_link_params_get(ifp)) == NULL)
- return NULL;
-
- memcpy(&iflp_copy, iflp, sizeof(iflp_copy));
+ iflp = if_link_params_get(ifp);
+ if (iflp) {
+ iflp_prev_set = true;
+ memcpy(&iflp_prev, ifp->link_params, sizeof(iflp_prev));
+ } else
+ iflp_prev_set = false;
- if (link_params_set_value(s, iflp) != 0)
+ /* read the link_params from stream
+ * Free ifp->link_params if the stream has no params
+ * to means that link-params are not enabled on links.
+ */
+ if (link_params_set_value(s, ifp) != 0)
goto stream_failure;
- if (memcmp(&iflp_copy, iflp, sizeof(iflp_copy)))
- params_changed = true;
+ if (changed == NULL)
+ return ifp;
- if (changed)
- *changed = params_changed;
+ if (iflp_prev_set && iflp) {
+ if (memcmp(&iflp_prev, iflp, sizeof(iflp_prev)))
+ *changed = true;
+ else
+ *changed = false;
+ } else if (!iflp_prev_set && !iflp)
+ *changed = false;
+ else
+ *changed = true;
return ifp;
@@ -2415,10 +2434,8 @@ static void zebra_interface_if_set_value(struct stream *s,
/* Read Traffic Engineering status */
link_params_status = stream_getc(s);
/* Then, Traffic Engineering parameters if any */
- if (link_params_status) {
- struct if_link_params *iflp = if_link_params_get(ifp);
- link_params_set_value(s, iflp);
- }
+ if (link_params_status)
+ link_params_set_value(s, ifp);
nexthop_group_interface_state_change(ifp, old_ifindex);
@@ -2435,12 +2452,20 @@ size_t zebra_interface_link_params_write(struct stream *s,
struct if_link_params *iflp;
int i;
- if (s == NULL || ifp == NULL || ifp->link_params == NULL)
+ if (s == NULL || ifp == NULL)
return 0;
iflp = ifp->link_params;
w = 0;
+ /* encode if link_params is enabled */
+ if (iflp) {
+ w += stream_putc(s, true);
+ } else {
+ w += stream_putc(s, false);
+ return w;
+ }
+
w += stream_putl(s, iflp->lp_status);
w += stream_putl(s, iflp->te_metric);
diff --git a/lib/zclient.h b/lib/zclient.h
index c3ea2a16ff..fb5da9aad2 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -100,6 +100,8 @@ enum zserv_client_capabilities {
extern struct sockaddr_storage zclient_addr;
extern socklen_t zclient_addr_len;
+#define ZAPI_ORR_FLAG_UNICAST 0x01
+
/* Zebra message types. */
typedef enum {
ZEBRA_INTERFACE_ADD,
@@ -1229,6 +1231,10 @@ enum zapi_opaque_registry {
LDP_RLFA_UNREGISTER_ALL = 8,
/* Announce LDP labels associated to a previously registered RLFA */
LDP_RLFA_LABELS = 9,
+ /* Register for IGP METRIC with OSPF/ISIS */
+ ORR_IGP_METRIC_REGISTER = 10,
+ /* Send SPF data to BGP */
+ ORR_IGP_METRIC_UPDATE = 11
};
/* Send the hello message.