]> git.puffer.fish Git - matthieu/frr.git/commitdiff
2005-04-28 Paul Jakma <paul.jakma@sun.com>
authorpaul <paul>
Thu, 28 Apr 2005 17:35:14 +0000 (17:35 +0000)
committerpaul <paul>
Thu, 28 Apr 2005 17:35:14 +0000 (17:35 +0000)
* rib.h: (struct rib) Add lock field for refcounting.
* zserv.h: (struct zebra_t) Add a ribq workqueue to the zebra
  'master' struct.
* zserv.c: (zread_ipv4_add) XMALLOC then memset should be XCALLOC.
* zebra_rib.c: Clean up refcounting of route_node, make struct rib
  refcounted and convert rib_process to work-queue. In general,
  rib's should be rib_addnode'd and delnode'd to route_nodes, and
  these symmetrical functions will manage the locking of referenced
  route_node and freeing of struct rib - rather than having users
  manage each seperately - with much scope for bugs..
  (newrib_free) removed and replaced with rib_lock
  (rib_lock) new function, check state of lock and increment.
  (rib_unlock) new function, check lock state and decrement. Free
  struct rib if refcount hits 0, freeing struct nexthop's, as
  newrib_free did.
  (rib_addnode) Add RIB to route_node, locking both.
  (rib_delnode) Delete RIB from route_node, unlocking each.
  (rib_process) Converted to a work-queue work function.
  Functional changes are minimal, just arguments, comments and
  whitespace.
  (rib_queue_add_qnode) Helper function to setup a ribq item.
  (rib_queue_add) Helper function, same arguments as old
  rib_process, to replace in callers of rib_process.
  (rib_queue_qnode_del) ribq deconstructor.
  (rib_queue_init) Create the ribq.
  (rib_init) call rib_queue_init.
  (remainder) Sanitise refcounting of route_node's. Convert to
  rib_queue_add, rib_addnode and rib_delnode. Change XMALLOC/memset
  to XCALLOC. Remove calls to nexthop_delete and nexthop_free.

zebra/ChangeLog
zebra/rib.h
zebra/zebra_rib.c
zebra/zserv.c
zebra/zserv.h

index 7210c7a8a18f6a836f71a5ad4126b91f45b2f57f..4ddf101fd1132562c0760aa09001fd0498826cd4 100644 (file)
@@ -1,3 +1,35 @@
+2005-04-28 Paul Jakma <paul.jakma@sun.com>
+
+       * rib.h: (struct rib) Add lock field for refcounting.
+       * zserv.h: (struct zebra_t) Add a ribq workqueue to the zebra
+         'master' struct.
+       * zserv.c: (zread_ipv4_add) XMALLOC then memset should be XCALLOC.
+       * zebra_rib.c: Clean up refcounting of route_node, make struct rib
+         refcounted and convert rib_process to work-queue. In general,
+         rib's should be rib_addnode'd and delnode'd to route_nodes, and 
+         these symmetrical functions will manage the locking of referenced
+         route_node and freeing of struct rib - rather than having users
+         manage each seperately - with much scope for bugs..
+         (newrib_free) removed and replaced with rib_lock
+         (rib_lock) new function, check state of lock and increment.
+         (rib_unlock) new function, check lock state and decrement. Free
+         struct rib if refcount hits 0, freeing struct nexthop's, as 
+         newrib_free did.
+         (rib_addnode) Add RIB to route_node, locking both.
+         (rib_delnode) Delete RIB from route_node, unlocking each.
+         (rib_process) Converted to a work-queue work function.
+         Functional changes are minimal, just arguments, comments and 
+         whitespace.
+         (rib_queue_add_qnode) Helper function to setup a ribq item.
+         (rib_queue_add) Helper function, same arguments as old
+         rib_process, to replace in callers of rib_process.
+         (rib_queue_qnode_del) ribq deconstructor.
+         (rib_queue_init) Create the ribq.
+         (rib_init) call rib_queue_init.
+         (remainder) Sanitise refcounting of route_node's. Convert to 
+         rib_queue_add, rib_addnode and rib_delnode. Change XMALLOC/memset
+         to XCALLOC. Remove calls to nexthop_delete and nexthop_free.
+         
 2005-04-10 Paul Jakma <paul@dishone.st>
 
        * if_ioctl_solaris.c: (if_lookup_linklocal) fix order of args
