diff options
Diffstat (limited to 'ospfd')
-rw-r--r-- | ospfd/ospf_ase.c | 77 | ||||
-rw-r--r-- | ospfd/ospf_ase.h | 2 | ||||
-rw-r--r-- | ospfd/ospf_lsa.c | 4 | ||||
-rw-r--r-- | ospfd/ospf_nsm.c | 24 | ||||
-rw-r--r-- | ospfd/ospf_nsm.h | 2 | ||||
-rw-r--r-- | ospfd/ospf_packet.c | 113 | ||||
-rw-r--r-- | ospfd/ospf_packet.h | 1 | ||||
-rw-r--r-- | ospfd/ospf_spf.c | 3 | ||||
-rw-r--r-- | ospfd/ospfd.h | 3 |
9 files changed, 138 insertions, 91 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_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 { |