diff options
| -rw-r--r-- | bgpd/bgp_mplsvpn.c | 11 | ||||
| -rw-r--r-- | bgpd/bgp_routemap.c | 77 | ||||
| -rw-r--r-- | bgpd/subdir.am | 2 | ||||
| -rwxr-xr-x | configure.ac | 2 | ||||
| -rw-r--r-- | doc/manpages/watchfrr.rst | 29 | ||||
| -rw-r--r-- | doc/user/setup.rst | 31 | ||||
| -rw-r--r-- | lib/command.h | 3 | ||||
| -rw-r--r-- | pimd/pim_cmd.c | 53 | ||||
| -rw-r--r-- | tools/frrcommon.sh.in | 13 | ||||
| -rw-r--r-- | vtysh/vtysh.c | 12 |
10 files changed, 181 insertions, 52 deletions
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_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 488a1380b2..157dad33a9 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/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/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 fa2fdc94b2..065295f527 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() { @@ -89,9 +89,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" @@ -116,7 +119,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 @@ -276,7 +279,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); |