index b21e087f24098e291256fe838801a3fb6be33205..1e6393e6ae13bb49e0bde1d15363981f50b7a733 100644 (file)
@@ -32,6 +32,9 @@ struct rib
   struct rib *next;
   struct rib *prev;
 
+  /* ref count */
+  unsigned int lock;
+  
   /* Type fo this route. */
   int type;
 
index 8eb80619c3759ce559a0711cb156f4ebc0e5eb5d..a8aaef3eb665c7e71726032596c5e733f662ed4b 100644 (file)
@@ -29,6 +29,9 @@
 #include "if.h"
 #include "log.h"
 #include "sockunion.h"
+#include "linklist.h"
+#include "thread.h"
+#include "workqueue.h"
 
 #include "zebra/rib.h"
 #include "zebra/rt.h"
@@ -57,6 +60,12 @@ struct
   {ZEBRA_ROUTE_ISIS,    115},
   {ZEBRA_ROUTE_BGP,      20  /* IBGP is 200. */}
 };
+
+struct zebra_queue_node_t
+{
+  struct route_node *node;
+  struct rib *del;
+};
 \f
 /* Vector for routing table.  */
 vector vrf_vector;
@@ -776,18 +785,35 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
 #define RIB_SYSTEM_ROUTE(R) \
         ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
 
-void
-newrib_free (struct rib *rib)
+static struct rib *
+rib_lock (struct rib *rib)
+{
+  assert (rib->lock >= 0);
+  
+  rib->lock++;
+  return rib;
+}
+
+static struct rib *
+rib_unlock (struct rib *rib)
 {
   struct nexthop *nexthop;
   struct nexthop *next;
+  
+  assert (rib->lock > 0);
+  rib->lock--;
 
-  for (nexthop = rib->nexthop; nexthop; nexthop = next)
+  if (rib->lock == 0)
     {
-      next = nexthop->next;
-      nexthop_free (nexthop);
+      for (nexthop = rib->nexthop; nexthop; nexthop = next)
+        {
+          next = nexthop->next;
+          nexthop_free (nexthop);
+        }
+      XFREE (MTYPE_RIB, rib);
+      return NULL;
     }
-  XFREE (MTYPE_RIB, rib);
+  return rib;
 }
 
 void
@@ -854,16 +880,28 @@ rib_uninstall (struct route_node *rn, struct rib *rib)
 }
 
 /* Core function for processing routing information base. */
-void
-rib_process (struct route_node *rn, struct rib *del)
+wq_item_status
+rib_process (struct zebra_queue_node_t *qnode)
 {
   struct rib *rib;
   struct rib *next;
   struct rib *fib = NULL;
   struct rib *select = NULL;
+  struct rib *del = qnode->del;
+  struct route_node *rn = qnode->node;
   int installed = 0;
   struct nexthop *nexthop = NULL;
-
+  
+  assert (rn);
+  
+  /* possibly should lock and unlock rib on each iteration. however, for
+   * now, we assume called functions are synchronous and dont delete RIBs
+   * (as the work-queue deconstructor for this function is supposed to be
+   * the canonical 'delete' path for RIBs). Further if called functions
+   * below were to made asynchronous they should themselves acquire any
+   * locks/refcounts as needed and not depend on this caller to do it for
+   * them
+   */
   for (rib = rn->info; rib; rib = next)
     {
       next = rib->next;
@@ -871,7 +909,7 @@ rib_process (struct route_node *rn, struct rib *del)
       /* Currently installed rib. */
       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
         fib = rib;
-
+      
       /* Skip unreachable nexthop. */
       if (! nexthop_active_update (rn, rib, 0))
         continue;
@@ -885,44 +923,51 @@ rib_process (struct route_node *rn, struct rib *del)
           || rib->type == ZEBRA_ROUTE_CONNECT)
         select = rib;
     }
-
+  
   /* Deleted route check. */
   if (del && CHECK_FLAG (del->flags, ZEBRA_FLAG_SELECTED))
     fib = del;
