summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--ospfd/ospf_interface.c53
-rw-r--r--ospfd/ospf_spf.c21
-rw-r--r--ospfd/ospf_spf.h3
4 files changed, 66 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index 36c421f4..50efbb78 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2004-04-08 Paul Jakma <paul@dishone.st>
+
+ * ospf_spf.h: Add backlink field to struct vertex
+ * ospf_spf.h: (ospf_vertex_new) initialise backlink
+ (ospf_lsa_has_link) return index of link back to
+ vertex V from candidate vertex W, or -1 if no link exists.
+ (ospf_spf_next) save backlink index for candidate vertex
+ * ospf_interface.c: (ospf_vl_set_params) Use the backlink index
+ to determine correct address for virtual-link peers. Fall back
+ to older "pick first link" method if no backlink index exists.
+
2004-04-06 Hasso Tepper <hasso@estpak.ee>
* zebra/ipforward_proc.c: Fixed lowering privileges.
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index acce9076..b4872914 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -933,24 +933,49 @@ ospf_vl_set_params (struct ospf_vl_data *vl_data, struct vertex *v)
}
rl = (struct router_lsa *)v->lsa;
-
- for (i = 0; i < ntohs (rl->links); i++)
+
+ /* use SPF determined backlink index in struct vertex
+ * for virtual link destination address
+ */
+ if (v->backlink >= 0)
+ {
+ if (!IPV4_ADDR_SAME (&vl_data->peer_addr,
+ &rl->link[v->backlink].link_data))
+ changed = 1;
+ vl_data->peer_addr = rl->link[v->backlink].link_data;
+ }
+ else
{
- switch (rl->link[i].type)
+ /* This is highly odd, there is no backlink index
+ * there should be due to the ospf_spf_has_link() check
+ * in SPF. Lets warn and try pick a link anyway.
+ */
+ zlog_warn ("ospf_vl_set_params: No backlink for %s!",
+ vl_data->vl_oi->ifp->name);
+ for (i = 0; i < ntohs (rl->links); i++)
{
- case LSA_LINK_TYPE_VIRTUALLINK:
- if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("found back link through VL");
- case LSA_LINK_TYPE_TRANSIT:
- case LSA_LINK_TYPE_POINTOPOINT:
- vl_data->peer_addr = rl->link[i].link_data;
- if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("%s peer address is %s\n",
- vl_data->vl_oi->ifp->name,
- inet_ntoa(vl_data->peer_addr));
- return changed;
+ switch (rl->link[i].type)
+ {
+ case LSA_LINK_TYPE_VIRTUALLINK:
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_info ("found back link through VL");
+ case LSA_LINK_TYPE_TRANSIT:
+ case LSA_LINK_TYPE_POINTOPOINT:
+ vl_data->peer_addr = rl->link[i].link_data;
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_info ("%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_info ("ospf_vl_set_params: %s peer address is %s\n",
+ vl_data->vl_oi->ifp->name,
+ inet_ntoa(vl_data->peer_addr));
+
return changed;
}
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index 5ced71ca..916e9800 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -93,6 +93,7 @@ ospf_vertex_new (struct ospf_lsa *lsa)
new->distance = 0;
new->child = list_new ();
new->nexthop = list_new ();
+ new->backlink = -1;
return new;
}
@@ -184,6 +185,7 @@ ospf_vertex_lookup (list vlist, struct in_addr id, int type)
return NULL;
}
+/* return index of link back to V from W, or -1 if no link found */
int
ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
{
@@ -196,15 +198,15 @@ ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
if (w->type == OSPF_NETWORK_LSA)
{
if (v->type == OSPF_NETWORK_LSA)
- return 0;
+ return -1;
nl = (struct network_lsa *) w;
length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
for (i = 0; i < length; i++)
if (IPV4_ADDR_SAME (&nl->routers[i], &v->id))
- return 1;
- return 0;
+ return i;
+ return -1;
}
/* In case of W is Router LSA. */
@@ -226,7 +228,7 @@ ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
if (v->type == OSPF_ROUTER_LSA &&
IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
{
- return 1;
+ return i;
}
break;
case LSA_LINK_TYPE_TRANSIT:
@@ -234,7 +236,7 @@ ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
if (v->type == OSPF_NETWORK_LSA &&
IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
{
- return 1;
+ return i;
}
break;
case LSA_LINK_TYPE_STUB:
@@ -245,7 +247,7 @@ ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
}
}
}
- return 0;
+ return -1;
}
/* Add the nexthop to the list, only if it is unique.
@@ -544,6 +546,8 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area,
while (p < lim)
{
+ int link = -1; /* link index for w's back link */
+
/* In case of V is Router-LSA. */
if (v->lsa->type == OSPF_ROUTER_LSA)
{
@@ -616,7 +620,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area,
if (IS_LSA_MAXAGE (w_lsa))
continue;
- if (!ospf_lsa_has_link (w_lsa->data, v->lsa))
+ if ( (link = ospf_lsa_has_link (w_lsa->data, v->lsa)) < 0 )
{
if (IS_DEBUG_OSPF_EVENT)
zlog_info ("The LSA doesn't have a link back");
@@ -641,6 +645,9 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area,
/* prepare vertex W. */
w = ospf_vertex_new (w_lsa);
+ /* Save W's back link index number, for use by virtual links */
+ w->backlink = link;
+
/* calculate link cost D. */
if (v->lsa->type == OSPF_ROUTER_LSA)
w->distance = v->distance + ntohs (l->m[0].metric);
diff --git a/ospfd/ospf_spf.h b/ospfd/ospf_spf.h
index 7fe682ee..73120000 100644
--- a/ospfd/ospf_spf.h
+++ b/ospfd/ospf_spf.h
@@ -33,6 +33,7 @@ struct vertex
struct in_addr id;
struct lsa_header *lsa;
u_int32_t distance;
+ int backlink; /* link index of back-link */
list child;
list nexthop;
};
@@ -44,7 +45,7 @@ struct vertex_nexthop
struct vertex *parent;
};
-void ospf_spf_calculate_schedule ();
+void ospf_spf_calculate_schedule (struct ospf *);
void ospf_rtrs_free (struct route_table *);
/* void ospf_spf_calculate_timer_add (); */