diff options
Diffstat (limited to 'zebra/rtadv.c')
| -rw-r--r-- | zebra/rtadv.c | 87 |
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); |
