diff options
Diffstat (limited to 'ospf6d/ospf6_abr.c')
| -rw-r--r-- | ospf6d/ospf6_abr.c | 373 |
1 files changed, 195 insertions, 178 deletions
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index f289bf26b9..a9b4c7756c 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -53,6 +53,16 @@ unsigned char conf_debug_ospf6_abr; +int ospf6_ls_origin_same(struct ospf6_path *o_path, struct ospf6_path *r_path) +{ + if (((o_path->origin.type == r_path->origin.type) + && (o_path->origin.id == r_path->origin.id) + && (o_path->origin.adv_router == r_path->origin.adv_router))) + return 1; + else + return 0; +} + bool ospf6_check_and_set_router_abr(struct ospf6 *o) { struct listnode *node; @@ -96,8 +106,7 @@ static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route, return 0; } -static void ospf6_abr_delete_route(struct ospf6_route *range, - struct ospf6_route *summary, +static void ospf6_abr_delete_route(struct ospf6_route *summary, struct ospf6_route_table *summary_table, struct ospf6_lsa *old) { @@ -172,9 +181,19 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, uint16_t type; int is_debug = 0; - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("%s : start area %s, route %pFX", __func__, - area->name, &route->prefix); + if (IS_OSPF6_DEBUG_ABR) { + char buf[BUFSIZ]; + + if (route->type == OSPF6_DEST_TYPE_ROUTER) + inet_ntop(AF_INET, + &ADV_ROUTER_IN_PREFIX(&route->prefix), buf, + sizeof(buf)); + else + prefix2str(&route->prefix, buf, sizeof(buf)); + + zlog_debug("%s : start area %s, route %s", __func__, area->name, + buf); + } if (route->type == OSPF6_DEST_TYPE_ROUTER) summary_table = area->summary_router; @@ -221,6 +240,69 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, return 0; } + if (route->type == OSPF6_DEST_TYPE_NETWORK) { + bool filter = false; + + route_area = + ospf6_area_lookup(route->path.area_id, area->ospf6); + assert(route_area); + + /* Check export-list */ + if (EXPORT_LIST(route_area) + && access_list_apply(EXPORT_LIST(route_area), + &route->prefix) + == FILTER_DENY) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug( + "%s: prefix %pFX was denied by export-list", + __func__, &route->prefix); + filter = true; + } + + /* Check output prefix-list */ + if (PREFIX_LIST_OUT(route_area) + && prefix_list_apply(PREFIX_LIST_OUT(route_area), + &route->prefix) + != PREFIX_PERMIT) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug( + "%s: prefix %pFX was denied by prefix-list out", + __func__, &route->prefix); + filter = true; + } + + /* Check import-list */ + if (IMPORT_LIST(area) + && access_list_apply(IMPORT_LIST(area), &route->prefix) + == FILTER_DENY) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug( + "%s: prefix %pFX was denied by import-list", + __func__, &route->prefix); + filter = true; + } + + /* Check input prefix-list */ + if (PREFIX_LIST_IN(area) + && prefix_list_apply(PREFIX_LIST_IN(area), &route->prefix) + != PREFIX_PERMIT) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug( + "%s: prefix %pFX was denied by prefix-list in", + __func__, &route->prefix); + filter = true; + } + + if (filter) { + if (summary) { + ospf6_route_remove(summary, summary_table); + if (old) + ospf6_lsa_purge(old); + } + return 0; + } + } + /* do not generate if the nexthops belongs to the target area */ if (ospf6_abr_nexthops_belong_to_area(route, area)) { if (IS_OSPF6_DEBUG_ABR) @@ -302,8 +384,8 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "The range is not active. withdraw"); - ospf6_abr_delete_route(route, summary, - summary_table, old); + ospf6_abr_delete_route(summary, summary_table, + old); } } else if (old) { ospf6_route_remove(summary, summary_table); @@ -317,7 +399,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "Area has been stubbed, purge Inter-Router LSA"); - ospf6_abr_delete_route(route, summary, summary_table, old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -326,7 +408,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug("Area has been stubbed, purge prefix LSA"); - ospf6_abr_delete_route(route, summary, summary_table, old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -361,8 +443,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "This is the secondary path to the ASBR, ignore"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -392,8 +473,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "Suppressed by range %pFX of area %s", &range->prefix, route_area->name); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } } @@ -405,8 +485,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "This is the range with DoNotAdvertise set. ignore"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -414,45 +493,11 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) { if (is_debug) zlog_debug("The range is not active. withdraw"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } } - /* Check export list */ - if (EXPORT_NAME(area)) { - if (EXPORT_LIST(area) == NULL) - EXPORT_LIST(area) = - access_list_lookup(AFI_IP6, EXPORT_NAME(area)); - - if (EXPORT_LIST(area)) - if (access_list_apply(EXPORT_LIST(area), &route->prefix) - == FILTER_DENY) { - if (is_debug) - zlog_debug( - "prefix %pFX was denied by export list", - &route->prefix); - ospf6_abr_delete_route(route, summary, - summary_table, old); - return 0; - } - } - - /* Check filter-list */ - if (PREFIX_LIST_OUT(area)) - if (prefix_list_apply(PREFIX_LIST_OUT(area), &route->prefix) - != PREFIX_PERMIT) { - if (is_debug) - zlog_debug( - "prefix %pFX was denied by filter-list out", - &route->prefix); - ospf6_abr_delete_route(route, summary, summary_table, - old); - - return 0; - } - /* the route is going to be originated. store it in area's summary_table */ if (summary == NULL) { @@ -477,11 +522,11 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, monotime(&summary->changed); } + summary->prefix_options = route->prefix_options; summary->path.router_bits = route->path.router_bits; summary->path.options[0] = route->path.options[0]; summary->path.options[1] = route->path.options[1]; summary->path.options[2] = route->path.options[2]; - 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; @@ -514,7 +559,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, /* Fill Inter-Area-Prefix-LSA */ OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa, route->path.cost); prefix_lsa->prefix.prefix_length = route->prefix.prefixlen; - prefix_lsa->prefix.prefix_options = route->path.prefix_options; + prefix_lsa->prefix.prefix_options = route->prefix_options; /* set Prefix */ memcpy(p, &route->prefix.u.prefix6, @@ -558,10 +603,14 @@ void ospf6_abr_range_reset_cost(struct ospf6 *ospf6) struct ospf6_area *oa; struct ospf6_route *range; - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + 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); + for (range = ospf6_route_head(oa->nssa_range_table); range; + range = ospf6_route_next(range)) + OSPF6_ABR_RANGE_CLEAR_COST(range); + } } static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range, @@ -572,10 +621,19 @@ static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range, 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); + if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE)) + continue; + if (ro->path.area_id != range->path.area_id) + continue; + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE) + && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1 + && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2) + continue; + if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE) + && ro->path.type != OSPF6_PATH_TYPE_INTRA) + continue; + + cost = MAX(cost, ro->path.cost); } return cost; @@ -624,6 +682,8 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6) int summary_orig = 0; assert(range->type == OSPF6_DEST_TYPE_RANGE); + oa = ospf6_area_lookup(range->path.area_id, ospf6); + assert(oa); /* update range's cost and active flag */ cost = ospf6_abr_range_compute_cost(range, ospf6); @@ -646,34 +706,49 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6) * if there * were active ranges. */ + if (!ospf6_abr_range_summary_needs_update(range, cost)) + return; - if (ospf6_abr_range_summary_needs_update(range, cost)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("%s: range %pFX update", __func__, - &range->prefix); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("%s: range %pFX update", __func__, &range->prefix); + + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) { + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) + && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) { + ospf6_nssa_lsa_originate(range, oa, true); + summary_orig = 1; + } else { + struct ospf6_lsa *lsa; + + lsa = ospf6_lsdb_lookup(range->path.origin.type, + range->path.origin.id, + ospf6->router_id, oa->lsdb); + if (lsa) + ospf6_lsa_premature_aging(lsa); + } + } else { + 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) - && summary_orig) { - if (!CHECK_FLAG(range->flag, - OSPF6_ROUTE_BLACKHOLE_ADDED)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("Add discard route"); + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) + && summary_orig) { + 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); - } - } 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"); + ospf6_zebra_add_discard(range, ospf6); + } + } 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"); - ospf6_zebra_delete_discard(range, ospf6); - } + ospf6_zebra_delete_discard(range, ospf6); } } } @@ -684,8 +759,18 @@ void ospf6_abr_originate_summary(struct ospf6_route *route, struct ospf6 *ospf6) struct ospf6_area *oa; struct ospf6_route *range = NULL; - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("%s: route %pFX", __func__, &route->prefix); + if (IS_OSPF6_DEBUG_ABR) { + char buf[BUFSIZ]; + + if (route->type == OSPF6_DEST_TYPE_ROUTER) + inet_ntop(AF_INET, + &ADV_ROUTER_IN_PREFIX(&route->prefix), buf, + sizeof(buf)); + else + prefix2str(&route->prefix, buf, sizeof(buf)); + + zlog_debug("%s: route %s", __func__, buf); + } if (route->type == OSPF6_DEST_TYPE_NETWORK) { oa = ospf6_area_lookup(route->path.area_id, ospf6); @@ -710,25 +795,12 @@ void ospf6_abr_defaults_to_stub(struct ospf6 *o) struct listnode *node, *nnode; struct ospf6_area *oa; struct ospf6_route *def, *route; - struct ospf6_redist *red; int type = DEFAULT_ROUTE; - struct prefix_ipv6 p = {}; if (!o->backbone) return; - red = ospf6_redist_lookup(o, type, 0); - if (!red) - return; - - p.family = AF_INET6; - p.prefixlen = 0; - - route = ospf6_route_lookup((struct prefix *)&p, o->external_table); - if (!route) - return; - - def = ospf6_route_create(); + def = ospf6_route_create(o); def->type = OSPF6_DEST_TYPE_NETWORK; def->prefix.family = AF_INET6; def->prefix.prefixlen = 0; @@ -741,7 +813,15 @@ void ospf6_abr_defaults_to_stub(struct ospf6 *o) def->path.cost = metric_value(o, type, 0); for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) { - if (!IS_AREA_STUB(oa)) { + if (IS_AREA_STUB(oa) || (IS_AREA_NSSA(oa) && oa->no_summary)) { + /* 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); + } else { /* withdraw defaults when an area switches from stub to * non-stub */ route = ospf6_route_lookup(&def->prefix, @@ -755,14 +835,6 @@ void ospf6_abr_defaults_to_stub(struct ospf6 *o) 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); @@ -778,9 +850,8 @@ void ospf6_abr_old_path_update(struct ospf6_route *old_route, struct ospf6_nexthop *nh, *rnh; for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) { - if (o_path->area_id != route->path.area_id || - (memcmp(&(o_path)->origin, &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) != 0)) + if (o_path->area_id != route->path.area_id + || !ospf6_ls_origin_same(o_path, &route->path)) continue; if ((o_path->cost == route->path.cost) && @@ -1127,46 +1198,14 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) return; } - /* Check import list */ - if (IMPORT_NAME(oa)) { - if (IMPORT_LIST(oa) == NULL) - IMPORT_LIST(oa) = - access_list_lookup(AFI_IP6, IMPORT_NAME(oa)); - - if (IMPORT_LIST(oa)) - if (access_list_apply(IMPORT_LIST(oa), &prefix) - == FILTER_DENY) { - if (is_debug) - zlog_debug( - "Prefix %pFX was denied by import-list", - &prefix); - if (old) - ospf6_route_remove(old, table); - return; - } - } - - /* Check input prefix-list */ - if (PREFIX_LIST_IN(oa)) { - if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix) - != PREFIX_PERMIT) { - if (is_debug) - zlog_debug( - "Prefix %pFX was denied by prefix-list in", - &prefix); - if (old) - ospf6_route_remove(old, table); - return; - } - } - /* (5),(6): the path preference is handled by the sorting in the routing table. Always install the path by substituting old route (if any). */ - route = ospf6_route_create(); + route = ospf6_route_create(oa->ospf6); route->type = type; route->prefix = prefix; + route->prefix_options = prefix_options; route->path.origin.type = lsa->header->type; route->path.origin.id = lsa->header->id; route->path.origin.adv_router = lsa->header->adv_router; @@ -1174,7 +1213,6 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) route->path.options[0] = options[0]; route->path.options[1] = options[1]; route->path.options[2] = options[2]; - route->path.prefix_options = prefix_options; route->path.area_id = oa->area_id; route->path.type = OSPF6_PATH_TYPE_INTER; route->path.cost = abr_entry->path.cost + cost; @@ -1194,9 +1232,16 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) __func__, &prefix, listcount(old->paths)); } for (old_route = old; old_route; old_route = old_route->next) { - if (!ospf6_route_is_same(old_route, route) || - (old_route->type != route->type) || - (old_route->path.type != route->path.type)) + + /* The route linked-list is grouped in batches of prefix. + * If the new prefix is not the same as the one of interest + * then we have walked over the end of the batch and so we + * should break rather than continuing unnecessarily. + */ + if (!ospf6_route_is_same(old_route, route)) + break; + if ((old_route->type != route->type) + || (old_route->path.type != route->path.type)) continue; if ((ospf6_route_cmp(route, old_route) != 0)) { @@ -1221,9 +1266,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { - if (o_path->area_id == route->path.area_id && - (memcmp(&(o_path)->origin, &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) == 0)) + if (o_path->area_id == route->path.area_id + && ospf6_ls_origin_same(o_path, &route->path)) break; } @@ -1250,7 +1294,9 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) listcount(old_route->nh_list)); } } else { - struct ospf6_route *tmp_route = ospf6_route_create(); + struct ospf6_route *tmp_route; + + tmp_route = ospf6_route_create(oa->ospf6); ospf6_copy_nexthops(tmp_route->nh_list, o_path->nh_list); @@ -1339,35 +1385,6 @@ void ospf6_abr_examin_brouter(uint32_t router_id, struct ospf6_route *route, ospf6_abr_examin_summary(lsa, oa); } -void ospf6_abr_reimport(struct ospf6_area *oa) -{ - struct ospf6_lsa *lsa; - uint16_t type; - - type = htons(OSPF6_LSTYPE_INTER_ROUTER); - for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) - ospf6_abr_examin_summary(lsa, oa); - - type = htons(OSPF6_LSTYPE_INTER_PREFIX); - for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) - ospf6_abr_examin_summary(lsa, oa); -} - -/* export filter removed so determine if we should reoriginate summary LSAs */ -void ospf6_abr_reexport(struct ospf6_area *oa) -{ - struct ospf6_route *route; - - /* if not a ABR return success */ - if (!ospf6_check_and_set_router_abr(oa->ospf6)) - return; - - /* Redo summaries if required */ - for (route = ospf6_route_head(oa->ospf6->route_table); route; - route = ospf6_route_next(route)) - ospf6_abr_originate_summary_to_area(route, oa); -} - void ospf6_abr_prefix_resummarize(struct ospf6 *o) { struct ospf6_route *route; |
