]> git.puffer.fish Git - mirror/frr.git/commitdiff
+ fixed bug #418 (changing address on an existing interface doesn't cause existing...
authorDenis Ovsienko <linux@pilot.org.ua>
Mon, 12 Nov 2007 14:55:01 +0000 (14:55 +0000)
committerDenis Ovsienko <linux@pilot.org.ua>
Mon, 12 Nov 2007 14:55:01 +0000 (14:55 +0000)
lib/ChangeLog
lib/linklist.c
lib/workqueue.c
lib/workqueue.h
zebra/ChangeLog
zebra/connected.c

index 0725f795c1ed093d09494d1351a8a236299f285e..bd66f071c3083c1e6f50989ff7a4055a30b41fa5 100644 (file)
@@ -1,3 +1,19 @@
+2007-11-12 Denis Ovsienko
+
+       * linklist.c: (listnode_add_after) Don't forget to increment list
+         items counter.
+       * workqueue.h: Changed working queue flags from enum into integer
+         and introduced WQ_AIM_HEAD flag to indicate our will to insert
+         new data before the list head.
+       * workqueue.[ch]: (work_queue_schedule, show_work_queues,
+         work_queue_plug, work_queue_unplug) Adjust to the new flags style.
+       * workqueue.[ch]: (work_queue_aim_head) new function to control the
+         WQ_AIM_HEAD flag
+       * workqueue.[ch]: (work_queue_new) Explicitly set both WQ flags
+         during new WQ initialization.
+       * workqueue.[ch]: (work_queue_add) If WQ_AIM_HEAD indicates a need
+         to place the new data into list head, do it.
+
 2007-10-22 Lorenzo Colitti <lorenzo@colitti.com>
 
        * smux.c: (smux_stop) Avoid cancelling a defunct thread pointer
index 11e16a8a4af61e505aef4461d2e1e4bee203db79..983da2d155b637a71ae8b408a117bfa19d8b6568 100644 (file)
@@ -158,6 +158,7 @@ listnode_add_after (struct list *list, struct listnode *pp, void *val)
 
       pp->next = nn;
     }
+  list->count++;
 }
 
 
index a0f48bc8d6625d521d96f93c717fb182be605b49..8880b9e22ed01ae31ed1c9290940ecd94cb233a2 100644 (file)
@@ -66,6 +66,8 @@ work_queue_new (struct thread_master *m, const char *queue_name)
   
   new->name = XSTRDUP (MTYPE_WORK_QUEUE_NAME, queue_name);
   new->master = m;
