[ospfd] Bug #330 regression: Fix ospf_spf_add_parent assert

2007-05-07 Paul Jakma <paul.jakma@sun.com>

	* ospf_spf.c: (ospf_vertex_new) Dont init vertices to infinity,
	  just let 0 be a special case.
	  (ospf_spf_add_parent) 0 distance candidate vertex is special,
	  cost still to be initialised - asserting that new distance
	  is <= existing only makes sense where w already has a cost.
	  (ospf_spf_next) Infinite cost links should not be followed,
	  bar those of the root.
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog
index d329bfa..153b086 100644
--- a/ospfd/ChangeLog
+++ b/ospfd/ChangeLog
@@ -1,3 +1,13 @@
+2007-05-07 Paul Jakma <paul.jakma@sun.com>
+
+	* ospf_spf.c: (ospf_vertex_new) Dont init vertices to infinity,
+	  just let 0 be a special case.
+	  (ospf_spf_add_parent) 0 distance candidate vertex is special,
+	  cost still to be initialised - asserting that new distance
+	  is <= existing only makes sense where w already has a cost.
+	  (ospf_spf_next) Infinite cost links should not be followed,
+	  bar those of the root.
+
 2007-04-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
 
 	* ospfd.c: (ospf_network_match_iface) Comment out
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index c8cbe3f..51e3383 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -172,7 +172,6 @@
   new->type = lsa->data->type;
   new->id = lsa->data->id;
   new->lsa = lsa->data;
-  new->distance = OSPF_OUTPUT_COST_INFINITE;
   new->children = list_new ();
   new->parents = list_new ();
   new->parents->del = vertex_parent_free;
@@ -285,7 +284,6 @@
   
   /* Create root node. */
   v = ospf_vertex_new (area->router_lsa_self);
-  v->distance = 0;
   
   area->spf = v;
 
@@ -431,13 +429,18 @@
 {
   struct vertex_parent *vp;
     
-  /* we must have a newhop.. */
+  /* we must have a newhop, and a distance */
   assert (v && w && newhop);
+  assert (distance);
   
-  /* We shouldn't get here unless callers have determined V(l)->W is
-   * shortest / equal-shortest path.
+  /* IFF w has already been assigned a distance, then we shouldn't get here
+   * unless callers have determined V(l)->W is shortest / equal-shortest
+   * path (0 is a special case distance (no distance yet assigned)).
    */
-  assert (distance <= w->distance);
+  if (w->distance)
+    assert (distance <= w->distance);
+  else
+    w->distance = distance;
   
   if (IS_DEBUG_OSPF_EVENT)
     {
@@ -750,6 +753,13 @@
              calculation. */
           if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
             continue;
+          
+          /* Infinite distance links shouldn't be followed, except
+           * for local links (a stub-routed router still wants to
+           * calculate tree, so must follow its own links).
+           */
+          if ((v != area->spf) && l->m[0].metric >= OSPF_OUTPUT_COST_INFINITE)
+            continue;
 
           /* (b) Otherwise, W is a transit vertex (router or transit
              network).  Look up the vertex W's LSA (router-LSA or