summaryrefslogtreecommitdiff
path: root/ospfd/ospf_route.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd/ospf_route.c')
-rw-r--r--ospfd/ospf_route.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
index 590122e223..7cfcaf14be 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -71,15 +71,31 @@ struct ospf_path *ospf_path_new(void)
static struct ospf_path *ospf_path_dup(struct ospf_path *path)
{
struct ospf_path *new;
+ int memsize;
new = ospf_path_new();
memcpy(new, path, sizeof(struct ospf_path));
+ /* optional TI-LFA backup paths */
+ if (path->srni.backup_label_stack) {
+ memsize = sizeof(struct mpls_label_stack)
+ + (sizeof(mpls_label_t)
+ * path->srni.backup_label_stack->num_labels);
+ new->srni.backup_label_stack =
+ XCALLOC(MTYPE_OSPF_PATH, memsize);
+ memcpy(new->srni.backup_label_stack,
+ path->srni.backup_label_stack, memsize);
+ }
+
return new;
}
void ospf_path_free(struct ospf_path *op)
{
+ /* optional TI-LFA backup paths */
+ if (op->srni.backup_label_stack)
+ XFREE(MTYPE_OSPF_PATH, op->srni.backup_label_stack);
+
XFREE(MTYPE_OSPF_PATH, op);
}
@@ -140,6 +156,35 @@ static int ospf_route_exist_new_table(struct route_table *rt,
return 1;
}
+static int ospf_route_backup_path_same(struct sr_nexthop_info *srni1,
+ struct sr_nexthop_info *srni2)
+{
+ struct mpls_label_stack *ls1, *ls2;
+ uint8_t label_count;
+
+ ls1 = srni1->backup_label_stack;
+ ls2 = srni2->backup_label_stack;
+
+ if (!ls1 && !ls2)
+ return 1;
+
+ if ((ls1 && !ls2) || (!ls1 && ls2))
+ return 0;
+
+ if (ls1->num_labels != ls2->num_labels)
+ return 0;
+
+ for (label_count = 0; label_count < ls1->num_labels; label_count++) {
+ if (ls1->label[label_count] != ls2->label[label_count])
+ return 0;
+ }
+
+ if (!IPV4_ADDR_SAME(&srni1->backup_nexthop, &srni2->backup_nexthop))
+ return 0;
+
+ return 1;
+}
+
/* If a prefix and a nexthop match any route in the routing table,
then return 1, otherwise return 0. */
int ospf_route_match_same(struct route_table *rt, struct prefix_ipv4 *prefix,
@@ -180,6 +225,11 @@ int ospf_route_match_same(struct route_table *rt, struct prefix_ipv4 *prefix,
return 0;
if (op->ifindex != newop->ifindex)
return 0;
+
+ /* check TI-LFA backup paths */
+ if (!ospf_route_backup_path_same(&op->srni,
+ &newop->srni))
+ return 0;
}
return 1;
} else if (prefix_same(&rn->p, (struct prefix *)prefix))
@@ -664,38 +714,6 @@ void ospf_route_table_dump(struct route_table *rt)
zlog_debug("========================================");
}
-void ospf_route_table_print(struct vty *vty, struct route_table *rt)
-{
- struct route_node *rn;
- struct ospf_route * or ;
- struct listnode *pnode;
- struct ospf_path *path;
-
- vty_out(vty, "========== OSPF routing table ==========\n");
- for (rn = route_top(rt); rn; rn = route_next(rn))
- if ((or = rn->info) != NULL) {
- if (or->type == OSPF_DESTINATION_NETWORK) {
- vty_out(vty, "N %-18pFX %-15pI4 %s %d\n",
- &rn->p, & or->u.std.area_id,
- ospf_path_type_str[or->path_type],
- or->cost);
- for (ALL_LIST_ELEMENTS_RO(or->paths, pnode,
- path))
- if (path->nexthop.s_addr != INADDR_ANY)
- vty_out(vty, " -> %pI4\n",
- &path->nexthop);
- else
- vty_out(vty, " -> %s\n",
- "directly connected");
- } else
- vty_out(vty, "R %-18pI4 %-15pI4 %s %d\n",
- &rn->p.u.prefix4, & or->u.std.area_id,
- ospf_path_type_str[or->path_type],
- or->cost);
- }
- vty_out(vty, "========================================\n");
-}
-
/* This is 16.4.1 implementation.
o Intra-area paths using non-backbone areas are always the most preferred.
o The other paths, intra-area backbone paths and inter-area paths,
@@ -802,6 +820,7 @@ void ospf_route_copy_nexthops_from_vertex(struct ospf_area *area,
|| area->spf_dry_run) {
path = ospf_path_new();
path->nexthop = nexthop->router;
+ path->adv_router = v->id;
if (oi) {
path->ifindex = oi->ifp->ifindex;