[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 52adc42..1264cac 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -931,16 +931,36 @@
vlink_count--;
}
+/* Look up vl_data for given peer, optionally qualified to be in the
+ * specified area. NULL area returns first found..
+ */
struct ospf_vl_data *
-ospf_vl_lookup (struct ospf_area *area, struct in_addr vl_peer)
+ospf_vl_lookup (struct ospf *ospf, struct ospf_area *area,
+ struct in_addr vl_peer)
{
struct ospf_vl_data *vl_data;
struct listnode *node;
-
- for (ALL_LIST_ELEMENTS_RO (area->ospf->vlinks, node, vl_data))
- if (vl_data->vl_peer.s_addr == vl_peer.s_addr &&
- IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
- return vl_data;
+
+ if (IS_DEBUG_OSPF_EVENT)
+ {
+ zlog_debug ("%s: Looking for %s", __func__, inet_ntoa (vl_peer));
+ if (area)
+ zlog_debug ("%s: in area %s", __func__, inet_ntoa (area->area_id));
+ }
+
+ for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
+ {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("%s: VL %s, peer %s", __func__,
+ vl_data->vl_oi->ifp->name,
+ inet_ntoa (vl_data->vl_peer));
+
+ if (area && !IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
+ continue;
+
+ if (IPV4_ADDR_SAME (&vl_data->vl_peer, &vl_peer))
+ return vl_data;
+ }
return NULL;
}
@@ -1005,14 +1025,15 @@
for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
{
- vl_data->out_oi = vp->nexthop->oi;
+ vl_data->nexthop.oi = vp->nexthop->oi;
+ vl_data->nexthop.router = vp->nexthop->router;
if (!IPV4_ADDR_SAME(&voi->address->u.prefix4,
- &vl_data->out_oi->address->u.prefix4))
+ &vl_data->nexthop.oi->address->u.prefix4))
changed = 1;
- voi->address->u.prefix4 = vl_data->out_oi->address->u.prefix4;
- voi->address->prefixlen = vl_data->out_oi->address->prefixlen;
+ voi->address->u.prefix4 = vl_data->nexthop.oi->address->u.prefix4;
+ voi->address->prefixlen = vl_data->nexthop.oi->address->prefixlen;
break; /* We take the first interface. */
}
@@ -1050,19 +1071,16 @@
&rl->link[i].link_data))
changed = 1;
vl_data->peer_addr = rl->link[i].link_data;
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("ospf_vl_set_params: %s peer address is %s\n",
- vl_data->vl_oi->ifp->name,
- inet_ntoa(vl_data->peer_addr));
- return changed;
}
}
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("ospf_vl_set_params: %s peer address is %s\n",
+ zlog_debug ("%s: %s peer address: %s, cost: %d,%schanged", __func__,
vl_data->vl_oi->ifp->name,
- inet_ntoa(vl_data->peer_addr));
+ inet_ntoa(vl_data->peer_addr),
+ voi->output_cost,
+ (changed ? " " : " un"));
return changed;
}
@@ -1088,10 +1106,10 @@
{
if (IS_DEBUG_OSPF_EVENT)
{
- zlog_debug ("ospf_vl_up_check(): considering VL, name: %s",
- vl_data->vl_oi->ifp->name);
- zlog_debug ("ospf_vl_up_check(): VL area: %s, peer ID: %s",
- inet_ntoa (vl_data->vl_area_id),
+ zlog_debug ("%s: considering VL, %s in area %s", __func__,
+ vl_data->vl_oi->ifp->name,
+ inet_ntoa (vl_data->vl_area_id));
+ zlog_debug ("%s: peer ID: %s", __func__,
inet_ntoa (vl_data->vl_peer));
}