diff options
-rw-r--r-- | lib/libospf.h | 5 | ||||
-rw-r--r-- | lib/thread.c | 2 | ||||
-rw-r--r-- | lib/thread.h | 3 | ||||
-rw-r--r-- | ospf6d/ospf6_abr.c | 254 | ||||
-rw-r--r-- | ospf6d/ospf6_abr.h | 6 | ||||
-rw-r--r-- | ospf6d/ospf6_area.c | 221 | ||||
-rw-r--r-- | ospf6d/ospf6_area.h | 3 | ||||
-rw-r--r-- | ospf6d/ospf6_asbr.c | 17 | ||||
-rw-r--r-- | ospf6d/ospf6_asbr.h | 1 | ||||
-rw-r--r-- | ospf6d/ospf6_flood.c | 2 | ||||
-rw-r--r-- | ospf6d/ospf6_flood.h | 2 | ||||
-rw-r--r-- | ospf6d/ospf6_intra.c | 57 | ||||
-rw-r--r-- | ospf6d/ospf6_lsa.h | 1 | ||||
-rw-r--r-- | ospf6d/ospf6_route.h | 4 | ||||
-rw-r--r-- | ospf6d/ospf6_spf.c | 11 | ||||
-rw-r--r-- | ospfd/ospfd.h | 4 |
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 |