summaryrefslogtreecommitdiff
path: root/ospfd/ospf_packet.c
diff options
context:
space:
mode:
authorpaul <paul>2004-07-14 20:50:36 +0000
committerpaul <paul>2004-07-14 20:50:36 +0000
commit59ea14c6c9c877a7b9c9cc1555e3079acd9200e9 (patch)
tree2d4842a8982e7fd2ff6f6c5cbb3522e62d729a31 /ospfd/ospf_packet.c
parentaa9af78c6f29cb37fb54b9875aad19105a72ae1d (diff)
2004-07-14 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_ls_upd_send_queue_event) Partial fix for problem reported by Peter Frost amongst others, where function will spin indefinitely if update list contains LSAs greater than MTU-headers or other condition leading to update list never being cleared. Problem of what to do with these LSAs remains. (ospf_make_ls_upd) add comment about large LSA problem, indentation cleanup.
Diffstat (limited to 'ospfd/ospf_packet.c')
-rw-r--r--ospfd/ospf_packet.c58
1 files changed, 43 insertions, 15 deletions
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 5692db62..990fe6ab 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -2702,8 +2702,8 @@ ospf_make_ls_upd (struct ospf_interface *oi, list update, struct stream *s)
int count = 0;
if (IS_DEBUG_OSPF_EVENT)
- zlog_info("ospf_make_ls_upd: Start");
-
+ zlog_info ("ospf_make_ls_upd: Start");
+
pp = stream_get_putp (s);
ospf_output_forward (s, 4);
@@ -2713,16 +2713,20 @@ ospf_make_ls_upd (struct ospf_interface *oi, list update, struct stream *s)
u_int16_t ls_age;
if (IS_DEBUG_OSPF_EVENT)
- zlog_info("ospf_make_ls_upd: List Iteration");
+ zlog_info ("ospf_make_ls_upd: List Iteration");
lsa = getdata (node);
assert (lsa);
assert (lsa->data);
/* Check packet size. */
+ /* XXX: LSA can be > packet-headers, eg router-lsas for machines
+ * with hundreds of interfaces, received as several
+ * fragmented packets.
+ */
if (length + delta + ntohs (lsa->data->length) > OSPF_PACKET_MAX (oi))
- break;
-
+ break;
+
/* Keep pointer to LS age. */
lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_putp (s));
@@ -2749,7 +2753,7 @@ ospf_make_ls_upd (struct ospf_interface *oi, list update, struct stream *s)
stream_set_putp (s, s->endp);
if (IS_DEBUG_OSPF_EVENT)
- zlog_info("ospf_make_ls_upd: Stop");
+ zlog_info ("ospf_make_ls_upd: Stop");
return length;
}
@@ -3100,8 +3104,9 @@ ospf_ls_upd_queue_send (struct ospf_interface *oi, list update,
/* Prepare OSPF common header. */
ospf_make_header (OSPF_MSG_LS_UPD, oi, op->s);
- /* Prepare OSPF Link State Update body. */
- /* Includes Type-7 translation. */
+ /* Prepare OSPF Link State Update body.
+ * Includes Type-7 translation.
+ */
length += ospf_make_ls_upd (oi, update, op->s);
/* Fill OSPF header. */
@@ -3126,6 +3131,9 @@ ospf_ls_upd_send_queue_event (struct thread *thread)
struct ospf_interface *oi = THREAD_ARG(thread);
struct route_node *rn;
struct route_node *rnext;
+ struct list *update;
+ struct listnode *tn, *nn;
+ unsigned int again = 0;
oi->t_ls_upd_event = NULL;
@@ -3134,23 +3142,43 @@ ospf_ls_upd_send_queue_event (struct thread *thread)
for (rn = route_top (oi->ls_upd_queue); rn; rn = rnext)
{
-
+ update = (struct list *)rn->info;
rnext = route_next (rn);
if (rn->info == NULL)
continue;
- while (!list_isempty ((list)rn->info))
- ospf_ls_upd_queue_send (oi, rn->info, rn->p.u.prefix4);
-
- list_delete (rn->info);
- rn->info = NULL;
+ for (tn = update->head; tn; tn = nn)
+ {
+ nn = tn->next;
+ ospf_ls_upd_queue_send (oi, update, rn->p.u.prefix4);
+ }
- route_unlock_node (rn);
+ /* list might not be empty.
+ * TODO: work out what to do about oversized LSAs.
+ */
+ if (listcount(update) == 0)
+ {
+ list_delete (rn->info);
+ rn->info = NULL;
+ route_unlock_node (rn);
+ }
+ else
+ again++;
+ }
+
+ if (again != 0)
+ {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_info ("ospf_ls_upd_send_queue: update lists not cleared,"
+ " %d nodes to try again, raising new event", again);
+ oi->t_ls_upd_event =
+ thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
}
if (IS_DEBUG_OSPF_EVENT)
zlog_info ("ospf_ls_upd_send_queue stop");
+
return 0;
}