-
+  
+  /* We possibly should lock fib and select here However, all functions
+   * below are 'inline' and not asynchronous And if any were to be
+   * converted, they should manage references themselves really..  See
+   * previous comment above.
+   */
+  
   /* Same route is selected. */
   if (select && select == fib)
     {
       if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
-       {
-         redistribute_delete (&rn->p, select);
-         if (! RIB_SYSTEM_ROUTE (select))
-           rib_uninstall_kernel (rn, select);
+        {
+          redistribute_delete (&rn->p, select);
+          if (! RIB_SYSTEM_ROUTE (select))
+            rib_uninstall_kernel (rn, select);
 
-         /* Set real nexthop. */
-         nexthop_active_update (rn, select, 1);
+          /* Set real nexthop. */
+          nexthop_active_update (rn, select, 1);
   
-         if (! RIB_SYSTEM_ROUTE (select))
-           rib_install_kernel (rn, select);
-         redistribute_add (&rn->p, select);
-       }
+          if (! RIB_SYSTEM_ROUTE (select))
+            rib_install_kernel (rn, select);
+          redistribute_add (&rn->p, select);
+        }
       else if (! RIB_SYSTEM_ROUTE (select))
-       {
-         /* Housekeeping code to deal with 
-            race conditions in kernel with linux
-            netlink reporting interface up before IPv4 or IPv6 protocol
-            is ready to add routes.
-            This makes sure the routes are IN the kernel.
-         */
-
-         for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
-           {
-             if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
-               installed = 1;
-           }
-           if (! installed) rib_install_kernel (rn, select);
-       }
-      return;
+        {
+          /* Housekeeping code to deal with 
+             race conditions in kernel with linux
+             netlink reporting interface up before IPv4 or IPv6 protocol
+             is ready to add routes.
+             This makes sure the routes are IN the kernel.
+           */
+
+          for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
+            {
+              if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+                installed = 1;
+            }
+          if (! installed) 
+            rib_install_kernel (rn, select);
+        }
+      return WQ_SUCCESS;
     }
 
   /* Uninstall old rib from forwarding table. */
@@ -944,10 +989,102 @@ rib_process (struct route_node *rn, struct rib *del)
       nexthop_active_update (rn, select, 1);
 
       if (! RIB_SYSTEM_ROUTE (select))
-       rib_install_kernel (rn, select);
+        rib_install_kernel (rn, select);
       SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
       redistribute_add (&rn->p, select);
     }
+
+  return WQ_SUCCESS;
+
+}
+
+/* Add work queue item to work queue and schedule processing */
+void
+rib_queue_add_qnode (struct zebra_t *zebra, struct zebra_queue_node_t *qnode)
+{
+  route_lock_node (qnode->node);
+  
+  if (IS_ZEBRA_DEBUG_EVENT)
+    zlog_info ("rib_queue_add_qnode: work queue added");
+
+  assert (zebra && qnode && qnode->node);
+
+  if (qnode->del)
+    rib_lock (qnode->del);
+  
+  if (zebra->ribq == NULL)
+    {
+      zlog_err ("rib_queue_add_qnode: ribq work_queue does not exist!");
+      route_unlock_node (qnode->node);
+      return;
+    }
+  
+  work_queue_add (zebra->ribq, qnode);
+
+  return;
+}
+
+/* Add route node and rib to work queue and schedule processing */
+void
+rib_queue_add (struct zebra_t *zebra, struct route_node *rn, struct rib *del)
+{
+ struct zebra_queue_node_t *qnode;
+
+ assert (zebra && rn);
+ qnode = (struct zebra_queue_node_t *) 
+          XCALLOC (MTYPE_RIB_QUEUE, sizeof (struct zebra_queue_node_t));
+ if (qnode == NULL)
+   {
+     zlog_err ("rib_queue_add: failed to allocate queue node memory, %s",
+               strerror (errno));
+     return;
+   }
+
+ qnode->node = rn;
+ qnode->del = del;
+ rib_queue_add_qnode (zebra, qnode);
+
+ return;
+}
+
+/* free zebra_queue_node_t */
+void
+rib_queue_qnode_del (struct zebra_queue_node_t *qnode)
+{
+  route_unlock_node (qnode->node);
+  
+  if (qnode->del)
+    rib_unlock (qnode->del);
+  
+  XFREE (MTYPE_RIB_QUEUE, qnode);
+}
+
+/* initialise zebra rib work queue */
+void
+rib_queue_init (struct zebra_t *zebra)
+{
+  assert (zebra);
+  
+  if (! (zebra->ribq = work_queue_new (zebra->master, 
+                                       "zebra_rib_work_queue")))
+    {
+      zlog_err ("rib_queue_init: could not initialise work queue!");
+      return;
+    }
+
+  /* fill in the work queue spec */
+  zebra->ribq->spec.workfunc = (wq_item_status (*) (void *))&rib_process;
+  zebra->ribq->spec.errorfunc = NULL;
+  zebra->ribq->spec.del_item_data = (void (*) (void *)) &rib_queue_qnode_del;
+  /* XXX: TODO: These should be runtime configurable via vty */
+  zebra->ribq->spec.max_retries = 3;
+  zebra->ribq->spec.hold = 500;
+  zebra->ribq->spec.delay = 10;
+  
+  return;
 }
 
 /* Add RIB to head of the route node. */
