summaryrefslogtreecommitdiffstats
path: root/ospfd
diff options
context:
space:
mode:
authorPaul Jakma <paul@quagga.net>2010-01-11 15:48:22 +0000
committerDavid Lamparter <equinox@diac24.net>2010-02-05 01:02:21 +0100
commitb0c8c48d7fa4c691ddbe07403ccc37a26258a25e (patch)
treefbb59b63b3bf37cecd5718b598d325be4c3c4251 /ospfd
parentd0f7c7eadaa8d46306609305bc610ec902c522c2 (diff)
downloadquagga-b0c8c48d7fa4c691ddbe07403ccc37a26258a25e.tar.bz2
quagga-b0c8c48d7fa4c691ddbe07403ccc37a26258a25e.tar.xz
ospfd: use workqueue for ospf_ase_calculate_route
* The ospf_ase_calculate_timer can take a long time to run, as it scales O(# of AS-External LSAs), in domains with lots of external routes. Fix this by using a work-queue for the per-LSA processing, thus splitting it up a bit. * ospf_ase.h: (ospf_ase_calculate_route, ospf_ase_calculate_schedule) no need for these to be exported. * ospf_spf.c: (ospf_spf_calculate_timer) ospf_ase_calculate_schedule is gone. * ospfd.h: (struct ospf) add a work-queue for the AS-External route calculation. * ospf_ase.c: (ospf_ase_calc_completion) completion func, for when ase-calculation is done. Also have to take care to see if the timer needs to be rescheduled, which is the case if ospf->ase_calc is set again but there is no timer scheduled. (ospf_ase_calc_process) workqueue processing function, calls to the existing ospf_ase_calculate_route. (ospf_ase_calculate_timer) add to work-queue, instead of calling ospf_ase_calculate_route directly. (ospf_ase_calculate_timer_add) do the job of ospf_ase_calculate_schedule which can be removed. Set flag so we can tell if a timer schedule comes in while the previous timer is running.
Diffstat (limited to 'ospfd')
-rw-r--r--ospfd/ospf_ase.c77
-rw-r--r--ospfd/ospf_ase.h2
-rw-r--r--ospfd/ospf_spf.c3
-rw-r--r--ospfd/ospfd.h3
4 files changed, 57 insertions, 28 deletions
diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c
index d3873561..c06f0178 100644
--- a/ospfd/ospf_ase.c
+++ b/ospfd/ospf_ase.c
@@ -31,6 +31,7 @@
#include "table.h"
#include "vty.h"
#include "log.h"
+#include "workqueue.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
@@ -272,8 +273,8 @@ ospf_ase_calculate_new_route (struct ospf_lsa *lsa,
#define OSPF_ASE_CALC_INTERVAL 1
-int
-ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa)
+static int
+ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa *lsa)
{
u_int32_t metric;
struct as_external_lsa *al;
@@ -612,6 +613,50 @@ ospf_ase_compare_tables (struct route_table *new_external_route,
return 0;
}
+static int ospf_ase_calculate_timer (struct thread *);
+
+static void ospf_ase_calc_completion (struct work_queue *wq)
+{
+ struct ospf *ospf = wq->spec.data;
+
+ /* Compare old and new external routing table and install the
+ difference info zebra/kernel */
+ ospf_ase_compare_tables (ospf->new_external_route,
+ ospf->old_external_route);
+
+ /* Delete old external routing table */
+ ospf_route_table_free (ospf->old_external_route);
+ ospf->old_external_route = ospf->new_external_route;
+ ospf->new_external_route = route_table_init ();
+
+ /* another timer fired since, so another run might be needed */
+ if (ospf->ase_calc && !ospf->t_ase_calc)
+ ospf->t_ase_calc = thread_add_timer (master, ospf_ase_calculate_timer,
+ ospf, 0);
+}
+
+static wq_item_status
+ospf_ase_calc_process (struct work_queue *wq, void *data)
+{
+ struct ospf_lsa *lsa = data;
+ ospf_ase_calculate_route (wq->spec.data, lsa);
+ ospf_lsa_unlock (&lsa);
+ return WQ_SUCCESS;
+}
+
+static void
+ospf_ase_calc_queue_init (struct ospf *ospf)
+{
+ ospf->ase_calc_queue = work_queue_new (master, "ase_calc_queue");
+
+ ospf->ase_calc_queue->spec.workfunc = &ospf_ase_calc_process;
+ ospf->ase_calc_queue->spec.completion_func = &ospf_ase_calc_completion;
+
+ ospf->ase_calc_queue->spec.data = ospf;
+ ospf->ase_calc_queue->spec.max_retries = 0;
+ ospf->ase_calc_queue->spec.hold = 0;
+}
+
static int
ospf_ase_calculate_timer (struct thread *t)
{
@@ -628,9 +673,12 @@ ospf_ase_calculate_timer (struct thread *t)
{
ospf->ase_calc = 0;
+ if (!ospf->ase_calc_queue)
+ ospf_ase_calc_queue_init (ospf);
+
/* Calculate external route for each AS-external-LSA */
LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
- ospf_ase_calculate_route (ospf, lsa);
+ work_queue_add (ospf->ase_calc_queue, ospf_lsa_lock (lsa));
/* This version simple adds to the table all NSSA areas */
if (ospf->anyNSSA)
@@ -642,39 +690,22 @@ ospf_ase_calculate_timer (struct thread *t)
if (area->external_routing == OSPF_AREA_NSSA)
LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
- ospf_ase_calculate_route (ospf, lsa);
+ work_queue_add (ospf->ase_calc_queue, ospf_lsa_lock (lsa));
}
/* kevinm: And add the NSSA routes in ospf_top */
LSDB_LOOP (NSSA_LSDB (ospf),rn,lsa)
- ospf_ase_calculate_route(ospf,lsa);
-
- /* Compare old and new external routing table and install the
- difference info zebra/kernel */
- ospf_ase_compare_tables (ospf->new_external_route,
- ospf->old_external_route);
-
- /* Delete old external routing table */
- ospf_route_table_free (ospf->old_external_route);
- ospf->old_external_route = ospf->new_external_route;
- ospf->new_external_route = route_table_init ();
+ work_queue_add (ospf->ase_calc_queue, ospf_lsa_lock (lsa));
}
return 0;
}
void
-ospf_ase_calculate_schedule (struct ospf *ospf)
+ospf_ase_calculate_timer_add (struct ospf *ospf)
{
if (ospf == NULL)
return;
ospf->ase_calc = 1;
-}
-
-void
-ospf_ase_calculate_timer_add (struct ospf *ospf)
-{
- if (ospf == NULL)
- return;
if (! ospf->t_ase_calc)
ospf->t_ase_calc = thread_add_timer (master, ospf_ase_calculate_timer,
diff --git a/ospfd/ospf_ase.h b/ospfd/ospf_ase.h
index e6a1b2fb..646a38c0 100644
--- a/ospfd/ospf_ase.h
+++ b/ospfd/ospf_ase.h
@@ -34,8 +34,6 @@ extern struct ospf_route *ospf_find_asbr_route_through_area (struct
struct ospf_area
*);
-extern int ospf_ase_calculate_route (struct ospf *, struct ospf_lsa *);
-extern void ospf_ase_calculate_schedule (struct ospf *);
extern void ospf_ase_calculate_timer_add (struct ospf *);
extern void ospf_ase_external_lsas_finish (struct route_table *);
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index fb863681..c744cb2a 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -1259,9 +1259,6 @@ ospf_spf_calculate_timer (struct thread *thread)
/* If new Router Route is installed,
then schedule re-calculate External routes. */
- if (1)
- ospf_ase_calculate_schedule (ospf);
-
ospf_ase_calculate_timer_add (ospf);
/* Update routing table. */
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index af6d495c..a47c313d 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -272,6 +272,9 @@ struct ospf
struct stream *ibuf;
struct list *oi_write_q;
+ /* queue for AS-External route calculation */
+ struct work_queue *ase_calc_queue;
+
/* Distribute lists out of other route sources. */
struct
{