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 */
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;
}
/*
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;
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",
" 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",
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);
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);