]> git.puffer.fish Git - mirror/frr.git/commitdiff
Zebra: Schedule RIB processing based on trigger event
authorvivek <vivek@cumulusnetworks.com>
Wed, 9 Dec 2015 00:55:43 +0000 (16:55 -0800)
committervivek <vivek@cumulusnetworks.com>
Wed, 9 Dec 2015 00:55:43 +0000 (16:55 -0800)
Currently, when RIB processing is initiated (i.e., by calling rib_update()),
all routes are queued for processing. This is not desirable in all situations
because, sometimes the protocol may have an alternate path. In addition,
with NHT tracking nexthops, there are situations when NHT should be kicked
off first and that can trigger subsequent RIB processing.

This patch addresses this by introducing the notion of a trigger event. This
is only for the situation when the entire RIB is walked. The current triggers
- based on when rib_update() is invoked - are "interface change" and "route-
map change". In the former case, only the relevant routes are walked and
scheduled, in the latter case, currently all routes are scheduled for
processing.

Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Ticket: CM-7662
Reviewed By: CCR-3905

Note: The initial defect in this area was CM-7420. This was addressed in
2.5.4 with an interim change that only walked static routes upon interface
down. The change was considered a bit risky to do for interface up etc. Also,
this did not address scenarios like CM-7662. The current fix addresses CM-7662.

zebra/connected.c
zebra/interface.c
zebra/rib.h
zebra/zebra_rib.c
zebra/zebra_routemap.c

index f67b44ba805289f8cdc70fd64c554c5410f989ee..b2fababc1bc14f8f8d5d447090c1d259e9e16712 100644 (file)
@@ -215,9 +215,9 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
        ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update", __func__);
-
-  rib_update (ifp->vrf_id);
+    zlog_debug ("%u: IF %s IPv4 address add/up, scheduling RIB processing",
+                ifp->vrf_id, ifp->name);
+  rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
 }
 
 /* Add connected IPv4 route to the interface. */
@@ -334,9 +334,10 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
                    SAFI_MULTICAST);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update_static", __func__);
+    zlog_debug ("%u: IF %s IPv4 address down, scheduling RIB processing",
+                ifp->vrf_id, ifp->name);
 
-  rib_update_static (ifp->vrf_id);
+  rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
 }
 
 /* Delete connected IPv4 route to the interface. */
@@ -359,9 +360,10 @@ connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
   connected_withdraw (ifc);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update_static", __func__);
+    zlog_debug ("%u: IF %s IPv4 address del, scheduling RIB processing",
+                ifp->vrf_id, ifp->name);
 
-  rib_update_static(ifp->vrf_id);
+  rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
 }
 
 #ifdef HAVE_IPV6
@@ -388,9 +390,10 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
                 RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update", __func__);
+    zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing",
+                ifp->vrf_id, ifp->name);
 
-  rib_update (ifp->vrf_id);
+  rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
 }
 
 /* Add connected IPv6 route to the interface. */
@@ -477,9 +480,10 @@ connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
                    ifp->vrf_id, 0, SAFI_UNICAST);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update_static", __func__);
+    zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing",
+                ifp->vrf_id, ifp->name);
 
-  rib_update_static (ifp->vrf_id);
+  rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
 }
 
 void
@@ -501,9 +505,10 @@ connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
   connected_withdraw (ifc);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update_static", __func__);
+    zlog_debug ("%u: IF %s IPv6 address del, scheduling RIB processing",
+                ifp->vrf_id, ifp->name);
 
-  rib_update_static(ifp->vrf_id);
+  rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
 }
 #endif /* HAVE_IPV6 */
 
