summaryrefslogtreecommitdiffstats
path: root/ospfd/ospf_ase.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd/ospf_ase.c')
-rw-r--r--ospfd/ospf_ase.c104
1 files changed, 59 insertions, 45 deletions
diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c
index 5d0cae42..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"
@@ -130,18 +131,6 @@ ospf_find_asbr_route_through_area (struct route_table *rtrs,
return NULL;
}
-static void
-ospf_ase_complete_direct_routes (struct ospf_route *ro, struct in_addr nexthop)
-{
- struct listnode *node;
- struct ospf_path *op;
- struct interface *ifp;
-
- for (ALL_LIST_ELEMENTS_RO (ro->paths, node, op))
- if (op->nexthop.s_addr == 0)
- op->nexthop.s_addr = nexthop.s_addr;
-}
-
static int
ospf_ase_forward_address_check (struct ospf *ospf, struct in_addr fwd_addr)
{
@@ -284,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;
@@ -451,8 +440,8 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa)
/* if there is a Intra/Inter area route to the N
do not install external route */
- if (rn = route_node_lookup (ospf->new_table,
- (struct prefix *) &p))
+ if ((rn = route_node_lookup (ospf->new_table,
+ (struct prefix *) &p)))
{
route_unlock_node(rn);
if (rn->info == NULL)
@@ -463,8 +452,8 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa)
}
/* Find a route to the same dest */
/* If there is no route, create new one. */
- if (rn = route_node_lookup (ospf->new_external_route,
- (struct prefix *) &p))
+ if ((rn = route_node_lookup (ospf->new_external_route,
+ (struct prefix *) &p)))
route_unlock_node(rn);
if (!rn || (or = rn->info) == NULL)
@@ -475,8 +464,6 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa)
ospf_route_add (ospf->new_external_route, &p, new, asbr_route);
- if (al->e[0].fwd_addr.s_addr)
- ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr);
return 0;
}
else
@@ -513,8 +500,7 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa)
if (IS_DEBUG_OSPF (lsa, LSA))
zlog_debug ("Route[External]: New route is better");
ospf_route_subst (rn, new, asbr_route);
- if (al->e[0].fwd_addr.s_addr)
- ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr);
+
or = new;
new = NULL;
}
@@ -531,8 +517,6 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa)
if (IS_DEBUG_OSPF (lsa, LSA))
zlog_debug ("Route[External]: Routes are equal");
ospf_route_copy_nexthops (or, asbr_route->paths);
- if (al->e[0].fwd_addr.s_addr)
- ospf_ase_complete_direct_routes (or, al->e[0].fwd_addr);
}
}
/* Make sure setting newly calculated ASBR route.*/
@@ -629,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)
{
@@ -645,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)
@@ -659,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,