summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_route.c13
-rw-r--r--lib/command.c2
-rw-r--r--lib/thread.c138
-rw-r--r--lib/thread.h1
-rw-r--r--lib/workqueue.c17
-rw-r--r--ospfd/ospf_ase.c77
-rw-r--r--ospfd/ospf_ase.h2
-rw-r--r--ospfd/ospf_lsa.c4
-rw-r--r--ospfd/ospf_nsm.c24
-rw-r--r--ospfd/ospf_nsm.h2
-rw-r--r--ospfd/ospf_packet.c113
-rw-r--r--ospfd/ospf_packet.h1
-rw-r--r--ospfd/ospf_spf.c3
-rw-r--r--ospfd/ospfd.h3
14 files changed, 279 insertions, 121 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 8e068fc4..3d0417b1 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1614,14 +1614,13 @@ bgp_process_queue_init (void)
}
bm->process_main_queue->spec.workfunc = &bgp_process_main;
- bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
- bm->process_rsclient_queue->spec.del_item_data
- = bm->process_main_queue->spec.del_item_data;
- bm->process_main_queue->spec.max_retries
- = bm->process_main_queue->spec.max_retries = 0;
- bm->process_rsclient_queue->spec.hold
- = bm->process_main_queue->spec.hold = 50;
+ bm->process_main_queue->spec.max_retries = 0;
+ bm->process_main_queue->spec.hold = 50;
+
+ memcpy (bm->process_rsclient_queue, bm->process_main_queue,
+ sizeof (struct work_queue *));
+ bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
}
void
diff --git a/lib/command.c b/lib/command.c
index bf624cc0..19fc192a 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -3618,6 +3618,8 @@ cmd_init (int terminal)
install_element (VIEW_NODE, &show_thread_cpu_cmd);
install_element (ENABLE_NODE, &show_thread_cpu_cmd);
install_element (RESTRICTED_NODE, &show_thread_cpu_cmd);
+
+ install_element (ENABLE_NODE, &clear_thread_cpu_cmd);
install_element (VIEW_NODE, &show_work_queues_cmd);
install_element (ENABLE_NODE, &show_work_queues_cmd);
}
diff --git a/lib/thread.c b/lib/thread.c
index 1e714417..208f5a2a 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -430,6 +430,89 @@ DEFUN(show_thread_cpu,
cpu_record_print(vty, filter);
return CMD_SUCCESS;
}
+
+static void
+cpu_record_hash_clear (struct hash_backet *bucket,
+ void *args)
+{
+ thread_type *filter = args;
+ struct cpu_thread_history *a = bucket->data;
+
+ a = bucket->data;
+ if ( !(a->types & *filter) )
+ return;
+
+ hash_release (cpu_record, bucket->data);
+}
+
+static void
+cpu_record_clear (thread_type filter)
+{
+ thread_type *tmp = &filter;
+ hash_iterate (cpu_record,
+ (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear,
+ tmp);
+}
+
+DEFUN(clear_thread_cpu,
+ clear_thread_cpu_cmd,
+ "clear thread cpu [FILTER]",
+ "Clear stored data\n"
+ "Thread information\n"
+ "Thread CPU usage\n"
+ "Display filter (rwtexb)\n")
+{
+ int i = 0;
+ thread_type filter = (thread_type) -1U;
+
+ if (argc > 0)
+ {
+ filter = 0;
+ while (argv[0][i] != '\0')
+ {
+ switch ( argv[0][i] )
+ {
+ case 'r':
+ case 'R':
+ filter |= (1 << THREAD_READ);
+ break;
+ case 'w':
+ case 'W':
+ filter |= (1 << THREAD_WRITE);
+ break;
+ case 't':
+ case 'T':
+ filter |= (1 << THREAD_TIMER);
+ break;
+ case 'e':
+ case 'E':
+ filter |= (1 << THREAD_EVENT);
+ break;
+ case 'x':
+ case 'X':
+ filter |= (1 << THREAD_EXECUTE);
+ break;
+ case 'b':
+ case 'B':
+ filter |= (1 << THREAD_BACKGROUND);
+ break;
+ default:
+ break;
+ }
+ ++i;
+ }
+ if (filter == 0)
+ {
+ vty_out(vty, "Invalid filter \"%s\" specified,"
+ " must contain at least one of 'RWTEXB'%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ cpu_record_clear (filter);
+ return CMD_SUCCESS;
+}
/* List allocation and head/tail print out. */
static void
@@ -951,6 +1034,24 @@ thread_timer_process (struct thread_list *list, struct timeval *timenow)
return ready;
}
+/* process a list en masse, e.g. for event thread lists */
+static unsigned int
+thread_process (struct thread_list *list)
+{
+ struct thread *thread;
+ unsigned int ready = 0;
+
+ for (thread = list->head; thread; thread = thread->next)
+ {
+ thread_list_delete (list, thread);
+ thread->type = THREAD_READY;
+ thread_list_add (&thread->master->ready, thread);
+ ready++;
+ }
+ return ready;
+}
+
+
/* Fetch next ready thread. */
struct thread *
thread_fetch (struct thread_master *m, struct thread *fetch)
@@ -960,38 +1061,45 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
fd_set writefd;
struct timeval timer_val;
struct timeval timer_val_bg;
- struct timeval *timer_wait;
+ struct timeval *timer_wait = &timer_val;
struct timeval *timer_wait_bg;
while (1)
{
int num = 0;
- /* Signals are highest priority */
+ /* Signals pre-empt everything */
quagga_sigevent_process ();
- /* Normal event are the next highest priority. */
- if ((thread = thread_trim_head (&m->event)) != NULL)
- return thread_run (m, thread, fetch);
-
- /* If there are any ready threads from previous scheduler runs,
- * process top of them.
+ /* Drain the ready queue of already scheduled jobs, before scheduling
+ * more.
*/
if ((thread = thread_trim_head (&m->ready)) != NULL)
return thread_run (m, thread, fetch);
+ /* To be fair to all kinds of threads, and avoid starvation, we
+ * need to be careful to consider all thread types for scheduling
+ * in each quanta. I.e. we should not return early from here on.
+ */
+
+ /* Normal event are the next highest priority. */
+ thread_process (&m->event);
+
/* Structure copy. */
readfd = m->readfd;
writefd = m->writefd;
/* Calculate select wait timer if nothing else to do */
- quagga_get_relative (NULL);
- timer_wait = thread_timer_wait (&m->timer, &timer_val);
- timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg);
-
- if (timer_wait_bg &&
- (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
- timer_wait = timer_wait_bg;
+ if (m->ready.count == 0)
+ {
+ quagga_get_relative (NULL);
+ timer_wait = thread_timer_wait (&m->timer, &timer_val);
+ timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg);
+
+ if (timer_wait_bg &&
+ (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
+ timer_wait = timer_wait_bg;
+ }
num = select (FD_SETSIZE, &readfd, &writefd, NULL, timer_wait);
diff --git a/lib/thread.h b/lib/thread.h
index c0198a36..7de679c8 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -203,6 +203,7 @@ extern int thread_should_yield (struct thread *);
/* Internal libzebra exports */
extern void thread_getrusage (RUSAGE_T *);
extern struct cmd_element show_thread_cpu_cmd;
+extern struct cmd_element clear_thread_cpu_cmd;
/* replacements for the system gettimeofday(), clock_gettime() and
* time() functions, providing support for non-decrementing clock on
diff --git a/lib/workqueue.c b/lib/workqueue.c
index 7c811edd..52b5f41c 100644
--- a/lib/workqueue.c
+++ b/lib/workqueue.c
@@ -341,7 +341,7 @@ work_queue_run (struct thread *thread)
stats:
-#define WQ_HYSTERIS_FACTOR 2
+#define WQ_HYSTERESIS_FACTOR 4
/* we yielded, check whether granularity should be reduced */
if (yielded && (cycles < wq->cycles.granularity))
@@ -349,17 +349,18 @@ stats:
wq->cycles.granularity = ((cycles > 0) ? cycles
: WORK_QUEUE_MIN_GRANULARITY);
}
-
- if (cycles >= (wq->cycles.granularity))
+ /* otherwise, should granularity increase? */
+ else if (cycles >= (wq->cycles.granularity))
{
if (cycles > wq->cycles.best)
wq->cycles.best = cycles;
- /* along with yielded check, provides hysteris for granularity */
- if (cycles > (wq->cycles.granularity * WQ_HYSTERIS_FACTOR * 2))
- wq->cycles.granularity *= WQ_HYSTERIS_FACTOR; /* quick ramp-up */
- else if (cycles > (wq->cycles.granularity * WQ_HYSTERIS_FACTOR))
- wq->cycles.granularity += WQ_HYSTERIS_FACTOR;
+ /* along with yielded check, provides hysteresis for granularity */
+ if (cycles > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR
+ * WQ_HYSTERESIS_FACTOR))
+ wq->cycles.granularity *= WQ_HYSTERESIS_FACTOR; /* quick ramp-up */
+ else if (cycles > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR))
+ wq->cycles.granularity += WQ_HYSTERESIS_FACTOR;
}
#undef WQ_HYSTERIS_FACTOR
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_lsa.c b/ospfd/ospf_lsa.c
index 6dd1d341..25bd754d 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -2914,6 +2914,10 @@ ospf_maxage_lsa_remover (struct thread *thread)
continue;
}
+ /* TODO: maybe convert this function to a work-queue */
+ if (thread_should_yield (thread))
+ OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 0);
+
/* Remove LSA from the LSDB */
if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF))
if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c
index b15efbd6..26e32d9b 100644
--- a/ospfd/ospf_nsm.c
+++ b/ospfd/ospf_nsm.c
@@ -162,7 +162,7 @@ nsm_should_adj (struct ospf_neighbor *nbr)
/* OSPF NSM functions. */
static int
-nsm_hello_received (struct ospf_neighbor *nbr)
+nsm_packet_received (struct ospf_neighbor *nbr)
{
/* Start or Restart Inactivity Timer. */
OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
@@ -408,7 +408,7 @@ struct {
{
/* DependUpon: dummy state. */
{ NULL, NSM_DependUpon }, /* NoEvent */
- { NULL, NSM_DependUpon }, /* HelloReceived */
+ { NULL, NSM_DependUpon }, /* PacketReceived */
{ NULL, NSM_DependUpon }, /* Start */
{ NULL, NSM_DependUpon }, /* 2-WayReceived */
{ NULL, NSM_DependUpon }, /* NegotiationDone */
@@ -425,7 +425,7 @@ struct {
{
/* Deleted: dummy state. */
{ NULL, NSM_Deleted }, /* NoEvent */
- { NULL, NSM_Deleted }, /* HelloReceived */
+ { NULL, NSM_Deleted }, /* PacketReceived */
{ NULL, NSM_Deleted }, /* Start */
{ NULL, NSM_Deleted }, /* 2-WayReceived */
{ NULL, NSM_Deleted }, /* NegotiationDone */
@@ -442,7 +442,7 @@ struct {
{
/* Down: */
{ NULL, NSM_DependUpon }, /* NoEvent */
- { nsm_hello_received, NSM_Init }, /* HelloReceived */
+ { nsm_packet_received, NSM_Init }, /* PacketReceived */
{ nsm_start, NSM_Attempt }, /* Start */
{ NULL, NSM_Down }, /* 2-WayReceived */
{ NULL, NSM_Down }, /* NegotiationDone */
@@ -459,7 +459,7 @@ struct {
{
/* Attempt: */
{ NULL, NSM_DependUpon }, /* NoEvent */
- { nsm_hello_received, NSM_Init }, /* HelloReceived */
+ { nsm_packet_received, NSM_Init }, /* PacketReceived */
{ NULL, NSM_Attempt }, /* Start */
{ NULL, NSM_Attempt }, /* 2-WayReceived */
{ NULL, NSM_Attempt }, /* NegotiationDone */
@@ -476,7 +476,7 @@ struct {
{
/* Init: */
{ NULL, NSM_DependUpon }, /* NoEvent */
- { nsm_hello_received, NSM_Init }, /* HelloReceived */
+ { nsm_packet_received, NSM_Init }, /* PacketReceived */
{ NULL, NSM_Init }, /* Start */
{ nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */
{ NULL, NSM_Init }, /* NegotiationDone */
@@ -493,7 +493,7 @@ struct {
{
/* 2-Way: */
{ NULL, NSM_DependUpon }, /* NoEvent */
- { nsm_hello_received, NSM_TwoWay }, /* HelloReceived */
+ { nsm_packet_received, NSM_TwoWay }, /* HelloReceived */
{ NULL, NSM_TwoWay }, /* Start */
{ NULL, NSM_TwoWay }, /* 2-WayReceived */
{ NULL, NSM_TwoWay }, /* NegotiationDone */
@@ -510,7 +510,7 @@ struct {
{
/* ExStart: */
{ NULL, NSM_DependUpon }, /* NoEvent */
- { nsm_hello_received, NSM_ExStart }, /* HelloReceived */
+ { nsm_packet_received, NSM_ExStart }, /* PacaketReceived */
{ NULL, NSM_ExStart }, /* Start */
{ NULL, NSM_ExStart }, /* 2-WayReceived */
{ nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */
@@ -527,7 +527,7 @@ struct {
{
/* Exchange: */
{ NULL, NSM_DependUpon }, /* NoEvent */
- { nsm_hello_received, NSM_Exchange }, /* HelloReceived */
+ { nsm_packet_received, NSM_Exchange }, /* PacketReceived */
{ NULL, NSM_Exchange }, /* Start */
{ NULL, NSM_Exchange }, /* 2-WayReceived */
{ NULL, NSM_Exchange }, /* NegotiationDone */
@@ -544,7 +544,7 @@ struct {
{
/* Loading: */
{ NULL, NSM_DependUpon }, /* NoEvent */
- { nsm_hello_received, NSM_Loading }, /* HelloReceived */
+ { nsm_packet_received, NSM_Loading }, /* PacketReceived */
{ NULL, NSM_Loading }, /* Start */
{ NULL, NSM_Loading }, /* 2-WayReceived */
{ NULL, NSM_Loading }, /* NegotiationDone */
@@ -560,7 +560,7 @@ struct {
},
{ /* Full: */
{ NULL, NSM_DependUpon }, /* NoEvent */
- { nsm_hello_received, NSM_Full }, /* HelloReceived */
+ { nsm_packet_received, NSM_Full }, /* PacketReceived */
{ NULL, NSM_Full }, /* Start */
{ NULL, NSM_Full }, /* 2-WayReceived */
{ NULL, NSM_Full }, /* NegotiationDone */
@@ -579,7 +579,7 @@ struct {
static const char *ospf_nsm_event_str[] =
{
"NoEvent",
- "HelloReceived",
+ "PacketReceived",
"Start",
"2-WayReceived",
"NegotiationDone",
diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h
index 1121dae6..4f2ae808 100644
--- a/ospfd/ospf_nsm.h
+++ b/ospfd/ospf_nsm.h
@@ -39,7 +39,7 @@
/* OSPF Neighbor State Machine Event. */
#define NSM_NoEvent 0
-#define NSM_HelloReceived 1
+#define NSM_PacketReceived 1 /* HelloReceived in the protocol */
#define NSM_Start 2
#define NSM_TwoWayReceived 3
#define NSM_NegotiationDone 4
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 74e1d46f..c4a6bf92 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -125,6 +125,20 @@ ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
fifo->count++;
}
+/* Add new packet to head of fifo. */
+static void
+ospf_fifo_push_head (struct ospf_fifo *fifo, struct ospf_packet *op)
+{
+ op->next = fifo->head;
+
+ if (fifo->tail == NULL)
+ fifo->tail = op;
+
+ fifo->head = op;
+
+ fifo->count++;
+}
+
/* Delete first packet from fifo. */
struct ospf_packet *
ospf_fifo_pop (struct ospf_fifo *fifo)
@@ -199,6 +213,27 @@ ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
/* ospf_fifo_debug (oi->obuf); */
}
+static void
+ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op)
+{
+ if (!oi->obuf)
+ {
+ zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
+ "destination %s) called with NULL obuf, ignoring "
+ "(please report this bug)!\n",
+ IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
+ ospf_packet_type_str[stream_getc_from(op->s, 1)],
+ inet_ntoa (op->dst));
+ return;
+ }
+
+ /* Add packet to head of queue. */
+ ospf_fifo_push_head (oi->obuf, op);
+
+ /* Debug of packet fifo*/
+ /* ospf_fifo_debug (oi->obuf); */
+}
+
void
ospf_packet_delete (struct ospf_interface *oi)
{
@@ -875,7 +910,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
old_state = nbr->state;
/* Add event to thread. */
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
/* RFC2328 Section 9.5.1
If the router is not eligible to become Designated Router,
@@ -895,19 +930,19 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
if (oi->type == OSPF_IFTYPE_NBMA &&
(old_state == NSM_Down || old_state == NSM_Attempt))
{
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
goto done;
}
if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors,
size - OSPF_HELLO_MIN_SIZE))
{
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_TwoWayReceived);
nbr->options |= hello->options;
}
else
{
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
goto done;
}
@@ -1190,6 +1225,9 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
}
#endif /* HAVE_OPAQUE_LSA */
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Process DD packet by neighbor status. */
switch (nbr->state)
{
@@ -1411,6 +1449,9 @@ ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Neighbor State should be Exchange or later. */
if (nbr->state != NSM_Exchange &&
nbr->state != NSM_Loading &&
@@ -1643,6 +1684,9 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Check neighbor state. */
if (nbr->state < NSM_Exchange)
{
@@ -1976,6 +2020,9 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
if (nbr->state < NSM_Exchange)
{
zlog_warn ("Link State Acknowledgment: "
@@ -2953,8 +3000,8 @@ ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
return length;
}
-void
-ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
+static void
+ospf_hello_send_sub (struct ospf_interface *oi, in_addr_t addr)
{
struct ospf_packet *op;
u_int16_t length = OSPF_HEADER_SIZE;
@@ -2973,10 +3020,12 @@ ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
/* Set packet length. */
op->length = length;
- op->dst.s_addr = addr->s_addr;
+ op->dst.s_addr = addr;
- /* Add packet to the interface output queue. */
- ospf_packet_add (oi, op);
+ /* Add packet to the top of the interface output queue, so that they
+ * can't get delayed by things like long queues of LS Update packets
+ */
+ ospf_packet_add_top (oi, op);
/* Hook thread to write packet. */
OSPF_ISM_WRITE_ON (oi->ospf);
@@ -3007,7 +3056,7 @@ ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
&& oi->state != ISM_DR && oi->state != ISM_Backup)
return;
- ospf_hello_send_sub (oi, &nbr_nbma->addr);
+ ospf_hello_send_sub (oi, nbr_nbma->addr.s_addr);
}
int
@@ -3046,7 +3095,7 @@ ospf_hello_reply_timer (struct thread *thread)
zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)",
IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
- ospf_hello_send_sub (nbr->oi, &nbr->src);
+ ospf_hello_send_sub (nbr->oi, nbr->src.s_addr);
return 0;
}
@@ -3055,27 +3104,10 @@ ospf_hello_reply_timer (struct thread *thread)
void
ospf_hello_send (struct ospf_interface *oi)
{
- struct ospf_packet *op;
- u_int16_t length = OSPF_HEADER_SIZE;
-
/* If this is passive interface, do not send OSPF Hello. */
if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
return;
- op = ospf_packet_new (oi->ifp->mtu);
-
- /* Prepare OSPF common header. */
- ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
-
- /* Prepare OSPF Hello body. */
- length += ospf_make_hello (oi, op->s);
-
- /* Fill OSPF header. */
- ospf_fill_header (oi, op->s, length);
-
- /* Set packet length. */
- op->length = length;
-
if (oi->type == OSPF_IFTYPE_NBMA)
{
struct ospf_neighbor *nbr;
@@ -3104,33 +3136,16 @@ ospf_hello_send (struct ospf_interface *oi)
if (nbr->priority == 0 && oi->state == ISM_DROther)
continue;
/* if oi->state == Waiting, send hello to all neighbors */
- {
- struct ospf_packet *op_dup;
-
- op_dup = ospf_packet_dup(op);
- op_dup->dst = nbr->src;
-
- /* Add packet to the interface output queue. */
- ospf_packet_add (oi, op_dup);
-
- OSPF_ISM_WRITE_ON (oi->ospf);
- }
+ ospf_hello_send_sub (oi, nbr->src.s_addr);
}
- ospf_packet_free (op);
}
else
{
/* Decide destination address. */
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
- op->dst.s_addr = oi->vl_data->peer_addr.s_addr;
- else
- op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
-
- /* Add packet to the interface output queue. */
- ospf_packet_add (oi, op);
-
- /* Hook thread to write packet. */
- OSPF_ISM_WRITE_ON (oi->ospf);
+ ospf_hello_send_sub (oi, oi->vl_data->peer_addr.s_addr);
+ else
+ ospf_hello_send_sub (oi, htonl (OSPF_ALLSPFROUTERS));
}
}
diff --git a/ospfd/ospf_packet.h b/ospfd/ospf_packet.h
index 7b3d6866..9a472081 100644
--- a/ospfd/ospf_packet.h
+++ b/ospfd/ospf_packet.h
@@ -162,6 +162,5 @@ extern int ospf_ls_upd_timer (struct thread *);
extern int ospf_ls_ack_timer (struct thread *);
extern int ospf_poll_timer (struct thread *);
extern int ospf_hello_reply_timer (struct thread *);
-extern void ospf_hello_send_sub (struct ospf_interface *, struct in_addr *);
#endif /* _ZEBRA_OSPF_PACKET_H */
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index 89289f60..b06c7b9e 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -1261,9 +1261,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 3fc86256..6cde1099 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -274,6 +274,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
{