@@ -955,7 +1092,12 @@ void
 rib_addnode (struct route_node *rn, struct rib *rib)
 {
   struct rib *head;
-
+  
+  assert (rib && rn);
+  
+  rib_lock (rib);
+  route_lock_node (rn);
+  
   head = rn->info;
   if (head)
     head->prev = rib;
@@ -966,12 +1108,17 @@ rib_addnode (struct route_node *rn, struct rib *rib)
 void
 rib_delnode (struct route_node *rn, struct rib *rib)
 {
+  assert (rn && rib);
+  
   if (rib->next)
     rib->next->prev = rib->prev;
   if (rib->prev)
     rib->prev->next = rib->next;
   else
     rn->info = rib->next;
+  
+  rib_unlock (rib);
+  route_unlock_node (rn);
 }
 
 int
@@ -1011,30 +1158,27 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
   for (rib = rn->info; rib; rib = rib->next)
     {
       if (rib->type == ZEBRA_ROUTE_CONNECT)
-       {
-         nexthop = rib->nexthop;
+        {
+          nexthop = rib->nexthop;
 
-         /* Duplicate connected route comes in. */
-         if (rib->type == type
-             && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
-             && nexthop->ifindex == ifindex)
-           {
-             rib->refcnt++;
-             return 0 ;
-           }
-       }
+          /* Duplicate connected route comes in. */
+          if (rib->type == type
+              && nexthop && nexthop->type == NEXTHOP_TYPE_IFINDEX
+              && nexthop->ifindex == ifindex)
+            {
+              rib->refcnt++;
+              return 0 ;
+            }
+        }
       else if (rib->type == type)
-       {
-         same = rib;
-         rib_delnode (rn, same);
-         route_unlock_node (rn);
-         break;
-       }
+        {
+          same = rib;
+          break;
+        }
     }
 
   /* Allocate new rib structure. */
-  rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
-  memset (rib, 0, sizeof (struct rib));
+  rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
   rib->type = type;
   rib->distance = distance;
   rib->flags = flags;
@@ -1061,14 +1205,15 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
 
   /* Link new rib to node.*/
   rib_addnode (rn, rib);
-
+  
   /* Process this route node. */
-  rib_process (rn, same);
-
+  rib_queue_add (&zebrad, rn, same);
+  
   /* Free implicit route.*/
   if (same)
-    newrib_free (same);
-
+    rib_delnode (rn, same);
+  
+  route_unlock_node (rn);
   return 0;
 }
 
@@ -1079,12 +1224,11 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
   struct route_node *rn;
   struct rib *same;
   struct nexthop *nexthop;
-
+  
   /* Lookup table.  */
   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
   if (! table)
     return 0;
-
   /* Make it sure prefixlen is applied to the prefix. */
   apply_mask_ipv4 (p);
 
