From 6c9678b4544510205d1243c979c9d81001e1b78b Mon Sep 17 00:00:00 2001 From: Dinesh G Dutt Date: Tue, 26 Apr 2016 18:26:10 -0700 Subject: [PATCH] Add support for fast rexmit of RA on link transitions. Ticket: CM-7076 Reviewed By: CCR-4568 Testing Done: To allow for faster convergence, modify transmission of IPv6 RA so that on link transitions(link up, change VRF, link add etc.), we transmit RA fast to ensure faster convergence with BGP Unnumbered. But we don't enable Fast RA if RA interval is in msecs as we've fixed the fast RA interval to be 1s. We retransmit RA 4 times, once each second on link events and when RA is first enabled. --- zebra/interface.c | 8 ++++++++ zebra/interface.h | 6 ++++++ zebra/rtadv.c | 37 +++++++++++++++++++++++++++++-------- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index 760b1a9852..66ab536cf6 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -805,6 +805,14 @@ if_up (struct interface *ifp) if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (ifp); + /* Enable fast tx of RA if enabled && RA interval is not in msecs */ + if (zif->rtadv.AdvSendAdvertisements && + (zif->rtadv.MaxRtrAdvInterval >= 1000)) + { + zif->rtadv.inFastRexmit = 1; + zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS; + } + /* Install connected routes to the kernel. */ if_install_connected (ifp); diff --git a/zebra/interface.h b/zebra/interface.h index bb76612ff1..2e88566e1a 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -170,6 +170,12 @@ struct rtadvconf Default: 0 (medium) */ int DefaultPreference; #define RTADV_PREF_MEDIUM 0x0 /* Per RFC4191. */ + + u_char inFastRexmit; /* True if we're rexmits faster than usual */ + int NumFastReXmitsRemain; /* Loaded first with number of fast rexmits to do */ + +#define RTADV_FAST_REXMIT_PERIOD 1 /* 1 sec */ +#define RTADV_NUM_FAST_REXMITS 4 /* Fast Rexmit RA 4 times on certain events */ }; #endif /* HAVE_RTADV */ diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 4807782d4d..e3e390d565 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -402,14 +402,28 @@ rtadv_timer (struct thread *thread) if (zif->rtadv.AdvSendAdvertisements) { - zif->rtadv.AdvIntervalTimer -= period; - if (zif->rtadv.AdvIntervalTimer <= 0) + if (zif->rtadv.inFastRexmit) { - /* FIXME: using MaxRtrAdvInterval each time isn't what section - 6.2.4 of RFC4861 tells to do. */ - zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; + /* We assume we fast rexmit every sec so no additional vars */ + if (--zif->rtadv.NumFastReXmitsRemain <= 0) + zif->rtadv.inFastRexmit = 0; + + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug("Fast RA Rexmit on interface %s", ifp->name); + rtadv_send_packet (zns->rtadv.sock, ifp); } + else + { + zif->rtadv.AdvIntervalTimer -= period; + if (zif->rtadv.AdvIntervalTimer <= 0) + { + /* FIXME: using MaxRtrAdvInterval each time isn't what section + 6.2.4 of RFC4861 tells to do. */ + zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; + rtadv_send_packet (zns->rtadv.sock, ifp); + } + } } } @@ -754,6 +768,13 @@ ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status statu zif->rtadv.AdvIntervalTimer = 0; zns->rtadv.adv_if_count++; + if (zif->rtadv.MaxRtrAdvInterval >= 1000) + { + /* Enable Fast RA only when RA interval is in secs */ + zif->rtadv.inFastRexmit = 1; + zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS; + } + if_join_all_router (zns->rtadv.sock, ifp); if (zns->rtadv.adv_if_count == 1) @@ -1889,10 +1910,10 @@ rtadv_event (struct zebra_ns *zns, enum rtadv_event event, int val) { case RTADV_START: if (! rtadv->ra_read) - rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zns, val); + rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zns, val); if (! rtadv->ra_timer) - rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer, - zns, 0); + rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer, + zns, 0); break; case RTADV_STOP: if (rtadv->ra_timer) -- 2.39.5