Skip to content

Commit

Permalink
zebra: add ipv6 nd disable-ra command
Browse files Browse the repository at this point in the history
Introduce a command to completely disable sending IPv6 router
advertisement messages on an interface. Before, there were cases where
it could be enabled by other daemons, namely bgpd and vrrpd.
Particularly, it happens when BGP extended-nexthop capability is used:
bgpd tells zebra to enable RA in this case, though it wasn't intended.

Signed-off-by: Mikhail Sokolovskiy <sokolmish@gmail.com>
  • Loading branch information
Sokolmish committed Jul 7, 2024
1 parent d7d4915 commit 1d07dba
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 5 deletions.
10 changes: 9 additions & 1 deletion doc/user/ipv6.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,15 @@ Router Advertisement
.. clicmd:: ipv6 nd suppress-ra

Don't send router advertisement messages. The ``no`` form of this command
enables sending RA messages.
enables sending RA messages. Note that while being suppressed, RA messages
might still be enabled by other daemons, such as bgpd.

.. clicmd:: ipv6 nd disable-ra

Don't send router advertisement messages at all, even if other daemons
request to enable them. The ``no`` form of this command allows sending RA
messages. Note that this command cannot enable sending RA by itself.


.. clicmd:: ipv6 nd prefix ipv6prefix [valid-lifetime] [preferred-lifetime] [off-link] [no-autoconfig] [router-address]

Expand Down
13 changes: 12 additions & 1 deletion yang/frr-zebra.yang
Original file line number Diff line number Diff line change
Expand Up @@ -2284,7 +2284,18 @@ module frr-zebra {
description
"A flag indicating whether or not the router sends
periodic Router Advertisements and responds to
Router Solicitations.";
Router Solicitations. Note that if this option is
disabled, RA can still be enabled by other daemons.";
reference
"RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
- AdvSendAdvertisements";
}
leaf disable-advertisements {
type boolean;
default "false";
description
"A flag indicating whether sending Router Advertisements
messages is allowed on the interface.";
reference
"RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
- AdvSendAdvertisements";
Expand Down
8 changes: 6 additions & 2 deletions zebra/rtadv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1347,7 +1347,8 @@ void ipv6_nd_interval_set(struct interface *ifp, uint32_t interval)
}

/*
* Handle client (BGP) message to enable or disable IPv6 RA on an interface.
* Handle client (BGP/VRRP) message to enable or disable IPv6 RA on an
* interface.
* Note that while the client could request RA on an interface on which the
* operator has not enabled RA, RA won't be disabled upon client request
* if the operator has explicitly enabled RA. The enable request can also
Expand Down Expand Up @@ -1403,7 +1404,10 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
interfaces_configured_for_ra_from_bgp++;

SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);

if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_DISABLED))
ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);

if (ra_interval
&& (ra_interval * 1000) < (unsigned int) zif->rtadv.MaxRtrAdvInterval
&& !CHECK_FLAG(zif->rtadv.ra_configured,
Expand Down
2 changes: 2 additions & 0 deletions zebra/rtadv.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ struct rtadvconf {
#define VTY_RA_CONFIGURED (1 << 1) /* Operator configured RA? */
#define VTY_RA_INTERVAL_CONFIGURED \
(1 << 2) /* Operator configured RA interval */
#define VTY_RA_DISABLED (1 << 3) /* Operator completely disabled RA? */

int NumFastReXmitsRemain; /* Loaded first with number of fast
rexmits to do */

Expand Down
36 changes: 36 additions & 0 deletions zebra/zebra_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,25 @@ DEFPY_YANG (ipv6_nd_suppress_ra,
return nb_cli_apply_changes(vty, NULL);
}

DEFPY_YANG (ipv6_nd_disable_ra,
ipv6_nd_disable_ra_cmd,
"[no] ipv6 nd disable-ra",
NO_STR
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Disable Router Advertisement completely\n")
{
if (!no)
nb_cli_enqueue_change(vty,
"./frr-zebra:zebra/ipv6-router-advertisements/disable-advertisements",
NB_OP_MODIFY, "true");
else
nb_cli_enqueue_change(vty,
"./frr-zebra:zebra/ipv6-router-advertisements/disable-advertisements",
NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}

static void
lib_interface_zebra_ipv6_router_advertisements_send_advertisements_cli_write(
struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
Expand All @@ -1255,6 +1274,18 @@ lib_interface_zebra_ipv6_router_advertisements_send_advertisements_cli_write(
vty_out(vty, " ipv6 nd suppress-ra\n");
}

static void
lib_interface_zebra_ipv6_router_advertisements_disable_advertisements_cli_write(
struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
{
bool disable_advertisements = yang_dnode_get_bool(dnode, NULL);

if (disable_advertisements)
vty_out(vty, " ipv6 nd disable-ra\n");
else if (show_defaults)
vty_out(vty, " no ipv6 nd disable-ra\n");
}

DEFPY_YANG (ipv6_nd_ra_interval,
ipv6_nd_ra_interval_cmd,
"[no] ipv6 nd ra-interval ![<(1-1800)$sec|msec (70-1800000)$msec>]",
Expand Down Expand Up @@ -2748,6 +2779,10 @@ const struct frr_yang_module_info frr_zebra_cli_info = {
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/send-advertisements",
.cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_send_advertisements_cli_write,
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/disable-advertisements",
.cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_disable_advertisements_cli_write,
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval",
.cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_cli_write,
Expand Down Expand Up @@ -2913,6 +2948,7 @@ void zebra_cli_init(void)
install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_ra_hop_limit_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_disable_ra_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
Expand Down
6 changes: 6 additions & 0 deletions zebra/zebra_nb.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,12 @@ const struct frr_yang_module_info frr_zebra_info = {
.modify = lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify,
}
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/disable-advertisements",
.cbs = {
.modify = lib_interface_zebra_ipv6_router_advertisements_disable_advertisements_modify,
}
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval",
.cbs = {
Expand Down
2 changes: 2 additions & 0 deletions zebra/zebra_nb.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ int lib_interface_zebra_evpn_mh_uplink_modify(struct nb_cb_modify_args *args);
#if defined(HAVE_RTADV)
int lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify(
struct nb_cb_modify_args *args);
int lib_interface_zebra_ipv6_router_advertisements_disable_advertisements_modify(
struct nb_cb_modify_args *args);
int lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_modify(
struct nb_cb_modify_args *args);
int lib_interface_zebra_ipv6_router_advertisements_managed_flag_modify(
Expand Down
36 changes: 35 additions & 1 deletion zebra/zebra_nb_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -2562,7 +2562,8 @@ int lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify(
send_adv = yang_dnode_get_bool(args->dnode, NULL);

if (send_adv) {
ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_DISABLED))
ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
} else {
if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
Expand All @@ -2573,6 +2574,39 @@ int lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify(
return NB_OK;
}

/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/disable-advertisements
*/
int lib_interface_zebra_ipv6_router_advertisements_disable_advertisements_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
bool disable_adv;

if (args->event != NB_EV_APPLY)
return NB_OK;

ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;

disable_adv = yang_dnode_get_bool(args->dnode, NULL);

if (disable_adv) {
/* Do it regardless of current status */
ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
SET_FLAG(zif->rtadv.ra_configured, VTY_RA_DISABLED);
} else {
/* Enable if it has been activated by someone before disabling */
if (CHECK_FLAG(zif->rtadv.ra_configured,
(VTY_RA_CONFIGURED | BGP_RA_CONFIGURED)))
ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_DISABLED);
}

return NB_OK;
}

/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval
*/
Expand Down

0 comments on commit 1d07dba

Please sign in to comment.