@@ -1108,13 +1252,9 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
     {
       if (same->type == rib->type && same->table == rib->table
          && same->type != ZEBRA_ROUTE_CONNECT)
-       {
-         rib_delnode (rn, same);
-         route_unlock_node (rn);
-         break;
-       }
+        break;
     }
-
+  
   /* If this route is kernel route, set FIB flag to the route. */
   if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
     for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
@@ -1124,12 +1264,13 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
   rib_addnode (rn, rib);
 
   /* Process this route node. */
-  rib_process (rn, same);
+  rib_queue_add (&zebrad, rn, same);
 
   /* Free implicit route.*/
   if (same)
-    newrib_free (same);
-
+    rib_delnode (rn, same);
+  
+  route_unlock_node (rn);
   return 0;
 }
 
@@ -1265,21 +1406,14 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
          return ZEBRA_ERR_RTNOEXIST;
        }
     }
-
-  if (same)
-    rib_delnode (rn, same);
-
+  
   /* Process changes. */
-  rib_process (rn, same);
+  rib_queue_add (&zebrad, rn, same);
 
   if (same)
-    {
-      newrib_free (same);
-      route_unlock_node (rn);
-    }
-
+    rib_delnode (rn, same);
+  
   route_unlock_node (rn);
-
   return 0;
 }
 \f
@@ -1318,15 +1452,14 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
           case STATIC_IPV4_BLACKHOLE:
             nexthop_blackhole_add (rib);
             break;
-         }
-      rib_process (rn, NULL);
+        }
+      rib_queue_add (&zebrad, rn, NULL);
     }
   else
     {
       /* This is new static route. */
-      rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
-      memset (rib, 0, sizeof (struct rib));
-
+      rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
+      
       rib->type = ZEBRA_ROUTE_STATIC;
       rib->distance = si->distance;
       rib->metric = 0;
@@ -1352,7 +1485,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
       rib_addnode (rn, rib);
 
       /* Process this prefix. */
-      rib_process (rn, NULL);
+      rib_queue_add (&zebrad, rn, NULL);
     }
 }
 
@@ -1386,7 +1519,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
   if (! table)
     return;
-
+  
   /* Lookup existing route with type and distance. */
   rn = route_node_lookup (table, p);
   if (! rn)
@@ -1417,20 +1550,15 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
   /* Check nexthop. */
   if (rib->nexthop_num == 1)
     {
+      rib_queue_add (&zebrad, rn, rib);
       rib_delnode (rn, rib);
-      rib_process (rn, rib);
-      newrib_free (rib);
-      route_unlock_node (rn);
     }
   else
     {
       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
         rib_uninstall (rn, rib);
-      nexthop_delete (rib, nexthop);
-      nexthop_free (nexthop);
-      rib_process (rn, rib);
+      rib_queue_add (&zebrad, rn, rib);
     }
-
   /* Unlock node. */
   route_unlock_node (rn);
 }
@@ -1671,15 +1799,13 @@ rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
       else if (rib->type == type)
        {
          same = rib;
-         rib_delnode (rn, same);
-         route_unlock_node (rn);
          break;
        }
     }
 
   /* Allocate new rib structure. */
-  rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
-  memset (rib, 0, sizeof (struct rib));
+  rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
+  
   rib->type = type;
   rib->distance = distance;
   rib->flags = flags;
@@ -1708,12 +1834,13 @@ rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
   rib_addnode (rn, rib);
 
   /* Process this route node. */
-  rib_process (rn, same);
-
+  rib_queue_add (&zebrad, rn, same);
+  
   /* Free implicit route.*/
   if (same)
-    newrib_free (same);
-
+    rib_delnode (rn, same);
+  
+  route_unlock_node (rn);
   return 0;
 }
 
@@ -1737,7 +1864,7 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
   table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
   if (! table)
     return 0;
-
+  
   /* Lookup route node. */
   rn = route_node_lookup (table, (struct prefix *) p);
   if (! rn)
@@ -1829,20 +1956,13 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
        }
     }
 
-  if (same)
-    rib_delnode (rn, same);
-
   /* Process changes. */
-  rib_process (rn, same);
+  rib_queue_add (&zebrad, rn, same);
 
   if (same)
