diff options
author | Paul Jakma <paul@quagga.net> | 2010-01-11 15:48:22 +0000 |
---|---|---|
committer | David Lamparter <equinox@diac24.net> | 2010-02-05 01:02:21 +0100 |
commit | b0c8c48d7fa4c691ddbe07403ccc37a26258a25e (patch) | |
tree | fbb59b63b3bf37cecd5718b598d325be4c3c4251 | |
parent | d0f7c7eadaa8d46306609305bc610ec902c522c2 (diff) | |
download | quagga-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.
-rw-r--r-- | ospfd/ospf_ase.c | 77 | ||||
-rw-r--r-- | ospfd/ospf_ase.h | 2 | ||||
-rw-r--r-- | ospfd/ospf_spf.c | 3 | ||||
-rw-r--r-- | ospfd/ospfd.h | 3 |
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 { |