/* RFC2328 16.1. (4). For "router". */
void ospf_intra_add_router(struct route_table *rt, struct vertex *v,
- struct ospf_area *area)
+ struct ospf_area *area, bool add_all)
{
struct route_node *rn;
struct ospf_route * or ;
/* If the newly added vertex is an area border router or AS boundary
router, a routing table entry is added whose destination type is
"router". */
- if (!IS_ROUTER_LSA_BORDER(lsa) && !IS_ROUTER_LSA_EXTERNAL(lsa)) {
+ if (!add_all && !IS_ROUTER_LSA_BORDER(lsa) &&
+ !IS_ROUTER_LSA_EXTERNAL(lsa)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"ospf_intra_add_router: this router is neither ASBR nor ABR, skipping it");
zlog_debug("========================================");
}
+void ospf_router_route_table_dump(struct route_table *rt)
+{
+ struct route_node *rn;
+ struct ospf_route *or;
+ struct listnode *node;
+
+ zlog_debug("========== OSPF routing table ==========");
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+ for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, or)) {
+ assert(or->type == OSPF_DESTINATION_ROUTER);
+ zlog_debug("R %-18pI4 %-15pI4 %s %d", &rn->p.u.prefix4,
+ &or->u.std.area_id,
+ ospf_path_type_str[or->path_type], or->cost);
+ }
+ }
+ zlog_debug("========================================");
+}
+
/* 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,
extern void ospf_route_install(struct ospf *, struct route_table *);
extern void ospf_route_table_dump(struct route_table *);
+extern void ospf_router_route_table_dump(struct route_table *rt);
-extern void ospf_intra_add_router(struct route_table *, struct vertex *,
- struct ospf_area *);
+extern void ospf_intra_add_router(struct route_table *rt, struct vertex *v,
+ struct ospf_area *area, bool add_all);
extern void ospf_intra_add_transit(struct route_table *, struct vertex *,
struct ospf_area *);
/* Calculating the shortest-path tree for an area, see RFC2328 16.1. */
void ospf_spf_calculate(struct ospf_area *area, struct ospf_lsa *root_lsa,
struct route_table *new_table,
+ struct route_table *all_rtrs,
struct route_table *new_rtrs, bool is_dry_run,
bool is_root_node)
{
ospf_vertex_add_parent(v);
/* RFC2328 16.1. (4). */
- if (v->type == OSPF_VERTEX_ROUTER)
- ospf_intra_add_router(new_rtrs, v, area);
- else
+ if (v->type != OSPF_VERTEX_ROUTER)
ospf_intra_add_transit(new_table, v, area);
+ else {
+ ospf_intra_add_router(new_rtrs, v, area, false);
+ if (all_rtrs)
+ ospf_intra_add_router(all_rtrs, v, area, true);
+ }
/* Iterate back to (2), see RFC2328 16.1. (5). */
}
if (IS_DEBUG_OSPF_EVENT) {
ospf_spf_dump(area->spf, 0);
ospf_route_table_dump(new_table);
+ if (all_rtrs)
+ ospf_router_route_table_dump(all_rtrs);
}
/*
void ospf_spf_calculate_area(struct ospf *ospf, struct ospf_area *area,
struct route_table *new_table,
+ struct route_table *all_rtrs,
struct route_table *new_rtrs)
{
- ospf_spf_calculate(area, area->router_lsa_self, new_table, new_rtrs,
- false, true);
+ ospf_spf_calculate(area, area->router_lsa_self, new_table, all_rtrs,
+ new_rtrs, false, true);
if (ospf->ti_lfa_enabled)
ospf_ti_lfa_compute(area, new_table,
}
void ospf_spf_calculate_areas(struct ospf *ospf, struct route_table *new_table,
+ struct route_table *all_rtrs,
struct route_table *new_rtrs)
{
struct ospf_area *area;
if (ospf->backbone && ospf->backbone == area)
continue;
- ospf_spf_calculate_area(ospf, area, new_table, new_rtrs);
+ ospf_spf_calculate_area(ospf, area, new_table, all_rtrs,
+ new_rtrs);
}
/* SPF for backbone, if required */
if (ospf->backbone)
ospf_spf_calculate_area(ospf, ospf->backbone, new_table,
- new_rtrs);
+ all_rtrs, new_rtrs);
}
/* Worker for SPF calculation scheduler. */
{
struct ospf *ospf = THREAD_ARG(thread);
struct route_table *new_table, *new_rtrs;
+ struct route_table *all_rtrs = NULL;
struct timeval start_time, spf_start_time;
unsigned long ia_time, prune_time, rt_time;
unsigned long abr_time, total_spf_time, spf_time;
monotime(&spf_start_time);
new_table = route_table_init(); /* routing table */
new_rtrs = route_table_init(); /* ABR/ASBR routing table */
- ospf_spf_calculate_areas(ospf, new_table, new_rtrs);
+
+ /* If we have opaque enabled then track all router reachability */
+ if (CHECK_FLAG(ospf->opaque, OPAQUE_OPERATION_READY_BIT))
+ all_rtrs = route_table_init();
+
+ ospf_spf_calculate_areas(ospf, new_table, all_rtrs, new_rtrs);
spf_time = monotime_since(&spf_start_time, NULL);
ospf_vl_shut_unapproved(ospf);
/* Get rid of transit networks and routers we cannot reach anyway. */
monotime(&start_time);
ospf_prune_unreachable_networks(new_table);
+ if (all_rtrs)
+ ospf_prune_unreachable_routers(all_rtrs);
ospf_prune_unreachable_routers(new_rtrs);
prune_time = monotime_since(&start_time, NULL);
ospf_route_install(ospf, new_table);
rt_time = monotime_since(&start_time, NULL);
+ /* Free old all routers routing table */
+ if (ospf->oall_rtrs)
+ /* ospf_route_delete (ospf->old_rtrs); */
+ ospf_rtrs_free(ospf->oall_rtrs);
+
+ /* Update all routers routing table */
+ ospf->oall_rtrs = ospf->all_rtrs;
+ ospf->all_rtrs = all_rtrs;
+
/* Free old ABR/ASBR routing table */
if (ospf->old_rtrs)
/* ospf_route_delete (ospf->old_rtrs); */
extern void ospf_spf_calculate(struct ospf_area *area,
struct ospf_lsa *root_lsa,
struct route_table *new_table,
+ struct route_table *all_rtrs,
struct route_table *new_rtrs, bool is_dry_run,
bool is_root_node);
extern void ospf_spf_calculate_area(struct ospf *ospf, struct ospf_area *area,
struct route_table *new_table,
+ struct route_table *all_rtrs,
struct route_table *new_rtrs);
extern void ospf_spf_calculate_areas(struct ospf *ospf,
struct route_table *new_table,
+ struct route_table *all_rtrs,
struct route_table *new_rtrs);
extern void ospf_rtrs_free(struct route_table *);
extern void ospf_spf_cleanup(struct vertex *spf, struct list *vertex_list);
XCALLOC(MTYPE_OSPF_P_SPACE, sizeof(struct p_spaces_head));
/* dry run true, root node false */
- ospf_spf_calculate(area, start_vertex->lsa_p, new_table, new_rtrs, true,
- false);
+ ospf_spf_calculate(area, start_vertex->lsa_p, new_table, NULL, new_rtrs,
+ true, false);
q_node = ospf_spf_vertex_find(end_vertex->id, area->spf_vertex_list);
sizeof(struct ospf_ti_lfa_node_info));
new_table = route_table_init();
+ /* XXX do these get freed?? */
new_rtrs = route_table_init();
/*
* dry run true, root node false
*/
area->spf_reversed = true;
- ospf_spf_calculate(area, dest->lsa_p, new_table, new_rtrs, true, false);
+ ospf_spf_calculate(area, dest->lsa_p, new_table, NULL, new_rtrs, true,
+ false);
/* Reset the flag for reverse SPF */
area->spf_reversed = false;
struct route_table *new_table, *new_rtrs;
new_table = route_table_init();
+ /* XXX do these get freed?? */
new_rtrs = route_table_init();
area->spf_protected_resource = p_space->protected_resource;
* endeavour (because LSAs are stored as a 'raw' stream), so we go with
* this rather hacky way for now.
*/
- ospf_spf_calculate(area, area->router_lsa_self, new_table, new_rtrs,
- true, false);
+ ospf_spf_calculate(area, area->router_lsa_self, new_table, NULL,
+ new_rtrs, true, false);
p_space->pc_spf = area->spf;
p_space->pc_vertex_list = area->spf_vertex_list;
struct route_table *old_table; /* Old routing table. */
struct route_table *new_table; /* Current routing table. */
+ struct route_table *oall_rtrs; /* Old router RT. */
+ struct route_table *all_rtrs; /* New routers RT. */
+
struct route_table *old_rtrs; /* Old ABR/ASBR RT. */
struct route_table *new_rtrs; /* New ABR/ASBR RT. */
enum protection_type protection_type, bool verbose)
{
struct route_table *new_table, *new_rtrs;
+ struct route_table *all_rtrs = NULL;
struct ospf_area *area;
struct p_space *p_space;
struct q_space *q_space;
new_table = route_table_init();
new_rtrs = route_table_init();
+ all_rtrs = route_table_init();
/* dryrun true, root_node false */
- ospf_spf_calculate(area, area->router_lsa_self, new_table, new_rtrs,
- true, false);
+ ospf_spf_calculate(area, area->router_lsa_self, new_table, all_rtrs,
+ new_rtrs, true, false);
if (verbose) {
vty_out(vty, "SPF Tree without TI-LFA backup paths:\n\n");