-    {
-      newrib_free (same);
-      route_unlock_node (rn);
-    }
-
+    rib_delnode (rn, same);
+  
   route_unlock_node (rn);
-
   return 0;
 }
 \f
@@ -1883,14 +2003,13 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
          nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
          break;
        }
-      rib_process (rn, NULL);
+      rib_queue_add (&zebrad, rn, NULL);
     }
   else
     {
       /* This is new static route. */
-      rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
-      memset (rib, 0, sizeof (struct rib));
-
+      rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
+      
       rib->type = ZEBRA_ROUTE_STATIC;
       rib->distance = si->distance;
       rib->metric = 0;
@@ -1916,7 +2035,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
       rib_addnode (rn, rib);
 
       /* Process this prefix. */
-      rib_process (rn, NULL);
+      rib_queue_add (&zebrad, rn, NULL);
     }
 }
 
@@ -1982,19 +2101,14 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
   if (rib->nexthop_num == 1)
     {
       rib_delnode (rn, rib);
-      rib_process (rn, rib);
-      newrib_free (rib);
-      route_unlock_node (rn);
+      rib_queue_add (&zebrad, rn, rib);
     }
   else
     {
       if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
         rib_uninstall (rn, rib);
-      nexthop_delete (rib, nexthop);
-      nexthop_free (nexthop);
-      rib_process (rn, rib);
+      rib_queue_add (&zebrad, rn, rib);
     }
-
   /* Unlock node. */
   route_unlock_node (rn);
 }
@@ -2140,16 +2254,18 @@ rib_update ()
 {
   struct route_node *rn;
   struct route_table *table;
-
+  
   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
   if (table)
     for (rn = route_top (table); rn; rn = route_next (rn))
-      rib_process (rn, NULL);
+      if (rn->info)
+        rib_queue_add (&zebrad, rn, NULL);
 
   table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
   if (table)
     for (rn = route_top (table); rn; rn = route_next (rn))
-      rib_process (rn, NULL);
+      if (rn->info)
+        rib_queue_add (&zebrad, rn, NULL);
 }
 
 /* Interface goes up. */
@@ -2182,11 +2298,7 @@ rib_weed_table (struct route_table *table)
 
          if (rib->table != zebrad.rtm_table_default &&
              rib->table != RT_TABLE_MAIN)
-           {
-             rib_delnode (rn, rib);
-             newrib_free (rib);
-             route_unlock_node (rn);
-           }
+            rib_delnode (rn, rib);
        }
 }
 
@@ -2218,11 +2330,7 @@ rib_sweep_table (struct route_table *table)
            {
              ret = rib_uninstall_kernel (rn, rib);
              if (! ret)
-               {
-                 rib_delnode (rn, rib);
-                 newrib_free (rib);
-                 route_unlock_node (rn);
-               }
+                rib_delnode (rn, rib);
            }
        }
 }
@@ -2262,6 +2370,7 @@ rib_close ()
 void
 rib_init ()
 {
+  rib_queue_init (&zebrad);
   /* VRF initialization.  */
   vrf_init ();
 }
index e90fe0194a101f8da509b8f834bd5fc135e96af5..c02eac89211a61a2540c013c72de3817f34fc05d 100644 (file)
@@ -780,9 +780,8 @@ zread_ipv4_add (struct zserv *client, u_short length)
   s = client->ibuf;
 
   /* Allocate new rib. */
-  rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
-  memset (rib, 0, sizeof (struct rib));
-
+  rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
+  
   /* Type, flags, message. */
   rib->type = stream_getc (s);
   rib->flags = stream_getc (s);
index 445dc766577e788021654b90b2aeaec073ba906e..db822a9b9770deefb745bb44f0a0fbb94de0e31a 100644 (file)
@@ -23,6 +23,7 @@
 #define _ZEBRA_ZSERV_H
 
 #include "rib.h"
+#include "workqueue.h"
 
 /* Default port information. */
 #define ZEBRA_PORT                    2600
@@ -76,7 +77,9 @@ struct zebra_t
 
   /* default table */
   int rtm_table_default;
-  
+
+  /* rib work queue */
+  struct work_queue *ribq;
 };
 
 /* Count prefix size from mask length */