+  SET_FLAG (new->flags, WQ_UNPLUGGED);
+  UNSET_FLAG (new->flags, WQ_AIM_HEAD);
   
   if ( (new->items = list_new ()) == NULL)
     {
@@ -103,7 +105,7 @@ static inline int
 work_queue_schedule (struct work_queue *wq, unsigned int delay)
 {
   /* if appropriate, schedule work queue thread */
-  if ( (wq->flags == WQ_UNPLUGGED) 
+  if ( CHECK_FLAG (wq->flags, WQ_UNPLUGGED)
        && (wq->thread == NULL)
        && (listcount (wq->items) > 0) )
     {
@@ -129,7 +131,10 @@ work_queue_add (struct work_queue *wq, void *data)
     }
   
   item->data = data;
-  listnode_add (wq->items, item);
+  if (CHECK_FLAG (wq->flags, WQ_AIM_HEAD))
+    listnode_add_after (wq->items, NULL, item);
+  else
+    listnode_add (wq->items, item);
   
   work_queue_schedule (wq, wq->spec.hold);
   
@@ -186,7 +191,7 @@ DEFUN(show_work_queues,
   for (ALL_LIST_ELEMENTS_RO ((&work_queues), node, wq))
     {
       vty_out (vty,"%c %8d %5d %8ld %7d %6d %6u %s%s",
-               (wq->flags == WQ_PLUGGED ? 'P' : ' '),
+               (CHECK_FLAG (wq->flags, WQ_UNPLUGGED) ? ' ' : 'P'),
                listcount (wq->items),
                wq->spec.hold,
                wq->runs,
@@ -211,7 +216,7 @@ work_queue_plug (struct work_queue *wq)
   
   wq->thread = NULL;
   
-  wq->flags = WQ_PLUGGED;
+  UNSET_FLAG (wq->flags, WQ_UNPLUGGED);
 }
 
 /* unplug queue, schedule it again, if appropriate
@@ -220,12 +225,21 @@ work_queue_plug (struct work_queue *wq)
 void
 work_queue_unplug (struct work_queue *wq)
 {
-  wq->flags = WQ_UNPLUGGED;
+  SET_FLAG (wq->flags, WQ_UNPLUGGED);
 
   /* if thread isnt already waiting, add one */
   work_queue_schedule (wq, wq->spec.hold);
 }
 
+void
+work_queue_aim_head (struct work_queue *wq, const unsigned aim_head)
+{
+  if (aim_head)
+    SET_FLAG (wq->flags, WQ_AIM_HEAD);
+  else
+    UNSET_FLAG (wq->flags, WQ_AIM_HEAD);
+}
+
 /* timer thread to process a work queue
  * will reschedule itself if required,
  * otherwise work_queue_item_add 
index 7e0e78abcbfb7be5cd8ca16aa934db0c8cd6e8a3..3150c32e7adf7c2fb2c8198143f4be61a71d1bb6 100644 (file)
@@ -47,11 +47,8 @@ struct work_queue_item
   unsigned short ran;                  /* # of times item has been run */
 };
 
-enum work_queue_flags
-{
-  WQ_UNPLUGGED = 0,
-  WQ_PLUGGED = 1,
-};
+#define WQ_UNPLUGGED   (1 << 0) /* available for draining */
+#define WQ_AIM_HEAD    (1 << 1) /* add new items before list head, not after tail */
 
 struct work_queue
 {
@@ -101,7 +98,7 @@ struct work_queue
   } cycles;    /* cycle counts */
   
   /* private state */
-  enum work_queue_flags flags;         /* user set flag */
+  u_int16_t flags;             /* user set flag */
 };
 
 /* User API */
@@ -122,6 +119,8 @@ extern void work_queue_add (struct work_queue *, void *);
 extern void work_queue_plug (struct work_queue *wq);
 /* unplug the queue, allow it to be drained again */
 extern void work_queue_unplug (struct work_queue *wq);
+/* control the value for WQ_AIM_HEAD flag */
+extern void work_queue_aim_head (struct work_queue *wq, const unsigned);
 
 /* Helpers, exported for thread.c and command.c */
 extern int work_queue_run (struct thread *);
index e152729d3ce00d66134db60b3e29d78d638c78bf..3ce7b9ea691526ceb083f08cee59894d51aef8e4 100644 (file)
@@ -1,3 +1,10 @@
+2007-11-12 Denis Ovsienko
+
+       * connected.c: (connected_up_ipv4, connected_down_ipv4,
+         connected_up_ipv6, connected_down_ipv6) Collect all changed
+         connected routes closest possible to the RIB work queue, so
+         that the rest can be revalidated correctly.
+
 2007-10-24 Denis Ovsienko
 
        * kernel_socket.c: (rtm_read) we used to ignore own messages,
index 53aa25432fa4eb76c865f8231ff4c0e46fa54e27..8bf1d337dbcd67f0f2113f17e95c8f25df019a17 100644 (file)
@@ -35,6 +35,7 @@
 #include "zebra/redistribute.h"
 #include "zebra/interface.h"
 #include "zebra/connected.h"
+extern struct zebra_t zebrad;
 \f
 /* withdraw a connected address */
 static void
@@ -187,8 +188,15 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
   if (prefix_ipv4_any (&p))
     return;
 
+  /* Always push arriving/departing connected routes into the head of
+   * the working queue to make possible proper validation of the rest
+   * of the RIB queue (which will contain the whole RIB after the first
+   * call to rib_update()).
+   */
+  work_queue_aim_head (zebrad.ribq, 1);
   rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
        RT_TABLE_MAIN, ifp->metric, 0);
+  work_queue_aim_head (zebrad.ribq, 0);
 
   rib_update ();
 }
@@ -293,7 +301,10 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
   if (prefix_ipv4_any (&p))
     return;
 
+  /* Same logic as for connected_up_ipv4(): push the changes into the head. */
+  work_queue_aim_head (zebrad.ribq, 1);
   rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
+  work_queue_aim_head (zebrad.ribq, 0);
 
   rib_update ();
 }
@@ -338,8 +349,10 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
     return;
 #endif
 
+  work_queue_aim_head (zebrad.ribq, 1);
   rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0,
                 ifp->metric, 0);
+  work_queue_aim_head (zebrad.ribq, 0);
 
   rib_update ();
 }
@@ -413,7 +426,9 @@ connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
   if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
     return;
 
+  work_queue_aim_head (zebrad.ribq, 1);
   rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
+  work_queue_aim_head (zebrad.ribq, 0);
 
   rib_update ();
 }