summaryrefslogtreecommitdiff
path: root/zebra/rtadv.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/rtadv.c')
-rw-r--r--zebra/rtadv.c87
1 files changed, 82 insertions, 5 deletions
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 4903455a2b..f51c199f6b 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -495,7 +495,8 @@ static int rtadv_timer(struct thread *thread)
zif = ifp->info;
if (zif->rtadv.AdvSendAdvertisements) {
- if (zif->rtadv.inFastRexmit) {
+ if (zif->rtadv.inFastRexmit
+ && zif->rtadv.UseFastRexmit) {
/* We assume we fast rexmit every sec so
* no
* additional vars */
@@ -535,9 +536,28 @@ static int rtadv_timer(struct thread *thread)
static void rtadv_process_solicit(struct interface *ifp)
{
struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_if *zif;
assert(zvrf);
- rtadv_send_packet(rtadv_get_socket(zvrf), ifp);
+ zif = ifp->info;
+
+ /*
+ * If FastRetransmit is enabled, send the RA immediately.
+ * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
+ * (3 seconds) since the last RA was sent, send it now and reset
+ * the timer to start at the max (configured) again.
+ * If not enabled and it is less than 3 seconds since the last
+ * RA packet was sent, set the timer for 3 seconds so the next
+ * one will be sent with a minimum of 3 seconds between RAs.
+ * RFC4861 sec 6.2.6
+ */
+ if ((zif->rtadv.UseFastRexmit)
+ || (zif->rtadv.AdvIntervalTimer <=
+ (zif->rtadv.MaxRtrAdvInterval - MIN_DELAY_BETWEEN_RAS))) {
+ rtadv_send_packet(rtadv_get_socket(zvrf), ifp);
+ zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
+ } else
+ zif->rtadv.AdvIntervalTimer = MIN_DELAY_BETWEEN_RAS;
}
/*
@@ -904,9 +924,12 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
zif->rtadv.AdvIntervalTimer = 0;
zvrf->rtadv.adv_if_count++;
- if (zif->rtadv.MaxRtrAdvInterval >= 1000) {
- /* Enable Fast RA only when RA interval is in
- * secs */
+ if ((zif->rtadv.MaxRtrAdvInterval >= 1000)
+ && zif->rtadv.UseFastRexmit) {
+ /*
+ * Enable Fast RA only when RA interval is in
+ * secs and Fast RA retransmit is enabled
+ */
zif->rtadv.inFastRexmit = 1;
zif->rtadv.NumFastReXmitsRemain =
RTADV_NUM_FAST_REXMITS;
@@ -996,6 +1019,51 @@ void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
}
+DEFUN (ipv6_nd_ra_fast_retrans,
+ ipv6_nd_ra_fast_retrans_cmd,
+ "ipv6 nd ra-fast-retrans",
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Fast retransmit of RA packets\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct zebra_if *zif = ifp->info;
+
+ if (if_is_loopback(ifp)
+ || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
+ vty_out(vty,
+ "Cannot configure IPv6 Router Advertisements on this interface\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ zif->rtadv.UseFastRexmit = true;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_nd_ra_fast_retrans,
+ no_ipv6_nd_ra_fast_retrans_cmd,
+ "no ipv6 nd ra-fast-retrans",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Fast retransmit of RA packets\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct zebra_if *zif = ifp->info;
+
+ if (if_is_loopback(ifp)
+ || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
+ vty_out(vty,
+ "Cannot configure IPv6 Router Advertisements on this interface\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ zif->rtadv.UseFastRexmit = false;
+
+ return CMD_SUCCESS;
+}
+
DEFUN (ipv6_nd_suppress_ra,
ipv6_nd_suppress_ra_cmd,
"ipv6 nd suppress-ra",
@@ -1954,6 +2022,10 @@ static int nd_dump_vty(struct vty *vty, struct interface *ifp)
" ND router advertisements are sent every "
"%d seconds\n",
interval / 1000);
+ if (!rtadv->UseFastRexmit)
+ vty_out(vty,
+ " ND router advertisements do not use fast retransmit\n");
+
if (rtadv->AdvDefaultLifetime != -1)
vty_out(vty,
" ND router advertisements live for %d seconds\n",
@@ -2025,6 +2097,9 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
if (zif->rtadv.AdvIntervalOption)
vty_out(vty, " ipv6 nd adv-interval-option\n");
+ if (!zif->rtadv.UseFastRexmit)
+ vty_out(vty, " no ipv6 nd ra-fast-retrans\n");
+
if (zif->rtadv.AdvDefaultLifetime != -1)
vty_out(vty, " ipv6 nd ra-lifetime %d\n",
zif->rtadv.AdvDefaultLifetime);
@@ -2173,6 +2248,8 @@ void rtadv_cmd_init(void)
hook_register(zebra_if_extra_info, nd_dump_vty);
hook_register(zebra_if_config_wr, rtadv_config_write);
+ install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
+ install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);