ospf6d: ospfv3-stub-area-support.patch

Support stubby and totally stubby areas in OSPFv3

Signed-off-by: Dinesh G Dutt <ddutt at cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat at cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2015-05-19 18:03:40 -07:00
parent c3c0ac8395
commit ca1f4309e6
16 changed files with 470 additions and 133 deletions

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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);
}
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,25 +510,25 @@ 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)
{
u_int32_t cost = 0;
struct ospf6_route *ro;
int gen_range_summary = 0;
char buf[INET6_ADDRSTRLEN];
struct listnode *node, *nnode;
struct ospf6_area *oa;
struct ospf6_route *range;
assert (range->type == OSPF6_DEST_TYPE_RANGE);
prefix2str (&range->prefix, buf, sizeof (buf));
if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE))
{
UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
gen_range_summary = 1;
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);
}
else
static inline u_int32_t
ospf6_abr_range_compute_cost (struct ospf6_route *range, struct ospf6 *o)
{
/* update range's cost and active flag */
for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table);
struct ospf6_route *ro;
u_int32_t cost = 0;
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 &&
@ -549,8 +536,70 @@ ospf6_abr_range_update (struct ospf6_route *range)
! 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);
redo_summary = 1;
}
else if (CHECK_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
{
if (range->path.cost != 0)
{
range->path.cost = 0;
redo_summary = 1;
}
}
else if (cost)
{
if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path) &&
range->path.cost != range->path.u.cost_config))
{
range->path.cost = range->path.u.cost_config;
SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
redo_summary = 1;
}
else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path) &&
range->path.cost != cost)
{
range->path.cost = cost;
SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
redo_summary = 1;
}
}
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;
redo_summary = 1;
}
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.
@ -561,51 +610,26 @@ ospf6_abr_range_update (struct ospf6_route *range)
* 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))
{
if (range->path.cost != 0)
{
range->path.cost = 0;
gen_range_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))))
{
if (range->path.u.cost_config == OSPF_AREA_RANGE_COST_UNSPEC)
{
range->path.cost = cost;
}
else
{
range->path.cost = range->path.u.cost_config;
}
SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
gen_range_summary = 1;
}
else if (!cost && CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
if (ospf6_abr_range_summary_needs_update (range, cost))
{
UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
gen_range_summary = 1;
}
for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
summary_orig += ospf6_abr_originate_summary_to_area (range, oa);
if (gen_range_summary)
if (CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) && summary_orig)
{
ospf6_abr_originate_summary (range);
if (CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
if (! CHECK_FLAG (range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED))
{
if (IS_OSPF6_DEBUG_ABR)
zlog_debug ("Add discard route");
ospf6_zebra_add_discard (range);
}
}
else
{
/* 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");
@ -614,6 +638,7 @@ ospf6_abr_range_update (struct ospf6_route *range)
}
}
}
}
void
ospf6_abr_originate_summary (struct ospf6_route *route)
@ -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 */

View File

@ -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);

View File

@ -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;
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);

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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)
{

View File

@ -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,

View File

@ -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))

View File

@ -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

View File

@ -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"

View File

@ -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);

View File

@ -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