summaryrefslogtreecommitdiffstats
path: root/ospfd/ospf_spf.c
diff options
context:
space:
mode:
authorwhitespace / reindent <invalid@invalid.invalid>2017-07-17 14:03:14 +0200
committerwhitespace / reindent <invalid@invalid.invalid>2017-07-17 14:04:07 +0200
commitd62a17aedeb0eebdba98238874bb13d62c48dbf9 (patch)
tree3b319b1d61c8b85b4d1f06adf8b844bb8a9b5107 /ospfd/ospf_spf.c
parent*: add indent control files (diff)
downloadfrr-d62a17aedeb0eebdba98238874bb13d62c48dbf9.tar.xz
frr-d62a17aedeb0eebdba98238874bb13d62c48dbf9.zip
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'` Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'ospfd/ospf_spf.c')
-rw-r--r--ospfd/ospf_spf.c2371
1 files changed, 1185 insertions, 1186 deletions
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index 173c4e91d..c520a3126 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -29,7 +29,7 @@
#include "if.h"
#include "table.h"
#include "log.h"
-#include "sockunion.h" /* for inet_ntop () */
+#include "sockunion.h" /* for inet_ntop () */
#include "pqueue.h"
#include "ospfd/ospfd.h"
@@ -51,326 +51,304 @@
static unsigned int spf_reason_flags = 0;
-static void
-ospf_clear_spf_reason_flags (void)
+static void ospf_clear_spf_reason_flags(void)
{
- spf_reason_flags = 0;
+ spf_reason_flags = 0;
}
-static void
-ospf_spf_set_reason (ospf_spf_reason_t reason)
+static void ospf_spf_set_reason(ospf_spf_reason_t reason)
{
- spf_reason_flags |= 1 << reason;
+ spf_reason_flags |= 1 << reason;
}
-static void ospf_vertex_free (void *);
+static void ospf_vertex_free(void *);
/* List of allocated vertices, to simplify cleanup of SPF.
* Not thread-safe obviously. If it ever needs to be, it'd have to be
* dynamically allocated at begin of ospf_spf_calculate
*/
-static struct list vertex_list = { .del = ospf_vertex_free };
+static struct list vertex_list = {.del = ospf_vertex_free};
/* Heap related functions, for the managment of the candidates, to
* be used with pqueue. */
-static int
-cmp (void * node1 , void * node2)
+static int cmp(void *node1, void *node2)
{
- struct vertex * v1 = (struct vertex *) node1;
- struct vertex * v2 = (struct vertex *) node2;
- if (v1 != NULL && v2 != NULL )
- {
- /* network vertices must be chosen before router vertices of same
- * cost in order to find all shortest paths
- */
- if ( ((v1->distance - v2->distance) == 0)
- && (v1->type != v2->type))
- {
- switch (v1->type)
- {
- case OSPF_VERTEX_NETWORK:
- return -1;
- case OSPF_VERTEX_ROUTER:
- return 1;
- }
- }
- else
- return (v1->distance - v2->distance);
- }
- return 0;
+ struct vertex *v1 = (struct vertex *)node1;
+ struct vertex *v2 = (struct vertex *)node2;
+ if (v1 != NULL && v2 != NULL) {
+ /* network vertices must be chosen before router vertices of
+ * same
+ * cost in order to find all shortest paths
+ */
+ if (((v1->distance - v2->distance) == 0)
+ && (v1->type != v2->type)) {
+ switch (v1->type) {
+ case OSPF_VERTEX_NETWORK:
+ return -1;
+ case OSPF_VERTEX_ROUTER:
+ return 1;
+ }
+ } else
+ return (v1->distance - v2->distance);
+ }
+ return 0;
}
-static void
-update_stat (void *node , int position)
+static void update_stat(void *node, int position)
{
- struct vertex *v = node;
+ struct vertex *v = node;
- /* Set the status of the vertex, when its position changes. */
- *(v->stat) = position;
+ /* Set the status of the vertex, when its position changes. */
+ *(v->stat) = position;
}
-static struct vertex_nexthop *
-vertex_nexthop_new (void)
+static struct vertex_nexthop *vertex_nexthop_new(void)
{
- return XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop));
+ return XCALLOC(MTYPE_OSPF_NEXTHOP, sizeof(struct vertex_nexthop));
}
-static void
-vertex_nexthop_free (struct vertex_nexthop *nh)
+static void vertex_nexthop_free(struct vertex_nexthop *nh)
{
- XFREE (MTYPE_OSPF_NEXTHOP, nh);
+ XFREE(MTYPE_OSPF_NEXTHOP, nh);
}
/* Free the canonical nexthop objects for an area, ie the nexthop objects
* attached to the first-hop router vertices, and any intervening network
* vertices.
*/
-static void
-ospf_canonical_nexthops_free (struct vertex *root)
+static void ospf_canonical_nexthops_free(struct vertex *root)
{
- struct listnode *node, *nnode;
- struct vertex *child;
-
- for (ALL_LIST_ELEMENTS (root->children, node, nnode, child))
- {
- struct listnode *n2, *nn2;
- struct vertex_parent *vp;
-
- /* router vertices through an attached network each
- * have a distinct (canonical / not inherited) nexthop
- * which must be freed.
- *
- * A network vertex can only have router vertices as its
- * children, so only one level of recursion is possible.
- */
- if (child->type == OSPF_VERTEX_NETWORK)
- ospf_canonical_nexthops_free (child);
-
- /* Free child nexthops pointing back to this root vertex */
- for (ALL_LIST_ELEMENTS (child->parents, n2, nn2, vp))
- if (vp->parent == root && vp->nexthop)
- vertex_nexthop_free (vp->nexthop);
- }
-}
+ struct listnode *node, *nnode;
+ struct vertex *child;
+
+ for (ALL_LIST_ELEMENTS(root->children, node, nnode, child)) {
+ struct listnode *n2, *nn2;
+ struct vertex_parent *vp;
+
+ /* router vertices through an attached network each
+ * have a distinct (canonical / not inherited) nexthop
+ * which must be freed.
+ *
+ * A network vertex can only have router vertices as its
+ * children, so only one level of recursion is possible.
+ */
+ if (child->type == OSPF_VERTEX_NETWORK)
+ ospf_canonical_nexthops_free(child);
+
+ /* Free child nexthops pointing back to this root vertex */
+ for (ALL_LIST_ELEMENTS(child->parents, n2, nn2, vp))
+ if (vp->parent == root && vp->nexthop)
+ vertex_nexthop_free(vp->nexthop);
+ }
+}
/* TODO: Parent list should be excised, in favour of maintaining only
* vertex_nexthop, with refcounts.
*/
-static struct vertex_parent *
-vertex_parent_new (struct vertex *v, int backlink, struct vertex_nexthop *hop)
+static struct vertex_parent *vertex_parent_new(struct vertex *v, int backlink,
+ struct vertex_nexthop *hop)
{
- struct vertex_parent *new;
-
- new = XMALLOC (MTYPE_OSPF_VERTEX_PARENT, sizeof (struct vertex_parent));
-
- if (new == NULL)
- return NULL;
-
- new->parent = v;
- new->backlink = backlink;
- new->nexthop = hop;
- return new;
+ struct vertex_parent *new;
+
+ new = XMALLOC(MTYPE_OSPF_VERTEX_PARENT, sizeof(struct vertex_parent));
+
+ if (new == NULL)
+ return NULL;
+
+ new->parent = v;
+ new->backlink = backlink;
+ new->nexthop = hop;
+ return new;
}
-static void
-vertex_parent_free (void *p)
+static void vertex_parent_free(void *p)
{
- XFREE (MTYPE_OSPF_VERTEX_PARENT, p);
+ XFREE(MTYPE_OSPF_VERTEX_PARENT, p);
}
-static struct vertex *
-ospf_vertex_new (struct ospf_lsa *lsa)
+static struct vertex *ospf_vertex_new(struct ospf_lsa *lsa)
{
- struct vertex *new;
-
- new = XCALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex));
-
- new->flags = 0;
- new->stat = &(lsa->stat);
- new->type = lsa->data->type;
- new->id = lsa->data->id;
- new->lsa = lsa->data;
- new->children = list_new ();
- new->parents = list_new ();
- new->parents->del = vertex_parent_free;
-
- listnode_add (&vertex_list, new);
-
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("%s: Created %s vertex %s", __func__,
- new->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
- inet_ntoa (new->lsa->id));
- return new;
+ struct vertex *new;
+
+ new = XCALLOC(MTYPE_OSPF_VERTEX, sizeof(struct vertex));
+
+ new->flags = 0;
+ new->stat = &(lsa->stat);
+ new->type = lsa->data->type;
+ new->id = lsa->data->id;
+ new->lsa = lsa->data;
+ new->children = list_new();
+ new->parents = list_new();
+ new->parents->del = vertex_parent_free;
+
+ listnode_add(&vertex_list, new);
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("%s: Created %s vertex %s", __func__,
+ new->type == OSPF_VERTEX_ROUTER ? "Router"
+ : "Network",
+ inet_ntoa(new->lsa->id));
+ return new;
}
-static void
-ospf_vertex_free (void *data)
+static void ospf_vertex_free(void *data)
{
- struct vertex *v = data;
-
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("%s: Free %s vertex %s", __func__,
- v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
- inet_ntoa (v->lsa->id));
-
- /* There should be no parents potentially holding references to this vertex
- * Children however may still be there, but presumably referenced by other
- * vertices
- */
- //assert (listcount (v->parents) == 0);
-
- if (v->children)
- list_delete (v->children);
- v->children = NULL;
-
- if (v->parents)
- list_delete (v->parents);
- v->parents = NULL;
-
- v->lsa = NULL;
-
- XFREE (MTYPE_OSPF_VERTEX, v);
+ struct vertex *v = data;
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("%s: Free %s vertex %s", __func__,
+ v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
+ inet_ntoa(v->lsa->id));
+
+ /* There should be no parents potentially holding references to this
+ * vertex
+ * Children however may still be there, but presumably referenced by
+ * other
+ * vertices
+ */
+ // assert (listcount (v->parents) == 0);
+
+ if (v->children)
+ list_delete(v->children);
+ v->children = NULL;
+
+ if (v->parents)
+ list_delete(v->parents);
+ v->parents = NULL;
+
+ v->lsa = NULL;
+
+ XFREE(MTYPE_OSPF_VERTEX, v);
}
-static void
-ospf_vertex_dump(const char *msg, struct vertex *v,
- int print_parents, int print_children)
+static void ospf_vertex_dump(const char *msg, struct vertex *v,
+ int print_parents, int print_children)
{
- if ( ! IS_DEBUG_OSPF_EVENT)
- return;
-
- zlog_debug("%s %s vertex %s distance %u flags %u",
- msg,
- v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
- inet_ntoa(v->lsa->id),
- v->distance,
- (unsigned int)v->flags);
-
- if (print_parents)
- {
- struct listnode *node;
- struct vertex_parent *vp;
-
- for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
- {
- char buf1[BUFSIZ];
-
- if (vp)
- {
- zlog_debug ("parent %s backlink %d nexthop %s interface %s",
- inet_ntoa(vp->parent->lsa->id), vp->backlink,
- inet_ntop(AF_INET, &vp->nexthop->router, buf1, BUFSIZ),
- vp->nexthop->oi ? IF_NAME(vp->nexthop->oi) : "NULL");
- }
+ if (!IS_DEBUG_OSPF_EVENT)
+ return;
+
+ zlog_debug("%s %s vertex %s distance %u flags %u", msg,
+ v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
+ inet_ntoa(v->lsa->id), v->distance, (unsigned int)v->flags);
+
+ if (print_parents) {
+ struct listnode *node;
+ struct vertex_parent *vp;
+
+ for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) {
+ char buf1[BUFSIZ];
+
+ if (vp) {
+ zlog_debug(
+ "parent %s backlink %d nexthop %s interface %s",
+ inet_ntoa(vp->parent->lsa->id),
+ vp->backlink,
+ inet_ntop(AF_INET, &vp->nexthop->router,
+ buf1, BUFSIZ),
+ vp->nexthop->oi
+ ? IF_NAME(vp->nexthop->oi)
+ : "NULL");
+ }
+ }
+ }
+
+ if (print_children) {
+ struct listnode *cnode;
+ struct vertex *cv;
+
+ for (ALL_LIST_ELEMENTS_RO(v->children, cnode, cv))
+ ospf_vertex_dump(" child:", cv, 0, 0);
}
- }
-
- if (print_children)
- {
- struct listnode *cnode;
- struct vertex *cv;
-
- for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv))
- ospf_vertex_dump(" child:", cv, 0, 0);
- }
}
/* Add a vertex to the list of children in each of its parents. */
-static void
-ospf_vertex_add_parent (struct vertex *v)
+static void ospf_vertex_add_parent(struct vertex *v)
{
- struct vertex_parent *vp;
- struct listnode *node;
-
- assert (v && v->parents);
-
- for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
- {
- assert (vp->parent && vp->parent->children);
-
- /* No need to add two links from the same parent. */
- if (listnode_lookup (vp->parent->children, v) == NULL)
- listnode_add (vp->parent->children, v);
- }
+ struct vertex_parent *vp;
+ struct listnode *node;
+
+ assert(v && v->parents);
+
+ for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) {
+ assert(vp->parent && vp->parent->children);
+
+ /* No need to add two links from the same parent. */
+ if (listnode_lookup(vp->parent->children, v) == NULL)
+ listnode_add(vp->parent->children, v);
+ }
}
-static void
-ospf_spf_init (struct ospf_area *area)
+static void ospf_spf_init(struct ospf_area *area)
{
- struct vertex *v;
-
- /* Create root node. */
- v = ospf_vertex_new (area->router_lsa_self);
-
- area->spf = v;
-
- /* Reset ABR and ASBR router counts. */
- area->abr_count = 0;
- area->asbr_count = 0;
+ struct vertex *v;
+
+ /* Create root node. */
+ v = ospf_vertex_new(area->router_lsa_self);
+
+ area->spf = v;
+
+ /* Reset ABR and ASBR router counts. */
+ area->abr_count = 0;
+ area->asbr_count = 0;
}
/* return index of link back to V from W, or -1 if no link found */
-static int
-ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
+static int ospf_lsa_has_link(struct lsa_header *w, struct lsa_header *v)
{
- unsigned int i, length;
- struct router_lsa *rl;
- struct network_lsa *nl;
-
- /* In case of W is Network LSA. */
- if (w->type == OSPF_NETWORK_LSA)
- {
- if (v->type == OSPF_NETWORK_LSA)
- 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 i;
- return -1;
- }
-
- /* In case of W is Router LSA. */
- if (w->type == OSPF_ROUTER_LSA)
- {
- rl = (struct router_lsa *) w;
-
- length = ntohs (w->length);
-
- for (i = 0;
- i < ntohs (rl->links) && length >= sizeof (struct router_lsa);
- i++, length -= 12)
- {
- switch (rl->link[i].type)
- {
- case LSA_LINK_TYPE_POINTOPOINT:
- case LSA_LINK_TYPE_VIRTUALLINK:
- /* Router LSA ID. */
- if (v->type == OSPF_ROUTER_LSA &&
- IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
- {
- return i;
- }
- break;
- case LSA_LINK_TYPE_TRANSIT:
- /* Network LSA ID. */
- if (v->type == OSPF_NETWORK_LSA &&
- IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id))
- {
- return i;
- }
- break;
- case LSA_LINK_TYPE_STUB:
- /* Stub can't lead anywhere, carry on */
- continue;
- default:
- break;
- }
- }
- }
- return -1;
+ unsigned int i, length;
+ struct router_lsa *rl;
+ struct network_lsa *nl;
+
+ /* In case of W is Network LSA. */
+ if (w->type == OSPF_NETWORK_LSA) {
+ if (v->type == OSPF_NETWORK_LSA)
+ 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 i;
+ return -1;
+ }
+
+ /* In case of W is Router LSA. */
+ if (w->type == OSPF_ROUTER_LSA) {
+ rl = (struct router_lsa *)w;
+
+ length = ntohs(w->length);
+
+ for (i = 0; i < ntohs(rl->links)
+ && length >= sizeof(struct router_lsa);
+ i++, length -= 12) {
+ switch (rl->link[i].type) {
+ case LSA_LINK_TYPE_POINTOPOINT:
+ case LSA_LINK_TYPE_VIRTUALLINK:
+ /* Router LSA ID. */
+ if (v->type == OSPF_ROUTER_LSA
+ && IPV4_ADDR_SAME(&rl->link[i].link_id,
+ &v->id)) {
+ return i;
+ }
+ break;
+ case LSA_LINK_TYPE_TRANSIT:
+ /* Network LSA ID. */
+ if (v->type == OSPF_NETWORK_LSA
+ && IPV4_ADDR_SAME(&rl->link[i].link_id,
+ &v->id)) {
+ return i;
+ }
+ break;
+ case LSA_LINK_TYPE_STUB:
+ /* Stub can't lead anywhere, carry on */
+ continue;
+ default:
+ break;
+ }
+ }
+ }
+ return -1;
}
/* Find the next link after prev_link from v to w. If prev_link is
@@ -378,119 +356,117 @@ ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v)
* these link types will never be returned.
*/
static struct router_lsa_link *
-ospf_get_next_link (struct vertex *v, struct vertex *w,
- struct router_lsa_link *prev_link)
+ospf_get_next_link(struct vertex *v, struct vertex *w,
+ struct router_lsa_link *prev_link)
{
- u_char *p;
- u_char *lim;
- u_char lsa_type = LSA_LINK_TYPE_TRANSIT;
- struct router_lsa_link *l;
-
- if (w->type == OSPF_VERTEX_ROUTER)
- lsa_type = LSA_LINK_TYPE_POINTOPOINT;
-
- if (prev_link == NULL)
- p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
- else
- {
- p = (u_char *) prev_link;
- p += (OSPF_ROUTER_LSA_LINK_SIZE +
- (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
- }
+ u_char *p;
+ u_char *lim;
+ u_char lsa_type = LSA_LINK_TYPE_TRANSIT;
+ struct router_lsa_link *l;
+
+ if (w->type == OSPF_VERTEX_ROUTER)
+ lsa_type = LSA_LINK_TYPE_POINTOPOINT;
+
+ if (prev_link == NULL)
+ p = ((u_char *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
+ else {
+ p = (u_char *)prev_link;
+ p += (OSPF_ROUTER_LSA_LINK_SIZE
+ + (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
+ }
- lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
+ lim = ((u_char *)v->lsa) + ntohs(v->lsa->length);
- while (p < lim)
- {
- l = (struct router_lsa_link *) p;
+ while (p < lim) {
+ l = (struct router_lsa_link *)p;
- p += (OSPF_ROUTER_LSA_LINK_SIZE + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
+ p += (OSPF_ROUTER_LSA_LINK_SIZE
+ + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
- if (l->m[0].type != lsa_type)
- continue;
+ if (l->m[0].type != lsa_type)
+ continue;
- if (IPV4_ADDR_SAME (&l->link_id, &w->id))
- return l;
- }
+ if (IPV4_ADDR_SAME(&l->link_id, &w->id))
+ return l;
+ }
- return NULL;
+ return NULL;
}
-static void
-ospf_spf_flush_parents (struct vertex *w)
+static void ospf_spf_flush_parents(struct vertex *w)
{
- struct vertex_parent *vp;
- struct listnode *ln, *nn;
-
- /* delete the existing nexthops */
- for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp))
- {
- list_delete_node (w->parents, ln);
- vertex_parent_free (vp);
- }
+ struct vertex_parent *vp;
+ struct listnode *ln, *nn;
+
+ /* delete the existing nexthops */
+ for (ALL_LIST_ELEMENTS(w->parents, ln, nn, vp)) {
+ list_delete_node(w->parents, ln);
+ vertex_parent_free(vp);
+ }
}
-/*
+/*
* Consider supplied next-hop for inclusion to the supplied list of
- * equal-cost next-hops, adjust list as neccessary.
+ * equal-cost next-hops, adjust list as neccessary.
*/
-static void
-ospf_spf_add_parent (struct vertex *v, struct vertex *w,
- struct vertex_nexthop *newhop,
- unsigned int distance)
+static void ospf_spf_add_parent(struct vertex *v, struct vertex *w,
+ struct vertex_nexthop *newhop,
+ unsigned int distance)
{
- struct vertex_parent *vp, *wp;
- struct listnode *node;
-
- /* we must have a newhop, and a distance */
- assert (v && w && newhop);
- assert (distance);
-
- /* 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)).
- */
- if (w->distance)
- assert (distance <= w->distance);
- else
- w->distance = distance;
-
- if (IS_DEBUG_OSPF_EVENT)
- {
- char buf[2][INET_ADDRSTRLEN];
- zlog_debug ("%s: Adding %s as parent of %s",
- __func__,
- inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
- inet_ntop(AF_INET, &w->lsa->id, buf[1], sizeof(buf[1])));
- }
-
- /* Adding parent for a new, better path: flush existing parents from W. */
- if (distance < w->distance)
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("%s: distance %d better than %d, flushing existing parents",
- __func__, distance, w->distance);
- ospf_spf_flush_parents (w);
- w->distance = distance;
- }
-
- /* new parent is <= existing parents, add it to parent list (if nexthop
- * not on parent list)
- */
- for (ALL_LIST_ELEMENTS_RO(w->parents, node, wp))
- {
- if (memcmp(newhop, wp->nexthop, sizeof(*newhop)) == 0)
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("%s: ... nexthop already on parent list, skipping add", __func__);
- return;
- }
- }
+ struct vertex_parent *vp, *wp;
+ struct listnode *node;
+
+ /* we must have a newhop, and a distance */
+ assert(v && w && newhop);
+ assert(distance);
+
+ /* 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)).
+ */
+ if (w->distance)
+ assert(distance <= w->distance);
+ else
+ w->distance = distance;
+
+ if (IS_DEBUG_OSPF_EVENT) {
+ char buf[2][INET_ADDRSTRLEN];
+ zlog_debug(
+ "%s: Adding %s as parent of %s", __func__,
+ inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
+ inet_ntop(AF_INET, &w->lsa->id, buf[1],
+ sizeof(buf[1])));
+ }
+
+ /* Adding parent for a new, better path: flush existing parents from W.
+ */
+ if (distance < w->distance) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "%s: distance %d better than %d, flushing existing parents",
+ __func__, distance, w->distance);
+ ospf_spf_flush_parents(w);
+ w->distance = distance;
+ }
+
+ /* new parent is <= existing parents, add it to parent list (if nexthop
+ * not on parent list)
+ */
+ for (ALL_LIST_ELEMENTS_RO(w->parents, node, wp)) {
+ if (memcmp(newhop, wp->nexthop, sizeof(*newhop)) == 0) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "%s: ... nexthop already on parent list, skipping add",
+ __func__);
+ return;
+ }
+ }
- vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop);
- listnode_add (w->parents, vp);
+ vp = vertex_parent_new(v, ospf_lsa_has_link(w->lsa, v->lsa), newhop);
+ listnode_add(w->parents, vp);
- return;
+ return;
}
/* 16.1.1. Calculate nexthop from root through V (parent) to
@@ -504,256 +480,298 @@ ospf_spf_add_parent (struct vertex *v, struct vertex *w,
* this function returns. This function will update the W vertex with the
* provided distance as appropriate.
*/
-static unsigned int
-ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
- struct vertex *w, struct router_lsa_link *l,
- unsigned int distance, int lsa_pos)
+static unsigned int ospf_nexthop_calculation(struct ospf_area *area,
+ struct vertex *v, struct vertex *w,
+ struct router_lsa_link *l,
+ unsigned int distance, int lsa_pos)
{
- struct listnode *node, *nnode;
- struct vertex_nexthop *nh;
- struct vertex_parent *vp;
- struct ospf_interface *oi = NULL;
- unsigned int added = 0;
- char buf1[BUFSIZ];
- char buf2[BUFSIZ];
-
- if (IS_DEBUG_OSPF_EVENT)
- {
- zlog_debug ("ospf_nexthop_calculation(): Start");
- ospf_vertex_dump("V (parent):", v, 1, 1);
- ospf_vertex_dump("W (dest) :", w, 1, 1);
- zlog_debug ("V->W distance: %d", distance);
- }
-
- if (v == area->spf)
- {
- /* 16.1.1 para 4. In the first case, the parent vertex (V) is the
- root (the calculating router itself). This means that the
- destination is either a directly connected network or directly
- connected router. The outgoing interface in this case is simply
- the OSPF interface connecting to the destination network/router.
- */
-
- /* we *must* be supplied with the link data */
- assert (l != NULL);
- oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos);
- if (!oi)
- {
- zlog_debug("%s: OI not found in LSA: lsa_pos:%d link_id:%s link_data:%s",
- __func__, lsa_pos,
- inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
- inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
- return 0;
- }
-
- if (IS_DEBUG_OSPF_EVENT)
- {
- zlog_debug("%s: considering link:%s "
- "type:%d link_id:%s link_data:%s",
- __func__, oi->ifp->name, l->m[0].type,
- inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ),
- inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ));
+ struct listnode *node, *nnode;
+ struct vertex_nexthop *nh;
+ struct vertex_parent *vp;
+ struct ospf_interface *oi = NULL;
+ unsigned int added = 0;
+ char buf1[BUFSIZ];
+ char buf2[BUFSIZ];
+
+ if (IS_DEBUG_OSPF_EVENT) {
+ zlog_debug("ospf_nexthop_calculation(): Start");
+ ospf_vertex_dump("V (parent):", v, 1, 1);
+ ospf_vertex_dump("W (dest) :", w, 1, 1);
+ zlog_debug("V->W distance: %d", distance);
}
- if (w->type == OSPF_VERTEX_ROUTER)
- {
- /* l is a link from v to w
- * l2 will be link from w to v
- */
- struct router_lsa_link *l2 = NULL;
-
- if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
- {
- struct in_addr nexthop = { .s_addr = 0 };
-
- /* If the destination is a router which connects to
- the calculating router via a Point-to-MultiPoint
- network, the destination's next hop IP address(es)
- can be determined by examining the destination's
- router-LSA: each link pointing back to the
- calculating router and having a Link Data field
- belonging to the Point-to-MultiPoint network
- provides an IP address of the next hop router.
-
- At this point l is a link from V to W, and V is the
- root ("us"). If it is a point-to-multipoint interface,
- then look through the links in the opposite direction (W to V).
- If any of them have an address that lands within the
- subnet declared by the PtMP link, then that link
- is a constituent of the PtMP link, and its address is
- a nexthop address for V.
- */
- if (oi->type == OSPF_IFTYPE_POINTOPOINT)
- {
- /* Having nexthop = 0 is tempting, but NOT acceptable.
- It breaks AS-External routes with a forwarding address,
- since ospf_ase_complete_direct_routes() will mistakenly
- assume we've reached the last hop and should place the
- forwarding address as nexthop.
- Also, users may configure multi-access links in p2p mode,
- so we need the IP to ARP the nexthop.
- */
- struct ospf_neighbor *nbr_w;
-
- nbr_w = ospf_nbr_lookup_by_routerid (oi->nbrs, &l->link_id);
- if (nbr_w != NULL)
- {
- added = 1;
- nexthop = nbr_w->src;
- }
+ if (v == area->spf) {
+ /* 16.1.1 para 4. In the first case, the parent vertex (V) is
+ the
+ root (the calculating router itself). This means that the
+ destination is either a directly connected network or
+ directly
+ connected router. The outgoing interface in this case is
+ simply
+ the OSPF interface connecting to the destination
+ network/router.
+ */
+
+ /* we *must* be supplied with the link data */
+ assert(l != NULL);
+ oi = ospf_if_lookup_by_lsa_pos(area, lsa_pos);
+ if (!oi) {
+ zlog_debug(
+ "%s: OI not found in LSA: lsa_pos:%d link_id:%s link_data:%s",
+ __func__, lsa_pos,
+ inet_ntop(AF_INET, &l->link_id, buf1, BUFSIZ),
+ inet_ntop(AF_INET, &l->link_data, buf2,
+ BUFSIZ));
+ return 0;
}
- else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
- {
- struct prefix_ipv4 la;
-
- la.family = AF_INET;
- la.prefixlen = oi->address->prefixlen;
- /* V links to W on PtMP interface
- - find the interface address on W */
- while ((l2 = ospf_get_next_link (w, v, l2)))
- {
- la.prefix = l2->link_data;
+ if (IS_DEBUG_OSPF_EVENT) {
+ zlog_debug(
+ "%s: considering link:%s "
+ "type:%d link_id:%s link_data:%s",
+ __func__, oi->ifp->name, l->m[0].type,
+ inet_ntop(AF_INET, &l->link_id, buf1, BUFSIZ),
+ inet_ntop(AF_INET, &l->link_data, buf2,
+ BUFSIZ));
+ }
- if (prefix_cmp ((struct prefix *) &la,
- oi->address) != 0)
- continue;
- /* link_data is on our PtMP network */
- added = 1;
- nexthop = l2->link_data;
- break;
- }
+ if (w->type == OSPF_VERTEX_ROUTER) {
+ /* l is a link from v to w
+ * l2 will be link from w to v
+ */
+ struct router_lsa_link *l2 = NULL;
+
+ if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT) {
+ struct in_addr nexthop = {.s_addr = 0};
+
+ /* If the destination is a router which connects
+ to
+ the calculating router via a
+ Point-to-MultiPoint
+ network, the destination's next hop IP
+ address(es)
+ can be determined by examining the
+ destination's
+ router-LSA: each link pointing back to the
+ calculating router and having a Link Data
+ field
+ belonging to the Point-to-MultiPoint network
+ provides an IP address of the next hop
+ router.
+
+ At this point l is a link from V to W, and V
+ is the
+ root ("us"). If it is a point-to-multipoint
+ interface,
+ then look through the links in the opposite
+ direction (W to V).
+ If any of them have an address that lands
+ within the
+ subnet declared by the PtMP link, then that
+ link
+ is a constituent of the PtMP link, and its
+ address is
+ a nexthop address for V.
+ */
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
+ /* Having nexthop = 0 is tempting, but
+ NOT acceptable.
+ It breaks AS-External routes with a
+ forwarding address,
+ since
+ ospf_ase_complete_direct_routes()
+ will mistakenly
+ assume we've reached the last hop and
+ should place the
+ forwarding address as nexthop.
+ Also, users may configure
+ multi-access links in p2p mode,
+ so we need the IP to ARP the nexthop.
+ */
+ struct ospf_neighbor *nbr_w;
+
+ nbr_w = ospf_nbr_lookup_by_routerid(
+ oi->nbrs, &l->link_id);
+ if (nbr_w != NULL) {
+ added = 1;
+ nexthop = nbr_w->src;
+ }
+ } else if (oi->type
+ == OSPF_IFTYPE_POINTOMULTIPOINT) {
+ struct prefix_ipv4 la;
+
+ la.family = AF_INET;
+ la.prefixlen = oi->address->prefixlen;
+
+ /* V links to W on PtMP interface
+ - find the interface address on W */
+ while ((l2 = ospf_get_next_link(w, v,
+ l2))) {
+ la.prefix = l2->link_data;
+
+ if (prefix_cmp((struct prefix
+ *)&la,
+ oi->address)
+ != 0)
+ continue;
+ /* link_data is on our PtMP
+ * network */
+ added = 1;
+ nexthop = l2->link_data;
+ break;
+ }
+ }
+
+ if (added) {
+ /* found all necessary info to build
+ * nexthop */
+ nh = vertex_nexthop_new();
+ nh->oi = oi;
+ nh->router = nexthop;
+ ospf_spf_add_parent(v, w, nh, distance);
+ return 1;
+ } else
+ zlog_info(
+ "%s: could not determine nexthop for link %s",
+ __func__, oi->ifp->name);
+ } /* end point-to-point link from V to W */
+ else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK) {
+ struct ospf_vl_data *vl_data;
+
+ /* VLink implementation limitations:
+ * a) vl_data can only reference one nexthop, so
+ * no ECMP
+ * to backbone through VLinks. Though
+ * transit-area
+ * summaries may be considered, and those can
+ * be ECMP.
+ * b) We can only use /one/ VLink, even if
+ * multiple ones
+ * exist this router through multiple
+ * transit-areas.
+ */
+ vl_data = ospf_vl_lookup(area->ospf, NULL,
+ l->link_id);
+
+ if (vl_data
+ && CHECK_FLAG(vl_data->flags,
+ OSPF_VL_FLAG_APPROVED)) {
+ nh = vertex_nexthop_new();
+ nh->oi = vl_data->nexthop.oi;
+ nh->router = vl_data->nexthop.router;
+ ospf_spf_add_parent(v, w, nh, distance);
+ return 1;
+ } else
+ zlog_info(
+ "ospf_nexthop_calculation(): "
+ "vl_data for VL link not found");
+ } /* end virtual-link from V to W */
+ return 0;
+ } /* end W is a Router vertex */
+ else {
+ assert(w->type == OSPF_VERTEX_NETWORK);
+
+ nh = vertex_nexthop_new();
+ nh->oi = oi;
+ nh->router.s_addr = 0; /* Nexthop not required */
+ ospf_spf_add_parent(v, w, nh, distance);
+ return 1;
+ }
+ } /* end V is the root */
+ /* Check if W's parent is a network connected to root. */
+ else if (v->type == OSPF_VERTEX_NETWORK) {
+ /* See if any of V's parents are the root. */
+ for (ALL_LIST_ELEMENTS(v->parents, node, nnode, vp)) {
+ if (vp->parent == area->spf) /* connects to root? */
+ {
+ /* 16.1.1 para 5. ...the parent vertex is a
+ * network that
+ * directly connects the calculating router to
+ * the destination
+ * router. The list of next hops is then
+ * determined by
+ * examining the destination's router-LSA...
+ */
+
+ assert(w->type == OSPF_VERTEX_ROUTER);
+ while ((l = ospf_get_next_link(w, v, l))) {
+ /* ...For each link in the router-LSA
+ * that points back to the
+ * parent network, the link's Link Data
+ * field provides the IP
+ * address of a next hop router. The
+ * outgoing interface to
+ * use can then be derived from the next
+ * hop IP address (or
+ * it can be inherited from the parent
+ * network).
+ */
+ nh = vertex_nexthop_new();
+ nh->oi = vp->nexthop->oi;
+ nh->router = l->link_data;
+ added = 1;
+ ospf_spf_add_parent(v, w, nh, distance);
+ }
+ /* Note lack of return is deliberate. See next
+ * comment. */
+ }
}
+ /* NB: This code is non-trivial.
+ *
+ * E.g. it is not enough to know that V connects to the root. It
+ * is
+ * also important that the while above, looping through all
+ * links from
+ * W->V found at least one link, so that we know there is
+ * bi-directional connectivity between V and W (which need not
+ * be the
+ * case, e.g. when OSPF has not yet converged fully).
+ * Otherwise, if
+ * we /always/ return here, without having checked that
+ * root->V->-W
+ * actually resulted in a valid nexthop being created, then we
+ * we will
+ * prevent SPF from finding/using higher cost paths.
+ *
+ * It is important, if root->V->W has not been added, that we
+ * continue
+ * through to the intervening-router nexthop code below. So as
+ * to
+ * ensure other paths to V may be used. This avoids unnecessary
+ * blackholes while OSPF is convergening.
+ *
+ * I.e. we may have arrived at this function, examining V -> W,
+ * via
+ * workable paths other than root -> V, and it's important to
+ * avoid
+ * getting "confused" by non-working root->V->W path - it's
+ * important
+ * to *not* lose the working non-root paths, just because of a
+ * non-viable root->V->W.
+ *
+ * See also bug #330 (required reading!), and:
+ *
+ * http://blogs.oracle.com/paulj/entry/the_difference_a_line_makes
+ */
+ if (added)
+ return added;
+ }
- if (added)
- {
- /* found all necessary info to build nexthop */
- nh = vertex_nexthop_new ();
- nh->oi = oi;
- nh->router = nexthop;
- ospf_spf_add_parent (v, w, nh, distance);
- return 1;
- }
- else
- zlog_info("%s: could not determine nexthop for link %s",
- __func__, oi->ifp->name);
- } /* end point-to-point link from V to W */
- else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK)
- {
- struct ospf_vl_data *vl_data;
-
- /* VLink implementation limitations:
- * a) vl_data can only reference one nexthop, so no ECMP
- * to backbone through VLinks. Though transit-area
- * summaries may be considered, and those can be ECMP.
- * b) We can only use /one/ VLink, even if multiple ones
- * exist this router through multiple transit-areas.
- */
- vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id);
-
- if (vl_data
- && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
- {
- nh = vertex_nexthop_new ();
- nh->oi = vl_data->nexthop.oi;
- nh->router = vl_data->nexthop.router;
- ospf_spf_add_parent (v, w, nh, distance);
- return 1;
- }
- else
- zlog_info("ospf_nexthop_calculation(): "
- "vl_data for VL link not found");
- } /* end virtual-link from V to W */
- return 0;
- } /* end W is a Router vertex */
- else
- {
- assert(w->type == OSPF_VERTEX_NETWORK);
+ /* 16.1.1 para 4. If there is at least one intervening router in the
+ * current shortest path between the destination and the root, the
+ * destination simply inherits the set of next hops from the
+ * parent.
+ */
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("%s: Intervening routers, adding parent(s)",
+ __func__);
+
+ for (ALL_LIST_ELEMENTS(v->parents, node, nnode, vp)) {
+ added = 1;
+ ospf_spf_add_parent(v, w, vp->nexthop, distance);
+ }
- nh = vertex_nexthop_new ();
- nh->oi = oi;
- nh->router.s_addr = 0; /* Nexthop not required */
- ospf_spf_add_parent (v, w, nh, distance);
- return 1;
- }
- } /* end V is the root */
- /* Check if W's parent is a network connected to root. */
- else if (v->type == OSPF_VERTEX_NETWORK)
- {
- /* See if any of V's parents are the root. */
- for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
- {
- if (vp->parent == area->spf) /* connects to root? */
- {
- /* 16.1.1 para 5. ...the parent vertex is a network that
- * directly connects the calculating router to the destination
- * router. The list of next hops is then determined by
- * examining the destination's router-LSA...
- */
-
- assert(w->type == OSPF_VERTEX_ROUTER);
- while ((l = ospf_get_next_link (w, v, l)))
- {
- /* ...For each link in the router-LSA that points back to the
- * parent network, the link's Link Data field provides the IP
- * address of a next hop router. The outgoing interface to
- * use can then be derived from the next hop IP address (or
- * it can be inherited from the parent network).
- */
- nh = vertex_nexthop_new ();
- nh->oi = vp->nexthop->oi;
- nh->router = l->link_data;
- added = 1;
- ospf_spf_add_parent (v, w, nh, distance);
- }
- /* Note lack of return is deliberate. See next comment. */
- }
- }
- /* NB: This code is non-trivial.
- *
- * E.g. it is not enough to know that V connects to the root. It is
- * also important that the while above, looping through all links from
- * W->V found at least one link, so that we know there is
- * bi-directional connectivity between V and W (which need not be the
- * case, e.g. when OSPF has not yet converged fully). Otherwise, if
- * we /always/ return here, without having checked that root->V->-W
- * actually resulted in a valid nexthop being created, then we we will
- * prevent SPF from finding/using higher cost paths.
- *
- * It is important, if root->V->W has not been added, that we continue
- * through to the intervening-router nexthop code below. So as to
- * ensure other paths to V may be used. This avoids unnecessary
- * blackholes while OSPF is convergening.
- *
- * I.e. we may have arrived at this function, examining V -> W, via
- * workable paths other than root -> V, and it's important to avoid
- * getting "confused" by non-working root->V->W path - it's important
- * to *not* lose the working non-root paths, just because of a
- * non-viable root->V->W.
- *
- * See also bug #330 (required reading!), and:
- *
- * http://blogs.oracle.com/paulj/entry/the_difference_a_line_makes
- */
- if (added)
- return added;
- }
-
- /* 16.1.1 para 4. If there is at least one intervening router in the
- * current shortest path between the destination and the root, the
- * destination simply inherits the set of next hops from the
- * parent.
- */
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("%s: Intervening routers, adding parent(s)", __func__);
-
- for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp))
- {
- added = 1;
- ospf_spf_add_parent (v, w, vp->nexthop, distance);
- }
-
- return added;
+ return added;
}
/* RFC2328 Section 16.1 (2).
@@ -761,329 +779,319 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v,
* of candidates with any vertices not already on the list. If a lower-cost
* path is found to a vertex already on the candidate list, store the new cost.
*/
-static void
-ospf_spf_next (struct vertex *v, struct ospf_area *area,
- struct pqueue * candidate)
+static void ospf_spf_next(struct vertex *v, struct ospf_area *area,
+ struct pqueue *candidate)
{
- struct ospf_lsa *w_lsa = NULL;
- u_char *p;
- u_char *lim;
- struct router_lsa_link *l = NULL;
- struct in_addr *r;
- int type = 0, lsa_pos=-1, lsa_pos_next=0;
-
- /* If this is a router-LSA, and bit V of the router-LSA (see Section
- A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
- if (v->type == OSPF_VERTEX_ROUTER)
- {
- if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa))
- area->transit = OSPF_TRANSIT_TRUE;
- }
-
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("%s: Next vertex of %s vertex %s",
- __func__,
- v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
- inet_ntoa(v->lsa->id));
-
- p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
- lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
-
- while (p < lim)
- {
- struct vertex *w;
- unsigned int distance;
-
- /* In case of V is Router-LSA. */
- if (v->lsa->type == OSPF_ROUTER_LSA)
- {
- l = (struct router_lsa_link *) p;
-
- lsa_pos = lsa_pos_next; /* LSA link position */
- lsa_pos_next++;
- p += (OSPF_ROUTER_LSA_LINK_SIZE +
- (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
-
- /* (a) If this is a link to a stub network, examine the next
- link in V's LSA. Links to stub networks will be
- considered in the second stage of the shortest path
- calculation. */
- if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
- continue;
-
- /* (b) Otherwise, W is a transit vertex (router or transit
- network). Look up the vertex W's LSA (router-LSA or
- network-LSA) in Area A's link state database. */
- switch (type)
- {
- case LSA_LINK_TYPE_POINTOPOINT:
- case LSA_LINK_TYPE_VIRTUALLINK:
- if (type == LSA_LINK_TYPE_VIRTUALLINK)
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("looking up LSA through VL: %s",
- inet_ntoa (l->link_id));
- }
+ struct ospf_lsa *w_lsa = NULL;
+ u_char *p;
+ u_char *lim;
+ struct router_lsa_link *l = NULL;
+ struct in_addr *r;
+ int type = 0, lsa_pos = -1, lsa_pos_next = 0;
+
+ /* If this is a router-LSA, and bit V of the router-LSA (see Section
+ A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */
+ if (v->type == OSPF_VERTEX_ROUTER) {
+ if (IS_ROUTER_LSA_VIRTUAL((struct router_lsa *)v->lsa))
+ area->transit = OSPF_TRANSIT_TRUE;
+ }
- w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id,
- l->link_id);
- if (w_lsa)
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id));
- }
- break;
- case LSA_LINK_TYPE_TRANSIT:
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("Looking up Network LSA, ID: %s",
- inet_ntoa (l->link_id));
- w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA,
- l->link_id);
- if (w_lsa)
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("found the LSA");
- break;
- default:
- zlog_warn ("Invalid LSA link type %d", type);
- continue;
- }
- }
- else
- {
- /* In case of V is Network-LSA. */
- r = (struct in_addr *) p;
- p += sizeof (struct in_addr);
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("%s: Next vertex of %s vertex %s", __func__,
+ v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
+ inet_ntoa(v->lsa->id));
+
+ p = ((u_char *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
+ lim = ((u_char *)v->lsa) + ntohs(v->lsa->length);
+
+ while (p < lim) {
+ struct vertex *w;
+ unsigned int distance;
+
+ /* In case of V is Router-LSA. */
+ if (v->lsa->type == OSPF_ROUTER_LSA) {
+ l = (struct router_lsa_link *)p;
+
+ lsa_pos = lsa_pos_next; /* LSA link position */
+ lsa_pos_next++;
+ p += (OSPF_ROUTER_LSA_LINK_SIZE
+ + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
+
+ /* (a) If this is a link to a stub network, examine the
+ next
+ link in V's LSA. Links to stub networks will be
+ considered in the second stage of the shortest path
+ calculation. */
+ if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
+ continue;
+
+ /* (b) Otherwise, W is a transit vertex (router or
+ transit
+ network). Look up the vertex W's LSA (router-LSA or
+ network-LSA) in Area A's link state database. */
+ switch (type) {
+ case LSA_LINK_TYPE_POINTOPOINT:
+ case LSA_LINK_TYPE_VIRTUALLINK:
+ if (type == LSA_LINK_TYPE_VIRTUALLINK) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "looking up LSA through VL: %s",
+ inet_ntoa(l->link_id));
+ }
+
+ w_lsa = ospf_lsa_lookup(area, OSPF_ROUTER_LSA,
+ l->link_id, l->link_id);
+ if (w_lsa) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "found Router LSA %s",
+ inet_ntoa(l->link_id));
+ }
+ break;
+ case LSA_LINK_TYPE_TRANSIT:
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "Looking up Network LSA, ID: %s",
+ inet_ntoa(l->link_id));
+ w_lsa = ospf_lsa_lookup_by_id(
+ area, OSPF_NETWORK_LSA, l->link_id);
+ if (w_lsa)
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("found the LSA");
+ break;
+ default:
+ zlog_warn("Invalid LSA link type %d", type);
+ continue;
+ }
+ } else {
+ /* In case of V is Network-LSA. */
+ r = (struct in_addr *)p;
+ p += sizeof(struct in_addr);
+
+ /* Lookup the vertex W's LSA. */
+ w_lsa = ospf_lsa_lookup_by_id(area, OSPF_ROUTER_LSA,
+ *r);
+ if (w_lsa) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("found Router LSA %s",
+ inet_ntoa(w_lsa->data->id));
+ }
+ }
- /* Lookup the vertex W's LSA. */
- w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r);
- if (w_lsa)
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id));
- }
- }
+ /* (b cont.) If the LSA does not exist, or its LS age is equal
+ to MaxAge, or it does not have a link back to vertex V,
+ examine the next link in V's LSA.[23] */
+ if (w_lsa == NULL) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("No LSA found");
+ continue;
+ }
- /* (b cont.) If the LSA does not exist, or its LS age is equal
- to MaxAge, or it does not have a link back to vertex V,
- examine the next link in V's LSA.[23] */
- if (w_lsa == NULL)
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("No LSA found");
- continue;
- }
+ if (IS_LSA_MAXAGE(w_lsa)) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("LSA is MaxAge");
+ continue;
+ }
- if (IS_LSA_MAXAGE (w_lsa))
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("LSA is MaxAge");
- continue;
- }
+ if (ospf_lsa_has_link(w_lsa->data, v->lsa) < 0) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("The LSA doesn't have a link back");
+ continue;
+ }
- if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 )
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("The LSA doesn't have a link back");
- continue;
- }
+ /* (c) If vertex W is already on the shortest-path tree, examine
+ the next link in the LSA. */
+ if (w_lsa->stat == LSA_SPF_IN_SPFTREE) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("The LSA is already in SPF");
+ continue;
+ }
- /* (c) If vertex W is already on the shortest-path tree, examine
- the next link in the LSA. */
- if (w_lsa->stat == LSA_SPF_IN_SPFTREE)
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("The LSA is already in SPF");
- continue;
- }
+ /* (d) Calculate the link state cost D of the resulting path
+ from the root to vertex W. D is equal to the sum of the link
+ state cost of the (already calculated) shortest path to
+ vertex V and the advertised cost of the link between vertices
+ V and W. If D is: */
+
+ /* calculate link cost D. */
+ if (v->lsa->type == OSPF_ROUTER_LSA)
+ distance = v->distance + ntohs(l->m[0].metric);
+ else /* v is not a Router-LSA */
+ distance = v->distance;
+
+ /* Is there already vertex W in candidate list? */
+ if (w_lsa->stat == LSA_SPF_NOT_EXPLORED) {
+ /* prepare vertex W. */
+ w = ospf_vertex_new(w_lsa);
+
+ /* Calculate nexthop to W. */
+ if (ospf_nexthop_calculation(area, v, w, l, distance,
+ lsa_pos))
+ pqueue_enqueue(w, candidate);
+ else if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("Nexthop Calc failed");
+ } else if (w_lsa->stat >= 0) {
+ /* Get the vertex from candidates. */
+ w = candidate->array[w_lsa->stat];
+
+ /* if D is greater than. */
+ if (w->distance < distance) {
+ continue;
+ }
+ /* equal to. */
+ else if (w->distance == distance) {
+ /* Found an equal-cost path to W.
+ * Calculate nexthop of to W from V. */
+ ospf_nexthop_calculation(area, v, w, l,
+ distance, lsa_pos);
+ }
+ /* less than. */
+ else {
+ /* Found a lower-cost path to W.
+ * nexthop_calculation is conditional, if it
+ * finds
+ * valid nexthop it will call spf_add_parents,
+ * which
+ * will flush the old parents
+ */
+ if (ospf_nexthop_calculation(area, v, w, l,
+ distance, lsa_pos))
+ /* Decrease the key of the node in the
+ * heap.
+ * trickle-sort it up towards root, just
+ * in case this
+ * node should now be the new root due
+ * the cost change.
+ * (next pqueu_{de,en}queue will fully
+ * re-heap the queue).
+ */
+ trickle_up(w_lsa->stat, candidate);
+ }
+ } /* end W is already on the candidate list */
+ } /* end loop over the links in V's LSA */
+}
- /* (d) Calculate the link state cost D of the resulting path
- from the root to vertex W. D is equal to the sum of the link
- state cost of the (already calculated) shortest path to
- vertex V and the advertised cost of the link between vertices
- V and W. If D is: */
-
- /* calculate link cost D. */
- if (v->lsa->type == OSPF_ROUTER_LSA)
- distance = v->distance + ntohs (l->m[0].metric);
- else /* v is not a Router-LSA */
- distance = v->distance;
-
- /* Is there already vertex W in candidate list? */
- if (w_lsa->stat == LSA_SPF_NOT_EXPLORED)
- {
- /* prepare vertex W. */
- w = ospf_vertex_new (w_lsa);
-
- /* Calculate nexthop to W. */
- if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
- pqueue_enqueue (w, candidate);
- else if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("Nexthop Calc failed");
+static void ospf_spf_dump(struct vertex *v, int i)
+{
+ struct listnode *cnode;
+ struct listnode *nnode;
+ struct vertex_parent *parent;
+
+ if (v->type == OSPF_VERTEX_ROUTER) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("SPF Result: %d [R] %s", i,
+ inet_ntoa(v->lsa->id));
+ } else {
+ struct network_lsa *lsa = (struct network_lsa *)v->lsa;
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("SPF Result: %d [N] %s/%d", i,
+ inet_ntoa(v->lsa->id),
+ ip_masklen(lsa->mask));
}
- else if (w_lsa->stat >= 0)
- {
- /* Get the vertex from candidates. */
- w = candidate->array[w_lsa->stat];
- /* if D is greater than. */
- if (w->distance < distance)
- {
- continue;
- }
- /* equal to. */
- else if (w->distance == distance)
- {
- /* Found an equal-cost path to W.
- * Calculate nexthop of to W from V. */
- ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos);
- }
- /* less than. */
- else
- {
- /* Found a lower-cost path to W.
- * nexthop_calculation is conditional, if it finds
- * valid nexthop it will call spf_add_parents, which
- * will flush the old parents
- */
- if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos))
- /* Decrease the key of the node in the heap.
- * trickle-sort it up towards root, just in case this
- * node should now be the new root due the cost change.
- * (next pqueu_{de,en}queue will fully re-heap the queue).
- */
- trickle_up (w_lsa->stat, candidate);
- }
- } /* end W is already on the candidate list */
- } /* end loop over the links in V's LSA */
-}
+ if (IS_DEBUG_OSPF_EVENT)
+ for (ALL_LIST_ELEMENTS_RO(v->parents, nnode, parent)) {
+ zlog_debug(" nexthop %p %s %s", (void *)parent->nexthop,
+ inet_ntoa(parent->nexthop->router),
+ parent->nexthop->oi
+ ? IF_NAME(parent->nexthop->oi)
+ : "NULL");
+ }
-static void
-ospf_spf_dump (struct vertex *v, int i)
-{
- struct listnode *cnode;
- struct listnode *nnode;
- struct vertex_parent *parent;
-
- if (v->type == OSPF_VERTEX_ROUTER)
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id));
- }
- else
- {
- struct network_lsa *lsa = (struct network_lsa *) v->lsa;
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id),
- ip_masklen (lsa->mask));
- }
+ i++;
- if (IS_DEBUG_OSPF_EVENT)
- for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent))
- {
- zlog_debug (" nexthop %p %s %s",
- (void *)parent->nexthop,
- inet_ntoa (parent->nexthop->router),
- parent->nexthop->oi ? IF_NAME(parent->nexthop->oi)
- : "NULL");
- }
-
- i++;
-
- for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v))
- ospf_spf_dump (v, i);
+ for (ALL_LIST_ELEMENTS_RO(v->children, cnode, v))
+ ospf_spf_dump(v, i);
}
/* Second stage of SPF calculation. */
-static void
-ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v,
- struct route_table *rt,
- int parent_is_root)
+static void ospf_spf_process_stubs(struct ospf_area *area, struct vertex *v,
+ struct route_table *rt, int parent_is_root)
{
- struct listnode *cnode, *cnnode;
- struct vertex *child;
+ struct listnode *cnode, *cnnode;
+ struct vertex *child;
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("ospf_process_stub():processing stubs for area %s",
+ inet_ntoa(area->area_id));
+ if (v->type == OSPF_VERTEX_ROUTER) {
+ u_char *p;
+ u_char *lim;
+ struct router_lsa_link *l;
+ struct router_lsa *rlsa;
+ int lsa_pos = 0;
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "ospf_process_stubs():processing router LSA, id: %s",
+ inet_ntoa(v->lsa->id));
+ rlsa = (struct router_lsa *)v->lsa;
+
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "ospf_process_stubs(): we have %d links to process",
+ ntohs(rlsa->links));
+ p = ((u_char *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
+ lim = ((u_char *)v->lsa) + ntohs(v->lsa->length);
+
+ while (p < lim) {
+ l = (struct router_lsa_link *)p;
+
+ p += (OSPF_ROUTER_LSA_LINK_SIZE
+ + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
+
+ if (l->m[0].type == LSA_LINK_TYPE_STUB)
+ ospf_intra_add_stub(rt, l, v, area,
+ parent_is_root, lsa_pos);
+ lsa_pos++;
+ }
+ }
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("ospf_process_stub():processing stubs for area %s",
- inet_ntoa (area->area_id));
- if (v->type == OSPF_VERTEX_ROUTER)
- {
- u_char *p;
- u_char *lim;
- struct router_lsa_link *l;
- struct router_lsa *rlsa;
- int lsa_pos = 0;
-
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("ospf_process_stubs():processing router LSA, id: %s",
- inet_ntoa (v->lsa->id));
- rlsa = (struct router_lsa *) v->lsa;
-
-
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("ospf_process_stubs(): we have %d links to process",
- ntohs (rlsa->links));
- p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
- lim = ((u_char *) v->lsa) + ntohs (v->lsa->length);
-
- while (p < lim)
- {
- l = (struct router_lsa_link *) p;
+ ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1,
+ 1);
- p += (OSPF_ROUTER_LSA_LINK_SIZE +
- (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
+ for (ALL_LIST_ELEMENTS(v->children, cnode, cnnode, child)) {
+ if (CHECK_FLAG(child->flags, OSPF_VERTEX_PROCESSED))
+ continue;
- if (l->m[0].type == LSA_LINK_TYPE_STUB)
- ospf_intra_add_stub (rt, l, v, area, parent_is_root, lsa_pos);
- lsa_pos++;
- }
- }
-
- ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1);
-
- for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child))
- {
- if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED))
- continue;
-
- /* the first level of routers connected to the root
- * should have 'parent_is_root' set, including those
- * connected via a network vertex.
- */
- if (area->spf == v)
- parent_is_root = 1;
- else if (v->type == OSPF_VERTEX_ROUTER)
- parent_is_root = 0;
-
- ospf_spf_process_stubs (area, child, rt, parent_is_root);
-
- SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED);
- }
+ /* the first level of routers connected to the root
+ * should have 'parent_is_root' set, including those
+ * connected via a network vertex.
+ */
+ if (area->spf == v)
+ parent_is_root = 1;
+ else if (v->type == OSPF_VERTEX_ROUTER)
+ parent_is_root = 0;
+
+ ospf_spf_process_stubs(area, child, rt, parent_is_root);
+
+ SET_FLAG(child->flags, OSPF_VERTEX_PROCESSED);
+ }
}
-void
-ospf_rtrs_free (struct route_table *rtrs)
+void ospf_rtrs_free(struct route_table *rtrs)
{
- struct route_node *rn;
- struct list *or_list;
- struct ospf_route *or;
- struct listnode *node, *nnode;
+ struct route_node *rn;
+ struct list *or_list;
+ struct ospf_route * or ;
+ struct listnode *node, *nnode;
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("Route: Router Routing Table free");
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("Route: Router Routing Table free");
- for (rn = route_top (rtrs); rn; rn = route_next (rn))
- if ((or_list = rn->info) != NULL)
- {
- for (ALL_LIST_ELEMENTS (or_list, node, nnode, or))
- ospf_route_free (or);
+ for (rn = route_top(rtrs); rn; rn = route_next(rn))
+ if ((or_list = rn->info) != NULL) {
+ for (ALL_LIST_ELEMENTS(or_list, node, nnode, or))
+ ospf_route_free(or);
- list_delete (or_list);
+ list_delete(or_list);
- /* Unlock the node. */
- rn->info = NULL;
- route_unlock_node (rn);
- }
- route_table_finish (rtrs);
+ /* Unlock the node. */
+ rn->info = NULL;
+ route_unlock_node(rn);
+ }
+ route_table_finish(rtrs);
}
#if 0
@@ -1149,318 +1157,309 @@ ospf_rtrs_print (struct route_table *rtrs)
#endif
/* Calculating the shortest-path tree for an area. */
-static void
-ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table,
- struct route_table *new_rtrs)
+static void ospf_spf_calculate(struct ospf_area *area,
+ struct route_table *new_table,
+ struct route_table *new_rtrs)
{
- struct pqueue *candidate;
- struct vertex *v;
-
- if (IS_DEBUG_OSPF_EVENT)
- {
- zlog_debug ("ospf_spf_calculate: Start");
- zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s",
- inet_ntoa (area->area_id));
- }
-
- /* Check router-lsa-self. If self-router-lsa is not yet allocated,
- return this area's calculation. */
- if (!area->router_lsa_self)
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("ospf_spf_calculate: "
- "Skip area %s's calculation due to empty router_lsa_self",
- inet_ntoa (area->area_id));
- return;
- }
-
- /* RFC2328 16.1. (1). */
- /* Initialize the algorithm's data structures. */
-
- /* This function scans all the LSA database and set the stat field to
- * LSA_SPF_NOT_EXPLORED. */
- ospf_lsdb_clean_stat (area->lsdb);
- /* Create a new heap for the candidates. */
- candidate = pqueue_create();
- candidate->cmp = cmp;
- candidate->update = update_stat;
-
- /* Initialize the shortest-path tree to only the root (which is the
- router doing the calculation). */
- ospf_spf_init (area);
- v = area->spf;
- /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
- * spanning tree. */
- *(v->stat) = LSA_SPF_IN_SPFTREE;
-
- /* Set Area A's TransitCapability to FALSE. */
- area->transit = OSPF_TRANSIT_FALSE;
- area->shortcut_capability = 1;
-
- for (;;)
- {
- /* RFC2328 16.1. (2). */
- ospf_spf_next (v, area, candidate);
-
- /* RFC2328 16.1. (3). */
- /* If at this step the candidate list is empty, the shortest-
- path tree (of transit vertices) has been completely built and
- this stage of the procedure terminates. */
- if (candidate->size == 0)
- break;
-
- /* Otherwise, choose the vertex belonging to the candidate list
- that is closest to the root, and add it to the shortest-path
- tree (removing it from the candidate list in the
- process). */
- /* Extract from the candidates the node with the lower key. */
- v = (struct vertex *) pqueue_dequeue (candidate);
- /* Update stat field in vertex. */
- *(v->stat) = LSA_SPF_IN_SPFTREE;
-
- ospf_vertex_add_parent (v);
-
- /* RFC2328 16.1. (4). */
- if (v->type == OSPF_VERTEX_ROUTER)
- ospf_intra_add_router (new_rtrs, v, area);
- else
- ospf_intra_add_transit (new_table, v, area);
-
- /* RFC2328 16.1. (5). */
- /* Iterate the algorithm by returning to Step 2. */
-
- } /* end loop until no more candidate vertices */
+ struct pqueue *candidate;
+ struct vertex *v;
- if (IS_DEBUG_OSPF_EVENT)
- {
- ospf_spf_dump (area->spf, 0);
- ospf_route_table_dump (new_table);
- }
+ if (IS_DEBUG_OSPF_EVENT) {
+ zlog_debug("ospf_spf_calculate: Start");
+ zlog_debug("ospf_spf_calculate: running Dijkstra for area %s",
+ inet_ntoa(area->area_id));
+ }
- /* Second stage of SPF calculation procedure's */
- ospf_spf_process_stubs (area, area->spf, new_table, 0);
+ /* Check router-lsa-self. If self-router-lsa is not yet allocated,
+ return this area's calculation. */
+ if (!area->router_lsa_self) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "ospf_spf_calculate: "
+ "Skip area %s's calculation due to empty router_lsa_self",
+ inet_ntoa(area->area_id));
+ return;
+ }
- /* Free candidate queue. */
- pqueue_delete (candidate);
+ /* RFC2328 16.1. (1). */
+ /* Initialize the algorithm's data structures. */
+
+ /* This function scans all the LSA database and set the stat field to
+ * LSA_SPF_NOT_EXPLORED. */
+ ospf_lsdb_clean_stat(area->lsdb);
+ /* Create a new heap for the candidates. */
+ candidate = pqueue_create();
+ candidate->cmp = cmp;
+ candidate->update = update_stat;
+
+ /* Initialize the shortest-path tree to only the root (which is the
+ router doing the calculation). */
+ ospf_spf_init(area);
+ v = area->spf;
+ /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of
+ * the
+ * spanning tree. */
+ *(v->stat) = LSA_SPF_IN_SPFTREE;
+
+ /* Set Area A's TransitCapability to FALSE. */
+ area->transit = OSPF_TRANSIT_FALSE;
+ area->shortcut_capability = 1;
+
+ for (;;) {
+ /* RFC2328 16.1. (2). */
+ ospf_spf_next(v, area, candidate);
+
+ /* RFC2328 16.1. (3). */
+ /* If at this step the candidate list is empty, the shortest-
+ path tree (of transit vertices) has been completely built and
+ this stage of the procedure terminates. */
+ if (candidate->size == 0)
+ break;
+
+ /* Otherwise, choose the vertex belonging to the candidate list
+ that is closest to the root, and add it to the shortest-path
+ tree (removing it from the candidate list in the
+ process). */
+ /* Extract from the candidates the node with the lower key. */
+ v = (struct vertex *)pqueue_dequeue(candidate);
+ /* Update stat field in vertex. */
+ *(v->stat) = LSA_SPF_IN_SPFTREE;
+
+ ospf_vertex_add_parent(v);
+
+ /* RFC2328 16.1. (4). */
+ if (v->type == OSPF_VERTEX_ROUTER)
+ ospf_intra_add_router(new_rtrs, v, area);
+ else
+ ospf_intra_add_transit(new_table, v, area);
+
+ /* RFC2328 16.1. (5). */
+ /* Iterate the algorithm by returning to Step 2. */
+
+ } /* end loop until no more candidate vertices */
+
+ if (IS_DEBUG_OSPF_EVENT) {
+ ospf_spf_dump(area->spf, 0);
+ ospf_route_table_dump(new_table);
+ }
- ospf_vertex_dump (__func__, area->spf, 0, 1);
- /* Free nexthop information, canonical versions of which are attached
- * the first level of router vertices attached to the root vertex, see
- * ospf_nexthop_calculation.
- */
- ospf_canonical_nexthops_free (area->spf);
+ /* Second stage of SPF calculation procedure's */
+ ospf_spf_process_stubs(area, area->spf, new_table, 0);
- /* Increment SPF Calculation Counter. */
- area->spf_calculation++;
+ /* Free candidate queue. */
+ pqueue_delete(candidate);
- monotime(&area->ospf->ts_spf);
- area->ts_spf = area->ospf->ts_spf;
+ ospf_vertex_dump(__func__, area->spf, 0, 1);
+ /* Free nexthop information, canonical versions of which are attached
+ * the first level of router vertices attached to the root vertex, see
+ * ospf_nexthop_calculation.
+ */
+ ospf_canonical_nexthops_free(area->spf);
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("ospf_spf_calculate: Stop. %zd vertices",
- mtype_stats_alloc(MTYPE_OSPF_VERTEX));
+ /* Increment SPF Calculation Counter. */
+ area->spf_calculation++;
+
+ monotime(&area->ospf->ts_spf);
+ area->ts_spf = area->ospf->ts_spf;
- /* Free SPF vertices, but not the list. List has ospf_vertex_free
- * as deconstructor.
- */
- list_delete_all_node (&vertex_list);
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("ospf_spf_calculate: Stop. %zd vertices",
+ mtype_stats_alloc(MTYPE_OSPF_VERTEX));
+
+ /* Free SPF vertices, but not the list. List has ospf_vertex_free
+ * as deconstructor.
+ */
+ list_delete_all_node(&vertex_list);
}
/* Timer for SPF calculation. */
-static int
-ospf_spf_calculate_timer (struct thread *thread)
+static int ospf_spf_calculate_timer(struct thread *thread)
{
- struct ospf *ospf = THREAD_ARG (thread);
- struct route_table *new_table, *new_rtrs;
- struct ospf_area *area;
- struct listnode *node, *nnode;
- struct timeval start_time, spf_start_time;
- int areas_processed = 0;
- unsigned long ia_time, prune_time, rt_time;
- unsigned long abr_time, total_spf_time, spf_time;
- char rbuf[32]; /* reason_buf */
-
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("SPF: Timer (SPF calculation expire)");
-
- ospf->t_spf_calc = NULL;
-
- monotime(&spf_start_time);
- /* Allocate new table tree. */
- new_table = route_table_init ();
- new_rtrs = route_table_init ();
-
- ospf_vl_unapprove (ospf);
-
- /* Calculate SPF for each area. */
- for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
- {
- /* Do backbone last, so as to first discover intra-area paths
- * for any back-bone virtual-links
- */
- if (ospf->backbone && ospf->backbone == area)
- continue;
-
- ospf_spf_calculate (area, new_table, new_rtrs);
- areas_processed++;
- }
-
- /* SPF for backbone, if required */
- if (ospf->backbone)
- {
- ospf_spf_calculate (ospf->backbone, new_table, new_rtrs);
- areas_processed++;
- }
-
- spf_time = monotime_since(&spf_start_time, NULL);
-
- ospf_vl_shut_unapproved (ospf);
-
- monotime(&start_time);
- ospf_ia_routing (ospf, new_table, new_rtrs);
- ia_time = monotime_since(&start_time, NULL);
-
- monotime(&start_time);
- ospf_prune_unreachable_networks (new_table);
- ospf_prune_unreachable_routers (new_rtrs);
- prune_time = monotime_since(&start_time, NULL);
-
- /* AS-external-LSA calculation should not be performed here. */
-
- /* If new Router Route is installed,
- then schedule re-calculate External routes. */
- if (1)
- ospf_ase_calculate_schedule (ospf);
-
- ospf_ase_calculate_timer_add (ospf);
-
- /* Update routing table. */
- monotime(&start_time);
- ospf_route_install (ospf, new_table);
- rt_time = monotime_since(&start_time, NULL);
-
- /* Update ABR/ASBR routing table */
- if (ospf->old_rtrs)
- {
- /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */
- /* ospf_route_delete (ospf->old_rtrs); */
- ospf_rtrs_free (ospf->old_rtrs);
- }
-
- ospf->old_rtrs = ospf->new_rtrs;
- ospf->new_rtrs = new_rtrs;
-
- monotime(&start_time);
- if (IS_OSPF_ABR (ospf))
- ospf_abr_task (ospf);
- abr_time = monotime_since(&start_time, NULL);
-
- total_spf_time = monotime_since(&spf_start_time, &ospf->ts_spf_duration);
-
- rbuf[0] = '\0';
- if (spf_reason_flags)
- {
- if (spf_reason_flags & SPF_FLAG_ROUTER_LSA_INSTALL)
- strncat (rbuf, "R, ", sizeof(rbuf) - strlen(rbuf) - 1);
- if (spf_reason_flags & SPF_FLAG_NETWORK_LSA_INSTALL)
- strncat (rbuf, "N, ", sizeof(rbuf) - strlen(rbuf) - 1);
- if (spf_reason_flags & SPF_FLAG_SUMMARY_LSA_INSTALL)
- strncat (rbuf, "S, ", sizeof(rbuf) - strlen(rbuf) - 1);
- if (spf_reason_flags & SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL)
- strncat (rbuf, "AS, ", sizeof(rbuf) - strlen(rbuf) - 1);
- if (spf_reason_flags & SPF_FLAG_ABR_STATUS_CHANGE)
- strncat (rbuf, "ABR, ", sizeof(rbuf) - strlen(rbuf) - 1);
- if (spf_reason_flags & SPF_FLAG_ASBR_STATUS_CHANGE)
- strncat (rbuf, "ASBR, ", sizeof(rbuf) - strlen(rbuf) - 1);
- if (spf_reason_flags & SPF_FLAG_MAXAGE)
- strncat (rbuf, "M, ", sizeof(rbuf) - strlen(rbuf) - 1);
-
- size_t rbuflen = strlen(rbuf);
- if (rbuflen >= 2)
- rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */
- else
- rbuf[0] = '\0';
- }
+ struct ospf *ospf = THREAD_ARG(thread);
+ struct route_table *new_table, *new_rtrs;
+ struct ospf_area *area;
+ struct listnode *node, *nnode;
+ struct timeval start_time, spf_start_time;
+ int areas_processed = 0;
+ unsigned long ia_time, prune_time, rt_time;
+ unsigned long abr_time, total_spf_time, spf_time;
+ char rbuf[32]; /* reason_buf */
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("SPF: Timer (SPF calculation expire)");
+
+ ospf->t_spf_calc = NULL;
+
+ monotime(&spf_start_time);
+ /* Allocate new table tree. */
+ new_table = route_table_init();
+ new_rtrs = route_table_init();
+
+ ospf_vl_unapprove(ospf);
+
+ /* Calculate SPF for each area. */
+ for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
+ /* Do backbone last, so as to first discover intra-area paths
+ * for any back-bone virtual-links
+ */
+ if (ospf->backbone && ospf->backbone == area)
+ continue;
- if (IS_DEBUG_OSPF_EVENT)
- {
- zlog_info ("SPF Processing Time(usecs): %ld", total_spf_time);
- zlog_info ("\t SPF Time: %ld", spf_time);
- zlog_info ("\t InterArea: %ld", ia_time);
- zlog_info ("\t Prune: %ld", prune_time);
- zlog_info ("\tRouteInstall: %ld", rt_time);
- if (IS_OSPF_ABR (ospf))
- zlog_info ("\t ABR: %ld (%d areas)",
- abr_time, areas_processed);
- zlog_info ("Reason(s) for SPF: %s", rbuf);
- }
-
- ospf_clear_spf_reason_flags ();
-
- return 0;
+ ospf_spf_calculate(area, new_table, new_rtrs);
+ areas_processed++;
+ }
+
+ /* SPF for backbone, if required */
+ if (ospf->backbone) {
+ ospf_spf_calculate(ospf->backbone, new_table, new_rtrs);
+ areas_processed++;
+ }
+
+ spf_time = monotime_since(&spf_start_time, NULL);
+
+ ospf_vl_shut_unapproved(ospf);
+
+ monotime(&start_time);
+ ospf_ia_routing(ospf, new_table, new_rtrs);
+ ia_time = monotime_since(&start_time, NULL);
+
+ monotime(&start_time);
+ ospf_prune_unreachable_networks(new_table);
+ ospf_prune_unreachable_routers(new_rtrs);
+ prune_time = monotime_since(&start_time, NULL);
+
+ /* AS-external-LSA calculation should not be performed here. */
+
+ /* If new Router Route is installed,
+ then schedule re-calculate External routes. */
+ if (1)
+ ospf_ase_calculate_schedule(ospf);
+
+ ospf_ase_calculate_timer_add(ospf);
+
+ /* Update routing table. */
+ monotime(&start_time);
+ ospf_route_install(ospf, new_table);
+ rt_time = monotime_since(&start_time, NULL);
+
+ /* Update ABR/ASBR routing table */
+ if (ospf->old_rtrs) {
+ /* old_rtrs's node holds linked list of ospf_route. --kunihiro.
+ */
+ /* ospf_route_delete (ospf->old_rtrs); */
+ ospf_rtrs_free(ospf->old_rtrs);
+ }
+
+ ospf->old_rtrs = ospf->new_rtrs;
+ ospf->new_rtrs = new_rtrs;
+
+ monotime(&start_time);
+ if (IS_OSPF_ABR(ospf))
+ ospf_abr_task(ospf);
+ abr_time = monotime_since(&start_time, NULL);
+
+ total_spf_time =
+ monotime_since(&spf_start_time, &ospf->ts_spf_duration);
+
+ rbuf[0] = '\0';
+ if (spf_reason_flags) {
+ if (spf_reason_flags & SPF_FLAG_ROUTER_LSA_INSTALL)
+ strncat(rbuf, "R, ", sizeof(rbuf) - strlen(rbuf) - 1);
+ if (spf_reason_flags & SPF_FLAG_NETWORK_LSA_INSTALL)
+ strncat(rbuf, "N, ", sizeof(rbuf) - strlen(rbuf) - 1);
+ if (spf_reason_flags & SPF_FLAG_SUMMARY_LSA_INSTALL)
+ strncat(rbuf, "S, ", sizeof(rbuf) - strlen(rbuf) - 1);
+ if (spf_reason_flags & SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL)
+ strncat(rbuf, "AS, ", sizeof(rbuf) - strlen(rbuf) - 1);
+ if (spf_reason_flags & SPF_FLAG_ABR_STATUS_CHANGE)
+ strncat(rbuf, "ABR, ", sizeof(rbuf) - strlen(rbuf) - 1);
+ if (spf_reason_flags & SPF_FLAG_ASBR_STATUS_CHANGE)
+ strncat(rbuf, "ASBR, ",
+ sizeof(rbuf) - strlen(rbuf) - 1);
+ if (spf_reason_flags & SPF_FLAG_MAXAGE)
+ strncat(rbuf, "M, ", sizeof(rbuf) - strlen(rbuf) - 1);
+
+ size_t rbuflen = strlen(rbuf);
+ if (rbuflen >= 2)
+ rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */
+ else
+ rbuf[0] = '\0';
+ }
+
+ if (IS_DEBUG_OSPF_EVENT) {
+ zlog_info("SPF Processing Time(usecs): %ld", total_spf_time);
+ zlog_info("\t SPF Time: %ld", spf_time);
+ zlog_info("\t InterArea: %ld", ia_time);
+ zlog_info("\t Prune: %ld", prune_time);
+ zlog_info("\tRouteInstall: %ld", rt_time);
+ if (IS_OSPF_ABR(ospf))
+ zlog_info("\t ABR: %ld (%d areas)", abr_time,
+ areas_processed);
+ zlog_info("Reason(s) for SPF: %s", rbuf);
+ }
+
+ ospf_clear_spf_reason_flags();
+
+ return 0;
}
/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
set timer for SPF calc. */
-void
-ospf_spf_calculate_schedule (struct ospf *ospf, ospf_spf_reason_t reason)
+void ospf_spf_calculate_schedule(struct ospf *ospf, ospf_spf_reason_t reason)
{
- unsigned long delay, elapsed, ht;
+ unsigned long delay, elapsed, ht;
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("SPF: calculation timer scheduled");
-
- /* OSPF instance does not exist. */
- if (ospf == NULL)
- return;
-
- ospf_spf_set_reason (reason);
-
- /* SPF calculation timer is already scheduled. */
- if (ospf->t_spf_calc)
- {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("SPF: calculation timer is already scheduled: %p",
- (void *)ospf->t_spf_calc);
- return;
- }
-
- elapsed = monotime_since (&ospf->ts_spf, NULL) / 1000;
-
- ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
-
- if (ht > ospf->spf_max_holdtime)
- ht = ospf->spf_max_holdtime;
-
- /* Get SPF calculation delay time. */
- if (elapsed < ht)
- {
- /* Got an event within the hold time of last SPF. We need to
- * increase the hold_multiplier, if it's not already at/past
- * maximum value, and wasn't already increased..
- */
- if (ht < ospf->spf_max_holdtime)
- ospf->spf_hold_multiplier++;
-
- /* always honour the SPF initial delay */
- if ( (ht - elapsed) < ospf->spf_delay)
- delay = ospf->spf_delay;
- else
- delay = ht - elapsed;
- }
- else
- {
- /* Event is past required hold-time of last SPF */
- delay = ospf->spf_delay;
- ospf->spf_hold_multiplier = 1;
- }
-
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("SPF: calculation timer delay = %ld", delay);
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("SPF: calculation timer scheduled");
+
+ /* OSPF instance does not exist. */
+ if (ospf == NULL)
+ return;
+
+ ospf_spf_set_reason(reason);
+
+ /* SPF calculation timer is already scheduled. */
+ if (ospf->t_spf_calc) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "SPF: calculation timer is already scheduled: %p",
+ (void *)ospf->t_spf_calc);
+ return;
+ }
+
+ elapsed = monotime_since(&ospf->ts_spf, NULL) / 1000;
+
+ ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
+
+ if (ht > ospf->spf_max_holdtime)
+ ht = ospf->spf_max_holdtime;
+
+ /* Get SPF calculation delay time. */
+ if (elapsed < ht) {
+ /* Got an event within the hold time of last SPF. We need to
+ * increase the hold_multiplier, if it's not already at/past
+ * maximum value, and wasn't already increased..
+ */
+ if (ht < ospf->spf_max_holdtime)
+ ospf->spf_hold_multiplier++;
+
+ /* always honour the SPF initial delay */
+ if ((ht - elapsed) < ospf->spf_delay)
+ delay = ospf->spf_delay;
+ else
+ delay = ht - elapsed;
+ } else {
+ /* Event is past required hold-time of last SPF */
+ delay = ospf->spf_delay;
+ ospf->spf_hold_multiplier = 1;
+ }
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("SPF: calculation timer delay = %ld", delay);
- zlog_info ("SPF: Scheduled in %ld msec", delay);
+ zlog_info("SPF: Scheduled in %ld msec", delay);
- ospf->t_spf_calc = NULL;
- thread_add_timer_msec(master, ospf_spf_calculate_timer, ospf, delay,
- &ospf->t_spf_calc);
+ ospf->t_spf_calc = NULL;
+ thread_add_timer_msec(master, ospf_spf_calculate_timer, ospf, delay,
+ &ospf->t_spf_calc);
}