summaryrefslogtreecommitdiff
path: root/ospfd/ospf_spf.c
diff options
context:
space:
mode:
authorpaul <paul>2004-08-05 09:10:31 +0000
committerpaul <paul>2004-08-05 09:10:31 +0000
commit75ee0b8eed29619b98c67dcb5f6b10e1c8f201ae (patch)
treeebbf492147767a7161e48cb2ece2e0d36b061abe /ospfd/ospf_spf.c
parent049207c31d9b5da023c6c2e3689b771010098f94 (diff)
2004-08-04 Paul Jakma <paul@dishone.st>
* ospf_spf.c: (ospf_spf_consider_nexthop) Add comment about issue. Compare only against list head - all nexthops must be same cost anyway, fixes a reference-listnode-after-delete bug noted by Kir Kostuchenko. (ospf_nexthop_calculation) Use ospf_spf_consider_nexthop for all candidates attached to root.
Diffstat (limited to 'ospfd/ospf_spf.c')
-rw-r--r--ospfd/ospf_spf.c58
1 files changed, 39 insertions, 19 deletions
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index 916e9800..5afdf161 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -341,31 +341,51 @@ ospf_get_next_link (struct vertex *v, struct vertex *w,
return NULL;
}
-/* Consider supplied next-hop for inclusion to the supplied list
- * of next-hops, adjust list as neccessary
+/*
+ * Consider supplied next-hop for inclusion to the supplied list of
+ * equal-cost next-hops, adjust list as neccessary.
+ *
+ * (Discussed on GNU Zebra list 27 May 2003, [zebra 19184])
+ *
+ * Note that below is a bit of a hack, and limits ECMP to paths that go to
+ * same nexthop. Where as paths via inequal output_cost interfaces could
+ * still quite easily be ECMP due to remote cost differences.
+ *
+ * TODO: It really should be done by way of recording currently valid
+ * backlinks and determining the appropriate nexthops from the list of
+ * backlinks, or even simpler, just flushing nexthop list if we find a lower
+ * cost path to a candidate vertex in SPF, maybe.
*/
void
ospf_spf_consider_nexthop (struct list *nexthops,
struct vertex_nexthop *newhop)
{
- struct listnode *nnode;
struct vertex_nexthop *hop;
+ struct listnode *ln, *nn;
- LIST_LOOP (nexthops, hop, nnode)
- {
- assert (hop->oi);
- /* weed out hops with higher cost than the newhop */
- if (hop->oi->output_cost > newhop->oi->output_cost)
- {
- /* delete the existing nexthop */
- listnode_delete (nexthops, hop);
- vertex_nexthop_free (hop);
- }
- else if (hop->oi->output_cost < newhop->oi->output_cost)
- {
+ /* nexthop list should contain only the set of nexthops that have the lowest
+ * equal cost
+ */
+ if (nexthops->head != NULL)
+ {
+ hop = getdata (nexthops->head);
+
+ /* weed out hops with higher cost than the newhop */
+ if (hop->oi->output_cost > newhop->oi->output_cost)
+ {
+ /* delete the existing nexthops */
+ for (ln = nexthops->head; ln; ln = nn)
+ {
+ nn = ln->next;
+ hop = getdata (ln);
+
+ listnode_delete (nexthops, hop);
+ vertex_nexthop_free (hop);
+ }
+ }
+ else if (hop->oi->output_cost < newhop->oi->output_cost)
return;
- }
- }
+ }
/* new hop is <= existing hops, add it */
listnode_add (nexthops, newhop);
@@ -455,7 +475,7 @@ ospf_nexthop_calculation (struct ospf_area *area,
nh = vertex_nexthop_new (v);
nh->oi = oi;
nh->router.s_addr = 0;
- listnode_add (w->nexthop, nh);
+ ospf_spf_consider_nexthop (w->nexthop, nh);
}
}
}
@@ -474,7 +494,7 @@ ospf_nexthop_calculation (struct ospf_area *area,
nh = vertex_nexthop_new (v);
nh->oi = x->oi;
nh->router = l->link_data;
- listnode_add (w->nexthop, nh);
+ ospf_spf_consider_nexthop (w->nexthop, nh);
}
return;
}