diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | ospfd/ospf_interface.c | 53 | ||||
-rw-r--r-- | ospfd/ospf_spf.c | 21 | ||||
-rw-r--r-- | ospfd/ospf_spf.h | 3 |
4 files changed, 66 insertions, 22 deletions
@@ -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 (); */ |