index 2768e69a6d21e2c136a5bdd657e6b34676cecddb..cb4645c2f1a18eba59e5e2fb964907c43ea7fb0c 100644 (file)
@@ -639,11 +639,9 @@ if_up (struct interface *ifp)
     }
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update on interface %s up", __func__,
-                ifp->name);
-
-  /* Examine all static routes. */
-  rib_update (ifp->vrf_id);
+    zlog_debug ("%u: IF %s up, scheduling RIB processing",
+                ifp->vrf_id, ifp->name);
+  rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
 }
 
 /* Interface goes down.  We have to manage different behavior of based
@@ -675,12 +673,10 @@ if_down (struct interface *ifp)
        }
     }
 
-  /* Examine all static routes which direct to the interface. */
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update_static on interface %s down", __func__,
-                ifp->name);
-
-  rib_update_static (ifp->vrf_id);
+    zlog_debug ("%u: IF %s down, scheduling RIB processing",
+                ifp->vrf_id, ifp->name);
+  rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
 
   if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
 
index aefe437be2756fa84494684c29b38a00cf6cc8b2..4d5ccac6063474c17f3530d0c87b0be06259b33d 100644 (file)
@@ -371,6 +371,14 @@ typedef struct rib_tables_iter_t_
   rib_tables_iter_state_t state;
 } rib_tables_iter_t;
 
+/* Events/reasons triggering a RIB update. */
+typedef enum
+{
+  RIB_UPDATE_IF_CHANGE,
+  RIB_UPDATE_RMAP_CHANGE,
+  RIB_UPDATE_OTHER
+} rib_update_event_t;
+
 extern struct nexthop *rib_nexthop_ifindex_add (struct rib *, unsigned int);
 extern struct nexthop *rib_nexthop_ifname_add (struct rib *, char *);
 extern struct nexthop *rib_nexthop_blackhole_add (struct rib *);
@@ -433,8 +441,7 @@ extern struct rib *rib_match_ipv4 (struct in_addr, vrf_id_t);
 
 extern struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *, vrf_id_t);
 
-extern void rib_update (vrf_id_t);
-extern void rib_update_static (vrf_id_t);
+extern void rib_update (vrf_id_t, rib_update_event_t);
 extern void rib_weed_tables (void);
 extern void rib_sweep_route (void);
 extern void rib_close_table (struct route_table *);
index 87425cb4b93943dabbe5e8f70cf6d518cadc58a6..d5b1f82343abf452616578f1f55e3f0d1b65c819 100644 (file)
@@ -3545,56 +3545,83 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
   return 1;
 }
 
-/* RIB update function. */
-void
-rib_update_static (vrf_id_t vrf_id)
+/* Schedule routes of a particular table (address-family) based on event. */
+static void
+rib_update_table (struct route_table *table, rib_update_event_t event)
 {
   struct route_node *rn;
-  struct route_table *table;
   struct rib *rib, *next;
 
-  table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
-  if (table)
-    for (rn = route_top (table); rn; rn = route_next (rn))
-      RNODE_FOREACH_RIB_SAFE (rn, rib, next)
-        if (rib->type == ZEBRA_ROUTE_STATIC)
-          {
-            rib_queue_add (&zebrad, rn);
-            break;
-          }
+  /* Walk all routes and queue for processing, if appropriate for
+   * the trigger event.
+   */
+  for (rn = route_top (table); rn; rn = route_next (rn))
+    {
+      switch (event)
+        {
+        case RIB_UPDATE_IF_CHANGE:
+          /* Examine all routes that won't get processed by the protocol or
+           * triggered by nexthop evaluation (NHT). This would be system,
+           * kernel and certain static routes. Note that NHT will get
+           * triggered upon an interface event as connected routes always
+           * get queued for processing.
+           */
+          RNODE_FOREACH_RIB_SAFE (rn, rib, next)
+            {
+              if (rib->type == ZEBRA_ROUTE_OSPF ||
+                  rib->type == ZEBRA_ROUTE_OSPF6 ||
+                  rib->type == ZEBRA_ROUTE_BGP)
+                continue; /* protocol will handle. */
+              else if (rib->type == ZEBRA_ROUTE_STATIC)
+                {
+                  struct nexthop *nh;
+                  for (nh = rib->nexthop; nh; nh = nh->next)
+                    if (!(nh->type == NEXTHOP_TYPE_IPV4 ||
+                        nh->type == NEXTHOP_TYPE_IPV6))
+                      break;
+
+                  /* If we only have nexthops to a gateway, NHT will
+                   * take care.
+                   */
+                  if (nh)
+                    rib_queue_add (&zebrad, rn);
+                }
+              else
+                  rib_queue_add (&zebrad, rn);
+            }
+          break;
 
-  table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
-  if (table)
-    for (rn = route_top (table); rn; rn = route_next (rn))
-      RNODE_FOREACH_RIB_SAFE (rn, rib, next)
-        if (rib->type == ZEBRA_ROUTE_STATIC)
-          {
+        case RIB_UPDATE_RMAP_CHANGE:
+        case RIB_UPDATE_OTHER:
+          /* Right now, examine all routes. Can restrict to a protocol in
+           * some cases (TODO).
+           */
+          if (rnode_to_ribs (rn))
             rib_queue_add (&zebrad, rn);
-            break;
-          }
+          break;
+
+        default:
+          break;
+        }
+    }
 }
 
 /* RIB update function. */
 void
