summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_addpath.c83
-rw-r--r--bgpd/bgp_mplsvpn.c11
-rw-r--r--bgpd/bgp_route.c5
-rw-r--r--bgpd/bgp_routemap.c77
-rw-r--r--bgpd/subdir.am2
-rwxr-xr-xconfigure.ac2
-rw-r--r--doc/manpages/watchfrr.rst29
-rw-r--r--doc/user/setup.rst31
-rw-r--r--isisd/isis_cli.c23
-rw-r--r--lib/command.h3
-rw-r--r--pbrd/pbr_nht.c4
-rw-r--r--pbrd/pbr_vty.c2
-rw-r--r--pimd/pim_cmd.c53
-rw-r--r--tools/frrcommon.sh.in13
-rw-r--r--vtysh/vtysh.c12
-rw-r--r--zebra/zebra_rib.c2
16 files changed, 262 insertions, 90 deletions
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c
index 55a86f99fc..c7fd1ba0e2 100644
--- a/bgpd/bgp_addpath.c
+++ b/bgpd/bgp_addpath.c
@@ -175,6 +175,28 @@ int bgp_addpath_tx_path(enum bgp_addpath_strat strat,
}
}
+static void bgp_addpath_flush_type_rn(struct bgp *bgp, afi_t afi, safi_t safi,
+ enum bgp_addpath_strat addpath_type,
+ struct bgp_node *rn)
+{
+ struct bgp_path_info *pi;
+
+ idalloc_drain_pool(
+ bgp->tx_addpath.id_allocators[afi][safi][addpath_type],
+ &(rn->tx_addpath.free_ids[addpath_type]));
+ for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
+ if (pi->tx_addpath.addpath_tx_id[addpath_type]
+ != IDALLOC_INVALID) {
+ idalloc_free(
+ bgp->tx_addpath
+ .id_allocators[afi][safi][addpath_type],
+ pi->tx_addpath.addpath_tx_id[addpath_type]);
+ pi->tx_addpath.addpath_tx_id[addpath_type] =
+ IDALLOC_INVALID;
+ }
+ }
+}
+
/*
* Purge all addpath ID's on a BGP instance associated with the addpath
* strategy, and afi/safi combination. This lets us let go of all memory held to
@@ -185,26 +207,24 @@ int bgp_addpath_tx_path(enum bgp_addpath_strat strat,
static void bgp_addpath_flush_type(struct bgp *bgp, afi_t afi, safi_t safi,
enum bgp_addpath_strat addpath_type)
{
- struct bgp_node *rn;
- struct bgp_path_info *pi;
+ struct bgp_node *rn, *nrn;
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
rn = bgp_route_next(rn)) {
- idalloc_drain_pool(
- bgp->tx_addpath.id_allocators[afi][safi][addpath_type],
- &(rn->tx_addpath.free_ids[addpath_type]));
- for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
- if (pi->tx_addpath.addpath_tx_id[addpath_type]
- != IDALLOC_INVALID) {
- idalloc_free(
- bgp->tx_addpath
- .id_allocators[afi][safi]
- [addpath_type],
- pi->tx_addpath
- .addpath_tx_id[addpath_type]);
- pi->tx_addpath.addpath_tx_id[addpath_type] =
- IDALLOC_INVALID;
- }
+ if (safi == SAFI_MPLS_VPN) {
+ struct bgp_table *table;
+
+ table = bgp_node_get_bgp_table_info(rn);
+ if (!table)
+ continue;
+
+ for (nrn = bgp_table_top(table); nrn;
+ nrn = bgp_route_next(nrn))
+ bgp_addpath_flush_type_rn(bgp, afi, safi,
+ addpath_type, nrn);
+ } else {
+ bgp_addpath_flush_type_rn(bgp, afi, safi, addpath_type,
+ rn);
}
}
@@ -234,8 +254,7 @@ static void bgp_addpath_populate_path(struct id_alloc *allocator,
static void bgp_addpath_populate_type(struct bgp *bgp, afi_t afi, safi_t safi,
enum bgp_addpath_strat addpath_type)
{
- struct bgp_node *rn;
- struct bgp_path_info *bi;
+ struct bgp_node *rn, *nrn;
char buf[200];
struct id_alloc *allocator;
@@ -255,9 +274,29 @@ static void bgp_addpath_populate_type(struct bgp *bgp, afi_t afi, safi_t safi,
allocator = bgp->tx_addpath.id_allocators[afi][safi][addpath_type];
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
- rn = bgp_route_next(rn))
- for (bi = bgp_node_get_bgp_path_info(rn); bi; bi = bi->next)
- bgp_addpath_populate_path(allocator, bi, addpath_type);
+ rn = bgp_route_next(rn)) {
+ struct bgp_path_info *bi;
+
+ if (safi == SAFI_MPLS_VPN) {
+ struct bgp_table *table;
+
+ table = bgp_node_get_bgp_table_info(rn);
+ if (!table)
+ continue;
+
+ for (nrn = bgp_table_top(table); nrn;
+ nrn = bgp_route_next(nrn))
+ for (bi = bgp_node_get_bgp_path_info(nrn); bi;
+ bi = bi->next)
+ bgp_addpath_populate_path(allocator, bi,
+ addpath_type);
+ } else {
+ for (bi = bgp_node_get_bgp_path_info(rn); bi;
+ bi = bi->next)
+ bgp_addpath_populate_path(allocator, bi,
+ addpath_type);
+ }
+ }
}
/*
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index d0ccdcedfb..4baac3e57a 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -1073,9 +1073,13 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
return;
}
- if (debug)
- zlog_debug("%s: updating to vrf %s", __func__,
- bgp_vrf->name_pretty);
+ if (debug) {
+ char buf_prefix[PREFIX_STRLEN];
+
+ prefix2str(p, buf_prefix, sizeof(buf_prefix));
+ zlog_debug("%s: updating %s to vrf %s", __func__,
+ buf_prefix, bgp_vrf->name_pretty);
+ }
bgp_attr_dup(&static_attr, path_vpn->attr); /* shallow copy */
@@ -1132,6 +1136,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
memset(&info, 0, sizeof(info));
info.peer = bgp_vrf->peer_self;
info.attr = &static_attr;
+ info.extra = path_vpn->extra; /* Used for source-vrf filter */
ret = route_map_apply(bgp_vrf->vpn_policy[afi]
.rmap[BGP_VPN_POLICY_DIR_FROMVPN],
p, RMAP_BGP, &info);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 8e72b742a3..230df715de 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -254,8 +254,9 @@ static void bgp_path_info_free(struct bgp_path_info *path)
bgp_unlink_nexthop(path);
bgp_path_info_extra_free(&path->extra);
bgp_path_info_mpath_free(&path->mpath);
- bgp_addpath_free_info_data(&path->tx_addpath,
- path->net ? &path->net->tx_addpath : NULL);
+ if (path->net)
+ bgp_addpath_free_info_data(&path->tx_addpath,
+ &path->net->tx_addpath);
peer_unlock(path->peer); /* bgp_path_info peer reference */
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index e28acdfbae..17109281bc 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -65,6 +65,10 @@
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
#endif
+#ifndef VTYSH_EXTRACT_PL
+#include "bgpd/bgp_routemap_clippy.c"
+#endif
+
/* Memo of route-map commands.
o Cisco route-map
@@ -905,6 +909,53 @@ struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
"evpn route-type", route_match_evpn_route_type,
route_match_evpn_route_type_compile, route_match_evpn_route_type_free};
+/* Route map commands for VRF route leak with source vrf matching */
+static route_map_result_t
+route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct bgp_path_info *path;
+ char *vrf_name;
+
+ if (type == RMAP_BGP) {
+ vrf_name = rule;
+ path = (struct bgp_path_info *)object;
+
+ if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
+ return RMAP_NOMATCH;
+
+ if (path->extra == NULL)
+ return RMAP_NOMATCH;
+
+ if (strncmp(vrf_name, vrf_id_to_name(
+ path->extra->bgp_orig->vrf_id), VRF_NAMSIZ)
+ == 0)
+ return RMAP_MATCH;
+ }
+
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_vrl_source_vrf_compile(const char *arg)
+{
+ uint8_t *vrf_name = NULL;
+
+ vrf_name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+
+ return vrf_name;
+}
+
+/* Free route map's compiled `route-type' value. */
+static void route_match_vrl_source_vrf_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
+ "source-vrf", route_match_vrl_source_vrf,
+ route_match_vrl_source_vrf_compile,
+ route_match_vrl_source_vrf_free};
+
/* `match local-preference LOCAL-PREF' */
/* Match function return 1 if match is success else return zero. */
@@ -3538,6 +3589,29 @@ DEFUN (no_match_evpn_default_route,
RMAP_EVENT_MATCH_DELETED);
}
+DEFPY(match_vrl_source_vrf,
+ match_vrl_source_vrf_cmd,
+ "match source-vrf NAME$vrf_name",
+ MATCH_STR
+ "source vrf\n"
+ "The VRF name\n")
+{
+ return bgp_route_match_add(vty, "source-vrf", vrf_name,
+ RMAP_EVENT_MATCH_ADDED);
+}
+
+DEFPY(no_match_vrl_source_vrf,
+ no_match_vrl_source_vrf_cmd,
+ "no match source-vrf NAME$vrf_name",
+ NO_STR
+ MATCH_STR
+ "source vrf\n"
+ "The VRF name\n")
+{
+ return bgp_route_match_delete(vty, "source-vrf", vrf_name,
+ RMAP_EVENT_MATCH_DELETED);
+}
+
DEFUN (match_peer,
match_peer_cmd,
"match peer <A.B.C.D|X:X::X:X|WORD>",
@@ -4992,6 +5066,7 @@ void bgp_route_map_init(void)
route_map_install_match(&route_match_evpn_vni_cmd);
route_map_install_match(&route_match_evpn_route_type_cmd);
route_map_install_match(&route_match_evpn_default_route_cmd);
+ route_map_install_match(&route_match_vrl_source_vrf_cmd);
route_map_install_set(&route_set_ip_nexthop_cmd);
route_map_install_set(&route_set_local_pref_cmd);
@@ -5030,6 +5105,8 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
install_element(RMAP_NODE, &match_evpn_default_route_cmd);
install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
+ install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
+ install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
install_element(RMAP_NODE, &match_aspath_cmd);
install_element(RMAP_NODE, &no_match_aspath_cmd);
diff --git a/bgpd/subdir.am b/bgpd/subdir.am
index aed2939d3e..d281fe4e59 100644
--- a/bgpd/subdir.am
+++ b/bgpd/subdir.am
@@ -224,6 +224,8 @@ bgpd/bgp_route_clippy.c: $(CLIPPY_DEPS)
bgpd/bgp_route.$(OBJEXT): bgpd/bgp_route_clippy.c
bgpd/bgp_debug_clippy.c: $(CLIPPY_DEPS)
bgpd/bgp_debug.$(OBJEXT): bgpd/bgp_debug_clippy.c
+bgpd/bgp_routemap_clippy.c: $(CLIPPY_DEPS)
+bgpd/bgp_routemap.$(OBJEXT): bgpd/bgp_routemap_clippy.c
bgpd/bgp_rpki_clippy.c: $(CLIPPY_DEPS)
$(AUTOMAKE_DUMMY)bgpd/bgpd_bgpd_rpki_la-bgp_rpki.lo: bgpd/bgp_rpki_clippy.c
$(AUTOMAKE_DUMMY)bgpd/bgpd_rpki_la-bgp_rpki.lo: bgpd/bgp_rpki_clippy.c
diff --git a/configure.ac b/configure.ac
index 4a05c0d69a..fcfc4bd2fb 100755
--- a/configure.ac
+++ b/configure.ac
@@ -1611,7 +1611,7 @@ CFLAGS="$CFLAGS $LIBYANG_CFLAGS"
AC_CHECK_MEMBER([struct lyd_node.priv], [], [
AC_MSG_ERROR([m4_normalize([
libyang needs to be compiled with ENABLE_LYD_PRIV=ON.
- See http://docs.frrouting.org/projects/dev-guide/en/latest/building-libyang.html for details.])
+ Instructions for this are included in the build documentation for your platform at http://docs.frrouting.org/projects/dev-guide/en/latest/building.html])
])
], [[#include <libyang/libyang.h>]])
CFLAGS="$ac_cflags_save"
diff --git a/doc/manpages/watchfrr.rst b/doc/manpages/watchfrr.rst
index f0b733298d..dceb423f82 100644
--- a/doc/manpages/watchfrr.rst
+++ b/doc/manpages/watchfrr.rst
@@ -22,21 +22,6 @@ In order to avoid restarting the daemons in quick succession, you can supply the
OPTIONS
=======
-The following 3 options specify scripts that |DAEMON| uses to perform start/stop/restart actions. These options are mandatory unless the --dry option is used:
-
-.. option:: -s command, --start-command command
-
- Supply a Bourne shell command to start a single daemon. The command string should contain the '%s' placeholder to be sub‐ stituted with the daemon name.
-
-.. option:: -k command, --kill-command command
-
- Supply a Bourne shell command to stop a single daemon. The command string should contain the '%s' placeholder to be substituted with the daemon name.
-
-.. option:: -r command, --restart command
-
- Supply a Bourne shell command to restart a single daemon. The command string should contain the '%s' placeholder to be substituted with the daemon name.
-
-Other options:
.. option:: --dry
@@ -92,6 +77,20 @@ Other options:
Display the usage information and exit.
+The following 3 options specify scripts that |DAEMON| uses to perform start/stop/restart actions. Reasonable default values are built into watchfrr, so the use of these options should no longer be necessary:
+
+.. option:: -s command, --start-command command
+
+ Supply a Bourne shell command to start a single daemon. The command string should contain the '%s' placeholder to be substituted with the daemon name.
+
+.. option:: -k command, --kill-command command
+
+ Supply a Bourne shell command to stop a single daemon. The command string should contain the '%s' placeholder to be substituted with the daemon name.
+
+.. option:: -r command, --restart command
+
+ Supply a Bourne shell command to restart a single daemon. The command string should contain the '%s' placeholder to be substituted with the daemon name.
+
PREVIOUS OPTIONS
================
Prior versions of |DAEMON| supported some additional options that no longer exist:::
diff --git a/doc/user/setup.rst b/doc/user/setup.rst
index 3a09c50309..ffefe37905 100644
--- a/doc/user/setup.rst
+++ b/doc/user/setup.rst
@@ -72,13 +72,14 @@ This file has several parts. Here is an example:
fabricd_options=" --daemon -A 127.0.0.1"
# The list of daemons to watch is automatically generated by the init script.
- watchfrr_enable=yes
- watchfrr_options=(-d -r /usr/sbin/servicebBfrrbBrestartbB%s -s /usr/sbin/servicebBfrrbBstartbB%s -k /usr/sbin/servicebBfrrbBstopbB%s -b bB)
+ #watchfrr_options=""
- # If valgrind_enable is 'yes' the frr daemons will be started via valgrind.
- # The use case for doing so is tracking down memory leaks, etc in frr.
- valgrind_enable=no
- valgrind=/usr/bin/valgrind
+ # for debugging purposes, you can specify a "wrap" command to start instead
+ # of starting the daemon directly, e.g. to use valgrind on ospfd:
+ # ospfd_wrap="/usr/bin/valgrind"
+ # or you can use "all_wrap" for all daemons, e.g. to use perf record:
+ # all_wrap="/usr/bin/perf record --call-graph -"
+ # the normal daemon command is added to this at the end.
Breaking this file down:
@@ -101,22 +102,8 @@ from the service script. Usually daemons will have ``--daemon`` and ``-A
<address>`` specified in order to daemonize and listen for VTY commands on a
particular address.
-::
-
- # The list of daemons to watch is automatically generated by the init script.
- watchfrr_enable=yes
- watchfrr_options=(-d -r /usr/sbin/servicebBfrrbBrestartbB%s -s /usr/sbin/servicebBfrrbBstartbB%s -k /usr/sbin/servicebBfrrbBstopbB%s -b bB)
-
-Options for the ``watchfrr``, the watchdog daemon.
-
-::
-
- valgrind_enable=no
- valgrind=/usr/bin/valgrind
-
-Whether or not to start FRR daemons under Valgrind. This is primarily useful
-for gathering information for bug reports and for developers.
-``valgrind_enable`` should be ``no`` for production use.
+The remaining file content regarding `watchfrr_options` and `*_wrap` settings
+should not normally be needed; refer to the comments in case they are.
Services
--------
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index bd8b58e8f0..ab5faf76b6 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -279,25 +279,26 @@ DEFPY(no_ip_router_isis, no_ip_router_isis_cmd,
"IS-IS routing protocol\n"
"Routing process tag\n")
{
- const struct lyd_node *dnode =
- yang_dnode_get(running_config->dnode, VTY_CURR_XPATH);
+ const struct lyd_node *dnode;
- /* if both ipv4 and ipv6 are off delete the interface isis container too
+ dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-isisd:isis", VTY_CURR_XPATH);
+ if (!dnode)
+ return CMD_SUCCESS;
+
+ /*
+ * If both ipv4 and ipv6 are off delete the interface isis container.
*/
- if (!strncmp(ip, "ipv6", strlen("ipv6"))) {
- if (dnode
- && !yang_dnode_get_bool(dnode,
- "./frr-isisd:isis/ipv4-routing"))
+ if (strmatch(ip, "ipv6")) {
+ if (!yang_dnode_get_bool(dnode, "./ipv4-routing"))
nb_cli_enqueue_change(vty, "./frr-isisd:isis",
NB_OP_DESTROY, NULL);
else
nb_cli_enqueue_change(vty,
"./frr-isisd:isis/ipv6-routing",
NB_OP_MODIFY, "false");
- } else { /* no ipv4 */
- if (dnode
- && !yang_dnode_get_bool(dnode,
- "./frr-isisd:isis/ipv6-routing"))
+ } else {
+ if (!yang_dnode_get_bool(dnode, "./ipv6-routing"))
nb_cli_enqueue_change(vty, "./frr-isisd:isis",
NB_OP_DESTROY, NULL);
else
diff --git a/lib/command.h b/lib/command.h
index 0faaa426ac..a5f9616dbf 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -318,6 +318,9 @@ struct cmd_node {
#define DEFPY_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, attr)
+
+#define DEFPY_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr)
#endif /* VTYSH_EXTRACT_PL */
/* Some macroes */
diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c
index 6103bd7db5..f3bfad3190 100644
--- a/pbrd/pbr_nht.c
+++ b/pbrd/pbr_nht.c
@@ -164,8 +164,8 @@ static bool pbr_nh_hash_equal(const void *arg1, const void *arg2)
== pbrnc2->nexthop->gate.ipv4.s_addr;
case NEXTHOP_TYPE_IPV6_IFINDEX:
case NEXTHOP_TYPE_IPV6:
- return !!memcmp(&pbrnc1->nexthop->gate.ipv6,
- &pbrnc2->nexthop->gate.ipv6, 16);
+ return !memcmp(&pbrnc1->nexthop->gate.ipv6,
+ &pbrnc2->nexthop->gate.ipv6, 16);
case NEXTHOP_TYPE_BLACKHOLE:
return pbrnc1->nexthop->bh_type == pbrnc2->nexthop->bh_type;
}
diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c
index 2b6c38593b..f8232c9581 100644
--- a/pbrd/pbr_vty.c
+++ b/pbrd/pbr_vty.c
@@ -300,7 +300,7 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
char buf[PBR_NHC_NAMELEN];
if (no) {
- vty_out(vty, "No nexthops to delete");
+ vty_out(vty, "No nexthops to delete\n");
return CMD_WARNING_CONFIG_FAILED;
}
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index d2d2445a15..193eddf68a 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -6404,6 +6404,56 @@ static int pim_cmd_interface_add(struct interface *ifp)
return 1;
}
+DEFPY_HIDDEN (pim_test_sg_keepalive,
+ pim_test_sg_keepalive_cmd,
+ "test pim [vrf NAME$name] keepalive-reset A.B.C.D$source A.B.C.D$group",
+ "Test code\n"
+ PIM_STR
+ VRF_CMD_HELP_STR
+ "Reset the Keepalive Timer\n"
+ "The Source we are resetting\n"
+ "The Group we are resetting\n")
+{
+ struct pim_upstream *up;
+ struct pim_instance *pim;
+ struct prefix_sg sg;
+
+ sg.src = source;
+ sg.grp = group;
+
+ if (!name)
+ pim = pim_get_pim_instance(VRF_DEFAULT);
+ else {
+ struct vrf *vrf = vrf_lookup_by_name(name);
+
+ if (!vrf) {
+ vty_out(vty, "%% Vrf specified: %s does not exist\n",
+ name);
+ return CMD_WARNING;
+ }
+
+ pim = pim_get_pim_instance(vrf->vrf_id);
+ }
+
+ if (!pim) {
+ vty_out(vty, "%% Unable to find pim instance\n");
+ return CMD_WARNING;
+ }
+
+ up = pim_upstream_find(pim, &sg);
+ if (!up) {
+ vty_out(vty, "%% Unable to find %s specified\n",
+ pim_str_sg_dump(&sg));
+ return CMD_WARNING;
+ }
+
+ vty_out(vty, "Setting %s to current keep alive time: %d\n",
+ pim_str_sg_dump(&sg), pim->keep_alive_time);
+ pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
+
+ return CMD_SUCCESS;
+}
+
DEFPY_HIDDEN (interface_ip_pim_activeactive,
interface_ip_pim_activeactive_cmd,
"[no$no] ip pim active-active",
@@ -8667,7 +8717,6 @@ DEFUN (show_ip_msdp_sa_sg_vrf_all,
return CMD_SUCCESS;
}
-
void pim_cmd_init(void)
{
install_node(&interface_node,
@@ -8676,6 +8725,8 @@ void pim_cmd_init(void)
install_node(&debug_node, pim_debug_config_write);
+ install_element(ENABLE_NODE, &pim_test_sg_keepalive_cmd);
+
install_element(CONFIG_NODE, &ip_pim_rp_cmd);
install_element(VRF_NODE, &ip_pim_rp_cmd);
install_element(CONFIG_NODE, &no_ip_pim_rp_cmd);
diff --git a/tools/frrcommon.sh.in b/tools/frrcommon.sh.in
index 37abfeb30d..76a0d617ba 100644
--- a/tools/frrcommon.sh.in
+++ b/tools/frrcommon.sh.in
@@ -67,9 +67,9 @@ vtysh_b () {
daemon_inst() {
# note this sets global variables ($dmninst, $daemon, $inst)
dmninst="$1"
- daemon="${dmninst%:*}"
+ daemon="${dmninst%-*}"
inst=""
- [ "$daemon" != "$dmninst" ] && inst="${dmninst#*:}"
+ [ "$daemon" != "$dmninst" ] && inst="${dmninst#*-}"
}
daemon_list() {
@@ -92,9 +92,12 @@ daemon_list() {
enabled="$enabled $daemon"
if [ -n "$inst" ]; then
debug "$daemon multi-instance $inst"
+ oldifs="${IFS}"
+ IFS="${IFS},"
for i in $inst; do
- enabled="$enabled $daemon:$inst"
+ enabled="$enabled $daemon-$i"
done
+ IFS="${oldifs}"
fi
else
debug "$daemon disabled"
@@ -119,7 +122,7 @@ daemon_prep() {
inst="$2"
[ "$daemon" = "watchfrr" ] && return 0
[ -x "$D_PATH/$daemon" ] || {
- log_failure_msg "cannot start $daemon${inst:+ (instance $inst)}: daemon binary not installed\n"
+ log_failure_msg "cannot start $daemon${inst:+ (instance $inst)}: daemon binary not installed"
return 1
}
[ -r "$C_PATH/frr.conf" ] && return 0
@@ -279,7 +282,7 @@ load_old_config() {
}
[ -r "$C_PATH/daemons" ] || {
- log_failure_msg "cannot run $@: $C_PATH/daemons does not exist\n"
+ log_failure_msg "cannot run $@: $C_PATH/daemons does not exist"
exit 1
}
. "$C_PATH/daemons"
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 41fd6ed7d6..9ff869e503 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -104,7 +104,7 @@ static int vty_close_pager(struct vty *vty)
return 0;
}
-static void vtysh_pager_envdef(void)
+static void vtysh_pager_envdef(bool fallback)
{
char *pager_defined;
@@ -112,7 +112,7 @@ static void vtysh_pager_envdef(void)
if (pager_defined)
vtysh_pager_name = strdup(pager_defined);
- else
+ else if (fallback)
vtysh_pager_name = strdup(VTYSH_PAGER);
}
@@ -2893,7 +2893,7 @@ DEFUN (vtysh_terminal_paginate,
vtysh_pager_name = NULL;
if (strcmp(argv[0]->text, "no"))
- vtysh_pager_envdef();
+ vtysh_pager_envdef(true);
return CMD_SUCCESS;
}
@@ -2913,7 +2913,7 @@ DEFUN (vtysh_terminal_length,
if (!strcmp(argv[0]->text, "no") || !strcmp(argv[1]->text, "no")) {
/* "terminal no length" = use VTYSH_PAGER */
- vtysh_pager_envdef();
+ vtysh_pager_envdef(true);
return CMD_SUCCESS;
}
@@ -2922,7 +2922,7 @@ DEFUN (vtysh_terminal_length,
vty_out(vty,
"%% The \"terminal length\" command is deprecated and its value is ignored.\n"
"%% Please use \"terminal paginate\" instead with OS TTY length handling.\n");
- vtysh_pager_envdef();
+ vtysh_pager_envdef(true);
}
return CMD_SUCCESS;
@@ -3479,6 +3479,7 @@ void vtysh_init_vty(void)
/* set default output */
vty->of = stdout;
+ vtysh_pager_envdef(false);
/* Initialize commands. */
cmd_init(0);
@@ -3812,6 +3813,7 @@ void vtysh_init_vty(void)
/* "write memory" command. */
install_element(ENABLE_NODE, &vtysh_write_memory_cmd);
+ install_element(CONFIG_NODE, &vtysh_terminal_paginate_cmd);
install_element(VIEW_NODE, &vtysh_terminal_paginate_cmd);
install_element(VIEW_NODE, &vtysh_terminal_length_cmd);
install_element(VIEW_NODE, &vtysh_terminal_no_length_cmd);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 8afcc2b685..b71bf77df2 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1879,6 +1879,8 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
goto done;
}
+ route_unlock_node(rn);
+
srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx);
op = dplane_ctx_get_op(ctx);