diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/command.c | 26 | ||||
| -rw-r--r-- | lib/command.h | 93 | ||||
| -rw-r--r-- | lib/command_graph.c | 5 | ||||
| -rw-r--r-- | lib/command_graph.h | 9 | ||||
| -rw-r--r-- | lib/command_match.c | 3 | ||||
| -rw-r--r-- | lib/command_py.c | 10 | ||||
| -rw-r--r-- | lib/frrscript.c | 28 | ||||
| -rw-r--r-- | lib/frrscript.h | 5 | ||||
| -rw-r--r-- | lib/grammar_sandbox.c | 3 | ||||
| -rw-r--r-- | lib/if.c | 26 | ||||
| -rw-r--r-- | lib/if.h | 2 | ||||
| -rw-r--r-- | lib/libfrr.c | 4 | ||||
| -rw-r--r-- | lib/log_vty.c | 4 | ||||
| -rw-r--r-- | lib/orr_msg.h | 94 | ||||
| -rw-r--r-- | lib/prefix.c | 57 | ||||
| -rw-r--r-- | lib/prefix.h | 1 | ||||
| -rw-r--r-- | lib/routemap.c | 32 | ||||
| -rw-r--r-- | lib/routemap.h | 2 | ||||
| -rw-r--r-- | lib/sockopt.c | 49 | ||||
| -rw-r--r-- | lib/sockopt.h | 22 | ||||
| -rw-r--r-- | lib/srv6.c | 13 | ||||
| -rw-r--r-- | lib/srv6.h | 1 | ||||
| -rw-r--r-- | lib/subdir.am | 1 | ||||
| -rw-r--r-- | lib/typesafe.h | 9 | ||||
| -rw-r--r-- | lib/zclient.c | 69 | ||||
| -rw-r--r-- | lib/zclient.h | 6 |
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); @@ -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); @@ -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. |
