]> git.puffer.fish Git - mirror/frr.git/commitdiff
Add support for fast rexmit of RA on link transitions.
authorDinesh G Dutt <ddutt@cumulusnetworks.com>
Wed, 27 Apr 2016 01:26:10 +0000 (18:26 -0700)
committerDinesh G Dutt <ddutt@cumulusnetworks.com>
Wed, 27 Apr 2016 20:54:08 +0000 (13:54 -0700)
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
zebra/interface.h
zebra/rtadv.c

index 760b1a9852c02ed4d7633e1ec941ed05f05bad98..66ab536cf61273b2ac7f5838251931860a44d835 100644 (file)
@@ -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);
 
index bb76612ff1b8e2924dda155aa22c09711ba1a11e..2e88566e1a48b816f30c5c794fc3babc8dbba37d 100644 (file)
@@ -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 */
index 4807782d4dd3ad2dd6eb7cc1eef5e3edf2dae9bb..e3e390d5655b9d50f8885e0e025da7332660adbe 100644 (file)
@@ -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)