-rib_update (vrf_id_t vrf_id)
+rib_update (vrf_id_t vrf_id, rib_update_event_t event)
 {
-  struct route_node *rn;
   struct route_table *table;
-  
+
+  /* Process routes of interested address-families. */
   table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
   if (table)
-    for (rn = route_top (table); rn; rn = route_next (rn))
-      if (rnode_to_ribs (rn))
-        rib_queue_add (&zebrad, rn);
+    rib_update_table (table, event);
 
   table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
   if (table)
-    for (rn = route_top (table); rn; rn = route_next (rn))
-      if (rnode_to_ribs (rn))
-        rib_queue_add (&zebrad, rn);
+    rib_update_table (table, event);
 }
 
-
 /* Remove all routes which comes from non main table.  */
 static void
 rib_weed_table (struct route_table *table)
index 5d16dbba4f15e9a896aeb28f1956f67324133d3c..fbd9db18796b56ffbe7a35dc05c7bdf506255532 100644 (file)
@@ -784,9 +784,10 @@ DEFUN (ip_protocol,
   proto_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update", __func__);
+    zlog_debug ("%u: IPv4 Routemap config for protocol %s, scheduling RIB processing",
+                VRF_DEFAULT, argv[0]);
 
-  rib_update(VRF_DEFAULT);
+  rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
   return CMD_SUCCESS;
 }
 
@@ -821,9 +822,9 @@ DEFUN (no_ip_protocol,
       proto_rm[AFI_IP][i] = NULL;
 
       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-        zlog_debug ("%s: calling rib_update", __func__);
-
-      rib_update(VRF_DEFAULT);
+        zlog_debug ("%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing",
+                    VRF_DEFAULT, argv[0]);
+      rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
     }
   return CMD_SUCCESS;
 }
@@ -896,9 +897,10 @@ DEFUN (ipv6_protocol,
   proto_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update", __func__);
+    zlog_debug ("%u: IPv6 Routemap config for protocol %s, scheduling RIB processing",
+                VRF_DEFAULT, argv[0]);
 
-  rib_update(VRF_DEFAULT);
+  rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
   return CMD_SUCCESS;
 }
 
@@ -933,9 +935,10 @@ DEFUN (no_ipv6_protocol,
       proto_rm[AFI_IP6][i] = NULL;
 
       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-        zlog_debug ("%s: calling rib_update", __func__);
+        zlog_debug ("%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing",
+                    VRF_DEFAULT, argv[0]);
 
-      rib_update(VRF_DEFAULT);
+      rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
     }
   return CMD_SUCCESS;
 }
@@ -1611,9 +1614,10 @@ zebra_route_map_update_timer (struct thread *thread)
     zlog_debug("Event driven route-map update triggered");
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-    zlog_debug ("%s: calling rib_update", __func__);
+    zlog_debug ("%u: Routemap update-timer fired, scheduling RIB processing",
+                VRF_DEFAULT);
 
-  rib_update(VRF_DEFAULT);
+  rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
   zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
   zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);