summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libospf.h5
-rw-r--r--lib/thread.c2
-rw-r--r--lib/thread.h3
-rw-r--r--ospf6d/ospf6_abr.c254
-rw-r--r--ospf6d/ospf6_abr.h6
-rw-r--r--ospf6d/ospf6_area.c221
-rw-r--r--ospf6d/ospf6_area.h3
-rw-r--r--ospf6d/ospf6_asbr.c17
-rw-r--r--ospf6d/ospf6_asbr.h1
-rw-r--r--ospf6d/ospf6_flood.c2
-rw-r--r--ospf6d/ospf6_flood.h2
-rw-r--r--ospf6d/ospf6_intra.c57
-rw-r--r--ospf6d/ospf6_lsa.h1
-rw-r--r--ospf6d/ospf6_route.h4
-rw-r--r--ospf6d/ospf6_spf.c11
-rw-r--r--ospfd/ospfd.h4
16 files changed, 465 insertions, 128 deletions
diff --git a/lib/libospf.h b/lib/libospf.h
index ade774db6..8762dfb25 100644
--- a/lib/libospf.h
+++ b/lib/libospf.h
@@ -82,6 +82,11 @@
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
#define OSPF_AREA_RANGE_COST_UNSPEC -1U
+#define OSPF_AREA_DEFAULT 0
+#define OSPF_AREA_STUB 1
+#define OSPF_AREA_NSSA 2
+#define OSPF_AREA_TYPE_MAX 3
+
/* SPF Throttling timer values. */
#define OSPF_SPF_DELAY_DEFAULT 200
#define OSPF_SPF_HOLDTIME_DEFAULT 1000
diff --git a/lib/thread.c b/lib/thread.c
index 43bae242c..00d0a639a 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -57,8 +57,6 @@ static unsigned short timers_inited;
static struct hash *cpu_record = NULL;
-/* Struct timeval's tv_usec one second value. */
-#define TIMER_SECOND_MICRO 1000000L
/* Adjust so that tv_usec is in the range [0,TIMER_SECOND_MICRO).
And change negative values to 0. */
diff --git a/lib/thread.h b/lib/thread.h
index f47dc9235..95008a73b 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -111,6 +111,9 @@ enum quagga_clkid {
QUAGGA_CLK_REALTIME_STABILISED, /* like realtime, but non-decrementing */
};
+/* Struct timeval's tv_usec one second value. */
+#define TIMER_SECOND_MICRO 1000000L
+
/* Thread types. */
#define THREAD_READ 0
#define THREAD_WRITE 1
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index f975ce842..7c6e89db5 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -91,7 +91,7 @@ ospf6_abr_delete_route (struct ospf6_route *range, struct ospf6_route *summary,
ospf6_route_remove (summary, summary_table);
}
- if (old)
+ if (old && !OSPF6_LSA_IS_MAXAGE (old))
ospf6_lsa_purge (old);
}
@@ -99,35 +99,11 @@ void
ospf6_abr_enable_area (struct ospf6_area *area)
{
struct ospf6_area *oa;
- struct ospf6_route *ro;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa))
- {
- /* update B bit for each area */
- OSPF6_ROUTER_LSA_SCHEDULE (oa);
-
- /* install other area's configured address range */
- if (oa != area)
- {
- for (ro = ospf6_route_head (oa->range_table); ro;
- ro = ospf6_route_next (ro))
- {
- if (CHECK_FLAG (ro->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
- ospf6_abr_originate_summary_to_area (ro, area);
- }
- }
- }
-
- /* install calculated routes to border routers */
- for (ro = ospf6_route_head (area->ospf6->brouter_table); ro;
- ro = ospf6_route_next (ro))
- ospf6_abr_originate_summary_to_area (ro, area);
-
- /* install calculated routes to network (may be rejected by ranges) */
- for (ro = ospf6_route_head (area->ospf6->route_table); ro;
- ro = ospf6_route_next (ro))
- ospf6_abr_originate_summary_to_area (ro, area);
+ /* update B bit for each area */
+ OSPF6_ROUTER_LSA_SCHEDULE (oa);
}
void
@@ -167,6 +143,8 @@ ospf6_abr_disable_area (struct ospf6_area *area)
}
/* RFC 2328 12.4.3. Summary-LSAs */
+/* Returns 1 if a summary LSA has been generated for the area */
+/* This is used by the area/range logic to add/remove blackhole routes */
int
ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
struct ospf6_area *area)
@@ -295,6 +273,15 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
return 0;
}
+ if (area->no_summary && (route->path.subtype != OSPF6_PATH_SUBTYPE_DEFAULT_RT))
+ {
+ if (is_debug)
+ zlog_debug ("Area has been stubbed, purge prefix LSA");
+
+ ospf6_abr_delete_route (route, summary, summary_table, old);
+ return 0;
+ }
+
/* do not generate if the route cost is greater or equal to LSInfinity */
if (route->path.cost >= OSPF_LS_INFINITY)
{
@@ -445,7 +432,6 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
summary->path.origin.adv_router, area->lsdb);
}
summary = ospf6_route_add (summary, summary_table);
-
}
else
{
@@ -460,6 +446,7 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
summary->path.prefix_options = route->path.prefix_options;
summary->path.area_id = area->area_id;
summary->path.type = OSPF6_PATH_TYPE_INTER;
+ summary->path.subtype = route->path.subtype;
summary->path.cost = route->path.cost;
/* summary->nexthop[0] = route->nexthop[0]; */
@@ -523,94 +510,132 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
}
void
-ospf6_abr_range_update (struct ospf6_route *range)
+ospf6_abr_range_reset_cost (struct ospf6 *ospf6)
+{
+ struct listnode *node, *nnode;
+ struct ospf6_area *oa;
+ struct ospf6_route *range;
+
+ for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
+ for (range = ospf6_route_head (oa->range_table); range;
+ range = ospf6_route_next (range))
+ OSPF6_ABR_RANGE_CLEAR_COST(range);
+}
+
+static inline u_int32_t
+ospf6_abr_range_compute_cost (struct ospf6_route *range, struct ospf6 *o)
{
- u_int32_t cost = 0;
struct ospf6_route *ro;
- int gen_range_summary = 0;
- char buf[INET6_ADDRSTRLEN];
+ u_int32_t cost = 0;
- assert (range->type == OSPF6_DEST_TYPE_RANGE);
- prefix2str (&range->prefix, buf, sizeof (buf));
+ for (ro = ospf6_route_match_head (&range->prefix, o->route_table);
+ ro; ro = ospf6_route_match_next (&range->prefix, ro))
+ {
+ if (ro->path.area_id == range->path.area_id &&
+ (ro->path.type == OSPF6_PATH_TYPE_INTRA) &&
+ ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE))
+ cost = MAX (cost, ro->path.cost);
+ }
+
+ return cost;
+}
+
+static inline int
+ospf6_abr_range_summary_needs_update (struct ospf6_route *range,
+ u_int32_t cost)
+{
+ int redo_summary = 0;
if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE))
{
UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
- gen_range_summary = 1;
+ redo_summary = 1;
}
- else
- {
- /* update range's cost and active flag */
- for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table);
- ro; ro = ospf6_route_match_next (&range->prefix, ro))
- {
- if (ro->path.area_id == range->path.area_id &&
- (ro->path.type == OSPF6_PATH_TYPE_INTRA) &&
- ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE))
- cost = MAX (cost, ro->path.cost);
- }
- }
-
- /* Non-zero cost is a proxy for active longer prefixes in this range.
- * If there are active routes covered by this range AND either the configured
- * cost has changed or the summarized cost has changed then redo summaries.
- * Alternately, if there are no longer active prefixes and there are
- * summary announcements, withdraw those announcements.
- *
- * The don't advertise code relies on the path.cost being set to UNSPEC to
- * work the first time. Subsequent times the path.cost is not 0 anyway if there
- * were active ranges.
- */
- if (CHECK_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
+ else if (CHECK_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
{
if (range->path.cost != 0)
{
range->path.cost = 0;
- gen_range_summary = 1;
+ redo_summary = 1;
}
}
- else if (cost &&
- (((range->path.u.cost_config != OSPF_AREA_RANGE_COST_UNSPEC) &&
- (range->path.cost != range->path.u.cost_config)) ||
- ((range->path.u.cost_config == OSPF_AREA_RANGE_COST_UNSPEC) &&
- (range->path.cost != cost))))
+ else if (cost)
{
- if (range->path.u.cost_config == OSPF_AREA_RANGE_COST_UNSPEC)
+ if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path) &&
+ range->path.cost != range->path.u.cost_config))
{
- range->path.cost = cost;
+ range->path.cost = range->path.u.cost_config;
+ SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
+ redo_summary = 1;
}
- else
+ else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path) &&
+ range->path.cost != cost)
{
- range->path.cost = range->path.u.cost_config;
+ range->path.cost = cost;
+ SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
+ redo_summary = 1;
}
-
- SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
- gen_range_summary = 1;
}
- else if (!cost && CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
+ else if (CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
{
+ /* Cost is zero, meaning no active range */
UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
- gen_range_summary = 1;
+ redo_summary = 1;
}
- if (gen_range_summary)
+ return (redo_summary);
+}
+
+static void
+ospf6_abr_range_update (struct ospf6_route *range)
+{
+ u_int32_t cost = 0;
+ struct listnode *node, *nnode;
+ struct ospf6_area *oa;
+ int summary_orig = 0;
+
+ assert (range->type == OSPF6_DEST_TYPE_RANGE);
+
+ /* update range's cost and active flag */
+ cost = ospf6_abr_range_compute_cost (range, ospf6);
+
+ /* Non-zero cost is a proxy for active longer prefixes in this range.
+ * If there are active routes covered by this range AND either the configured
+ * cost has changed or the summarized cost has changed then redo summaries.
+ * Alternately, if there are no longer active prefixes and there are
+ * summary announcements, withdraw those announcements.
+ *
+ * The don't advertise code relies on the path.cost being set to UNSPEC to
+ * work the first time. Subsequent times the path.cost is not 0 anyway if there
+ * were active ranges.
+ */
+
+ if (ospf6_abr_range_summary_needs_update (range, cost))
{
- ospf6_abr_originate_summary (range);
+ for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
+ summary_orig += ospf6_abr_originate_summary_to_area (range, oa);
- if (CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
+ if (CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) && summary_orig)
{
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug ("Add discard route");
+ if (! CHECK_FLAG (range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED))
+ {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug ("Add discard route");
- ospf6_zebra_add_discard (range);
+ ospf6_zebra_add_discard (range);
+ }
}
else
{
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug ("Delete discard route");
+ /* Summary removed or no summary generated as no specifics exist */
+ if (CHECK_FLAG (range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED))
+ {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug ("Delete discard route");
- ospf6_zebra_delete_discard (range);
+ ospf6_zebra_delete_discard (range);
+ }
}
}
}
@@ -636,6 +661,54 @@ ospf6_abr_originate_summary (struct ospf6_route *route)
ospf6_abr_originate_summary_to_area (route, oa);
}
+void
+ospf6_abr_defaults_to_stub (struct ospf6 *o)
+{
+ struct listnode *node, *nnode;
+ struct ospf6_area *oa;
+ struct ospf6_route *def, *route;
+
+ if (!o->backbone)
+ return;
+
+ def = ospf6_route_create();
+ def->type = OSPF6_DEST_TYPE_NETWORK;
+ def->prefix.family = AF_INET6;
+ def->prefix.prefixlen = 0;
+ memset (&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
+ def->type = OSPF6_DEST_TYPE_NETWORK;
+ def->path.type = OSPF6_PATH_TYPE_INTER;
+ def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
+ def->path.area_id = o->backbone->area_id;
+
+ for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
+ {
+ if (!IS_AREA_STUB (oa))
+ {
+ /* withdraw defaults when an area switches from stub to non-stub */
+ route = ospf6_route_lookup (&def->prefix, oa->summary_prefix);
+ if (route && (route->path.subtype == def->path.subtype))
+ {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug ("Withdrawing default route from non-stubby area %s",
+ oa->name);
+ SET_FLAG (def->flag, OSPF6_ROUTE_REMOVE);
+ ospf6_abr_originate_summary_to_area (def, oa);
+ }
+ }
+ else
+ {
+ /* announce defaults to stubby areas */
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug ("Announcing default route into stubby area %s",
+ oa->name);
+ UNSET_FLAG (def->flag, OSPF6_ROUTE_REMOVE);
+ ospf6_abr_originate_summary_to_area (def, oa);
+ }
+ }
+ ospf6_route_delete (def);
+}
+
/* RFC 2328 16.2. Calculating the inter-area routes */
void
ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
@@ -939,6 +1012,21 @@ ospf6_abr_reimport (struct ospf6_area *oa)
ospf6_abr_examin_summary (lsa, oa);
}
+void
+ospf6_abr_prefix_resummarize (struct ospf6 *o)
+{
+ struct ospf6_route *route;
+
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug ("Re-examining Inter-Prefix Summaries");
+
+ for (route = ospf6_route_head (o->route_table); route;
+ route = ospf6_route_next (route))
+ ospf6_abr_originate_summary(route);
+
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug ("Finished re-examining Inter-Prefix Summaries");
+}
/* Display functions */
diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h
index 09b1d87c4..bfd609c25 100644
--- a/ospf6d/ospf6_abr.h
+++ b/ospf6d/ospf6_abr.h
@@ -57,6 +57,8 @@ struct ospf6_inter_router_lsa
{ (E)->metric &= htonl (0x00000000); \
(E)->metric |= htonl (0x00ffffff) & htonl (C); }
+#define OSPF6_ABR_RANGE_CLEAR_COST(range) (range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC)
+
extern int ospf6_is_router_abr (struct ospf6 *o);
extern void ospf6_abr_enable_area (struct ospf6_area *oa);
@@ -66,9 +68,11 @@ extern int ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
struct ospf6_area *area);
extern void ospf6_abr_originate_summary (struct ospf6_route *route);
extern void ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa);
+extern void ospf6_abr_defaults_to_stub (struct ospf6 *);
extern void ospf6_abr_examin_brouter (u_int32_t router_id);
extern void ospf6_abr_reimport (struct ospf6_area *oa);
-extern void ospf6_abr_range_update (struct ospf6_route *range);
+extern void ospf6_abr_range_reset_cost (struct ospf6 *ospf6);
+extern void ospf6_abr_prefix_resummarize (struct ospf6 *ospf6);
extern int config_write_ospf6_debug_abr (struct vty *vty);
extern void install_element_ospf6_debug_abr (void);
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 12ab7ce03..c3a90df6d 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -43,6 +43,7 @@
#include "ospf6_interface.h"
#include "ospf6_intra.h"
#include "ospf6_abr.h"
+#include "ospf6_asbr.h"
#include "ospf6d.h"
int
@@ -133,12 +134,82 @@ ospf6_area_route_hook_remove (struct ospf6_route *route)
ospf6_route_remove (copy, ospf6->route_table);
}
+static void
+ospf6_area_stub_update (struct ospf6_area *area)
+{
+
+ if (IS_AREA_STUB (area))
+ {
+ if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
+ zlog_debug ("Stubbing out area for if %s\n", area->name);
+ OSPF6_OPT_CLEAR (area->options, OSPF6_OPT_E);
+ }
+ else if (IS_AREA_ENABLED (area))
+ {
+ if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
+ zlog_debug ("Normal area for if %s\n", area->name);
+ OSPF6_OPT_SET (area->options, OSPF6_OPT_E);
+ ospf6_asbr_send_externals_to_area (area);
+ }
+
+ OSPF6_ROUTER_LSA_SCHEDULE(area);
+}
+
+static int
+ospf6_area_stub_set (struct ospf6 *ospf6, struct ospf6_area *area)
+{
+ if (!IS_AREA_STUB(area))
+ {
+ SET_FLAG (area->flag, OSPF6_AREA_STUB);
+ ospf6_area_stub_update (area);
+ }
+
+ return (1);
+}
+
+static void
+ospf6_area_stub_unset (struct ospf6 *ospf6, struct ospf6_area *area)
+{
+ if (IS_AREA_STUB (area))
+ {
+ UNSET_FLAG (area->flag, OSPF6_AREA_STUB);
+ ospf6_area_stub_update (area);
+ }
+}
+
+static void
+ospf6_area_no_summary_set (struct ospf6 *ospf6, struct ospf6_area *area)
+{
+ if (area)
+ {
+ if (!area->no_summary)
+ {
+ area->no_summary = 1;
+ ospf6_abr_range_reset_cost (ospf6);
+ ospf6_abr_prefix_resummarize (ospf6);
+ }
+ }
+}
+
+static void
+ospf6_area_no_summary_unset (struct ospf6 *ospf6, struct ospf6_area *area)
+{
+ if (area)
+ {
+ if (area->no_summary)
+ {
+ area->no_summary = 0;
+ ospf6_abr_range_reset_cost (ospf6);
+ ospf6_abr_prefix_resummarize (ospf6);
+ }
+ }
+}
+
/* Make new area structure */
struct ospf6_area *
ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
{
struct ospf6_area *oa;
- struct ospf6_route *route;
oa = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area));
@@ -180,6 +251,9 @@ ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
+ SET_FLAG (oa->flag, OSPF6_AREA_ACTIVE);
+ SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
+
oa->ospf6 = o;
listnode_add_sort (o->area_list, oa);
@@ -188,11 +262,6 @@ ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
o->backbone = oa;
}
- /* import athoer area's routes as inter-area routes */
- for (route = ospf6_route_head (o->route_table); route;
- route = ospf6_route_next (route))
- ospf6_abr_originate_summary_to_area (route, oa);
-
return oa;
}
@@ -294,16 +363,46 @@ ospf6_area_show (struct vty *vty, struct ospf6_area *oa)
{
struct listnode *i;
struct ospf6_interface *oi;
+ unsigned long result;
- vty_out (vty, " Area %s%s", oa->name, VNL);
+ if (!IS_AREA_STUB (oa))
+ vty_out (vty, " Area %s%s", oa->name, VNL);
+ else
+ {
+ if (oa->no_summary)
+ {
+ vty_out (vty, " Area %s[Stub, No Summary]%s", oa->name, VNL);
+ }
+ else
+ {
+ vty_out (vty, " Area %s[Stub]%s", oa->name, VNL);
+ }
+ }
vty_out (vty, " Number of Area scoped LSAs is %u%s",
oa->lsdb->count, VNL);
vty_out (vty, " Interface attached to this area:");
for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
vty_out (vty, " %s", oi->interface->name);
-
vty_out (vty, "%s", VNL);
+
+ if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec)
+ {
+ result = timeval_elapsed (recent_relative_time (), oa->ts_spf);
+ if (result/TIMER_SECOND_MICRO > 0)
+ {
+ vty_out (vty, "SPF last executed %ld.%lds ago%s",
+ result/TIMER_SECOND_MICRO,
+ result%TIMER_SECOND_MICRO, VTY_NEWLINE);
+ }
+ else
+ {
+ vty_out (vty, "SPF last executed %ldus ago%s",
+ result, VTY_NEWLINE);
+ }
+ }
+ else
+ vty_out (vty, "SPF has not been run%s", VTY_NEWLINE);
}
@@ -346,7 +445,7 @@ DEFUN (area_range,
int ret;
struct ospf6_area *oa;
struct prefix prefix;
- struct ospf6_route *range, *route;
+ struct ospf6_route *range;
u_int32_t cost = OSPF_AREA_RANGE_COST_UNSPEC;
OSPF6_CMD_AREA_GET (argv[0], oa);
@@ -398,9 +497,7 @@ DEFUN (area_range,
if (ospf6_is_router_abr (ospf6))
{
/* Redo summaries if required */
- for (route = ospf6_route_head (ospf6->route_table); route;
- route = ospf6_route_next (route))
- ospf6_abr_originate_summary(route);
+ ospf6_abr_prefix_resummarize (ospf6);
}
return CMD_SUCCESS;
@@ -503,6 +600,13 @@ ospf6_area_config_write (struct vty *vty)
prefix2str (&range->prefix, buf, sizeof (buf));
vty_out (vty, " area %s range %s%s", oa->name, buf, VNL);
}
+ if (IS_AREA_STUB (oa))
+ {
+ if (oa->no_summary)
+ vty_out (vty, " area %s stub no-summary%s", oa->name, VNL);
+ else
+ vty_out (vty, " area %s stub%s", oa->name, VNL);
+ }
if (PREFIX_NAME_IN (oa))
vty_out (vty, " area %s filter-list prefix %s in%s",
oa->name, PREFIX_NAME_IN (oa), VNL);
@@ -842,6 +946,94 @@ DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
return CMD_SUCCESS;
}
+DEFUN (ospf6_area_stub,
+ ospf6_area_stub_cmd,
+ "area (A.B.C.D|<0-4294967295>) stub",
+ "OSPF6 area parameters\n"
+ "OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
+ "Configure OSPF6 area as stub\n")
+{
+ struct ospf6_area *area;
+
+ OSPF6_CMD_AREA_GET(argv[0], area);
+
+ if (!ospf6_area_stub_set (ospf6, area))
+ {
+ vty_out (vty, "First deconfigure all virtual link through this area%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ ospf6_area_no_summary_unset (ospf6, area);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (ospf6_area_stub_no_summary,
+ ospf6_area_stub_no_summary_cmd,
+ "area (A.B.C.D|<0-4294967295>) stub no-summary",
+ "OSPF6 stub parameters\n"
+ "OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
+ "Configure OSPF6 area as stub\n"
+ "Do not inject inter-area routes into stub\n")
+{
+ struct ospf6_area *area;
+
+ OSPF6_CMD_AREA_GET(argv[0], area);
+
+ if (!ospf6_area_stub_set (ospf6, area))
+ {
+ vty_out (vty, "First deconfigure all virtual link through this area%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ ospf6_area_no_summary_set (ospf6, area);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_area_stub,
+ no_ospf6_area_stub_cmd,
+ "no area (A.B.C.D|<0-4294967295>) stub",
+ NO_STR
+ "OSPF6 area parameters\n"
+ "OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
+ "Configure OSPF6 area as stub\n")
+{
+ struct ospf6_area *area;
+
+ OSPF6_CMD_AREA_GET(argv[0], area);
+
+ ospf6_area_stub_unset (ospf6, area);
+ ospf6_area_no_summary_unset (ospf6, area);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_area_stub_no_summary,
+ no_ospf6_area_stub_no_summary_cmd,
+ "no area (A.B.C.D|<0-4294967295>) stub no-summary",
+ NO_STR
+ "OSPF6 area parameters\n"
+ "OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
+ "Configure OSPF6 area as stub\n"
+ "Do not inject inter-area routes into area\n")
+{
+ struct ospf6_area *area;
+
+ OSPF6_CMD_AREA_GET(argv[0], area);
+
+ ospf6_area_stub_unset (ospf6, area);
+ ospf6_area_no_summary_unset (ospf6, area);
+
+ return CMD_SUCCESS;
+}
+
void
ospf6_area_init (void)
{
@@ -858,6 +1050,11 @@ ospf6_area_init (void)
install_element (OSPF6_NODE, &area_range_cost_cmd);
install_element (OSPF6_NODE, &area_range_advertise_cost_cmd);
install_element (OSPF6_NODE, &no_area_range_cmd);
+ install_element (OSPF6_NODE, &ospf6_area_stub_no_summary_cmd);
+ install_element (OSPF6_NODE, &ospf6_area_stub_cmd);
+ install_element (OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd);
+ install_element (OSPF6_NODE, &no_ospf6_area_stub_cmd);
+
install_element (OSPF6_NODE, &area_import_list_cmd);
install_element (OSPF6_NODE, &no_area_import_list_cmd);
diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h
index 691186906..3b752d948 100644
--- a/ospf6d/ospf6_area.h
+++ b/ospf6d/ospf6_area.h
@@ -46,6 +46,9 @@ struct ospf6_area
struct ospf6_route_table *summary_prefix;
struct ospf6_route_table *summary_router;
+ /* Area type */
+ int no_summary;
+
/* OSPF interface list */
struct list *if_list;
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 880e10ed6..97e9473ef 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -412,6 +412,23 @@ ospf6_asbr_redistribute_unset (int type)
ospf6_asbr_routemap_unset (type);
}
+/* When an area is unstubified, flood all the external LSAs in the area */
+void
+ospf6_asbr_send_externals_to_area (struct ospf6_area *oa)
+{
+ struct ospf6_lsa *lsa;
+
+ for (lsa = ospf6_lsdb_head (oa->ospf6->lsdb); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL)
+ {
+ zlog_debug ("%s: Flooding AS-External LSA %s\n", __func__, lsa->name);
+ ospf6_flood_area (NULL, lsa, oa);
+ }
+ }
+}
+
void
ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
u_int nexthop_num, struct in6_addr *nexthop)
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index 73770cc00..90befdc0d 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -91,6 +91,7 @@ extern int ospf6_redistribute_config_write (struct vty *vty);
extern void ospf6_asbr_init (void);
extern void ospf6_asbr_redistribute_reset (void);
extern void ospf6_asbr_terminate (void);
+extern void ospf6_asbr_send_externals_to_area (struct ospf6_area *);
extern int config_write_ospf6_debug_asbr (struct vty *vty);
extern void install_element_ospf6_debug_asbr (void);
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index 4d537f6ed..5fe4cda8a 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -422,7 +422,7 @@ ospf6_flood_interface (struct ospf6_neighbor *from,
}
}
-static void
+void
ospf6_flood_area (struct ospf6_neighbor *from,
struct ospf6_lsa *lsa, struct ospf6_area *oa)
{
diff --git a/ospf6d/ospf6_flood.h b/ospf6d/ospf6_flood.h
index 3a6f300ba..ba7fd25f9 100644
--- a/ospf6d/ospf6_flood.h
+++ b/ospf6d/ospf6_flood.h
@@ -52,6 +52,8 @@ extern void ospf6_decrement_retrans_count (struct ospf6_lsa *lsa);
/* flooding & clear flooding */
extern void ospf6_flood_clear (struct ospf6_lsa *lsa);
extern void ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa);
+extern void ospf6_flood_area (struct ospf6_neighbor *from,
+ struct ospf6_lsa *lsa, struct ospf6_area *oa);
/* receive & install */
extern void ospf6_receive_lsa (struct ospf6_neighbor *from,
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index a220437af..7dd6bd704 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -140,6 +140,31 @@ ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
return 0;
}
+static void
+ospf6_router_lsa_options_set (struct ospf6_area *oa,
+ struct ospf6_router_lsa *router_lsa)
+{
+ OSPF6_OPT_CLEAR_ALL (router_lsa->options);
+ memcpy (router_lsa->options, oa->options, 3);
+
+ if (ospf6_is_router_abr (ospf6))
+ SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
+ else
+ UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
+
+ if (!IS_AREA_STUB (oa) && ospf6_asbr_is_asbr (oa->ospf6))
+ {
+ SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
+ }
+ else
+ {
+ UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
+ }
+
+ UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V);
+ UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W);
+}
+
int
ospf6_router_is_stub_router (struct ospf6_lsa *lsa)
{
@@ -194,23 +219,7 @@ ospf6_router_lsa_originate (struct thread *thread)
router_lsa = (struct ospf6_router_lsa *)
((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
- OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6);
- OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E);
- OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC);
- OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N);
- OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
- OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
-
- if (ospf6_is_router_abr (ospf6))
- SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
- else
- UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
- if (ospf6_asbr_is_asbr (ospf6))
- SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
- else
- UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
- UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V);
- UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W);
+ ospf6_router_lsa_options_set (oa, router_lsa);
/* describe links for each interfaces */
lsdesc = (struct ospf6_router_lsdesc *)
@@ -1469,7 +1478,11 @@ ospf6_intra_route_calculation (struct ospf6_area *oa)
if (hook_add)
(*hook_add) (route);
}
-
+ else
+ {
+ /* Redo the summaries as things might have changed */
+ ospf6_abr_originate_summary (route);
+ }
route->flag = 0;
}
@@ -1554,7 +1567,7 @@ ospf6_intra_brouter_calculation (struct ospf6_area *oa)
inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
if (brouter->path.area_id != oa->area_id)
continue;
- brouter->flag = OSPF6_ROUTE_REMOVE;
+ SET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE);
if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
IS_OSPF6_DEBUG_ROUTE (MEMORY))
@@ -1647,9 +1660,11 @@ ospf6_intra_brouter_calculation (struct ospf6_area *oa)
IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
zlog_info ("brouter %s still exists via area %s",
brouter_name, oa->name);
+ /* But re-originate summaries */
+ ospf6_abr_originate_summary (brouter);
}
-
- brouter->flag = 0;
+ UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD);
+ UNSET_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE);
}
if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index a85ca66dc..aa64a772f 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -141,6 +141,7 @@ struct ospf6_lsa
#define OSPF6_LSA_FLOODBACK 0x02
#define OSPF6_LSA_DUPLICATE 0x04
#define OSPF6_LSA_IMPLIEDACK 0x08
+#define OSPF6_LSA_UNAPPROVED 0x10
#define OSPF6_LSA_SEQWRAPPED 0x20
struct ospf6_lsa_handler
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index 0f7159511..b0e43874a 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -110,6 +110,10 @@ struct ospf6_path
#define OSPF6_PATH_TYPE_REDISTRIBUTE 5
#define OSPF6_PATH_TYPE_MAX 6
+#define OSPF6_PATH_SUBTYPE_DEFAULT_RT 1
+
+#define OSPF6_PATH_COST_IS_CONFIGURED(path) (path.u.cost_config != OSPF_AREA_RANGE_COST_UNSPEC)
+
#include "prefix.h"
#include "table.h"
#include "bitfield.h"
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index 20ec3721d..04d02d708 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -36,6 +36,8 @@
#include "ospf6_lsdb.h"
#include "ospf6_route.h"
#include "ospf6_area.h"
+#include "ospf6_proto.h"
+#include "ospf6_abr.h"
#include "ospf6_spf.h"
#include "ospf6_intra.h"
#include "ospf6_interface.h"
@@ -601,6 +603,9 @@ ospf6_spf_calculation_thread (struct thread *t)
/* execute SPF calculation */
quagga_gettime (QUAGGA_CLK_MONOTONIC, &start);
+ if (ospf6_is_router_abr (ospf6))
+ ospf6_abr_range_reset_cost (ospf6);
+
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa))
{
@@ -634,10 +639,8 @@ ospf6_spf_calculation_thread (struct thread *t)
areas_processed++;
}
- /* Redo summaries if required */
- for (route = ospf6_route_head (ospf6->route_table); route;
- route = ospf6_route_next (route))
- ospf6_abr_originate_summary(route);
+ if (ospf6_is_router_abr (ospf6))
+ ospf6_abr_defaults_to_stub (ospf6);
quagga_gettime (QUAGGA_CLK_MONOTONIC, &end);
timersub (&end, &start, &runtime);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index d98519a16..53c4099f2 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -312,10 +312,6 @@ struct ospf_area
/* Configured variables. */
int external_routing; /* ExternalRoutingCapability. */
-#define OSPF_AREA_DEFAULT 0
-#define OSPF_AREA_STUB 1
-#define OSPF_AREA_NSSA 2
-#define OSPF_AREA_TYPE_MAX 3
int no_summary; /* Don't inject summaries into stub.*/
int shortcut_configured; /* Area configured as shortcut. */
#define OSPF_SHORTCUT_DEFAULT 0